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