Initial import
[samba] / source / libmsrpc / cac_lsarpc.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  MS-RPC client library implementation (LSA pipe)
4  *  Copyright (C) Chris Nicholls              2005.
5  *  
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *  
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *  
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "libmsrpc.h"
22 #include "libsmb_internal.h"
23
24 int cac_LsaOpenPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenPolicy *op) {
25    SMBCSRV *srv = NULL;
26    POLICY_HND *policy = NULL;
27    struct rpc_pipe_client *pipe_hnd = NULL;
28
29    if(!hnd)
30       return CAC_FAILURE;
31          
32    if(!hnd->_internal.ctx) {
33       hnd->status = NT_STATUS_INVALID_HANDLE;
34       return CAC_FAILURE;
35    }
36
37    if(!mem_ctx || !op) {
38       hnd->status = NT_STATUS_INVALID_PARAMETER;
39       return CAC_FAILURE;
40    }
41
42    op->out.pol = NULL;
43
44    srv = cac_GetServer(hnd);
45    if(!srv) {
46       hnd->status = NT_STATUS_INVALID_CONNECTION;
47       return CAC_FAILURE; 
48    }
49
50    /*see if there is already an active session on this pipe, if not then open one*/
51    if(!hnd->_internal.pipes[PI_LSARPC]) {
52       pipe_hnd = cli_rpc_pipe_open_noauth(&(srv->cli), PI_LSARPC, &(hnd->status));
53
54       if(!pipe_hnd) {
55          hnd->status = NT_STATUS_UNSUCCESSFUL;
56          return CAC_FAILURE;
57       }
58
59       hnd->_internal.pipes[PI_LSARPC] = True;
60    }
61
62    policy = SMB_MALLOC_P(POLICY_HND);
63    if(!policy) {
64       errno = ENOMEM;
65       hnd->status = NT_STATUS_NO_MEMORY;
66       return CAC_FAILURE;
67    }
68
69    /*need to make sure that our nt status is good otherwise check might fail below*/
70    hnd->status = NT_STATUS_OK;
71    
72    if(hnd->_internal.srv_level >= SRV_WIN_2K) { 
73
74       /*try using open_policy2, if this fails try again in next block using open_policy, if that works then adjust hnd->_internal.srv_level*/
75
76       /*we shouldn't need to modify the access mask to make it work here*/
77       hnd->status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, op->in.security_qos, op->in.access, policy);
78
79    }
80
81    if(hnd->_internal.srv_level < SRV_WIN_2K || !NT_STATUS_IS_OK(hnd->status)) {
82       hnd->status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, op->in.security_qos, op->in.access, policy);
83
84       if(hnd->_internal.srv_level > SRV_WIN_NT4 && NT_STATUS_IS_OK(hnd->status)) {
85          /*change the server level to 1*/
86          hnd->_internal.srv_level = SRV_WIN_NT4;
87       }
88       
89    }
90
91    if(!NT_STATUS_IS_OK(hnd->status)) {
92       SAFE_FREE(policy);
93       return CAC_FAILURE;
94    }
95
96    op->out.pol = policy;
97
98    return CAC_SUCCESS;
99 }
100
101 int cac_LsaClosePolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *pol) {
102
103    struct rpc_pipe_client *pipe_hnd = NULL;
104
105    if(!hnd)
106       return CAC_FAILURE;
107    
108    if(!pol)
109       return CAC_SUCCESS; /*if the policy handle doesnt exist then it's already closed*/
110
111    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
112       hnd->status = NT_STATUS_INVALID_HANDLE;
113       return CAC_FAILURE;
114    }
115
116    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
117    if(!pipe_hnd) {
118       hnd->status = NT_STATUS_INVALID_HANDLE;
119       return CAC_FAILURE;
120    }
121
122
123    hnd->status = rpccli_lsa_close(pipe_hnd, mem_ctx, pol);
124
125    if(!NT_STATUS_IS_OK(hnd->status))
126       return CAC_FAILURE;
127
128    SAFE_FREE(pol);
129
130    return CAC_SUCCESS;
131 }
132
133 int cac_LsaGetNamesFromSids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetNamesFromSids *op) {
134    struct rpc_pipe_client *pipe_hnd = NULL;
135
136    int result   = -1;
137
138    int i;
139
140    /*buffers for outputs*/
141    char **domains   = NULL;
142    char **names     = NULL;
143    uint32 *types    = NULL;
144
145    CacSidInfo *sids_out   = NULL;
146    DOM_SID *unknown_out   = NULL;
147    int num_unknown         = 0;
148
149    int num_sids;
150
151    int found_idx;
152    int unknown_idx;
153
154    if(!hnd)
155       return CAC_FAILURE;
156       
157    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
158       hnd->status = NT_STATUS_INVALID_HANDLE;
159       return CAC_FAILURE;
160    }
161
162    if(!mem_ctx || !op || !op->in.pol || !op->in.sids) {
163       hnd->status = NT_STATUS_INVALID_PARAMETER;
164       return CAC_FAILURE;
165    }
166
167    num_sids = op->in.num_sids;
168
169    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
170    if(!pipe_hnd) {
171       hnd->status = NT_STATUS_INVALID_HANDLE;
172       return CAC_FAILURE;
173    }
174
175
176
177    /*now actually lookup the names*/
178    hnd->status = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, op->in.pol, op->in.num_sids,
179                                        op->in.sids, &domains, &names, &types);
180
181    if(NT_STATUS_IS_OK(hnd->status)) {
182       /*this is the easy part, just make the out.sids array*/
183       sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, num_sids);
184       if(!sids_out) {
185          errno = ENOMEM;
186          hnd->status = NT_STATUS_NO_MEMORY;
187          return CAC_FAILURE;
188       }
189
190       for(i = 0; i < num_sids; i++) {
191          sids_out[i].sid    = op->in.sids[i];
192          sids_out[i].name   = names[i];
193          sids_out[i].domain = domains[i];
194       }
195
196       result = CAC_SUCCESS;
197    }
198    else if(NT_STATUS_V(hnd->status) == NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
199       /*first find out how many couldn't be looked up*/
200
201       for(i = 0; i < num_sids; i++) {
202          if(names[i] == NULL) {
203             num_unknown++;
204          }
205       }
206
207       if( num_unknown >= num_sids) {
208          hnd->status = NT_STATUS_UNSUCCESSFUL;
209          return CAC_FAILURE;
210       }
211
212       sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, (num_sids - num_unknown));
213       if(!sids_out) {
214          errno = ENOMEM;
215          hnd->status = NT_STATUS_NO_MEMORY;
216          return CAC_FAILURE;
217       }
218
219       unknown_out = TALLOC_ARRAY(mem_ctx, DOM_SID, num_unknown);
220       if(!unknown_out) {
221          errno = ENOMEM;
222          hnd->status = NT_STATUS_NO_MEMORY;
223          return CAC_FAILURE;
224       }
225
226       found_idx = unknown_idx = 0;
227
228       /*now we can actually do the real work*/
229       for(i = 0; i < num_sids; i++) {
230          if(names[i] != NULL) {
231             sids_out[found_idx].sid    = op->in.sids[i];
232             sids_out[found_idx].name   = names[i];
233             sids_out[found_idx].domain = domains[i];
234
235             found_idx++;
236          }
237          else { /*then this one didnt work out*/
238             unknown_out[unknown_idx] = op->in.sids[i];
239
240             unknown_idx++;
241          }
242       }
243
244       result = CAC_PARTIAL_SUCCESS;
245    }
246    else { /*then it failed for some reason*/
247       return CAC_FAILURE;
248    }
249
250    op->out.num_found    = num_sids - num_unknown;
251    op->out.sids         = sids_out;
252    op->out.unknown      = unknown_out;
253
254    return result;
255    
256 }
257
258 int cac_LsaGetSidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetSidsFromNames *op) {
259    struct rpc_pipe_client *pipe_hnd = NULL;
260    int result   = -1;
261
262    int i;
263
264    /*buffers for outputs*/
265    DOM_SID *sids     = NULL;
266    uint32 *types     = NULL;
267
268    CacSidInfo *sids_out  = NULL;
269    char **unknown_out     = NULL;
270    int num_unknown        = 0;
271
272    int num_names;
273
274    int found_idx          = 0;
275    int unknown_idx        = 0;
276
277    if(!hnd)
278       return CAC_FAILURE;
279
280    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
281       hnd->status = NT_STATUS_INVALID_HANDLE;
282       return CAC_FAILURE;
283    }
284
285    if(!mem_ctx || !op || !op->in.pol || !op->in.names) {
286       hnd->status = NT_STATUS_INVALID_PARAMETER;
287       return CAC_FAILURE;
288    }
289
290    num_names = op->in.num_names;
291
292    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
293    if(!pipe_hnd) {
294       hnd->status = NT_STATUS_INVALID_HANDLE;
295       return CAC_FAILURE;
296    }
297
298
299    /*now actually lookup the names*/
300    hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, num_names,
301                                           (const char **)op->in.names, &sids, &types);
302
303    if(NT_STATUS_IS_OK(hnd->status)) {
304       /*this is the easy part, just make the out.sids array*/
305       sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, num_names);
306       if(!sids_out) {
307          errno = ENOMEM;
308          hnd->status = NT_STATUS_NO_MEMORY;
309          return CAC_FAILURE;
310       }
311
312       for(i = 0; i < num_names; i++) {
313          sids_out[i].sid    = sids[i];
314          sids_out[i].name   = talloc_strdup(mem_ctx, op->in.names[i]);
315          sids_out[i].domain = NULL;
316       }
317       
318       result = CAC_SUCCESS;
319    }
320    else if(NT_STATUS_V(hnd->status) == NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
321       /*first find out how many couldn't be looked up*/
322
323       for(i = 0; i < num_names; i++) {
324          if(types[i] == SID_NAME_UNKNOWN) {
325             num_unknown++;
326          }
327       }
328
329       if( num_unknown >= num_names) {
330          hnd->status = NT_STATUS_UNSUCCESSFUL;
331          return CAC_FAILURE;
332       }
333
334       sids_out = TALLOC_ARRAY(mem_ctx, CacSidInfo, (num_names - num_unknown));
335       if(!sids_out) {
336          errno = ENOMEM;
337          hnd->status = NT_STATUS_NO_MEMORY;
338          return CAC_FAILURE;
339       }
340
341       unknown_out = TALLOC_ARRAY(mem_ctx, char *, num_unknown);
342       if(!unknown_out) {
343          errno = ENOMEM;
344          hnd->status = NT_STATUS_NO_MEMORY;
345          return CAC_FAILURE;
346       }
347
348       unknown_idx = found_idx = 0;
349
350       /*now we can actually do the real work*/
351       for(i = 0; i < num_names; i++) {
352          if(types[i] != SID_NAME_UNKNOWN) {
353             sids_out[found_idx].sid    = sids[i];
354             sids_out[found_idx].name   = talloc_strdup(mem_ctx, op->in.names[i]);
355             sids_out[found_idx].domain = NULL;
356
357             found_idx++;
358          }
359          else { /*then this one didnt work out*/
360             unknown_out[unknown_idx] = talloc_strdup(mem_ctx, op->in.names[i]);
361
362             unknown_idx++;
363          }
364       }
365
366       result = CAC_PARTIAL_SUCCESS;
367    }
368    else { /*then it failed for some reason*/
369       return CAC_FAILURE;
370    }
371
372    op->out.num_found    = num_names - num_unknown;
373    op->out.sids         = sids_out;
374    op->out.unknown      = unknown_out;
375
376    return result;
377    
378 }
379
380 int cac_LsaFetchSid(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaFetchSid *op) {
381    struct rpc_pipe_client *pipe_hnd = NULL;
382    int result   = -1;
383
384    if(!hnd)
385       return CAC_FAILURE;
386    
387    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC] ) {
388       hnd->status = NT_STATUS_INVALID_HANDLE;
389       return CAC_FAILURE;
390    }
391
392    if(!mem_ctx || !op || !op->in.pol) {
393       hnd->status = NT_STATUS_INVALID_PARAMETER;
394       return CAC_FAILURE;
395    }
396
397    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
398    if(!pipe_hnd) {
399       hnd->status = NT_STATUS_INVALID_HANDLE;
400       return CAC_FAILURE;
401    }
402
403    op->out.local_sid  = NULL;
404    op->out.domain_sid = NULL;
405
406    if( (op->in.info_class & CAC_LOCAL_INFO) == CAC_LOCAL_INFO) {
407       DOM_SID *local_sid = NULL;
408       char *dom_name     = NULL;
409
410       hnd->status = rpccli_lsa_query_info_policy( pipe_hnd, mem_ctx, op->in.pol, CAC_LOCAL_INFO, &dom_name, &local_sid);
411
412       if(!NT_STATUS_IS_OK(hnd->status)) {
413          result = CAC_FAILURE;
414          goto domain;
415       }
416
417       op->out.local_sid = talloc(mem_ctx, CacSidInfo);
418       if(!op->out.local_sid) {
419          hnd->status = NT_STATUS_NO_MEMORY;
420          result = CAC_FAILURE;
421          goto domain;
422       }
423
424       op->out.local_sid->domain = dom_name;
425       
426       sid_copy(&op->out.local_sid->sid, local_sid);
427       talloc_free(local_sid);
428    }
429
430 domain:
431
432    if( (op->in.info_class & CAC_DOMAIN_INFO) == CAC_DOMAIN_INFO) {
433       DOM_SID *domain_sid;
434       char *dom_name;
435
436       hnd->status = rpccli_lsa_query_info_policy( pipe_hnd, mem_ctx, op->in.pol, CAC_DOMAIN_INFO, &dom_name, &domain_sid);
437       if(!NT_STATUS_IS_OK(hnd->status)) {
438          /*if we succeeded above, report partial success*/
439          result = (result == CAC_SUCCESS) ? CAC_PARTIAL_SUCCESS : CAC_FAILURE;
440          goto done;
441       }
442       else if(result == CAC_FAILURE) {
443          /*if we failed above but succeded here then report partial success*/
444          result = CAC_PARTIAL_SUCCESS;
445       }
446
447       op->out.domain_sid = talloc(mem_ctx, CacSidInfo);
448       if(!op->out.domain_sid) {
449          hnd->status = NT_STATUS_NO_MEMORY;
450          result = CAC_FAILURE;
451          goto done;
452       }
453
454       op->out.domain_sid->domain = dom_name;
455       sid_copy(&op->out.domain_sid->sid, domain_sid);
456       talloc_free(domain_sid);
457    }
458    
459 done:
460    return result;
461 }
462
463 int cac_LsaQueryInfoPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaQueryInfoPolicy *op) {
464    struct rpc_pipe_client *pipe_hnd = NULL;
465
466    char *domain_name    = NULL;
467    char *dns_name       = NULL;
468    char *forest_name     = NULL;
469    struct uuid *domain_guid    = NULL;
470    DOM_SID *domain_sid  = NULL;
471
472    if(!hnd)
473       return CAC_FAILURE;
474
475    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
476       hnd->status = NT_STATUS_INVALID_HANDLE;
477       return CAC_FAILURE;
478    }
479
480    if(!op->in.pol) {
481       hnd->status = NT_STATUS_INVALID_PARAMETER;
482       return CAC_FAILURE;
483    }
484
485    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
486    if(!pipe_hnd) {
487       hnd->status = NT_STATUS_INVALID_HANDLE;
488       return CAC_FAILURE;
489    }
490
491    /*only works if info_class parm is 12*/
492    hnd->status = rpccli_lsa_query_info_policy2(pipe_hnd, mem_ctx, op->in.pol, 12,
493                                              &domain_name, &dns_name, &forest_name, &domain_guid, &domain_sid);
494
495    if(!NT_STATUS_IS_OK(hnd->status)) {
496       return CAC_FAILURE;
497    }
498    
499    op->out.domain_name    = domain_name;
500    op->out.dns_name       = dns_name;
501    op->out.forest_name    = forest_name;
502    op->out.domain_guid    = domain_guid;
503    op->out.domain_sid     = domain_sid;
504
505    return CAC_SUCCESS;
506 }
507
508 int cac_LsaEnumSids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumSids *op) {
509    struct rpc_pipe_client *pipe_hnd = NULL;
510
511    uint32 num_sids;
512    DOM_SID *sids;
513
514    if(!hnd)
515       return CAC_FAILURE;
516
517    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
518       hnd->status = NT_STATUS_INVALID_HANDLE;
519       return CAC_FAILURE;
520    }
521
522    if(!op || !op->in.pol) {
523       hnd->status = NT_STATUS_INVALID_PARAMETER;
524    }
525
526    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
527    if(!pipe_hnd) {
528       hnd->status = NT_STATUS_INVALID_HANDLE;
529       return CAC_FAILURE;
530    }
531
532    hnd->status = rpccli_lsa_enum_sids(pipe_hnd, mem_ctx, op->in.pol, &(op->out.resume_idx), op->in.pref_max_sids, &num_sids, &sids);
533
534    if(!NT_STATUS_IS_OK(hnd->status)) {
535       return CAC_FAILURE;
536    }
537
538    op->out.num_sids  = num_sids;
539    op->out.sids      = sids;
540
541    return CAC_SUCCESS;
542
543 }
544
545 int cac_LsaEnumAccountRights(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumAccountRights *op) {
546    struct rpc_pipe_client *pipe_hnd = NULL;
547
548    uint32 count = 0;
549    char **privs = NULL;
550
551    if(!hnd)
552       return CAC_FAILURE;
553
554    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
555       hnd->status = NT_STATUS_INVALID_HANDLE;
556       return CAC_FAILURE;
557    }
558
559    if(!op->in.pol) {
560       hnd->status = NT_STATUS_INVALID_PARAMETER;
561       return CAC_FAILURE;
562    }
563
564    if(!op->in.name && !op->in.sid) {
565       hnd->status = NT_STATUS_INVALID_PARAMETER;
566       return CAC_FAILURE;
567    }
568
569    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
570    if(!pipe_hnd) {
571       hnd->status = NT_STATUS_INVALID_HANDLE;
572       return CAC_FAILURE;
573    }
574
575    if(op->in.name && !op->in.sid) {
576       DOM_SID *user_sid = NULL;
577       uint32 *type;
578
579       /*lookup the SID*/
580       hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
581
582       if(!NT_STATUS_IS_OK(hnd->status))
583          return CAC_FAILURE;
584
585       op->in.sid = user_sid;
586    }
587    
588    hnd->status = rpccli_lsa_enum_account_rights( pipe_hnd, mem_ctx, op->in.pol, op->in.sid,
589                                                    &count, &privs);
590
591    if(!NT_STATUS_IS_OK(hnd->status)) {
592       return CAC_FAILURE;
593    }
594
595    op->out.num_privs = count;
596    op->out.priv_names = privs;
597
598    return CAC_SUCCESS;
599 }
600
601 int cac_LsaEnumTrustedDomains(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumTrustedDomains *op) {
602    struct rpc_pipe_client *pipe_hnd;
603    
604    uint32 num_domains;
605    char **domain_names;
606    DOM_SID *domain_sids;
607    
608    if(!hnd)
609       return CAC_FAILURE;
610
611    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
612       hnd->status = NT_STATUS_INVALID_HANDLE;
613       return CAC_FAILURE;
614    }
615
616    if(!op->in.pol) {
617       hnd->status = NT_STATUS_INVALID_PARAMETER;
618       return CAC_FAILURE;
619    }
620
621    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
622    if(!pipe_hnd) {
623       hnd->status = NT_STATUS_INVALID_HANDLE;
624       return CAC_FAILURE;
625    }
626
627    hnd->status = rpccli_lsa_enum_trust_dom( pipe_hnd, mem_ctx, op->in.pol, &(op->out.resume_idx), &num_domains, &domain_names, &domain_sids);
628
629    if(!NT_STATUS_IS_OK(hnd->status)) {
630       return CAC_FAILURE;
631    }
632
633    op->out.num_domains = num_domains;
634    op->out.domain_names = domain_names;
635    op->out.domain_sids  = domain_sids;
636
637    return CAC_SUCCESS;
638 }
639
640 int cac_LsaOpenTrustedDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenTrustedDomain *op) {
641    struct rpc_pipe_client *pipe_hnd = NULL;
642
643    POLICY_HND *dom_pol = NULL;
644
645    if(!hnd)
646       return CAC_FAILURE;
647
648    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
649       hnd->status = NT_STATUS_INVALID_HANDLE;
650       return CAC_FAILURE;
651    }
652
653    if(!op->in.pol || !op->in.access || !op->in.domain_sid) {
654       hnd->status = NT_STATUS_INVALID_PARAMETER;
655       return CAC_FAILURE;
656    }
657
658    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
659    if(!pipe_hnd) {
660       hnd->status = NT_STATUS_INVALID_HANDLE;
661       return CAC_FAILURE;
662    }
663
664    dom_pol = talloc(mem_ctx, POLICY_HND);
665    if(!dom_pol) {
666       hnd->status = NT_STATUS_NO_MEMORY;
667       errno = ENOMEM;
668       return CAC_FAILURE;
669    }
670    
671    hnd->status = rpccli_lsa_open_trusted_domain( pipe_hnd, mem_ctx, op->in.pol, op->in.domain_sid, op->in.access, dom_pol);
672
673    if(!NT_STATUS_IS_OK(hnd->status)) {
674       return CAC_FAILURE;
675    }
676
677    op->out.domain_pol = dom_pol;
678
679    return CAC_SUCCESS;
680 }
681
682 int cac_LsaQueryTrustedDomainInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaQueryTrustedDomainInfo *op) {
683    struct rpc_pipe_client *pipe_hnd = NULL;
684
685    LSA_TRUSTED_DOMAIN_INFO *dom_info;
686
687    if(!hnd)
688       return CAC_FAILURE;
689
690    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
691       hnd->status = NT_STATUS_INVALID_HANDLE;
692       return CAC_FAILURE;
693    }
694
695    if(!op->in.pol || !op->in.info_class) {
696       hnd->status = NT_STATUS_INVALID_PARAMETER;
697       return CAC_FAILURE;
698    }
699
700    if(!op->in.domain_sid && !op->in.domain_name) {
701       hnd->status = NT_STATUS_INVALID_PARAMETER;
702       return CAC_FAILURE;
703    }
704
705    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
706    if(!pipe_hnd) {
707       hnd->status = NT_STATUS_INVALID_HANDLE;
708       return CAC_FAILURE;
709    }
710
711    if(op->in.domain_sid) {
712       hnd->status = rpccli_lsa_query_trusted_domain_info_by_sid( pipe_hnd, mem_ctx, op->in.pol, op->in.info_class, op->in.domain_sid, &dom_info);
713    }
714    else if(op->in.domain_name) {
715       hnd->status = rpccli_lsa_query_trusted_domain_info_by_name( pipe_hnd, mem_ctx, op->in.pol, op->in.info_class, op->in.domain_name, &dom_info);
716    }
717
718    if(!NT_STATUS_IS_OK(hnd->status)) {
719       return CAC_FAILURE;
720    }
721
722    op->out.info = dom_info;
723
724    return CAC_SUCCESS;
725
726 }
727
728 int cac_LsaEnumPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumPrivileges *op) {
729    struct rpc_pipe_client *pipe_hnd = NULL;
730
731    uint32 num_privs;
732    char **priv_names;
733    uint32 *high_bits;
734    uint32 *low_bits;
735
736    if(!hnd) {
737       return CAC_FAILURE;
738    }
739
740    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
741       hnd->status = NT_STATUS_INVALID_HANDLE;
742       return CAC_FAILURE;
743    }
744
745    if(!op || !op->in.pol) {
746       hnd->status = NT_STATUS_INVALID_PARAMETER;
747       return CAC_FAILURE;
748    }
749
750    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
751    if(!pipe_hnd) {
752       hnd->status = NT_STATUS_INVALID_HANDLE;
753       return CAC_FAILURE;
754    }
755
756    hnd->status = rpccli_lsa_enum_privilege(pipe_hnd, mem_ctx, op->in.pol, &(op->out.resume_idx), op->in.pref_max_privs,
757                                              &num_privs, &priv_names, &high_bits, &low_bits);
758
759    if(!NT_STATUS_IS_OK(hnd->status)) {
760       return CAC_FAILURE;
761    }
762
763    op->out.num_privs  = num_privs;
764    op->out.priv_names = priv_names;
765    op->out.high_bits  = high_bits;
766    op->out.low_bits   = low_bits;
767
768    return CAC_SUCCESS;
769 }
770
771 int cac_LsaOpenAccount(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenAccount *op) {
772    struct rpc_pipe_client *pipe_hnd = NULL;
773
774    POLICY_HND *user_pol = NULL;
775
776    if(!hnd) {
777       return CAC_FAILURE;
778    }
779
780    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
781       hnd->status = NT_STATUS_INVALID_HANDLE;
782       return CAC_FAILURE;
783    }
784
785    if(!op || !op->in.pol) {
786       hnd->status = NT_STATUS_INVALID_PARAMETER;
787       return CAC_FAILURE;
788    }
789
790    if(!op->in.sid && !op->in.name) {
791       hnd->status = NT_STATUS_INVALID_PARAMETER;
792       return CAC_FAILURE;
793    }
794
795
796    /*look up the user's SID if we have to*/
797    if(op->in.name && !op->in.sid) {
798       DOM_SID *user_sid = NULL;
799       uint32 *type;
800
801       /*lookup the SID*/
802       hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
803
804       if(!NT_STATUS_IS_OK(hnd->status))
805          return CAC_FAILURE;
806
807       op->in.sid = user_sid;
808    }
809
810    user_pol = talloc(mem_ctx, POLICY_HND);
811    if(!user_pol) {
812       hnd->status = NT_STATUS_NO_MEMORY;
813       return CAC_FAILURE;
814    }
815
816    hnd->status = rpccli_lsa_open_account(pipe_hnd, mem_ctx, op->in.pol, op->in.sid, op->in.access, user_pol);
817
818    if(!NT_STATUS_IS_OK(hnd->status)) {
819       talloc_free(user_pol);
820       return CAC_FAILURE;
821    }
822
823    op->out.user = user_pol;
824
825    return CAC_SUCCESS;
826 }
827
828
829 int cac_LsaAddPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAddPrivileges *op) {
830    struct rpc_pipe_client *pipe_hnd = NULL;
831
832    DOM_SID *user_sid = NULL;
833    uint32  *type     = NULL;
834
835    if(!hnd) {
836       return CAC_FAILURE;
837    }
838
839    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
840       hnd->status = NT_STATUS_INVALID_HANDLE;
841       return CAC_FAILURE;
842    }
843
844    if(!op || !op->in.pol || !op->in.priv_names) {
845       hnd->status = NT_STATUS_INVALID_PARAMETER;
846       return CAC_FAILURE;
847    }
848
849    if(!op->in.sid && !op->in.name) {
850       hnd->status = NT_STATUS_INVALID_PARAMETER;
851       return CAC_FAILURE;
852    }
853
854    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
855    if(!pipe_hnd) {
856       hnd->status = NT_STATUS_INVALID_HANDLE;
857       return CAC_FAILURE;
858    }
859
860    if(op->in.name && !op->in.sid) {
861       /*lookup the SID*/
862       hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
863
864       if(!NT_STATUS_IS_OK(hnd->status))
865          return CAC_FAILURE;
866
867       op->in.sid = user_sid;
868    }
869
870    hnd->status = rpccli_lsa_add_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), op->in.num_privs, (const char **)op->in.priv_names);
871
872    if(!NT_STATUS_IS_OK(hnd->status)) {
873       return CAC_FAILURE;
874    }
875
876    return CAC_SUCCESS;
877 }
878
879 int cac_LsaRemovePrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaRemovePrivileges *op) {
880    struct rpc_pipe_client *pipe_hnd = NULL;
881
882    DOM_SID *user_sid = NULL;
883    uint32  *type     = NULL;
884
885    if(!hnd) {
886       return CAC_FAILURE;
887    }
888
889    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
890       hnd->status = NT_STATUS_INVALID_HANDLE;
891       return CAC_FAILURE;
892    }
893
894    if(!op || !op->in.pol || !op->in.priv_names) {
895       hnd->status = NT_STATUS_INVALID_PARAMETER;
896       return CAC_FAILURE;
897    }
898
899    if(!op->in.sid && !op->in.name) {
900       hnd->status = NT_STATUS_INVALID_PARAMETER;
901       return CAC_FAILURE;
902    }
903
904    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
905    if(!pipe_hnd) {
906       hnd->status = NT_STATUS_INVALID_HANDLE;
907       return CAC_FAILURE;
908    }
909
910    if(op->in.name && !op->in.sid) {
911       /*lookup the SID*/
912       hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
913
914       if(!NT_STATUS_IS_OK(hnd->status))
915          return CAC_FAILURE;
916
917       op->in.sid = user_sid;
918    }
919
920    hnd->status = rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), False, op->in.num_privs, (const char **)op->in.priv_names);
921
922    if(!NT_STATUS_IS_OK(hnd->status)) {
923       return CAC_FAILURE;
924    }
925
926    return CAC_SUCCESS;
927 }
928
929 int cac_LsaClearPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaClearPrivileges *op) {
930    struct rpc_pipe_client *pipe_hnd = NULL;
931
932    DOM_SID *user_sid = NULL;
933    uint32  *type     = NULL;
934
935    if(!hnd) {
936       return CAC_FAILURE;
937    }
938
939    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
940       hnd->status = NT_STATUS_INVALID_HANDLE;
941       return CAC_FAILURE;
942    }
943
944    if(!op || !op->in.pol) {
945       hnd->status = NT_STATUS_INVALID_PARAMETER;
946       return CAC_FAILURE;
947    }
948
949    if(!op->in.sid && !op->in.name) {
950       hnd->status = NT_STATUS_INVALID_PARAMETER;
951       return CAC_FAILURE;
952    }
953
954    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
955    if(!pipe_hnd) {
956       hnd->status = NT_STATUS_INVALID_HANDLE;
957       return CAC_FAILURE;
958    }
959
960    if(op->in.name && !op->in.sid) {
961       /*lookup the SID*/
962       hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
963
964       if(!NT_STATUS_IS_OK(hnd->status))
965          return CAC_FAILURE;
966
967       op->in.sid = user_sid;
968    }
969
970    hnd->status = rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), True, 0, NULL);
971
972    if(!NT_STATUS_IS_OK(hnd->status)) {
973       return CAC_FAILURE;
974    }
975
976    return CAC_SUCCESS;
977 }
978
979 int cac_LsaSetPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAddPrivileges *op) {
980    struct rpc_pipe_client *pipe_hnd = NULL;
981
982    DOM_SID *user_sid = NULL;
983    uint32  *type     = NULL;
984
985    if(!hnd) {
986       return CAC_FAILURE;
987    }
988
989    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
990       hnd->status = NT_STATUS_INVALID_HANDLE;
991       return CAC_FAILURE;
992    }
993
994    if(!op || !op->in.pol || !op->in.priv_names) {
995       hnd->status = NT_STATUS_INVALID_PARAMETER;
996       return CAC_FAILURE;
997    }
998
999    if(!op->in.sid && !op->in.name) {
1000       hnd->status = NT_STATUS_INVALID_PARAMETER;
1001       return CAC_FAILURE;
1002    }
1003
1004    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
1005    if(!pipe_hnd) {
1006       return CAC_FAILURE;
1007    }
1008
1009    if(op->in.name && !op->in.sid) {
1010       /*lookup the SID*/
1011       hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
1012
1013       if(!NT_STATUS_IS_OK(hnd->status))
1014          return CAC_FAILURE;
1015
1016       op->in.sid = user_sid;
1017    }
1018
1019    /*first remove all privileges*/
1020    hnd->status = rpccli_lsa_remove_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), True, 0, NULL);
1021
1022    if(!NT_STATUS_IS_OK(hnd->status)) {
1023       return CAC_FAILURE;
1024    }
1025
1026    hnd->status = rpccli_lsa_add_account_rights( pipe_hnd, mem_ctx, op->in.pol, *(op->in.sid), op->in.num_privs, (const char **)op->in.priv_names);
1027
1028    if(!NT_STATUS_IS_OK(hnd->status)) {
1029       return CAC_FAILURE;
1030    }
1031
1032    return CAC_SUCCESS;
1033 }
1034
1035 int cac_LsaGetSecurityObject(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaGetSecurityObject *op) {
1036    struct rpc_pipe_client *pipe_hnd = NULL;
1037
1038    /*this is taken from rpcclient/cmd_lsarpc.c*/
1039    uint16 info_level = 4;
1040
1041    SEC_DESC_BUF *sec_out = NULL;
1042
1043    if(!hnd) {
1044       return CAC_FAILURE;
1045    }
1046
1047    if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_LSARPC]) {
1048       hnd->status = NT_STATUS_INVALID_HANDLE;
1049       return CAC_FAILURE;
1050    }
1051
1052    if(!op || !op->in.pol) {
1053       hnd->status = NT_STATUS_INVALID_PARAMETER;
1054       return CAC_FAILURE;
1055    }
1056
1057    pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
1058    if(!pipe_hnd) {
1059       hnd->status = NT_STATUS_INVALID_HANDLE;
1060       return CAC_FAILURE;
1061    }
1062
1063    hnd->status = rpccli_lsa_query_secobj( pipe_hnd, mem_ctx, op->in.pol, info_level, &sec_out);
1064
1065    if(!NT_STATUS_IS_OK(hnd->status))
1066       return CAC_FAILURE;
1067
1068    op->out.sec = sec_out;
1069
1070    return CAC_FAILURE;
1071 }