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