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