r25598: Add missing become_root/unbecome_root around calls of add_aliases.
[sfrench/samba-autobuild/.git] / source3 / libmsrpc / cac_samr.c
1
2 /* 
3  *  Unix SMB/CIFS implementation.
4  *  MS-RPC client library implementation (SAMR 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 "libmsrpc_internal.h"
23
24 /*used by cac_SamGetNamesFromRids*/
25 #define SAMR_RID_UNKNOWN 8
26
27 #define SAMR_ENUM_MAX_SIZE 0xffff
28
29 /*not sure what this is.. taken from rpcclient/cmd_samr.c*/
30 #define SAMR_LOOKUP_FLAGS 0x000003e8
31
32 DOM_SID *cac_get_domain_sid( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
33                              uint32 des_access );
34
35 int cac_SamConnect( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
36                     struct SamConnect *op )
37 {
38         SMBCSRV *srv = NULL;
39         struct rpc_pipe_client *pipe_hnd = NULL;
40         POLICY_HND *sam_out = NULL;
41
42         if ( !hnd )
43                 return CAC_FAILURE;
44
45         if ( !hnd->_internal.ctx ) {
46                 hnd->status = NT_STATUS_INVALID_HANDLE;
47                 return CAC_FAILURE;
48         }
49
50         if ( !op || op->in.access == 0 || !mem_ctx ) {
51                 hnd->status = NT_STATUS_INVALID_PARAMETER;
52                 return CAC_FAILURE;
53         }
54
55         srv = cac_GetServer( hnd );
56         if ( !srv ) {
57                 hnd->status = NT_STATUS_INVALID_CONNECTION;
58                 return CAC_FAILURE;
59         }
60
61         /*initialize for samr pipe if we have to */
62         if ( !hnd->_internal.pipes[PI_SAMR] ) {
63                 if ( !
64                      ( pipe_hnd =
65                        cli_rpc_pipe_open_noauth( srv->cli, PI_SAMR,
66                                                  &hnd->status ) ) ) {
67                         return CAC_FAILURE;
68                 }
69
70                 hnd->_internal.pipes[PI_SAMR] = True;
71         }
72
73         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
74         if ( !pipe_hnd ) {
75                 hnd->status = NT_STATUS_INVALID_HANDLE;
76                 return CAC_FAILURE;
77         }
78
79         sam_out = talloc( mem_ctx, POLICY_HND );
80         if ( !sam_out ) {
81                 hnd->status = NT_STATUS_NO_MEMORY;
82                 return CAC_FAILURE;
83         }
84
85         if ( hnd->_internal.srv_level >= SRV_WIN_2K_SP3 ) {
86                 hnd->status =
87                         rpccli_samr_connect4( pipe_hnd, mem_ctx,
88                                               op->in.access, sam_out );
89         }
90
91         if ( hnd->_internal.srv_level < SRV_WIN_2K_SP3
92              || !NT_STATUS_IS_OK( hnd->status ) ) {
93                 /*if sam_connect4 failed, the use sam_connect and lower srv_level */
94
95                 hnd->status =
96                         rpccli_samr_connect( pipe_hnd, mem_ctx, op->in.access,
97                                              sam_out );
98
99                 if ( NT_STATUS_IS_OK( hnd->status )
100                      && hnd->_internal.srv_level > SRV_WIN_2K ) {
101                         hnd->_internal.srv_level = SRV_WIN_2K;
102                 }
103         }
104
105         if ( !NT_STATUS_IS_OK( hnd->status ) )
106                 return CAC_FAILURE;
107
108         op->out.sam = sam_out;
109
110         return CAC_SUCCESS;
111 }
112
113 int cac_SamClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
114                   POLICY_HND * sam )
115 {
116         struct rpc_pipe_client *pipe_hnd = NULL;
117
118         if ( !hnd )
119                 return CAC_FAILURE;
120
121         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
122                 hnd->status = NT_STATUS_INVALID_HANDLE;
123                 return CAC_FAILURE;
124         }
125
126         if ( !sam || !mem_ctx ) {
127                 hnd->status = NT_STATUS_INVALID_PARAMETER;
128                 return CAC_FAILURE;
129         }
130
131         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
132         if ( !pipe_hnd ) {
133                 hnd->status = NT_STATUS_INVALID_HANDLE;
134                 return CAC_FAILURE;
135         }
136
137         hnd->status = rpccli_samr_close( pipe_hnd, mem_ctx, sam );
138
139         if ( !NT_STATUS_IS_OK( hnd->status ) )
140                 return CAC_FAILURE;
141
142         return CAC_SUCCESS;
143 }
144
145 /*this is an internal function. Due to a circular dependency, it must be prototyped in libmsrpc.h (which I don't want to do)
146  * cac_SamOpenDomain() is the only function that calls it, so I just put the definition here
147  */
148
149 /*attempts to find the sid of the domain we are connected to*/
150 DOM_SID *cac_get_domain_sid( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
151                              uint32 des_access )
152 {
153         struct LsaOpenPolicy lop;
154         struct LsaFetchSid fs;
155
156         DOM_SID *sid;
157
158         ZERO_STRUCT( lop );
159         ZERO_STRUCT( fs );
160
161         lop.in.access = des_access;
162         lop.in.security_qos = True;
163
164         if ( !cac_LsaOpenPolicy( hnd, mem_ctx, &lop ) )
165                 return NULL;
166
167         fs.in.pol = lop.out.pol;
168         fs.in.info_class = CAC_DOMAIN_INFO;
169
170         if ( !cac_LsaFetchSid( hnd, mem_ctx, &fs ) )
171                 return NULL;
172
173         cac_LsaClosePolicy( hnd, mem_ctx, lop.out.pol );
174
175         if ( !fs.out.domain_sid )
176                 return NULL;
177
178         sid = ( DOM_SID * ) TALLOC_MEMDUP( mem_ctx,
179                                            &( fs.out.domain_sid->sid ),
180                                            sizeof( DOM_SID ) );
181
182         if ( !sid ) {
183                 hnd->status = NT_STATUS_NO_MEMORY;
184         }
185
186         return sid;
187
188 }
189
190 int cac_SamOpenDomain( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
191                        struct SamOpenDomain *op )
192 {
193         struct rpc_pipe_client *pipe_hnd = NULL;
194
195         DOM_SID *sid_buf;
196         POLICY_HND *sam_out;
197         POLICY_HND *pol_out;
198
199         struct SamLookupDomain sld;
200
201         if ( !hnd )
202                 return CAC_FAILURE;
203
204         if ( !hnd->_internal.ctx ) {
205                 hnd->status = NT_STATUS_INVALID_HANDLE;
206                 return CAC_FAILURE;
207         }
208
209         if ( !op || op->in.access == 0 || !mem_ctx ) {
210                 hnd->status = NT_STATUS_INVALID_PARAMETER;
211                 return CAC_FAILURE;
212         }
213
214         if ( !op->in.sam ) {
215                 /*use cac_SamConnect() since it does the session setup */
216                 struct SamConnect sc;
217
218                 ZERO_STRUCT( sc );
219
220                 sc.in.access = op->in.access;
221
222                 if ( !cac_SamConnect( hnd, mem_ctx, &sc ) ) {
223                         return CAC_FAILURE;
224                 }
225
226                 sam_out = sc.out.sam;
227         } else {
228                 sam_out = op->in.sam;
229         }
230
231         if ( !op->in.sid ) {
232                 /*find the sid for the SAM's domain */
233
234                 /*try using cac_SamLookupDomain() first */
235                 ZERO_STRUCT( sld );
236
237                 sld.in.sam = sam_out;
238                 sld.in.name = hnd->domain;
239
240                 if ( cac_SamLookupDomain( hnd, mem_ctx, &sld ) ) {
241                         /*then we got the sid */
242                         sid_buf = sld.out.sid;
243                 } else {
244                         /*try to get it from the LSA */
245                         sid_buf =
246                                 cac_get_domain_sid( hnd, mem_ctx,
247                                                     op->in.access );
248                 }
249         } else {
250                 /*we already have the sid for the domain we want */
251                 sid_buf = op->in.sid;
252         }
253
254         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
255         if ( !pipe_hnd ) {
256                 hnd->status = NT_STATUS_INVALID_HANDLE;
257                 return CAC_FAILURE;
258         }
259
260         pol_out = talloc( mem_ctx, POLICY_HND );
261         if ( !pol_out ) {
262                 hnd->status = NT_STATUS_NO_MEMORY;
263                 return CAC_FAILURE;
264         }
265
266         /*now open the domain */
267         hnd->status =
268                 rpccli_samr_open_domain( pipe_hnd, mem_ctx, sam_out,
269                                          op->in.access, sid_buf, pol_out );
270
271         if ( !NT_STATUS_IS_OK( hnd->status ) )
272                 return CAC_FAILURE;
273
274         op->out.sam = sam_out;
275         op->out.dom_hnd = pol_out;
276
277         return CAC_SUCCESS;
278 }
279
280 int cac_SamOpenUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
281                      struct SamOpenUser *op )
282 {
283         struct rpc_pipe_client *pipe_hnd = NULL;
284
285         uint32 *rid_buf = NULL;
286
287         uint32 num_rids = 0;
288         uint32 *rid_types = NULL;
289
290         POLICY_HND *user_out = NULL;
291
292         if ( !hnd )
293                 return CAC_FAILURE;
294
295         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
296                 hnd->status = NT_STATUS_INVALID_HANDLE;
297                 return CAC_FAILURE;
298         }
299
300         if ( !op || !op->in.dom_hnd || op->in.access == 0 || !mem_ctx ) {
301                 hnd->status = NT_STATUS_INVALID_PARAMETER;
302                 return CAC_FAILURE;
303         }
304
305         if ( op->in.rid == 0 && op->in.name == NULL ) {
306                 hnd->status = NT_STATUS_INVALID_PARAMETER;
307                 return CAC_FAILURE;
308         }
309
310         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
311         if ( !pipe_hnd ) {
312                 hnd->status = NT_STATUS_INVALID_HANDLE;
313                 return CAC_FAILURE;
314         }
315
316         if ( op->in.rid == 0 && op->in.name ) {
317                 /*lookup the name and then set rid_buf */
318
319                 hnd->status =
320                         rpccli_samr_lookup_names( pipe_hnd, mem_ctx,
321                                                   op->in.dom_hnd,
322                                                   SAMR_LOOKUP_FLAGS, 1,
323                                                   ( const char ** ) &op->in.
324                                                   name, &num_rids, &rid_buf,
325                                                   &rid_types );
326
327                 if ( !NT_STATUS_IS_OK( hnd->status ) )
328                         return CAC_FAILURE;
329
330                 if ( num_rids == 0 || rid_buf == NULL
331                      || rid_types[0] == SAMR_RID_UNKNOWN ) {
332                         hnd->status = NT_STATUS_INVALID_PARAMETER;
333                         return CAC_FAILURE;
334                 }
335
336                 TALLOC_FREE( rid_types );
337
338         } else {
339                 rid_buf = &op->in.rid;
340         }
341
342         user_out = talloc( mem_ctx, POLICY_HND );
343         if ( !user_out ) {
344                 hnd->status = NT_STATUS_NO_MEMORY;
345                 return CAC_FAILURE;
346         }
347
348         hnd->status =
349                 rpccli_samr_open_user( pipe_hnd, mem_ctx, op->in.dom_hnd,
350                                        op->in.access, *rid_buf, user_out );
351
352         if ( !NT_STATUS_IS_OK( hnd->status ) )
353                 return CAC_FAILURE;
354
355         op->out.user_hnd = user_out;
356
357         return CAC_SUCCESS;
358 }
359
360 int cac_SamCreateUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
361                        struct SamCreateUser *op )
362 {
363         struct rpc_pipe_client *pipe_hnd = NULL;
364
365         POLICY_HND *user_out = NULL;
366         uint32 rid_out;
367
368    /**found in rpcclient/cmd_samr.c*/
369         uint32 unknown = 0xe005000b;
370
371         if ( !hnd )
372                 return CAC_FAILURE;
373
374         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
375                 hnd->status = NT_STATUS_INVALID_HANDLE;
376                 return CAC_FAILURE;
377         }
378
379         if ( !op || !op->in.dom_hnd || !op->in.name || op->in.acb_mask == 0
380              || !mem_ctx ) {
381                 hnd->status = NT_STATUS_INVALID_PARAMETER;
382                 return CAC_FAILURE;
383         }
384
385         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
386         if ( !pipe_hnd ) {
387                 hnd->status = NT_STATUS_INVALID_HANDLE;
388                 return CAC_FAILURE;
389         }
390
391         user_out = talloc( mem_ctx, POLICY_HND );
392         if ( !user_out ) {
393                 hnd->status = NT_STATUS_NO_MEMORY;
394                 return CAC_FAILURE;
395         }
396
397         hnd->status =
398                 rpccli_samr_create_dom_user( pipe_hnd, mem_ctx,
399                                              op->in.dom_hnd, op->in.name,
400                                              op->in.acb_mask, unknown,
401                                              user_out, &rid_out );
402
403         if ( !NT_STATUS_IS_OK( hnd->status ) )
404                 return CAC_FAILURE;
405
406         op->out.user_hnd = user_out;
407         op->out.rid = rid_out;
408
409         return CAC_SUCCESS;
410 }
411
412 int cac_SamDeleteUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
413                        POLICY_HND * user_hnd )
414 {
415         struct rpc_pipe_client *pipe_hnd = NULL;
416
417         if ( !hnd )
418                 return CAC_FAILURE;
419
420         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
421                 hnd->status = NT_STATUS_INVALID_HANDLE;
422                 return CAC_FAILURE;
423         }
424
425         if ( !user_hnd || !mem_ctx ) {
426                 hnd->status = NT_STATUS_INVALID_PARAMETER;
427                 return CAC_FAILURE;
428         }
429
430         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
431         if ( !pipe_hnd ) {
432                 hnd->status = NT_STATUS_INVALID_HANDLE;
433                 return CAC_FAILURE;
434         }
435
436         hnd->status =
437                 rpccli_samr_delete_dom_user( pipe_hnd, mem_ctx, user_hnd );
438
439         if ( !NT_STATUS_IS_OK( hnd->status ) )
440                 return CAC_FAILURE;
441
442         return CAC_SUCCESS;
443 }
444
445 int cac_SamEnumUsers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
446                       struct SamEnumUsers *op )
447 {
448         struct rpc_pipe_client *pipe_hnd = NULL;
449
450         uint32 resume_idx_out = 0;
451         char **names_out = NULL;
452         uint32 *rids_out = NULL;
453         uint32 num_users_out = 0;
454
455         if ( !hnd )
456                 return CAC_FAILURE;
457
458         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
459                 hnd->status = NT_STATUS_INVALID_HANDLE;
460                 return CAC_FAILURE;
461         }
462
463         if ( !op || !op->in.dom_hnd || !mem_ctx ) {
464                 hnd->status = NT_STATUS_INVALID_PARAMETER;
465                 return CAC_FAILURE;
466         }
467
468         /*this is a hack.. but is the only reliable way to know if everything has been enumerated */
469         if ( op->out.done == True )
470                 return CAC_FAILURE;
471
472         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
473         if ( !pipe_hnd ) {
474                 hnd->status = NT_STATUS_INVALID_HANDLE;
475                 return CAC_FAILURE;
476         }
477
478         resume_idx_out = op->out.resume_idx;
479
480         hnd->status =
481                 rpccli_samr_enum_dom_users( pipe_hnd, mem_ctx, op->in.dom_hnd,
482                                             &resume_idx_out, op->in.acb_mask,
483                                             SAMR_ENUM_MAX_SIZE, &names_out,
484                                             &rids_out, &num_users_out );
485
486
487         if ( NT_STATUS_IS_OK( hnd->status ) )
488                 op->out.done = True;
489
490         /*if there are no more entries, the operation will return NT_STATUS_OK. 
491          * We want to return failure if no results were returned*/
492         if ( !NT_STATUS_IS_OK( hnd->status )
493              && NT_STATUS_V( hnd->status ) !=
494              NT_STATUS_V( STATUS_MORE_ENTRIES ) )
495                 return CAC_FAILURE;
496
497         op->out.resume_idx = resume_idx_out;
498         op->out.num_users = num_users_out;
499         op->out.rids = rids_out;
500         op->out.names = names_out;
501
502         return CAC_SUCCESS;
503 }
504
505 int cac_SamGetNamesFromRids( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
506                              struct SamGetNamesFromRids *op )
507 {
508         struct rpc_pipe_client *pipe_hnd = NULL;
509
510         uint32 num_names_out;
511         char **names_out;
512         uint32 *name_types_out;
513
514
515         uint32 i = 0;
516
517         CacLookupRidsRecord *map_out;
518
519         if ( !hnd )
520                 return CAC_FAILURE;
521
522         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
523                 hnd->status = NT_STATUS_INVALID_HANDLE;
524                 return CAC_FAILURE;
525         }
526
527         if ( !op || !op->in.dom_hnd || !mem_ctx ) {
528                 hnd->status = NT_STATUS_INVALID_PARAMETER;
529                 return CAC_FAILURE;
530         }
531
532         if ( !op->in.rids && op->in.num_rids != 0 ) {
533                 hnd->status = NT_STATUS_INVALID_PARAMETER;
534                 return CAC_FAILURE;
535         }
536
537         if ( op->in.num_rids == 0 ) {
538                 /*nothing to do */
539                 op->out.num_names = 0;
540                 return CAC_SUCCESS;
541         }
542
543         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
544         if ( !pipe_hnd ) {
545                 hnd->status = NT_STATUS_INVALID_HANDLE;
546                 return CAC_FAILURE;
547         }
548
549         hnd->status =
550                 rpccli_samr_lookup_rids( pipe_hnd, mem_ctx, op->in.dom_hnd,
551                                          op->in.num_rids, op->in.rids,
552                                          &num_names_out, &names_out,
553                                          &name_types_out );
554
555         if ( !NT_STATUS_IS_OK( hnd->status )
556              && !NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
557                 return CAC_FAILURE;
558
559         if (num_names_out) {
560                 map_out = TALLOC_ARRAY( mem_ctx, CacLookupRidsRecord, num_names_out );
561                 if ( !map_out ) {
562                         hnd->status = NT_STATUS_NO_MEMORY;
563                         return CAC_FAILURE;
564                 }
565         } else {
566                 map_out = NULL;
567         }
568
569         for ( i = 0; i < num_names_out; i++ ) {
570                 if ( name_types_out[i] == SAMR_RID_UNKNOWN ) {
571                         map_out[i].found = False;
572                         map_out[i].name = NULL;
573                         map_out[i].type = 0;
574                 } else {
575                         map_out[i].found = True;
576                         map_out[i].name =
577                                 talloc_strdup( mem_ctx, names_out[i] );
578                         map_out[i].type = name_types_out[i];
579                 }
580                 map_out[i].rid = op->in.rids[i];
581         }
582
583         TALLOC_FREE( names_out );
584         TALLOC_FREE( name_types_out );
585
586         op->out.num_names = num_names_out;
587         op->out.map = map_out;
588
589         if ( NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
590                 return CAC_PARTIAL_SUCCESS;
591
592         return CAC_SUCCESS;
593 }
594
595 int cac_SamGetRidsFromNames( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
596                              struct SamGetRidsFromNames *op )
597 {
598         struct rpc_pipe_client *pipe_hnd = NULL;
599
600         uint32 num_rids_out;
601         uint32 *rids_out;
602         uint32 *rid_types_out;
603
604         uint32 i = 0;
605
606         CacLookupRidsRecord *map_out;
607
608         if ( !hnd )
609                 return CAC_FAILURE;
610
611         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
612                 hnd->status = NT_STATUS_INVALID_HANDLE;
613                 return CAC_FAILURE;
614         }
615
616         if ( !op || !op->in.dom_hnd || !mem_ctx ) {
617                 hnd->status = NT_STATUS_INVALID_PARAMETER;
618                 return CAC_FAILURE;
619         }
620
621         if ( !op->in.names && op->in.num_names != 0 ) {
622                 hnd->status = NT_STATUS_INVALID_PARAMETER;
623                 return CAC_FAILURE;
624         }
625
626         if ( op->in.num_names == 0 ) {
627                 /*then we don't have to do anything */
628                 op->out.num_rids = 0;
629                 return CAC_SUCCESS;
630         }
631
632         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
633         if ( !pipe_hnd ) {
634                 hnd->status = NT_STATUS_INVALID_HANDLE;
635                 return CAC_FAILURE;
636         }
637
638         hnd->status =
639                 rpccli_samr_lookup_names( pipe_hnd, mem_ctx, op->in.dom_hnd,
640                                           SAMR_LOOKUP_FLAGS, op->in.num_names,
641                                           ( const char ** ) op->in.names,
642                                           &num_rids_out, &rids_out,
643                                           &rid_types_out );
644
645         if ( !NT_STATUS_IS_OK( hnd->status )
646              && !NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
647                 return CAC_FAILURE;
648
649         if (num_rids_out) {
650                 map_out = TALLOC_ARRAY( mem_ctx, CacLookupRidsRecord, num_rids_out );
651                 if ( !map_out ) {
652                         hnd->status = NT_STATUS_NO_MEMORY;
653                         return CAC_FAILURE;
654                 }
655         } else {
656                 map_out = NULL;
657         }
658
659         for ( i = 0; i < num_rids_out; i++ ) {
660
661                 if ( rid_types_out[i] == SAMR_RID_UNKNOWN ) {
662                         map_out[i].found = False;
663                         map_out[i].rid = 0;
664                         map_out[i].type = 0;
665                 } else {
666                         map_out[i].found = True;
667                         map_out[i].rid = rids_out[i];
668                         map_out[i].type = rid_types_out[i];
669                 }
670
671                 map_out[i].name = talloc_strdup( mem_ctx, op->in.names[i] );
672         }
673
674         op->out.num_rids = num_rids_out;
675         op->out.map = map_out;
676
677         TALLOC_FREE( rids_out );
678         TALLOC_FREE( rid_types_out );
679
680         if ( NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
681                 return CAC_PARTIAL_SUCCESS;
682
683         return CAC_SUCCESS;
684 }
685
686
687 int cac_SamGetGroupsForUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
688                              struct SamGetGroupsForUser *op )
689 {
690         struct rpc_pipe_client *pipe_hnd = NULL;
691
692         DOM_GID *groups = NULL;
693         uint32 num_groups_out = 0;
694
695         uint32 *rids_out = NULL;
696         uint32 *attr_out = NULL;
697
698         uint32 i;
699
700         if ( !hnd )
701                 return CAC_FAILURE;
702
703         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
704                 hnd->status = NT_STATUS_INVALID_HANDLE;
705                 return CAC_FAILURE;
706         }
707
708         if ( !op || !op->in.user_hnd || !mem_ctx ) {
709                 hnd->status = NT_STATUS_INVALID_PARAMETER;
710                 return CAC_FAILURE;
711         }
712
713         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
714         if ( !pipe_hnd ) {
715                 hnd->status = NT_STATUS_INVALID_HANDLE;
716                 return CAC_FAILURE;
717         }
718
719         hnd->status =
720                 rpccli_samr_query_usergroups( pipe_hnd, mem_ctx,
721                                               op->in.user_hnd,
722                                               &num_groups_out, &groups );
723
724         if ( !NT_STATUS_IS_OK( hnd->status ) )
725                 return CAC_FAILURE;
726
727
728         if (num_groups_out) {
729                 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
730                 if ( !rids_out ) {
731                         hnd->status = NT_STATUS_NO_MEMORY;
732                         return CAC_FAILURE;
733                 }
734                 attr_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
735                 if ( !attr_out ) {
736                         hnd->status = NT_STATUS_NO_MEMORY;
737                         return CAC_FAILURE;
738                 }
739         } else {
740                 rids_out = NULL;
741                 attr_out = NULL;
742         }
743
744         for ( i = 0; i < num_groups_out; i++ ) {
745                 rids_out[i] = groups[i].g_rid;
746                 attr_out[i] = groups[i].attr;
747         }
748
749         TALLOC_FREE( groups );
750
751         op->out.num_groups = num_groups_out;
752         op->out.rids = rids_out;
753         op->out.attributes = attr_out;
754
755         return CAC_SUCCESS;
756 }
757
758
759 int cac_SamOpenGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
760                       struct SamOpenGroup *op )
761 {
762         struct rpc_pipe_client *pipe_hnd = NULL;
763
764         POLICY_HND *group_hnd_out = NULL;
765
766         if ( !hnd )
767                 return CAC_FAILURE;
768
769         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
770                 hnd->status = NT_STATUS_INVALID_HANDLE;
771                 return CAC_FAILURE;
772         }
773
774         if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
775                 hnd->status = NT_STATUS_INVALID_PARAMETER;
776                 return CAC_FAILURE;
777         }
778
779         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
780         if ( !pipe_hnd ) {
781                 hnd->status = NT_STATUS_INVALID_HANDLE;
782                 return CAC_FAILURE;
783         }
784
785         group_hnd_out = talloc( mem_ctx, POLICY_HND );
786         if ( !group_hnd_out ) {
787                 hnd->status = NT_STATUS_NO_MEMORY;
788                 return CAC_FAILURE;
789         }
790
791         hnd->status =
792                 rpccli_samr_open_group( pipe_hnd, mem_ctx, op->in.dom_hnd,
793                                         op->in.access, op->in.rid,
794                                         group_hnd_out );
795
796         if ( !NT_STATUS_IS_OK( hnd->status ) )
797                 return CAC_FAILURE;
798
799         op->out.group_hnd = group_hnd_out;
800
801         return CAC_SUCCESS;
802 }
803
804 int cac_SamCreateGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
805                         struct SamCreateGroup *op )
806 {
807         struct rpc_pipe_client *pipe_hnd = NULL;
808
809         POLICY_HND *group_hnd_out = NULL;
810
811         if ( !hnd )
812                 return CAC_FAILURE;
813
814         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
815                 hnd->status = NT_STATUS_INVALID_HANDLE;
816                 return CAC_FAILURE;
817         }
818
819         if ( !op || !op->in.name || op->in.name[0] == '\0'
820              || op->in.access == 0 || !mem_ctx ) {
821                 hnd->status = NT_STATUS_INVALID_PARAMETER;
822                 return CAC_FAILURE;
823         }
824
825         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
826         if ( !pipe_hnd ) {
827                 hnd->status = NT_STATUS_INVALID_HANDLE;
828                 return CAC_FAILURE;
829         }
830
831         group_hnd_out = talloc( mem_ctx, POLICY_HND );
832         if ( !group_hnd_out ) {
833                 hnd->status = NT_STATUS_NO_MEMORY;
834                 return CAC_FAILURE;
835         }
836
837         hnd->status =
838                 rpccli_samr_create_dom_group( pipe_hnd, mem_ctx,
839                                               op->in.dom_hnd, op->in.name,
840                                               op->in.access, group_hnd_out );
841
842         if ( !NT_STATUS_IS_OK( hnd->status ) )
843                 return CAC_FAILURE;
844
845         op->out.group_hnd = group_hnd_out;
846
847         return CAC_SUCCESS;
848
849 }
850
851 int cac_SamDeleteGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
852                         POLICY_HND * group_hnd )
853 {
854         struct rpc_pipe_client *pipe_hnd = NULL;
855
856         if ( !hnd )
857                 return CAC_FAILURE;
858
859         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
860                 hnd->status = NT_STATUS_INVALID_HANDLE;
861                 return CAC_FAILURE;
862         }
863
864         if ( !group_hnd || !mem_ctx ) {
865                 hnd->status = NT_STATUS_INVALID_PARAMETER;
866                 return CAC_FAILURE;
867         }
868
869         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
870         if ( !pipe_hnd ) {
871                 hnd->status = NT_STATUS_INVALID_HANDLE;
872                 return CAC_FAILURE;
873         }
874
875         hnd->status =
876                 rpccli_samr_delete_dom_group( pipe_hnd, mem_ctx, group_hnd );
877
878         if ( !NT_STATUS_IS_OK( hnd->status ) )
879                 return CAC_FAILURE;
880
881         return CAC_SUCCESS;
882
883 }
884
885 int cac_SamGetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
886                             struct SamGetGroupMembers *op )
887 {
888         struct rpc_pipe_client *pipe_hnd = NULL;
889
890         uint32 num_mem_out;
891         uint32 *rids_out;
892         uint32 *attr_out;
893
894         if ( !hnd )
895                 return CAC_FAILURE;
896
897         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
898                 hnd->status = NT_STATUS_INVALID_HANDLE;
899                 return CAC_FAILURE;
900         }
901
902         if ( !op || !op->in.group_hnd || !mem_ctx ) {
903                 hnd->status = NT_STATUS_INVALID_PARAMETER;
904                 return CAC_FAILURE;
905         }
906
907         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
908         if ( !pipe_hnd ) {
909                 hnd->status = NT_STATUS_INVALID_HANDLE;
910                 return CAC_FAILURE;
911         }
912
913         hnd->status =
914                 rpccli_samr_query_groupmem( pipe_hnd, mem_ctx,
915                                             op->in.group_hnd, &num_mem_out,
916                                             &rids_out, &attr_out );
917
918         if ( !NT_STATUS_IS_OK( hnd->status ) )
919                 return CAC_FAILURE;
920
921         op->out.num_members = num_mem_out;
922         op->out.rids = rids_out;
923         op->out.attributes = attr_out;
924
925         return CAC_SUCCESS;
926 }
927
928
929 int cac_SamAddGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
930                            struct SamAddGroupMember *op )
931 {
932         struct rpc_pipe_client *pipe_hnd = NULL;
933
934         if ( !hnd )
935                 return CAC_FAILURE;
936
937         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
938                 hnd->status = NT_STATUS_INVALID_HANDLE;
939                 return CAC_FAILURE;
940         }
941
942         if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
943                 hnd->status = NT_STATUS_INVALID_PARAMETER;
944                 return CAC_FAILURE;
945         }
946
947         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
948         if ( !pipe_hnd ) {
949                 hnd->status = NT_STATUS_INVALID_HANDLE;
950                 return CAC_FAILURE;
951         }
952
953         hnd->status =
954                 rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
955                                           op->in.rid );
956
957         if ( !NT_STATUS_IS_OK( hnd->status ) )
958                 return CAC_FAILURE;
959
960         return CAC_SUCCESS;
961 }
962
963 int cac_SamRemoveGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
964                               struct SamRemoveGroupMember *op )
965 {
966         struct rpc_pipe_client *pipe_hnd = NULL;
967
968         if ( !hnd )
969                 return CAC_FAILURE;
970
971         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
972                 hnd->status = NT_STATUS_INVALID_HANDLE;
973                 return CAC_FAILURE;
974         }
975
976         if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
977                 hnd->status = NT_STATUS_INVALID_PARAMETER;
978                 return CAC_FAILURE;
979         }
980
981         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
982         if ( !pipe_hnd ) {
983                 hnd->status = NT_STATUS_INVALID_HANDLE;
984                 return CAC_FAILURE;
985         }
986
987         hnd->status =
988                 rpccli_samr_del_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
989                                           op->in.rid );
990
991         if ( !NT_STATUS_IS_OK( hnd->status ) )
992                 return CAC_FAILURE;
993
994         return CAC_SUCCESS;
995 }
996
997 int cac_SamClearGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
998                               POLICY_HND * group_hnd )
999 {
1000         struct rpc_pipe_client *pipe_hnd = NULL;
1001
1002         int result = CAC_SUCCESS;
1003
1004         int i = 0;
1005
1006         uint32 num_mem = 0;
1007         uint32 *rid = NULL;
1008         uint32 *attr = NULL;
1009
1010         NTSTATUS status;
1011
1012         if ( !hnd )
1013                 return CAC_FAILURE;
1014
1015         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1016                 hnd->status = NT_STATUS_INVALID_HANDLE;
1017                 return CAC_FAILURE;
1018         }
1019
1020         if ( !group_hnd || !mem_ctx ) {
1021                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1022                 return CAC_FAILURE;
1023         }
1024
1025         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1026         if ( !pipe_hnd ) {
1027                 hnd->status = NT_STATUS_INVALID_HANDLE;
1028                 return CAC_FAILURE;
1029         }
1030
1031         hnd->status =
1032                 rpccli_samr_query_groupmem( pipe_hnd, mem_ctx, group_hnd,
1033                                             &num_mem, &rid, &attr );
1034
1035         if ( !NT_STATUS_IS_OK( hnd->status ) )
1036                 return CAC_FAILURE;
1037
1038         /*try to delete the users one by one */
1039         for ( i = 0; i < num_mem && NT_STATUS_IS_OK( hnd->status ); i++ ) {
1040                 hnd->status =
1041                         rpccli_samr_del_groupmem( pipe_hnd, mem_ctx,
1042                                                   group_hnd, rid[i] );
1043         }
1044
1045         /*if not all members could be removed, then try to re-add the members that were already deleted */
1046         if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1047                 status = NT_STATUS_OK;
1048
1049                 for ( i -= 1; i >= 0 && NT_STATUS_IS_OK( status ); i-- ) {
1050                         status = rpccli_samr_add_groupmem( pipe_hnd, mem_ctx,
1051                                                            group_hnd,
1052                                                            rid[i] );
1053                 }
1054
1055                 /*we return with the NTSTATUS error that we got when trying to delete users */
1056                 if ( !NT_STATUS_IS_OK( status ) )
1057                         result = CAC_FAILURE;
1058         }
1059
1060         TALLOC_FREE( attr );
1061
1062         return result;
1063 }
1064
1065 int cac_SamSetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1066                             struct SamSetGroupMembers *op )
1067 {
1068         struct rpc_pipe_client *pipe_hnd = NULL;
1069
1070         uint32 i = 0;
1071
1072         if ( !hnd )
1073                 return CAC_FAILURE;
1074
1075         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1076                 hnd->status = NT_STATUS_INVALID_HANDLE;
1077                 return CAC_FAILURE;
1078         }
1079
1080         if ( !op || !op->in.group_hnd || !mem_ctx ) {
1081                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1082                 return CAC_FAILURE;
1083         }
1084
1085         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1086         if ( !pipe_hnd ) {
1087                 hnd->status = NT_STATUS_INVALID_HANDLE;
1088                 return CAC_FAILURE;
1089         }
1090
1091         /*use cac_SamClearGroupMembers() to clear them */
1092         if ( !cac_SamClearGroupMembers( hnd, mem_ctx, op->in.group_hnd ) )
1093                 return CAC_FAILURE;     /*hnd->status is already set */
1094
1095
1096         for ( i = 0; i < op->in.num_members && NT_STATUS_IS_OK( hnd->status );
1097               i++ ) {
1098                 hnd->status =
1099                         rpccli_samr_add_groupmem( pipe_hnd, mem_ctx,
1100                                                   op->in.group_hnd,
1101                                                   op->in.rids[i] );
1102         }
1103
1104         if ( !NT_STATUS_IS_OK( hnd->status ) )
1105                 return CAC_FAILURE;
1106
1107         return CAC_SUCCESS;
1108
1109 }
1110
1111 int cac_SamEnumGroups( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1112                        struct SamEnumGroups *op )
1113 {
1114         struct rpc_pipe_client *pipe_hnd = NULL;
1115
1116         uint32 i = 0;
1117
1118         uint32 resume_idx_out = 0;
1119         char **names_out = NULL;
1120         char **desc_out = NULL;
1121         uint32 *rids_out = NULL;
1122         uint32 num_groups_out = 0;
1123
1124         struct acct_info *acct_buf = NULL;
1125
1126         if ( !hnd )
1127                 return CAC_FAILURE;
1128
1129         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1130                 hnd->status = NT_STATUS_INVALID_HANDLE;
1131                 return CAC_FAILURE;
1132         }
1133
1134         if ( !op || !op->in.dom_hnd || !mem_ctx ) {
1135                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1136                 return CAC_FAILURE;
1137         }
1138
1139         /*using this BOOL is the only reliable way to know that we are done */
1140         if ( op->out.done == True )     /*we return failure so the call will break out of a loop */
1141                 return CAC_FAILURE;
1142
1143         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1144         if ( !pipe_hnd ) {
1145                 hnd->status = NT_STATUS_INVALID_HANDLE;
1146                 return CAC_FAILURE;
1147         }
1148
1149         resume_idx_out = op->out.resume_idx;
1150
1151         hnd->status =
1152                 rpccli_samr_enum_dom_groups( pipe_hnd, mem_ctx,
1153                                              op->in.dom_hnd, &resume_idx_out,
1154                                              SAMR_ENUM_MAX_SIZE, &acct_buf,
1155                                              &num_groups_out );
1156
1157
1158         if ( NT_STATUS_IS_OK( hnd->status ) ) {
1159                 op->out.done = True;
1160         } else if ( NT_STATUS_V( hnd->status ) !=
1161                     NT_STATUS_V( STATUS_MORE_ENTRIES ) ) {
1162                 /*if there are no more entries, the operation will return NT_STATUS_OK. 
1163                  * We want to return failure if no results were returned*/
1164                 return CAC_FAILURE;
1165         }
1166
1167         if (num_groups_out) {
1168                 names_out = TALLOC_ARRAY( mem_ctx, char *, num_groups_out );
1169                 if ( !names_out ) {
1170                         hnd->status = NT_STATUS_NO_MEMORY;
1171                         TALLOC_FREE( acct_buf );
1172                         return CAC_FAILURE;
1173                 }
1174
1175                 desc_out = TALLOC_ARRAY( mem_ctx, char *, num_groups_out );
1176                 if ( !desc_out ) {
1177                         hnd->status = NT_STATUS_NO_MEMORY;
1178                         TALLOC_FREE( acct_buf );
1179                         TALLOC_FREE( names_out );
1180                         return CAC_FAILURE;
1181                 }
1182
1183                 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
1184                 if ( !rids_out ) {
1185                         hnd->status = NT_STATUS_NO_MEMORY;
1186                         TALLOC_FREE( acct_buf );
1187                         TALLOC_FREE( names_out );
1188                         TALLOC_FREE( desc_out );
1189                         return CAC_FAILURE;
1190                 }
1191         } else {
1192                 names_out = NULL;
1193                 desc_out = NULL;
1194                 rids_out = NULL;
1195         }
1196
1197         for ( i = 0; i < num_groups_out; i++ ) {
1198                 names_out[i] =
1199                         talloc_strdup( mem_ctx, acct_buf[i].acct_name );
1200                 desc_out[i] = talloc_strdup( mem_ctx, acct_buf[i].acct_desc );
1201                 rids_out[i] = acct_buf[i].rid;
1202
1203                 if ( !names_out[i] || !desc_out[i] ) {
1204                         hnd->status = NT_STATUS_NO_MEMORY;
1205                         return CAC_FAILURE;
1206                 }
1207         }
1208
1209         op->out.resume_idx = resume_idx_out;
1210         op->out.num_groups = num_groups_out;
1211         op->out.rids = rids_out;
1212         op->out.names = names_out;
1213         op->out.descriptions = desc_out;
1214
1215         return CAC_SUCCESS;
1216 }
1217
1218 int cac_SamEnumAliases( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1219                         struct SamEnumAliases *op )
1220 {
1221         struct rpc_pipe_client *pipe_hnd = NULL;
1222
1223         uint32 i = 0;
1224
1225         uint32 resume_idx_out = 0;
1226         char **names_out = NULL;
1227         char **desc_out = NULL;
1228         uint32 *rids_out = NULL;
1229         uint32 num_als_out = 0;
1230
1231         struct acct_info *acct_buf = NULL;
1232
1233         if ( !hnd )
1234                 return CAC_FAILURE;
1235
1236         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1237                 hnd->status = NT_STATUS_INVALID_HANDLE;
1238                 return CAC_FAILURE;
1239         }
1240
1241         if ( !op || !op->in.dom_hnd || !mem_ctx ) {
1242                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1243                 return CAC_FAILURE;
1244         }
1245
1246         /*this is a hack.. but is the only reliable way to know if everything has been enumerated */
1247         if ( op->out.done == True ) {
1248                 return CAC_FAILURE;
1249         }
1250
1251         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1252         if ( !pipe_hnd ) {
1253                 hnd->status = NT_STATUS_INVALID_HANDLE;
1254                 return CAC_FAILURE;
1255         }
1256
1257         resume_idx_out = op->out.resume_idx;
1258
1259         hnd->status =
1260                 rpccli_samr_enum_als_groups( pipe_hnd, mem_ctx,
1261                                              op->in.dom_hnd, &resume_idx_out,
1262                                              SAMR_ENUM_MAX_SIZE, &acct_buf,
1263                                              &num_als_out );
1264
1265
1266         if ( NT_STATUS_IS_OK( hnd->status ) )
1267                 op->out.done = True;
1268
1269         /*if there are no more entries, the operation will return NT_STATUS_OK. 
1270          * We want to return failure if no results were returned*/
1271         if ( !NT_STATUS_IS_OK( hnd->status )
1272              && NT_STATUS_V( hnd->status ) !=
1273              NT_STATUS_V( STATUS_MORE_ENTRIES ) )
1274                 return CAC_FAILURE;
1275
1276         if (num_als_out) {
1277                 names_out = TALLOC_ARRAY( mem_ctx, char *, num_als_out );
1278                 if ( !names_out ) {
1279                         hnd->status = NT_STATUS_NO_MEMORY;
1280                         TALLOC_FREE( acct_buf );
1281                         return CAC_FAILURE;
1282                 }
1283
1284                 desc_out = TALLOC_ARRAY( mem_ctx, char *, num_als_out );
1285                 if ( !desc_out ) {
1286                         hnd->status = NT_STATUS_NO_MEMORY;
1287                         TALLOC_FREE( acct_buf );
1288                         TALLOC_FREE( names_out );
1289                         return CAC_FAILURE;
1290                 }
1291
1292                 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_als_out );
1293                 if ( !rids_out ) {
1294                         hnd->status = NT_STATUS_NO_MEMORY;
1295                         TALLOC_FREE( acct_buf );
1296                         TALLOC_FREE( names_out );
1297                         TALLOC_FREE( desc_out );
1298                         return CAC_FAILURE;
1299                 }
1300         } else {
1301                 names_out = NULL;
1302                 desc_out = NULL;
1303                 rids_out = NULL;
1304         }
1305
1306         for ( i = 0; i < num_als_out; i++ ) {
1307                 names_out[i] =
1308                         talloc_strdup( mem_ctx, acct_buf[i].acct_name );
1309                 desc_out[i] = talloc_strdup( mem_ctx, acct_buf[i].acct_desc );
1310                 rids_out[i] = acct_buf[i].rid;
1311
1312                 if ( !names_out[i] || !desc_out[i] ) {
1313                         hnd->status = NT_STATUS_NO_MEMORY;
1314                         return CAC_FAILURE;
1315                 }
1316         }
1317
1318         op->out.resume_idx = resume_idx_out;
1319         op->out.num_aliases = num_als_out;
1320         op->out.rids = rids_out;
1321         op->out.names = names_out;
1322         op->out.descriptions = desc_out;
1323
1324         return CAC_SUCCESS;
1325 }
1326
1327 int cac_SamCreateAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1328                         struct SamCreateAlias *op )
1329 {
1330         struct rpc_pipe_client *pipe_hnd = NULL;
1331
1332         POLICY_HND *als_hnd_out = NULL;
1333
1334         if ( !hnd )
1335                 return CAC_FAILURE;
1336
1337         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1338                 hnd->status = NT_STATUS_INVALID_HANDLE;
1339                 return CAC_FAILURE;
1340         }
1341
1342         if ( !op || !op->in.name || op->in.name[0] == '\0' || !mem_ctx ) {
1343                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1344                 return CAC_FAILURE;
1345         }
1346
1347         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1348         if ( !pipe_hnd ) {
1349                 hnd->status = NT_STATUS_INVALID_HANDLE;
1350                 return CAC_FAILURE;
1351         }
1352
1353         als_hnd_out = talloc( mem_ctx, POLICY_HND );
1354         if ( !als_hnd_out ) {
1355                 hnd->status = NT_STATUS_NO_MEMORY;
1356                 return CAC_FAILURE;
1357         }
1358
1359         hnd->status =
1360                 rpccli_samr_create_dom_alias( pipe_hnd, mem_ctx,
1361                                               op->in.dom_hnd, op->in.name,
1362                                               als_hnd_out );
1363
1364         if ( !NT_STATUS_IS_OK( hnd->status ) )
1365                 return CAC_FAILURE;
1366
1367         op->out.alias_hnd = als_hnd_out;
1368
1369         return CAC_SUCCESS;
1370
1371 }
1372
1373 int cac_SamOpenAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1374                       struct SamOpenAlias *op )
1375 {
1376         struct rpc_pipe_client *pipe_hnd = NULL;
1377
1378         POLICY_HND *als_hnd_out = NULL;
1379
1380         if ( !hnd )
1381                 return CAC_FAILURE;
1382
1383         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1384                 hnd->status = NT_STATUS_INVALID_HANDLE;
1385                 return CAC_FAILURE;
1386         }
1387
1388         if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
1389                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1390                 return CAC_FAILURE;
1391         }
1392
1393         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1394         if ( !pipe_hnd ) {
1395                 hnd->status = NT_STATUS_INVALID_HANDLE;
1396                 return CAC_FAILURE;
1397         }
1398
1399         als_hnd_out = talloc( mem_ctx, POLICY_HND );
1400         if ( !als_hnd_out ) {
1401                 hnd->status = NT_STATUS_NO_MEMORY;
1402                 return CAC_FAILURE;
1403         }
1404
1405         hnd->status =
1406                 rpccli_samr_open_alias( pipe_hnd, mem_ctx, op->in.dom_hnd,
1407                                         op->in.access, op->in.rid,
1408                                         als_hnd_out );
1409
1410         if ( !NT_STATUS_IS_OK( hnd->status ) )
1411                 return CAC_FAILURE;
1412
1413         op->out.alias_hnd = als_hnd_out;
1414
1415         return CAC_SUCCESS;
1416 }
1417
1418 int cac_SamDeleteAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1419                         POLICY_HND * alias_hnd )
1420 {
1421         struct rpc_pipe_client *pipe_hnd = NULL;
1422
1423         if ( !hnd )
1424                 return CAC_FAILURE;
1425
1426         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1427                 hnd->status = NT_STATUS_INVALID_HANDLE;
1428                 return CAC_FAILURE;
1429         }
1430
1431         if ( !alias_hnd || !mem_ctx ) {
1432                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1433                 return CAC_FAILURE;
1434         }
1435
1436         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1437         if ( !pipe_hnd ) {
1438                 hnd->status = NT_STATUS_INVALID_HANDLE;
1439                 return CAC_FAILURE;
1440         }
1441
1442         hnd->status =
1443                 rpccli_samr_delete_dom_alias( pipe_hnd, mem_ctx, alias_hnd );
1444
1445         if ( !NT_STATUS_IS_OK( hnd->status ) )
1446                 return CAC_FAILURE;
1447
1448         return CAC_SUCCESS;
1449
1450 }
1451
1452 int cac_SamAddAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1453                            struct SamAddAliasMember *op )
1454 {
1455         struct rpc_pipe_client *pipe_hnd = NULL;
1456
1457         if ( !hnd )
1458                 return CAC_FAILURE;
1459
1460         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1461                 hnd->status = NT_STATUS_INVALID_HANDLE;
1462                 return CAC_FAILURE;
1463         }
1464
1465         if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
1466                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1467                 return CAC_FAILURE;
1468         }
1469
1470         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1471         if ( !pipe_hnd ) {
1472                 hnd->status = NT_STATUS_INVALID_HANDLE;
1473                 return CAC_FAILURE;
1474         }
1475
1476         hnd->status =
1477                 rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
1478                                           op->in.sid );
1479
1480         if ( !NT_STATUS_IS_OK( hnd->status ) )
1481                 return CAC_FAILURE;
1482
1483         return CAC_SUCCESS;
1484 }
1485
1486 int cac_SamRemoveAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1487                               struct SamRemoveAliasMember *op )
1488 {
1489         struct rpc_pipe_client *pipe_hnd = NULL;
1490
1491         if ( !hnd )
1492                 return CAC_FAILURE;
1493
1494         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1495                 hnd->status = NT_STATUS_INVALID_HANDLE;
1496                 return CAC_FAILURE;
1497         }
1498
1499         if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
1500                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1501                 return CAC_FAILURE;
1502         }
1503
1504         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1505         if ( !pipe_hnd ) {
1506                 hnd->status = NT_STATUS_INVALID_HANDLE;
1507                 return CAC_FAILURE;
1508         }
1509
1510         hnd->status =
1511                 rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
1512                                           op->in.sid );
1513
1514         if ( !NT_STATUS_IS_OK( hnd->status ) )
1515                 return CAC_FAILURE;
1516
1517         return CAC_SUCCESS;
1518 }
1519
1520 int cac_SamGetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1521                             struct SamGetAliasMembers *op )
1522 {
1523         struct rpc_pipe_client *pipe_hnd = NULL;
1524
1525         uint32 num_mem_out;
1526         DOM_SID *sids_out;
1527
1528         if ( !hnd )
1529                 return CAC_FAILURE;
1530
1531         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1532                 hnd->status = NT_STATUS_INVALID_HANDLE;
1533                 return CAC_FAILURE;
1534         }
1535
1536         if ( !op || !op->in.alias_hnd || !mem_ctx ) {
1537                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1538                 return CAC_FAILURE;
1539         }
1540
1541         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1542         if ( !pipe_hnd ) {
1543                 hnd->status = NT_STATUS_INVALID_HANDLE;
1544                 return CAC_FAILURE;
1545         }
1546
1547         hnd->status =
1548                 rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx,
1549                                             op->in.alias_hnd, &num_mem_out,
1550                                             &sids_out );
1551
1552         if ( !NT_STATUS_IS_OK( hnd->status ) )
1553                 return CAC_FAILURE;
1554
1555         op->out.num_members = num_mem_out;
1556         op->out.sids = sids_out;
1557
1558         return CAC_SUCCESS;
1559 }
1560
1561 int cac_SamClearAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1562                               POLICY_HND * alias_hnd )
1563 {
1564         struct rpc_pipe_client *pipe_hnd = NULL;
1565
1566         int result = CAC_SUCCESS;
1567
1568         int i = 0;
1569
1570         uint32 num_mem = 0;
1571         DOM_SID *sid = NULL;
1572
1573         NTSTATUS status;
1574
1575         if ( !hnd )
1576                 return CAC_FAILURE;
1577
1578         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1579                 hnd->status = NT_STATUS_INVALID_HANDLE;
1580                 return CAC_FAILURE;
1581         }
1582
1583         if ( !alias_hnd || !mem_ctx ) {
1584                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1585                 return CAC_FAILURE;
1586         }
1587
1588         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1589         if ( !pipe_hnd ) {
1590                 hnd->status = NT_STATUS_INVALID_HANDLE;
1591                 return CAC_FAILURE;
1592         }
1593
1594         hnd->status =
1595                 rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx, alias_hnd,
1596                                             &num_mem, &sid );
1597
1598         if ( !NT_STATUS_IS_OK( hnd->status ) )
1599                 return CAC_FAILURE;
1600
1601         /*try to delete the users one by one */
1602         for ( i = 0; i < num_mem && NT_STATUS_IS_OK( hnd->status ); i++ ) {
1603                 hnd->status =
1604                         rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx,
1605                                                   alias_hnd, &sid[i] );
1606         }
1607
1608         /*if not all members could be removed, then try to re-add the members that were already deleted */
1609         if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1610                 status = NT_STATUS_OK;
1611
1612                 for ( i -= 1; i >= 0 && NT_STATUS_IS_OK( status ); i-- ) {
1613                         status = rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx,
1614                                                            alias_hnd,
1615                                                            &sid[i] );
1616                 }
1617
1618                 /*we return with the NTSTATUS error that we got when trying to delete users */
1619                 if ( !NT_STATUS_IS_OK( status ) )
1620                         result = CAC_FAILURE;
1621         }
1622
1623         TALLOC_FREE( sid );
1624         return result;
1625 }
1626
1627 int cac_SamSetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1628                             struct SamSetAliasMembers *op )
1629 {
1630         struct rpc_pipe_client *pipe_hnd = NULL;
1631
1632         uint32 i = 0;
1633
1634         if ( !hnd )
1635                 return CAC_FAILURE;
1636
1637         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1638                 hnd->status = NT_STATUS_INVALID_HANDLE;
1639                 return CAC_FAILURE;
1640         }
1641
1642         if ( !op || !op->in.alias_hnd || !mem_ctx ) {
1643                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1644                 return CAC_FAILURE;
1645         }
1646
1647         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1648         if ( !pipe_hnd ) {
1649                 hnd->status = NT_STATUS_INVALID_HANDLE;
1650                 return CAC_FAILURE;
1651         }
1652
1653         /*use cac_SamClearAliasMembers() to clear them */
1654         if ( !cac_SamClearAliasMembers( hnd, mem_ctx, op->in.alias_hnd ) )
1655                 return CAC_FAILURE;     /*hnd->status is already set */
1656
1657
1658         for ( i = 0; i < op->in.num_members && NT_STATUS_IS_OK( hnd->status );
1659               i++ ) {
1660                 hnd->status =
1661                         rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx,
1662                                                   op->in.alias_hnd,
1663                                                   &( op->in.sids[i] ) );
1664         }
1665
1666         if ( !NT_STATUS_IS_OK( hnd->status ) )
1667                 return CAC_FAILURE;
1668
1669         return CAC_SUCCESS;
1670
1671 }
1672
1673 int cac_SamUserChangePasswd( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1674                              struct SamUserChangePasswd *op )
1675 {
1676         SMBCSRV *srv = NULL;
1677         struct rpc_pipe_client *pipe_hnd = NULL;
1678
1679         if ( !hnd )
1680                 return CAC_FAILURE;
1681
1682         if ( !hnd->_internal.ctx ) {
1683                 hnd->status = NT_STATUS_INVALID_HANDLE;
1684                 return CAC_FAILURE;
1685         }
1686
1687         if ( !op || !op->in.username || !op->in.password
1688              || !op->in.new_password || !mem_ctx ) {
1689                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1690                 return CAC_FAILURE;
1691         }
1692
1693         srv = cac_GetServer( hnd );
1694         if ( !srv ) {
1695                 hnd->status = NT_STATUS_INVALID_CONNECTION;
1696                 return CAC_FAILURE;
1697         }
1698
1699         /*open a session on SAMR if we don't have one */
1700         if ( !hnd->_internal.pipes[PI_SAMR] ) {
1701                 if ( !
1702                      ( pipe_hnd =
1703                        cli_rpc_pipe_open_noauth( srv->cli, PI_SAMR,
1704                                                  &hnd->status ) ) ) {
1705                         return CAC_FAILURE;
1706                 }
1707
1708                 hnd->_internal.pipes[PI_SAMR] = True;
1709         }
1710
1711         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1712         if ( !pipe_hnd ) {
1713                 hnd->status = NT_STATUS_INVALID_HANDLE;
1714                 return CAC_FAILURE;
1715         }
1716
1717         hnd->status =
1718                 rpccli_samr_chgpasswd_user( pipe_hnd, mem_ctx,
1719                                             op->in.username,
1720                                             op->in.new_password,
1721                                             op->in.password );
1722
1723         if ( !NT_STATUS_IS_OK( hnd->status ) )
1724                 return CAC_FAILURE;
1725
1726         return CAC_SUCCESS;
1727 }
1728
1729 int cac_SamEnableUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1730                        POLICY_HND * user_hnd )
1731 {
1732         SMBCSRV *srv = NULL;
1733         struct rpc_pipe_client *pipe_hnd = NULL;
1734
1735         SAM_USERINFO_CTR *ctr;
1736
1737         if ( !hnd )
1738                 return CAC_FAILURE;
1739
1740         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1741                 hnd->status = NT_STATUS_INVALID_HANDLE;
1742                 return CAC_FAILURE;
1743         }
1744
1745         if ( !user_hnd || !mem_ctx ) {
1746                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1747                 return CAC_FAILURE;
1748         }
1749
1750         srv = cac_GetServer( hnd );
1751         if ( !srv ) {
1752                 hnd->status = NT_STATUS_INVALID_CONNECTION;
1753                 return CAC_FAILURE;
1754         }
1755
1756         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1757         if ( !pipe_hnd ) {
1758                 hnd->status = NT_STATUS_INVALID_HANDLE;
1759                 return CAC_FAILURE;
1760         }
1761
1762         /*info_level = 21 is the only level that I have found to work reliably. It would be nice if user_level = 10 worked. */
1763         hnd->status =
1764                 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10,
1765                                             &ctr );
1766
1767         if ( !NT_STATUS_IS_OK( hnd->status ) )
1768                 return CAC_FAILURE;
1769
1770    /**check the ACB mask*/
1771         if ( ( ctr->info.id16->acb_info & ACB_DISABLED ) == ACB_DISABLED ) {
1772                 /*toggle the disabled bit */
1773                 ctr->info.id16->acb_info ^= ACB_DISABLED;
1774         } else {
1775                 /*the user is already enabled so just return success */
1776                 return CAC_SUCCESS;
1777         }
1778
1779         /*now set the userinfo */
1780         hnd->status =
1781                 rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10,
1782                                            &srv->cli->user_session_key, ctr );
1783
1784         /*this will only work properly if we use set_userinfo2 - fail if it is not supported */
1785         if ( !NT_STATUS_IS_OK( hnd->status ) )
1786                 return CAC_FAILURE;
1787
1788         return CAC_SUCCESS;
1789 }
1790
1791 int cac_SamDisableUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1792                         POLICY_HND * user_hnd )
1793 {
1794         SMBCSRV *srv = NULL;
1795         struct rpc_pipe_client *pipe_hnd = NULL;
1796
1797         SAM_USERINFO_CTR *ctr;
1798
1799         if ( !hnd )
1800                 return CAC_FAILURE;
1801
1802         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1803                 hnd->status = NT_STATUS_INVALID_HANDLE;
1804                 return CAC_FAILURE;
1805         }
1806
1807         if ( !user_hnd || !mem_ctx ) {
1808                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1809                 return CAC_FAILURE;
1810         }
1811
1812         srv = cac_GetServer( hnd );
1813         if ( !srv ) {
1814                 hnd->status = NT_STATUS_INVALID_CONNECTION;
1815                 return CAC_FAILURE;
1816         }
1817
1818         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1819         if ( !pipe_hnd ) {
1820                 hnd->status = NT_STATUS_INVALID_HANDLE;
1821                 return CAC_FAILURE;
1822         }
1823
1824         hnd->status =
1825                 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10,
1826                                             &ctr );
1827
1828         if ( !NT_STATUS_IS_OK( hnd->status ) )
1829                 return CAC_FAILURE;
1830
1831         if ( ( ctr->info.id16->acb_info & ACB_DISABLED ) == ACB_DISABLED ) {
1832                 /*then the user is already disabled */
1833                 return CAC_SUCCESS;
1834         }
1835
1836         /*toggle the disabled bit */
1837         ctr->info.id16->acb_info ^= ACB_DISABLED;
1838
1839         /*this will only work properly if we use set_userinfo2 */
1840         hnd->status =
1841                 rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10,
1842                                            &srv->cli->user_session_key, ctr );
1843
1844         /*this will only work properly if we use set_userinfo2 fail if it is not supported */
1845         if ( !NT_STATUS_IS_OK( hnd->status ) )
1846                 return CAC_FAILURE;
1847
1848         return CAC_SUCCESS;
1849 }
1850
1851 int cac_SamSetPassword( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1852                         struct SamSetPassword *op )
1853 {
1854         SMBCSRV *srv = NULL;
1855         struct rpc_pipe_client *pipe_hnd = NULL;
1856
1857         SAM_USERINFO_CTR ctr;
1858         SAM_USER_INFO_24 info24;
1859         uint8 pw[516];
1860
1861         if ( !hnd )
1862                 return CAC_FAILURE;
1863
1864         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1865                 hnd->status = NT_STATUS_INVALID_HANDLE;
1866                 return CAC_FAILURE;
1867         }
1868
1869         if ( !op->in.user_hnd || !op->in.password || !mem_ctx ) {
1870                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1871                 return CAC_FAILURE;
1872         }
1873
1874         srv = cac_GetServer( hnd );
1875         if ( !srv ) {
1876                 hnd->status = NT_STATUS_INVALID_CONNECTION;
1877                 return CAC_FAILURE;
1878         }
1879
1880         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1881         if ( !pipe_hnd ) {
1882                 hnd->status = NT_STATUS_INVALID_HANDLE;
1883                 return CAC_FAILURE;
1884         }
1885
1886         ZERO_STRUCT( ctr );
1887         ZERO_STRUCT( info24 );
1888
1889         encode_pw_buffer( pw, op->in.password, STR_UNICODE );
1890
1891         init_sam_user_info24( &info24, ( char * ) pw, 24 );
1892
1893         ctr.switch_value = 24;
1894         ctr.info.id24 = &info24;
1895
1896         hnd->status =
1897                 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
1898                                           24, &srv->cli->user_session_key,
1899                                           &ctr );
1900
1901         if ( !NT_STATUS_IS_OK( hnd->status ) )
1902                 return CAC_FAILURE;
1903
1904         return CAC_SUCCESS;
1905 }
1906
1907 int cac_SamGetUserInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1908                         struct SamGetUserInfo *op )
1909 {
1910         struct rpc_pipe_client *pipe_hnd = NULL;
1911
1912         SAM_USERINFO_CTR *ctr;
1913
1914         if ( !hnd )
1915                 return CAC_FAILURE;
1916
1917         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1918                 hnd->status = NT_STATUS_INVALID_HANDLE;
1919                 return CAC_FAILURE;
1920         }
1921
1922         if ( !op->in.user_hnd || !mem_ctx ) {
1923                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1924                 return CAC_FAILURE;
1925         }
1926
1927         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1928         if ( !pipe_hnd ) {
1929                 hnd->status = NT_STATUS_INVALID_HANDLE;
1930                 return CAC_FAILURE;
1931         }
1932
1933         hnd->status =
1934                 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
1935                                             op->in.user_hnd, 21, &ctr );
1936
1937         if ( !NT_STATUS_IS_OK( hnd->status ) )
1938                 return CAC_FAILURE;
1939
1940         op->out.info = cac_MakeUserInfo( mem_ctx, ctr );
1941
1942         if ( !op->out.info ) {
1943                 hnd->status = NT_STATUS_NO_MEMORY;
1944                 return CAC_FAILURE;
1945         }
1946
1947         return CAC_SUCCESS;
1948 }
1949
1950 int cac_SamSetUserInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1951                         struct SamSetUserInfo *op )
1952 {
1953         SMBCSRV *srv = NULL;
1954         struct rpc_pipe_client *pipe_hnd = NULL;
1955
1956         SAM_USERINFO_CTR *ctr;
1957
1958         if ( !hnd )
1959                 return CAC_FAILURE;
1960
1961         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1962                 hnd->status = NT_STATUS_INVALID_HANDLE;
1963                 return CAC_FAILURE;
1964         }
1965
1966         if ( !op->in.user_hnd || !op->in.info || !mem_ctx ) {
1967                 hnd->status = NT_STATUS_INVALID_PARAMETER;
1968                 return CAC_FAILURE;
1969         }
1970
1971         ctr = cac_MakeUserInfoCtr( mem_ctx, op->in.info );
1972         if ( !ctr ) {
1973                 hnd->status = NT_STATUS_NO_MEMORY;
1974                 return CAC_FAILURE;
1975         }
1976
1977         srv = cac_GetServer( hnd );
1978         if ( !srv ) {
1979                 hnd->status = NT_STATUS_INVALID_CONNECTION;
1980                 return CAC_FAILURE;
1981         }
1982
1983         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1984         if ( !pipe_hnd ) {
1985                 hnd->status = NT_STATUS_INVALID_HANDLE;
1986                 return CAC_FAILURE;
1987         }
1988
1989         if ( hnd->_internal.srv_level >= SRV_WIN_NT4 ) {
1990                 hnd->status =
1991                         rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx,
1992                                                    op->in.user_hnd, 21,
1993                                                    &srv->cli->
1994                                                    user_session_key, ctr );
1995         }
1996
1997         if ( hnd->_internal.srv_level < SRV_WIN_NT4
1998              || !NT_STATUS_IS_OK( hnd->status ) ) {
1999                 hnd->status =
2000                         rpccli_samr_set_userinfo( pipe_hnd, mem_ctx,
2001                                                   op->in.user_hnd, 21,
2002                                                   &srv->cli->user_session_key,
2003                                                   ctr );
2004
2005                 if ( NT_STATUS_IS_OK( hnd->status )
2006                      && hnd->_internal.srv_level > SRV_WIN_NT4 ) {
2007                         hnd->_internal.srv_level = SRV_WIN_NT4;
2008                 }
2009         }
2010
2011
2012         if ( !NT_STATUS_IS_OK( hnd->status ) )
2013                 return CAC_FAILURE;
2014
2015         return CAC_SUCCESS;
2016 }
2017
2018
2019 int cac_SamGetUserInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2020                            struct SamGetUserInfoCtr *op )
2021 {
2022         struct rpc_pipe_client *pipe_hnd = NULL;
2023
2024         SAM_USERINFO_CTR *ctr_out;
2025
2026         if ( !hnd )
2027                 return CAC_FAILURE;
2028
2029         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2030                 hnd->status = NT_STATUS_INVALID_HANDLE;
2031                 return CAC_FAILURE;
2032         }
2033
2034         if ( !op->in.user_hnd || op->in.info_class == 0 || !mem_ctx ) {
2035                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2036                 return CAC_FAILURE;
2037         }
2038
2039         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2040         if ( !pipe_hnd ) {
2041                 hnd->status = NT_STATUS_INVALID_HANDLE;
2042                 return CAC_FAILURE;
2043         }
2044
2045         hnd->status =
2046                 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
2047                                             op->in.user_hnd,
2048                                             op->in.info_class, &ctr_out );
2049
2050         if ( !NT_STATUS_IS_OK( hnd->status ) )
2051                 return CAC_FAILURE;
2052
2053         op->out.ctr = ctr_out;
2054
2055         return CAC_SUCCESS;
2056 }
2057
2058 int cac_SamSetUserInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2059                            struct SamSetUserInfoCtr *op )
2060 {
2061         SMBCSRV *srv = NULL;
2062         struct rpc_pipe_client *pipe_hnd = NULL;
2063
2064         if ( !hnd )
2065                 return CAC_FAILURE;
2066
2067         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2068                 hnd->status = NT_STATUS_INVALID_HANDLE;
2069                 return CAC_FAILURE;
2070         }
2071
2072         if ( !op->in.user_hnd || !op->in.ctr || !mem_ctx ) {
2073                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2074                 return CAC_FAILURE;
2075         }
2076
2077         srv = cac_GetServer( hnd );
2078         if ( !srv ) {
2079                 hnd->status = NT_STATUS_INVALID_CONNECTION;
2080                 return CAC_FAILURE;
2081         }
2082
2083         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2084         if ( !pipe_hnd ) {
2085                 hnd->status = NT_STATUS_INVALID_HANDLE;
2086                 return CAC_FAILURE;
2087         }
2088
2089
2090         hnd->status =
2091                 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
2092                                           op->in.ctr->switch_value,
2093                                           &srv->cli->user_session_key,
2094                                           op->in.ctr );
2095
2096         if ( !NT_STATUS_IS_OK( hnd->status ) )
2097                 return CAC_FAILURE;
2098
2099         return CAC_SUCCESS;
2100
2101 }
2102
2103 int cac_SamRenameUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2104                        struct SamRenameUser *op )
2105 {
2106         SMBCSRV *srv = NULL;
2107         struct rpc_pipe_client *pipe_hnd = NULL;
2108
2109         SAM_USERINFO_CTR ctr;
2110         SAM_USER_INFO_7 info7;
2111
2112         if ( !hnd )
2113                 return CAC_FAILURE;
2114
2115         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2116                 hnd->status = NT_STATUS_INVALID_HANDLE;
2117                 return CAC_FAILURE;
2118         }
2119
2120         if ( !op->in.user_hnd || !op->in.new_name
2121              || op->in.new_name[0] == '\0' || !mem_ctx ) {
2122                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2123                 return CAC_FAILURE;
2124         }
2125
2126         srv = cac_GetServer( hnd );
2127         if ( !srv ) {
2128                 hnd->status = NT_STATUS_INVALID_CONNECTION;
2129                 return CAC_FAILURE;
2130         }
2131
2132         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2133         if ( !pipe_hnd ) {
2134                 hnd->status = NT_STATUS_INVALID_HANDLE;
2135                 return CAC_FAILURE;
2136         }
2137
2138         ZERO_STRUCT( ctr );
2139         ZERO_STRUCT( info7 );
2140
2141         init_sam_user_info7( &info7, op->in.new_name );
2142
2143         ctr.switch_value = 7;
2144         ctr.info.id7 = &info7;
2145
2146         hnd->status =
2147                 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
2148                                           7, &srv->cli->user_session_key,
2149                                           &ctr );
2150
2151         if ( !NT_STATUS_IS_OK( hnd->status ) )
2152                 return CAC_FAILURE;
2153
2154         return CAC_SUCCESS;
2155 }
2156
2157
2158 int cac_SamGetGroupInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2159                          struct SamGetGroupInfo *op )
2160 {
2161         struct rpc_pipe_client *pipe_hnd = NULL;
2162
2163         GROUP_INFO_CTR *ctr;
2164
2165         if ( !hnd )
2166                 return CAC_FAILURE;
2167
2168         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2169                 hnd->status = NT_STATUS_INVALID_HANDLE;
2170                 return CAC_FAILURE;
2171         }
2172
2173         if ( !op->in.group_hnd || !mem_ctx ) {
2174                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2175                 return CAC_FAILURE;
2176         }
2177
2178         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2179         if ( !pipe_hnd ) {
2180                 hnd->status = NT_STATUS_INVALID_HANDLE;
2181                 return CAC_FAILURE;
2182         }
2183
2184
2185         /*get a GROUP_INFO_1 structure */
2186         hnd->status =
2187                 rpccli_samr_query_groupinfo( pipe_hnd, mem_ctx,
2188                                              op->in.group_hnd, 1, &ctr );
2189
2190         if ( !NT_STATUS_IS_OK( hnd->status ) )
2191                 return CAC_FAILURE;
2192
2193         op->out.info = cac_MakeGroupInfo( mem_ctx, ctr );
2194         if ( !op->out.info ) {
2195                 hnd->status = NT_STATUS_NO_MEMORY;
2196                 return CAC_FAILURE;
2197         }
2198
2199         return CAC_SUCCESS;
2200 }
2201
2202 int cac_SamSetGroupInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2203                          struct SamSetGroupInfo *op )
2204 {
2205         struct rpc_pipe_client *pipe_hnd = NULL;
2206
2207         GROUP_INFO_CTR *ctr = NULL;
2208
2209         if ( !hnd )
2210                 return CAC_FAILURE;
2211
2212         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2213                 hnd->status = NT_STATUS_INVALID_HANDLE;
2214                 return CAC_FAILURE;
2215         }
2216
2217         if ( !op->in.group_hnd || !op->in.info || !mem_ctx ) {
2218                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2219                 return CAC_FAILURE;
2220         }
2221
2222         ctr = cac_MakeGroupInfoCtr( mem_ctx, op->in.info );
2223         if ( !ctr ) {
2224                 hnd->status = NT_STATUS_NO_MEMORY;
2225                 return CAC_FAILURE;
2226         }
2227
2228         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2229         if ( !pipe_hnd ) {
2230                 hnd->status = NT_STATUS_INVALID_HANDLE;
2231                 return CAC_FAILURE;
2232         }
2233
2234         hnd->status =
2235                 rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
2236                                            op->in.group_hnd, ctr );
2237
2238         if ( !NT_STATUS_IS_OK( hnd->status ) )
2239                 return CAC_FAILURE;
2240
2241         return CAC_SUCCESS;
2242 }
2243
2244 int cac_SamRenameGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2245                         struct SamRenameGroup *op )
2246 {
2247         struct rpc_pipe_client *pipe_hnd = NULL;
2248
2249         GROUP_INFO_CTR ctr;
2250
2251         if ( !hnd )
2252                 return CAC_FAILURE;
2253
2254         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2255                 hnd->status = NT_STATUS_INVALID_HANDLE;
2256                 return CAC_FAILURE;
2257         }
2258
2259         if ( !op->in.group_hnd || !op->in.new_name
2260              || op->in.new_name[0] == '\0' || !mem_ctx ) {
2261                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2262                 return CAC_FAILURE;
2263         }
2264
2265         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2266         if ( !pipe_hnd ) {
2267                 hnd->status = NT_STATUS_INVALID_HANDLE;
2268                 return CAC_FAILURE;
2269         }
2270
2271         ZERO_STRUCT( ctr );
2272
2273         init_samr_group_info2( &ctr.group.info2, op->in.new_name );
2274         ctr.switch_value1 = 2;
2275
2276         hnd->status =
2277                 rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
2278                                            op->in.group_hnd, &ctr );
2279
2280         if ( !NT_STATUS_IS_OK( hnd->status ) )
2281                 return CAC_FAILURE;
2282
2283         return CAC_SUCCESS;
2284 }
2285
2286 int cac_SamGetAliasInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2287                          struct SamGetAliasInfo *op )
2288 {
2289         struct rpc_pipe_client *pipe_hnd = NULL;
2290
2291         ALIAS_INFO_CTR ctr;
2292
2293         if ( !hnd )
2294                 return CAC_FAILURE;
2295
2296         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2297                 hnd->status = NT_STATUS_INVALID_HANDLE;
2298                 return CAC_FAILURE;
2299         }
2300
2301         if ( !op->in.alias_hnd || !mem_ctx ) {
2302                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2303                 return CAC_FAILURE;
2304         }
2305
2306         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2307         if ( !pipe_hnd ) {
2308                 hnd->status = NT_STATUS_INVALID_HANDLE;
2309                 return CAC_FAILURE;
2310         }
2311
2312         /*get a GROUP_INFO_1 structure */
2313         hnd->status =
2314                 rpccli_samr_query_alias_info( pipe_hnd, mem_ctx,
2315                                               op->in.alias_hnd, 1, &ctr );
2316
2317         if ( !NT_STATUS_IS_OK( hnd->status ) )
2318                 return CAC_FAILURE;
2319
2320         op->out.info = cac_MakeAliasInfo( mem_ctx, ctr );
2321         if ( !op->out.info ) {
2322                 hnd->status = NT_STATUS_NO_MEMORY;
2323                 return CAC_FAILURE;
2324         }
2325
2326         return CAC_SUCCESS;
2327
2328 }
2329
2330 int cac_SamSetAliasInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2331                          struct SamSetAliasInfo *op )
2332 {
2333         struct rpc_pipe_client *pipe_hnd = NULL;
2334
2335         ALIAS_INFO_CTR *ctr = NULL;
2336
2337         if ( !hnd )
2338                 return CAC_FAILURE;
2339
2340         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2341                 hnd->status = NT_STATUS_INVALID_HANDLE;
2342                 return CAC_FAILURE;
2343         }
2344
2345         if ( !op->in.alias_hnd || !op->in.info || !mem_ctx ) {
2346                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2347                 return CAC_FAILURE;
2348         }
2349
2350         ctr = cac_MakeAliasInfoCtr( mem_ctx, op->in.info );
2351         if ( !ctr ) {
2352                 hnd->status = NT_STATUS_NO_MEMORY;
2353                 return CAC_FAILURE;
2354         }
2355
2356         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2357         if ( !pipe_hnd ) {
2358                 hnd->status = NT_STATUS_INVALID_HANDLE;
2359                 return CAC_FAILURE;
2360         }
2361
2362         hnd->status =
2363                 rpccli_samr_set_aliasinfo( pipe_hnd, mem_ctx,
2364                                            op->in.alias_hnd, ctr );
2365
2366         if ( !NT_STATUS_IS_OK( hnd->status ) )
2367                 return CAC_FAILURE;
2368
2369         return CAC_SUCCESS;
2370 }
2371
2372 int cac_SamGetDomainInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2373                           struct SamGetDomainInfo *op )
2374 {
2375         struct rpc_pipe_client *pipe_hnd = NULL;
2376
2377         SAM_UNK_CTR ctr;
2378         SAM_UNK_INFO_1 info1;
2379         SAM_UNK_INFO_2 info2;
2380         SAM_UNK_INFO_12 info12;
2381
2382         /*use this to keep track of a failed call */
2383         NTSTATUS status_buf = NT_STATUS_OK;
2384
2385         uint16 fail_count = 0;
2386
2387
2388         if ( !hnd )
2389                 return CAC_FAILURE;
2390
2391         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2392                 hnd->status = NT_STATUS_INVALID_HANDLE;
2393                 return CAC_FAILURE;
2394         }
2395
2396         if ( !op->in.dom_hnd || !mem_ctx ) {
2397                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2398                 return CAC_FAILURE;
2399         }
2400
2401         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2402         if ( !pipe_hnd ) {
2403                 hnd->status = NT_STATUS_INVALID_HANDLE;
2404                 return CAC_FAILURE;
2405         }
2406
2407         /*first try with info 1 */
2408         hnd->status =
2409                 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2410                                             1, &ctr );
2411
2412         if ( NT_STATUS_IS_OK( hnd->status ) ) {
2413                 /*then we buffer the SAM_UNK_INFO_1 structure */
2414                 info1 = ctr.info.inf1;
2415         } else {
2416                 /*then the call failed, store the status and ZERO out the info structure */
2417                 ZERO_STRUCT( info1 );
2418                 status_buf = hnd->status;
2419                 fail_count++;
2420         }
2421
2422         /*try again for the next one */
2423         hnd->status =
2424                 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2425                                             2, &ctr );
2426
2427         if ( NT_STATUS_IS_OK( hnd->status ) ) {
2428                 /*store the info */
2429                 info2 = ctr.info.inf2;
2430         } else {
2431                 /*ZERO out the structure and store the bad status */
2432                 ZERO_STRUCT( info2 );
2433                 status_buf = hnd->status;
2434                 fail_count++;
2435         }
2436
2437         /*once more */
2438         hnd->status =
2439                 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2440                                             12, &ctr );
2441
2442         if ( NT_STATUS_IS_OK( hnd->status ) ) {
2443                 info12 = ctr.info.inf12;
2444         } else {
2445                 ZERO_STRUCT( info12 );
2446                 status_buf = hnd->status;
2447                 fail_count++;
2448         }
2449
2450         /*return failure if all 3 calls failed */
2451         if ( fail_count == 3 )
2452                 return CAC_FAILURE;
2453
2454         op->out.info = cac_MakeDomainInfo( mem_ctx, &info1, &info2, &info12 );
2455
2456         if ( !op->out.info ) {
2457                 hnd->status = NT_STATUS_NO_MEMORY;
2458                 return CAC_FAILURE;
2459         }
2460
2461         if ( fail_count > 0 ) {
2462                 hnd->status = status_buf;
2463                 return CAC_PARTIAL_SUCCESS;
2464         }
2465
2466         return CAC_SUCCESS;
2467 }
2468
2469 int cac_SamGetDomainInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2470                              struct SamGetDomainInfoCtr *op )
2471 {
2472         struct rpc_pipe_client *pipe_hnd = NULL;
2473
2474         SAM_UNK_CTR *ctr_out;
2475
2476         if ( !hnd )
2477                 return CAC_FAILURE;
2478
2479         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2480                 hnd->status = NT_STATUS_INVALID_HANDLE;
2481                 return CAC_FAILURE;
2482         }
2483
2484         if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
2485                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2486                 return CAC_FAILURE;
2487         }
2488
2489         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2490         if ( !pipe_hnd ) {
2491                 hnd->status = NT_STATUS_INVALID_HANDLE;
2492                 return CAC_FAILURE;
2493         }
2494
2495         ctr_out = talloc( mem_ctx, SAM_UNK_CTR );
2496         if ( !ctr_out ) {
2497                 hnd->status = NT_STATUS_NO_MEMORY;
2498                 return CAC_FAILURE;
2499         }
2500
2501         hnd->status =
2502                 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2503                                             op->in.info_class, ctr_out );
2504
2505         if ( !NT_STATUS_IS_OK( hnd->status ) )
2506                 return CAC_FAILURE;
2507
2508         op->out.info = ctr_out;
2509
2510         return CAC_SUCCESS;
2511 }
2512
2513 int cac_SamGetDisplayInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2514                            struct SamGetDisplayInfo *op )
2515 {
2516         struct rpc_pipe_client *pipe_hnd = NULL;
2517
2518         SAM_DISPINFO_CTR ctr_out;
2519
2520         uint32 max_entries_buf = 0;
2521         uint32 max_size_buf = 0;
2522
2523         uint32 resume_idx_out;
2524         uint32 num_entries_out;
2525
2526         if ( !hnd )
2527                 return CAC_FAILURE;
2528
2529         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2530                 hnd->status = NT_STATUS_INVALID_HANDLE;
2531                 return CAC_FAILURE;
2532         }
2533
2534         if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
2535                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2536                 return CAC_FAILURE;
2537         }
2538
2539         if ( op->out.done == True )     /*this is done so we can use the function as a loop condition */
2540                 return CAC_FAILURE;
2541
2542         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2543         if ( !pipe_hnd ) {
2544                 hnd->status = NT_STATUS_INVALID_HANDLE;
2545                 return CAC_FAILURE;
2546         }
2547
2548         if ( op->in.max_entries == 0 || op->in.max_size == 0 ) {
2549                 get_query_dispinfo_params( op->out.loop_count,
2550                                            &max_entries_buf, &max_size_buf );
2551         } else {
2552                 max_entries_buf = op->in.max_entries;
2553                 max_size_buf = op->in.max_size;
2554         }
2555
2556         resume_idx_out = op->out.resume_idx;
2557
2558         hnd->status =
2559                 rpccli_samr_query_dispinfo( pipe_hnd, mem_ctx, op->in.dom_hnd,
2560                                             &resume_idx_out,
2561                                             op->in.info_class,
2562                                             &num_entries_out, max_entries_buf,
2563                                             max_size_buf, &ctr_out );
2564
2565         if ( !NT_STATUS_IS_OK( hnd->status )
2566              && !NT_STATUS_EQUAL( hnd->status, STATUS_MORE_ENTRIES ) ) {
2567                 /*be defensive, maybe they'll call again without zeroing the struct */
2568                 op->out.loop_count = 0;
2569                 op->out.resume_idx = 0;
2570                 return CAC_FAILURE;
2571         }
2572
2573         if ( NT_STATUS_IS_OK( hnd->status ) ) {
2574                 /*we want to quit once the function is called next. so it can be used in a loop */
2575                 op->out.done = True;
2576         }
2577
2578         op->out.resume_idx = resume_idx_out;
2579         op->out.num_entries = num_entries_out;
2580         op->out.ctr = ctr_out;
2581         op->out.loop_count++;
2582
2583         return CAC_SUCCESS;
2584 }
2585
2586 int cac_SamLookupDomain( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2587                          struct SamLookupDomain *op )
2588 {
2589         struct rpc_pipe_client *pipe_hnd = NULL;
2590
2591         DOM_SID *sid_out = NULL;
2592
2593         if ( !hnd )
2594                 return CAC_FAILURE;
2595
2596         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2597                 hnd->status = NT_STATUS_INVALID_HANDLE;
2598                 return CAC_FAILURE;
2599         }
2600
2601         if ( !op->in.sam || !op->in.name || !mem_ctx ) {
2602                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2603                 return CAC_FAILURE;
2604         }
2605
2606         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2607         if ( !pipe_hnd ) {
2608                 hnd->status = NT_STATUS_INVALID_HANDLE;
2609                 return CAC_FAILURE;
2610         }
2611
2612         sid_out = talloc( mem_ctx, DOM_SID );
2613         if ( !sid_out ) {
2614                 hnd->status = NT_STATUS_NO_MEMORY;
2615                 return CAC_FAILURE;
2616         }
2617
2618         hnd->status =
2619                 rpccli_samr_lookup_domain( pipe_hnd, mem_ctx, op->in.sam,
2620                                            op->in.name, sid_out );
2621
2622         if ( !NT_STATUS_IS_OK( hnd->status ) )
2623                 return CAC_FAILURE;
2624
2625         op->out.sid = sid_out;
2626
2627         return CAC_SUCCESS;
2628 }
2629
2630 int cac_SamGetSecurityObject( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2631                               struct SamGetSecurityObject *op )
2632 {
2633         struct rpc_pipe_client *pipe_hnd = NULL;
2634
2635         /*this number taken from rpcclient/cmd_samr.c, I think it is the only supported level */
2636         uint32 sec_info = DACL_SECURITY_INFORMATION;
2637
2638         SEC_DESC_BUF *sec_out = NULL;
2639
2640         if ( !hnd )
2641                 return CAC_FAILURE;
2642
2643         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2644                 hnd->status = NT_STATUS_INVALID_HANDLE;
2645                 return CAC_FAILURE;
2646         }
2647
2648         if ( !op->in.pol || !mem_ctx ) {
2649                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2650                 return CAC_FAILURE;
2651         }
2652
2653         pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2654         if ( !pipe_hnd ) {
2655                 hnd->status = NT_STATUS_INVALID_HANDLE;
2656                 return CAC_FAILURE;
2657         }
2658
2659         hnd->status =
2660                 rpccli_samr_query_sec_obj( pipe_hnd, mem_ctx, op->in.pol,
2661                                            sec_info, mem_ctx, &sec_out );
2662
2663         if ( !NT_STATUS_IS_OK( hnd->status ) )
2664                 return CAC_FAILURE;
2665
2666         op->out.sec = sec_out;
2667
2668         return CAC_SUCCESS;
2669 }
2670
2671 int cac_SamFlush( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2672                   struct SamFlush *op )
2673 {
2674         struct SamOpenDomain od;
2675
2676         if ( !hnd )
2677                 return CAC_FAILURE;
2678
2679         if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2680                 hnd->status = NT_STATUS_INVALID_HANDLE;
2681                 return CAC_FAILURE;
2682         }
2683
2684         if ( !op || !op->in.dom_hnd || !mem_ctx ) {
2685                 hnd->status = NT_STATUS_INVALID_PARAMETER;
2686                 return CAC_FAILURE;
2687         }
2688
2689         if ( !cac_SamClose( hnd, mem_ctx, op->in.dom_hnd ) )
2690                 return CAC_FAILURE;
2691
2692         ZERO_STRUCT( od );
2693         od.in.access =
2694                 ( op->in.access ) ? op->in.access : MAXIMUM_ALLOWED_ACCESS;
2695         od.in.sid = op->in.sid;
2696
2697         if ( !cac_SamOpenDomain( hnd, mem_ctx, &od ) )
2698                 return CAC_FAILURE;
2699
2700         /*this function does not use an output parameter to make it as convenient as possible to use */
2701         *op->in.dom_hnd = *od.out.dom_hnd;
2702
2703         TALLOC_FREE( od.out.dom_hnd );
2704
2705         return CAC_SUCCESS;
2706 }