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