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