r21585: Start syncing the monster that will become 3.0.25pre1
[Samba.git] / source / libmsrpc / cac_samr.c
blobe85142af906ec0aa7da09e1b1e6546b2ce135a8e
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.
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.
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.
22 #include "libmsrpc.h"
23 #include "libmsrpc_internal.h"
25 /*used by cac_SamGetNamesFromRids*/
26 #define SAMR_RID_UNKNOWN 8
28 #define SAMR_ENUM_MAX_SIZE 0xffff
30 /*not sure what this is.. taken from rpcclient/cmd_samr.c*/
31 #define SAMR_LOOKUP_FLAGS 0x000003e8
33 DOM_SID *cac_get_domain_sid( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
34 uint32 des_access );
36 int cac_SamConnect( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
37 struct SamConnect *op )
39 SMBCSRV *srv = NULL;
40 struct rpc_pipe_client *pipe_hnd = NULL;
41 POLICY_HND *sam_out = NULL;
43 if ( !hnd )
44 return CAC_FAILURE;
46 if ( !hnd->_internal.ctx ) {
47 hnd->status = NT_STATUS_INVALID_HANDLE;
48 return CAC_FAILURE;
51 if ( !op || op->in.access == 0 || !mem_ctx ) {
52 hnd->status = NT_STATUS_INVALID_PARAMETER;
53 return CAC_FAILURE;
56 srv = cac_GetServer( hnd );
57 if ( !srv ) {
58 hnd->status = NT_STATUS_INVALID_CONNECTION;
59 return CAC_FAILURE;
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;
71 hnd->_internal.pipes[PI_SAMR] = True;
74 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
75 if ( !pipe_hnd ) {
76 hnd->status = NT_STATUS_INVALID_HANDLE;
77 return CAC_FAILURE;
80 sam_out = talloc( mem_ctx, POLICY_HND );
81 if ( !sam_out ) {
82 hnd->status = NT_STATUS_NO_MEMORY;
83 return CAC_FAILURE;
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 );
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 */
96 hnd->status =
97 rpccli_samr_connect( pipe_hnd, mem_ctx, op->in.access,
98 sam_out );
100 if ( NT_STATUS_IS_OK( hnd->status )
101 && hnd->_internal.srv_level > SRV_WIN_2K ) {
102 hnd->_internal.srv_level = SRV_WIN_2K;
106 if ( !NT_STATUS_IS_OK( hnd->status ) )
107 return CAC_FAILURE;
109 op->out.sam = sam_out;
111 return CAC_SUCCESS;
114 int cac_SamClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
115 POLICY_HND * sam )
117 struct rpc_pipe_client *pipe_hnd = NULL;
119 if ( !hnd )
120 return CAC_FAILURE;
122 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
123 hnd->status = NT_STATUS_INVALID_HANDLE;
124 return CAC_FAILURE;
127 if ( !sam || !mem_ctx ) {
128 hnd->status = NT_STATUS_INVALID_PARAMETER;
129 return CAC_FAILURE;
132 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
133 if ( !pipe_hnd ) {
134 hnd->status = NT_STATUS_INVALID_HANDLE;
135 return CAC_FAILURE;
138 hnd->status = rpccli_samr_close( pipe_hnd, mem_ctx, sam );
140 if ( !NT_STATUS_IS_OK( hnd->status ) )
141 return CAC_FAILURE;
143 return CAC_SUCCESS;
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
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 )
154 struct LsaOpenPolicy lop;
155 struct LsaFetchSid fs;
157 DOM_SID *sid;
159 ZERO_STRUCT( lop );
160 ZERO_STRUCT( fs );
162 lop.in.access = des_access;
163 lop.in.security_qos = True;
165 if ( !cac_LsaOpenPolicy( hnd, mem_ctx, &lop ) )
166 return NULL;
168 fs.in.pol = lop.out.pol;
169 fs.in.info_class = CAC_DOMAIN_INFO;
171 if ( !cac_LsaFetchSid( hnd, mem_ctx, &fs ) )
172 return NULL;
174 cac_LsaClosePolicy( hnd, mem_ctx, lop.out.pol );
176 if ( !fs.out.domain_sid )
177 return NULL;
179 sid = ( DOM_SID * ) talloc_memdup( mem_ctx,
180 &( fs.out.domain_sid->sid ),
181 sizeof( DOM_SID ) );
183 if ( !sid ) {
184 hnd->status = NT_STATUS_NO_MEMORY;
187 return sid;
191 int cac_SamOpenDomain( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
192 struct SamOpenDomain *op )
194 struct rpc_pipe_client *pipe_hnd = NULL;
196 DOM_SID *sid_buf;
197 POLICY_HND *sam_out;
198 POLICY_HND *pol_out;
200 struct SamLookupDomain sld;
202 if ( !hnd )
203 return CAC_FAILURE;
205 if ( !hnd->_internal.ctx ) {
206 hnd->status = NT_STATUS_INVALID_HANDLE;
207 return CAC_FAILURE;
210 if ( !op || op->in.access == 0 || !mem_ctx ) {
211 hnd->status = NT_STATUS_INVALID_PARAMETER;
212 return CAC_FAILURE;
215 if ( !op->in.sam ) {
216 /*use cac_SamConnect() since it does the session setup */
217 struct SamConnect sc;
219 ZERO_STRUCT( sc );
221 sc.in.access = op->in.access;
223 if ( !cac_SamConnect( hnd, mem_ctx, &sc ) ) {
224 return CAC_FAILURE;
227 sam_out = sc.out.sam;
228 } else {
229 sam_out = op->in.sam;
232 if ( !op->in.sid ) {
233 /*find the sid for the SAM's domain */
235 /*try using cac_SamLookupDomain() first */
236 ZERO_STRUCT( sld );
238 sld.in.sam = sam_out;
239 sld.in.name = hnd->domain;
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 );
250 } else {
251 /*we already have the sid for the domain we want */
252 sid_buf = op->in.sid;
255 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
256 if ( !pipe_hnd ) {
257 hnd->status = NT_STATUS_INVALID_HANDLE;
258 return CAC_FAILURE;
261 pol_out = talloc( mem_ctx, POLICY_HND );
262 if ( !pol_out ) {
263 hnd->status = NT_STATUS_NO_MEMORY;
264 return CAC_FAILURE;
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 );
272 if ( !NT_STATUS_IS_OK( hnd->status ) )
273 return CAC_FAILURE;
275 op->out.sam = sam_out;
276 op->out.dom_hnd = pol_out;
278 return CAC_SUCCESS;
281 int cac_SamOpenUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
282 struct SamOpenUser *op )
284 struct rpc_pipe_client *pipe_hnd = NULL;
286 uint32 *rid_buf = NULL;
288 uint32 num_rids = 0;
289 uint32 *rid_types = NULL;
291 POLICY_HND *user_out = NULL;
293 if ( !hnd )
294 return CAC_FAILURE;
296 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
297 hnd->status = NT_STATUS_INVALID_HANDLE;
298 return CAC_FAILURE;
301 if ( !op || !op->in.dom_hnd || op->in.access == 0 || !mem_ctx ) {
302 hnd->status = NT_STATUS_INVALID_PARAMETER;
303 return CAC_FAILURE;
306 if ( op->in.rid == 0 && op->in.name == NULL ) {
307 hnd->status = NT_STATUS_INVALID_PARAMETER;
308 return CAC_FAILURE;
311 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
312 if ( !pipe_hnd ) {
313 hnd->status = NT_STATUS_INVALID_HANDLE;
314 return CAC_FAILURE;
317 if ( op->in.rid == 0 && op->in.name ) {
318 /*lookup the name and then set rid_buf */
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 );
328 if ( !NT_STATUS_IS_OK( hnd->status ) )
329 return CAC_FAILURE;
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;
337 TALLOC_FREE( rid_types );
339 } else {
340 rid_buf = &op->in.rid;
343 user_out = talloc( mem_ctx, POLICY_HND );
344 if ( !user_out ) {
345 hnd->status = NT_STATUS_NO_MEMORY;
346 return CAC_FAILURE;
349 hnd->status =
350 rpccli_samr_open_user( pipe_hnd, mem_ctx, op->in.dom_hnd,
351 op->in.access, *rid_buf, user_out );
353 if ( !NT_STATUS_IS_OK( hnd->status ) )
354 return CAC_FAILURE;
356 op->out.user_hnd = user_out;
358 return CAC_SUCCESS;
361 int cac_SamCreateUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
362 struct SamCreateUser *op )
364 struct rpc_pipe_client *pipe_hnd = NULL;
366 POLICY_HND *user_out = NULL;
367 uint32 rid_out;
369 /**found in rpcclient/cmd_samr.c*/
370 uint32 unknown = 0xe005000b;
372 if ( !hnd )
373 return CAC_FAILURE;
375 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
376 hnd->status = NT_STATUS_INVALID_HANDLE;
377 return CAC_FAILURE;
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;
386 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
387 if ( !pipe_hnd ) {
388 hnd->status = NT_STATUS_INVALID_HANDLE;
389 return CAC_FAILURE;
392 user_out = talloc( mem_ctx, POLICY_HND );
393 if ( !user_out ) {
394 hnd->status = NT_STATUS_NO_MEMORY;
395 return CAC_FAILURE;
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 );
404 if ( !NT_STATUS_IS_OK( hnd->status ) )
405 return CAC_FAILURE;
407 op->out.user_hnd = user_out;
408 op->out.rid = rid_out;
410 return CAC_SUCCESS;
413 int cac_SamDeleteUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
414 POLICY_HND * user_hnd )
416 struct rpc_pipe_client *pipe_hnd = NULL;
418 if ( !hnd )
419 return CAC_FAILURE;
421 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
422 hnd->status = NT_STATUS_INVALID_HANDLE;
423 return CAC_FAILURE;
426 if ( !user_hnd || !mem_ctx ) {
427 hnd->status = NT_STATUS_INVALID_PARAMETER;
428 return CAC_FAILURE;
431 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
432 if ( !pipe_hnd ) {
433 hnd->status = NT_STATUS_INVALID_HANDLE;
434 return CAC_FAILURE;
437 hnd->status =
438 rpccli_samr_delete_dom_user( pipe_hnd, mem_ctx, user_hnd );
440 if ( !NT_STATUS_IS_OK( hnd->status ) )
441 return CAC_FAILURE;
443 return CAC_SUCCESS;
446 int cac_SamEnumUsers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
447 struct SamEnumUsers *op )
449 struct rpc_pipe_client *pipe_hnd = NULL;
451 uint32 resume_idx_out = 0;
452 char **names_out = NULL;
453 uint32 *rids_out = NULL;
454 uint32 num_users_out = 0;
456 if ( !hnd )
457 return CAC_FAILURE;
459 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
460 hnd->status = NT_STATUS_INVALID_HANDLE;
461 return CAC_FAILURE;
464 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
465 hnd->status = NT_STATUS_INVALID_PARAMETER;
466 return CAC_FAILURE;
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;
473 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
474 if ( !pipe_hnd ) {
475 hnd->status = NT_STATUS_INVALID_HANDLE;
476 return CAC_FAILURE;
479 resume_idx_out = op->out.resume_idx;
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 );
488 if ( NT_STATUS_IS_OK( hnd->status ) )
489 op->out.done = True;
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;
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;
503 return CAC_SUCCESS;
506 int cac_SamGetNamesFromRids( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
507 struct SamGetNamesFromRids *op )
509 struct rpc_pipe_client *pipe_hnd = NULL;
511 uint32 num_names_out;
512 char **names_out;
513 uint32 *name_types_out;
516 uint32 i = 0;
518 CacLookupRidsRecord *map_out;
520 if ( !hnd )
521 return CAC_FAILURE;
523 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
524 hnd->status = NT_STATUS_INVALID_HANDLE;
525 return CAC_FAILURE;
528 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
529 hnd->status = NT_STATUS_INVALID_PARAMETER;
530 return CAC_FAILURE;
533 if ( !op->in.rids && op->in.num_rids != 0 ) {
534 hnd->status = NT_STATUS_INVALID_PARAMETER;
535 return CAC_FAILURE;
538 if ( op->in.num_rids == 0 ) {
539 /*nothing to do */
540 op->out.num_names = 0;
541 return CAC_SUCCESS;
544 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
545 if ( !pipe_hnd ) {
546 hnd->status = NT_STATUS_INVALID_HANDLE;
547 return CAC_FAILURE;
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 );
556 if ( !NT_STATUS_IS_OK( hnd->status )
557 && !NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
558 return CAC_FAILURE;
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;
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];
577 map_out[i].rid = op->in.rids[i];
580 TALLOC_FREE( names_out );
581 TALLOC_FREE( name_types_out );
583 op->out.num_names = num_names_out;
584 op->out.map = map_out;
586 if ( NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
587 return CAC_PARTIAL_SUCCESS;
589 return CAC_SUCCESS;
592 int cac_SamGetRidsFromNames( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
593 struct SamGetRidsFromNames *op )
595 struct rpc_pipe_client *pipe_hnd = NULL;
597 uint32 num_rids_out;
598 uint32 *rids_out;
599 uint32 *rid_types_out;
601 uint32 i = 0;
603 CacLookupRidsRecord *map_out;
605 if ( !hnd )
606 return CAC_FAILURE;
608 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
609 hnd->status = NT_STATUS_INVALID_HANDLE;
610 return CAC_FAILURE;
613 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
614 hnd->status = NT_STATUS_INVALID_PARAMETER;
615 return CAC_FAILURE;
618 if ( !op->in.names && op->in.num_names != 0 ) {
619 hnd->status = NT_STATUS_INVALID_PARAMETER;
620 return CAC_FAILURE;
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;
629 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
630 if ( !pipe_hnd ) {
631 hnd->status = NT_STATUS_INVALID_HANDLE;
632 return CAC_FAILURE;
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 );
642 if ( !NT_STATUS_IS_OK( hnd->status )
643 && !NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
644 return CAC_FAILURE;
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;
652 for ( i = 0; i < num_rids_out; i++ ) {
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];
664 map_out[i].name = talloc_strdup( mem_ctx, op->in.names[i] );
667 op->out.num_rids = num_rids_out;
668 op->out.map = map_out;
670 TALLOC_FREE( rids_out );
671 TALLOC_FREE( rid_types_out );
673 if ( NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
674 return CAC_PARTIAL_SUCCESS;
676 return CAC_SUCCESS;
680 int cac_SamGetGroupsForUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
681 struct SamGetGroupsForUser *op )
683 struct rpc_pipe_client *pipe_hnd = NULL;
685 DOM_GID *groups = NULL;
686 uint32 num_groups_out = 0;
688 uint32 *rids_out = NULL;
689 uint32 *attr_out = NULL;
691 uint32 i;
693 if ( !hnd )
694 return CAC_FAILURE;
696 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
697 hnd->status = NT_STATUS_INVALID_HANDLE;
698 return CAC_FAILURE;
701 if ( !op || !op->in.user_hnd || !mem_ctx ) {
702 hnd->status = NT_STATUS_INVALID_PARAMETER;
703 return CAC_FAILURE;
706 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
707 if ( !pipe_hnd ) {
708 hnd->status = NT_STATUS_INVALID_HANDLE;
709 return CAC_FAILURE;
712 hnd->status =
713 rpccli_samr_query_usergroups( pipe_hnd, mem_ctx,
714 op->in.user_hnd,
715 &num_groups_out, &groups );
717 if ( !NT_STATUS_IS_OK( hnd->status ) )
718 return CAC_FAILURE;
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;
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;
733 for ( i = 0; i < num_groups_out; i++ ) {
734 rids_out[i] = groups[i].g_rid;
735 attr_out[i] = groups[i].attr;
738 TALLOC_FREE( groups );
740 op->out.num_groups = num_groups_out;
741 op->out.rids = rids_out;
742 op->out.attributes = attr_out;
744 return CAC_SUCCESS;
748 int cac_SamOpenGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
749 struct SamOpenGroup *op )
751 struct rpc_pipe_client *pipe_hnd = NULL;
753 POLICY_HND *group_hnd_out = NULL;
755 if ( !hnd )
756 return CAC_FAILURE;
758 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
759 hnd->status = NT_STATUS_INVALID_HANDLE;
760 return CAC_FAILURE;
763 if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
764 hnd->status = NT_STATUS_INVALID_PARAMETER;
765 return CAC_FAILURE;
768 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
769 if ( !pipe_hnd ) {
770 hnd->status = NT_STATUS_INVALID_HANDLE;
771 return CAC_FAILURE;
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;
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 );
785 if ( !NT_STATUS_IS_OK( hnd->status ) )
786 return CAC_FAILURE;
788 op->out.group_hnd = group_hnd_out;
790 return CAC_SUCCESS;
793 int cac_SamCreateGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
794 struct SamCreateGroup *op )
796 struct rpc_pipe_client *pipe_hnd = NULL;
798 POLICY_HND *group_hnd_out = NULL;
800 if ( !hnd )
801 return CAC_FAILURE;
803 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
804 hnd->status = NT_STATUS_INVALID_HANDLE;
805 return CAC_FAILURE;
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;
814 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
815 if ( !pipe_hnd ) {
816 hnd->status = NT_STATUS_INVALID_HANDLE;
817 return CAC_FAILURE;
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;
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 );
831 if ( !NT_STATUS_IS_OK( hnd->status ) )
832 return CAC_FAILURE;
834 op->out.group_hnd = group_hnd_out;
836 return CAC_SUCCESS;
840 int cac_SamDeleteGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
841 POLICY_HND * group_hnd )
843 struct rpc_pipe_client *pipe_hnd = NULL;
845 if ( !hnd )
846 return CAC_FAILURE;
848 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
849 hnd->status = NT_STATUS_INVALID_HANDLE;
850 return CAC_FAILURE;
853 if ( !group_hnd || !mem_ctx ) {
854 hnd->status = NT_STATUS_INVALID_PARAMETER;
855 return CAC_FAILURE;
858 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
859 if ( !pipe_hnd ) {
860 hnd->status = NT_STATUS_INVALID_HANDLE;
861 return CAC_FAILURE;
864 hnd->status =
865 rpccli_samr_delete_dom_group( pipe_hnd, mem_ctx, group_hnd );
867 if ( !NT_STATUS_IS_OK( hnd->status ) )
868 return CAC_FAILURE;
870 return CAC_SUCCESS;
874 int cac_SamGetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
875 struct SamGetGroupMembers *op )
877 struct rpc_pipe_client *pipe_hnd = NULL;
879 uint32 num_mem_out;
880 uint32 *rids_out;
881 uint32 *attr_out;
883 if ( !hnd )
884 return CAC_FAILURE;
886 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
887 hnd->status = NT_STATUS_INVALID_HANDLE;
888 return CAC_FAILURE;
891 if ( !op || !op->in.group_hnd || !mem_ctx ) {
892 hnd->status = NT_STATUS_INVALID_PARAMETER;
893 return CAC_FAILURE;
896 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
897 if ( !pipe_hnd ) {
898 hnd->status = NT_STATUS_INVALID_HANDLE;
899 return CAC_FAILURE;
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 );
907 if ( !NT_STATUS_IS_OK( hnd->status ) )
908 return CAC_FAILURE;
910 op->out.num_members = num_mem_out;
911 op->out.rids = rids_out;
912 op->out.attributes = attr_out;
914 return CAC_SUCCESS;
918 int cac_SamAddGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
919 struct SamAddGroupMember *op )
921 struct rpc_pipe_client *pipe_hnd = NULL;
923 if ( !hnd )
924 return CAC_FAILURE;
926 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
927 hnd->status = NT_STATUS_INVALID_HANDLE;
928 return CAC_FAILURE;
931 if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
932 hnd->status = NT_STATUS_INVALID_PARAMETER;
933 return CAC_FAILURE;
936 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
937 if ( !pipe_hnd ) {
938 hnd->status = NT_STATUS_INVALID_HANDLE;
939 return CAC_FAILURE;
942 hnd->status =
943 rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
944 op->in.rid );
946 if ( !NT_STATUS_IS_OK( hnd->status ) )
947 return CAC_FAILURE;
949 return CAC_SUCCESS;
952 int cac_SamRemoveGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
953 struct SamRemoveGroupMember *op )
955 struct rpc_pipe_client *pipe_hnd = NULL;
957 if ( !hnd )
958 return CAC_FAILURE;
960 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
961 hnd->status = NT_STATUS_INVALID_HANDLE;
962 return CAC_FAILURE;
965 if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
966 hnd->status = NT_STATUS_INVALID_PARAMETER;
967 return CAC_FAILURE;
970 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
971 if ( !pipe_hnd ) {
972 hnd->status = NT_STATUS_INVALID_HANDLE;
973 return CAC_FAILURE;
976 hnd->status =
977 rpccli_samr_del_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
978 op->in.rid );
980 if ( !NT_STATUS_IS_OK( hnd->status ) )
981 return CAC_FAILURE;
983 return CAC_SUCCESS;
986 int cac_SamClearGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
987 POLICY_HND * group_hnd )
989 struct rpc_pipe_client *pipe_hnd = NULL;
991 int result = CAC_SUCCESS;
993 int i = 0;
995 uint32 num_mem = 0;
996 uint32 *rid = NULL;
997 uint32 *attr = NULL;
999 NTSTATUS status;
1001 if ( !hnd )
1002 return CAC_FAILURE;
1004 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1005 hnd->status = NT_STATUS_INVALID_HANDLE;
1006 return CAC_FAILURE;
1009 if ( !group_hnd || !mem_ctx ) {
1010 hnd->status = NT_STATUS_INVALID_PARAMETER;
1011 return CAC_FAILURE;
1014 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1015 if ( !pipe_hnd ) {
1016 hnd->status = NT_STATUS_INVALID_HANDLE;
1017 return CAC_FAILURE;
1020 hnd->status =
1021 rpccli_samr_query_groupmem( pipe_hnd, mem_ctx, group_hnd,
1022 &num_mem, &rid, &attr );
1024 if ( !NT_STATUS_IS_OK( hnd->status ) )
1025 return CAC_FAILURE;
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] );
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;
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] );
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;
1049 TALLOC_FREE( attr );
1051 return result;
1054 int cac_SamSetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1055 struct SamSetGroupMembers *op )
1057 struct rpc_pipe_client *pipe_hnd = NULL;
1059 uint32 i = 0;
1061 if ( !hnd )
1062 return CAC_FAILURE;
1064 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1065 hnd->status = NT_STATUS_INVALID_HANDLE;
1066 return CAC_FAILURE;
1069 if ( !op || !op->in.group_hnd || !mem_ctx ) {
1070 hnd->status = NT_STATUS_INVALID_PARAMETER;
1071 return CAC_FAILURE;
1074 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1075 if ( !pipe_hnd ) {
1076 hnd->status = NT_STATUS_INVALID_HANDLE;
1077 return CAC_FAILURE;
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 */
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] );
1093 if ( !NT_STATUS_IS_OK( hnd->status ) )
1094 return CAC_FAILURE;
1096 return CAC_SUCCESS;
1100 int cac_SamEnumGroups( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1101 struct SamEnumGroups *op )
1103 struct rpc_pipe_client *pipe_hnd = NULL;
1105 uint32 i = 0;
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;
1113 struct acct_info *acct_buf = NULL;
1115 if ( !hnd )
1116 return CAC_FAILURE;
1118 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1119 hnd->status = NT_STATUS_INVALID_HANDLE;
1120 return CAC_FAILURE;
1123 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
1124 hnd->status = NT_STATUS_INVALID_PARAMETER;
1125 return CAC_FAILURE;
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;
1132 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1133 if ( !pipe_hnd ) {
1134 hnd->status = NT_STATUS_INVALID_HANDLE;
1135 return CAC_FAILURE;
1138 resume_idx_out = op->out.resume_idx;
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 );
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;
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;
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;
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;
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;
1186 if ( !names_out[i] || !desc_out[i] ) {
1187 hnd->status = NT_STATUS_NO_MEMORY;
1188 return CAC_FAILURE;
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;
1198 return CAC_SUCCESS;
1201 int cac_SamEnumAliases( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1202 struct SamEnumAliases *op )
1204 struct rpc_pipe_client *pipe_hnd = NULL;
1206 uint32 i = 0;
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;
1214 struct acct_info *acct_buf = NULL;
1216 if ( !hnd )
1217 return CAC_FAILURE;
1219 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1220 hnd->status = NT_STATUS_INVALID_HANDLE;
1221 return CAC_FAILURE;
1224 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
1225 hnd->status = NT_STATUS_INVALID_PARAMETER;
1226 return CAC_FAILURE;
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;
1234 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1235 if ( !pipe_hnd ) {
1236 hnd->status = NT_STATUS_INVALID_HANDLE;
1237 return CAC_FAILURE;
1240 resume_idx_out = op->out.resume_idx;
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 );
1249 if ( NT_STATUS_IS_OK( hnd->status ) )
1250 op->out.done = True;
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;
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;
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;
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;
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;
1289 if ( !names_out[i] || !desc_out[i] ) {
1290 hnd->status = NT_STATUS_NO_MEMORY;
1291 return CAC_FAILURE;
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;
1301 return CAC_SUCCESS;
1304 int cac_SamCreateAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1305 struct SamCreateAlias *op )
1307 struct rpc_pipe_client *pipe_hnd = NULL;
1309 POLICY_HND *als_hnd_out = NULL;
1311 if ( !hnd )
1312 return CAC_FAILURE;
1314 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1315 hnd->status = NT_STATUS_INVALID_HANDLE;
1316 return CAC_FAILURE;
1319 if ( !op || !op->in.name || op->in.name[0] == '\0' || !mem_ctx ) {
1320 hnd->status = NT_STATUS_INVALID_PARAMETER;
1321 return CAC_FAILURE;
1324 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1325 if ( !pipe_hnd ) {
1326 hnd->status = NT_STATUS_INVALID_HANDLE;
1327 return CAC_FAILURE;
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;
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 );
1341 if ( !NT_STATUS_IS_OK( hnd->status ) )
1342 return CAC_FAILURE;
1344 op->out.alias_hnd = als_hnd_out;
1346 return CAC_SUCCESS;
1350 int cac_SamOpenAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1351 struct SamOpenAlias *op )
1353 struct rpc_pipe_client *pipe_hnd = NULL;
1355 POLICY_HND *als_hnd_out = NULL;
1357 if ( !hnd )
1358 return CAC_FAILURE;
1360 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1361 hnd->status = NT_STATUS_INVALID_HANDLE;
1362 return CAC_FAILURE;
1365 if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
1366 hnd->status = NT_STATUS_INVALID_PARAMETER;
1367 return CAC_FAILURE;
1370 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1371 if ( !pipe_hnd ) {
1372 hnd->status = NT_STATUS_INVALID_HANDLE;
1373 return CAC_FAILURE;
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;
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 );
1387 if ( !NT_STATUS_IS_OK( hnd->status ) )
1388 return CAC_FAILURE;
1390 op->out.alias_hnd = als_hnd_out;
1392 return CAC_SUCCESS;
1395 int cac_SamDeleteAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1396 POLICY_HND * alias_hnd )
1398 struct rpc_pipe_client *pipe_hnd = NULL;
1400 if ( !hnd )
1401 return CAC_FAILURE;
1403 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1404 hnd->status = NT_STATUS_INVALID_HANDLE;
1405 return CAC_FAILURE;
1408 if ( !alias_hnd || !mem_ctx ) {
1409 hnd->status = NT_STATUS_INVALID_PARAMETER;
1410 return CAC_FAILURE;
1413 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1414 if ( !pipe_hnd ) {
1415 hnd->status = NT_STATUS_INVALID_HANDLE;
1416 return CAC_FAILURE;
1419 hnd->status =
1420 rpccli_samr_delete_dom_alias( pipe_hnd, mem_ctx, alias_hnd );
1422 if ( !NT_STATUS_IS_OK( hnd->status ) )
1423 return CAC_FAILURE;
1425 return CAC_SUCCESS;
1429 int cac_SamAddAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1430 struct SamAddAliasMember *op )
1432 struct rpc_pipe_client *pipe_hnd = NULL;
1434 if ( !hnd )
1435 return CAC_FAILURE;
1437 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1438 hnd->status = NT_STATUS_INVALID_HANDLE;
1439 return CAC_FAILURE;
1442 if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
1443 hnd->status = NT_STATUS_INVALID_PARAMETER;
1444 return CAC_FAILURE;
1447 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1448 if ( !pipe_hnd ) {
1449 hnd->status = NT_STATUS_INVALID_HANDLE;
1450 return CAC_FAILURE;
1453 hnd->status =
1454 rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
1455 op->in.sid );
1457 if ( !NT_STATUS_IS_OK( hnd->status ) )
1458 return CAC_FAILURE;
1460 return CAC_SUCCESS;
1463 int cac_SamRemoveAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1464 struct SamRemoveAliasMember *op )
1466 struct rpc_pipe_client *pipe_hnd = NULL;
1468 if ( !hnd )
1469 return CAC_FAILURE;
1471 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1472 hnd->status = NT_STATUS_INVALID_HANDLE;
1473 return CAC_FAILURE;
1476 if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
1477 hnd->status = NT_STATUS_INVALID_PARAMETER;
1478 return CAC_FAILURE;
1481 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1482 if ( !pipe_hnd ) {
1483 hnd->status = NT_STATUS_INVALID_HANDLE;
1484 return CAC_FAILURE;
1487 hnd->status =
1488 rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
1489 op->in.sid );
1491 if ( !NT_STATUS_IS_OK( hnd->status ) )
1492 return CAC_FAILURE;
1494 return CAC_SUCCESS;
1497 int cac_SamGetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1498 struct SamGetAliasMembers *op )
1500 struct rpc_pipe_client *pipe_hnd = NULL;
1502 uint32 num_mem_out;
1503 DOM_SID *sids_out;
1505 if ( !hnd )
1506 return CAC_FAILURE;
1508 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1509 hnd->status = NT_STATUS_INVALID_HANDLE;
1510 return CAC_FAILURE;
1513 if ( !op || !op->in.alias_hnd || !mem_ctx ) {
1514 hnd->status = NT_STATUS_INVALID_PARAMETER;
1515 return CAC_FAILURE;
1518 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1519 if ( !pipe_hnd ) {
1520 hnd->status = NT_STATUS_INVALID_HANDLE;
1521 return CAC_FAILURE;
1524 hnd->status =
1525 rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx,
1526 op->in.alias_hnd, &num_mem_out,
1527 &sids_out );
1529 if ( !NT_STATUS_IS_OK( hnd->status ) )
1530 return CAC_FAILURE;
1532 op->out.num_members = num_mem_out;
1533 op->out.sids = sids_out;
1535 return CAC_SUCCESS;
1538 int cac_SamClearAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1539 POLICY_HND * alias_hnd )
1541 struct rpc_pipe_client *pipe_hnd = NULL;
1543 int result = CAC_SUCCESS;
1545 int i = 0;
1547 uint32 num_mem = 0;
1548 DOM_SID *sid = NULL;
1550 NTSTATUS status;
1552 if ( !hnd )
1553 return CAC_FAILURE;
1555 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1556 hnd->status = NT_STATUS_INVALID_HANDLE;
1557 return CAC_FAILURE;
1560 if ( !alias_hnd || !mem_ctx ) {
1561 hnd->status = NT_STATUS_INVALID_PARAMETER;
1562 return CAC_FAILURE;
1565 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1566 if ( !pipe_hnd ) {
1567 hnd->status = NT_STATUS_INVALID_HANDLE;
1568 return CAC_FAILURE;
1571 hnd->status =
1572 rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx, alias_hnd,
1573 &num_mem, &sid );
1575 if ( !NT_STATUS_IS_OK( hnd->status ) )
1576 return CAC_FAILURE;
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] );
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;
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] );
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;
1600 TALLOC_FREE( sid );
1601 return result;
1604 int cac_SamSetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1605 struct SamSetAliasMembers *op )
1607 struct rpc_pipe_client *pipe_hnd = NULL;
1609 uint32 i = 0;
1611 if ( !hnd )
1612 return CAC_FAILURE;
1614 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1615 hnd->status = NT_STATUS_INVALID_HANDLE;
1616 return CAC_FAILURE;
1619 if ( !op || !op->in.alias_hnd || !mem_ctx ) {
1620 hnd->status = NT_STATUS_INVALID_PARAMETER;
1621 return CAC_FAILURE;
1624 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1625 if ( !pipe_hnd ) {
1626 hnd->status = NT_STATUS_INVALID_HANDLE;
1627 return CAC_FAILURE;
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 */
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] ) );
1643 if ( !NT_STATUS_IS_OK( hnd->status ) )
1644 return CAC_FAILURE;
1646 return CAC_SUCCESS;
1650 int cac_SamUserChangePasswd( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1651 struct SamUserChangePasswd *op )
1653 SMBCSRV *srv = NULL;
1654 struct rpc_pipe_client *pipe_hnd = NULL;
1656 if ( !hnd )
1657 return CAC_FAILURE;
1659 if ( !hnd->_internal.ctx ) {
1660 hnd->status = NT_STATUS_INVALID_HANDLE;
1661 return CAC_FAILURE;
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;
1670 srv = cac_GetServer( hnd );
1671 if ( !srv ) {
1672 hnd->status = NT_STATUS_INVALID_CONNECTION;
1673 return CAC_FAILURE;
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;
1685 hnd->_internal.pipes[PI_SAMR] = True;
1688 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1689 if ( !pipe_hnd ) {
1690 hnd->status = NT_STATUS_INVALID_HANDLE;
1691 return CAC_FAILURE;
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 );
1700 if ( !NT_STATUS_IS_OK( hnd->status ) )
1701 return CAC_FAILURE;
1703 return CAC_SUCCESS;
1706 int cac_SamEnableUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1707 POLICY_HND * user_hnd )
1709 SMBCSRV *srv = NULL;
1710 struct rpc_pipe_client *pipe_hnd = NULL;
1712 SAM_USERINFO_CTR *ctr;
1714 if ( !hnd )
1715 return CAC_FAILURE;
1717 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1718 hnd->status = NT_STATUS_INVALID_HANDLE;
1719 return CAC_FAILURE;
1722 if ( !user_hnd || !mem_ctx ) {
1723 hnd->status = NT_STATUS_INVALID_PARAMETER;
1724 return CAC_FAILURE;
1727 srv = cac_GetServer( hnd );
1728 if ( !srv ) {
1729 hnd->status = NT_STATUS_INVALID_CONNECTION;
1730 return CAC_FAILURE;
1733 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1734 if ( !pipe_hnd ) {
1735 hnd->status = NT_STATUS_INVALID_HANDLE;
1736 return CAC_FAILURE;
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 );
1744 if ( !NT_STATUS_IS_OK( hnd->status ) )
1745 return CAC_FAILURE;
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;
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 );
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;
1765 return CAC_SUCCESS;
1768 int cac_SamDisableUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1769 POLICY_HND * user_hnd )
1771 SMBCSRV *srv = NULL;
1772 struct rpc_pipe_client *pipe_hnd = NULL;
1774 SAM_USERINFO_CTR *ctr;
1776 if ( !hnd )
1777 return CAC_FAILURE;
1779 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1780 hnd->status = NT_STATUS_INVALID_HANDLE;
1781 return CAC_FAILURE;
1784 if ( !user_hnd || !mem_ctx ) {
1785 hnd->status = NT_STATUS_INVALID_PARAMETER;
1786 return CAC_FAILURE;
1789 srv = cac_GetServer( hnd );
1790 if ( !srv ) {
1791 hnd->status = NT_STATUS_INVALID_CONNECTION;
1792 return CAC_FAILURE;
1795 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1796 if ( !pipe_hnd ) {
1797 hnd->status = NT_STATUS_INVALID_HANDLE;
1798 return CAC_FAILURE;
1801 hnd->status =
1802 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10,
1803 &ctr );
1805 if ( !NT_STATUS_IS_OK( hnd->status ) )
1806 return CAC_FAILURE;
1808 if ( ( ctr->info.id16->acb_info & ACB_DISABLED ) == ACB_DISABLED ) {
1809 /*then the user is already disabled */
1810 return CAC_SUCCESS;
1813 /*toggle the disabled bit */
1814 ctr->info.id16->acb_info ^= ACB_DISABLED;
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 );
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;
1825 return CAC_SUCCESS;
1828 int cac_SamSetPassword( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1829 struct SamSetPassword *op )
1831 SMBCSRV *srv = NULL;
1832 struct rpc_pipe_client *pipe_hnd = NULL;
1834 SAM_USERINFO_CTR ctr;
1835 SAM_USER_INFO_24 info24;
1836 uint8 pw[516];
1838 if ( !hnd )
1839 return CAC_FAILURE;
1841 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1842 hnd->status = NT_STATUS_INVALID_HANDLE;
1843 return CAC_FAILURE;
1846 if ( !op->in.user_hnd || !op->in.password || !mem_ctx ) {
1847 hnd->status = NT_STATUS_INVALID_PARAMETER;
1848 return CAC_FAILURE;
1851 srv = cac_GetServer( hnd );
1852 if ( !srv ) {
1853 hnd->status = NT_STATUS_INVALID_CONNECTION;
1854 return CAC_FAILURE;
1857 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1858 if ( !pipe_hnd ) {
1859 hnd->status = NT_STATUS_INVALID_HANDLE;
1860 return CAC_FAILURE;
1863 ZERO_STRUCT( ctr );
1864 ZERO_STRUCT( info24 );
1866 encode_pw_buffer( pw, op->in.password, STR_UNICODE );
1868 init_sam_user_info24( &info24, ( char * ) pw, 24 );
1870 ctr.switch_value = 24;
1871 ctr.info.id24 = &info24;
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 );
1878 if ( !NT_STATUS_IS_OK( hnd->status ) )
1879 return CAC_FAILURE;
1881 return CAC_SUCCESS;
1884 int cac_SamGetUserInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1885 struct SamGetUserInfo *op )
1887 struct rpc_pipe_client *pipe_hnd = NULL;
1889 SAM_USERINFO_CTR *ctr;
1891 if ( !hnd )
1892 return CAC_FAILURE;
1894 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1895 hnd->status = NT_STATUS_INVALID_HANDLE;
1896 return CAC_FAILURE;
1899 if ( !op->in.user_hnd || !mem_ctx ) {
1900 hnd->status = NT_STATUS_INVALID_PARAMETER;
1901 return CAC_FAILURE;
1904 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1905 if ( !pipe_hnd ) {
1906 hnd->status = NT_STATUS_INVALID_HANDLE;
1907 return CAC_FAILURE;
1910 hnd->status =
1911 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
1912 op->in.user_hnd, 21, &ctr );
1914 if ( !NT_STATUS_IS_OK( hnd->status ) )
1915 return CAC_FAILURE;
1917 op->out.info = cac_MakeUserInfo( mem_ctx, ctr );
1919 if ( !op->out.info ) {
1920 hnd->status = NT_STATUS_NO_MEMORY;
1921 return CAC_FAILURE;
1924 return CAC_SUCCESS;
1927 int cac_SamSetUserInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1928 struct SamSetUserInfo *op )
1930 SMBCSRV *srv = NULL;
1931 struct rpc_pipe_client *pipe_hnd = NULL;
1933 SAM_USERINFO_CTR *ctr;
1935 if ( !hnd )
1936 return CAC_FAILURE;
1938 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1939 hnd->status = NT_STATUS_INVALID_HANDLE;
1940 return CAC_FAILURE;
1943 if ( !op->in.user_hnd || !op->in.info || !mem_ctx ) {
1944 hnd->status = NT_STATUS_INVALID_PARAMETER;
1945 return CAC_FAILURE;
1948 ctr = cac_MakeUserInfoCtr( mem_ctx, op->in.info );
1949 if ( !ctr ) {
1950 hnd->status = NT_STATUS_NO_MEMORY;
1951 return CAC_FAILURE;
1954 srv = cac_GetServer( hnd );
1955 if ( !srv ) {
1956 hnd->status = NT_STATUS_INVALID_CONNECTION;
1957 return CAC_FAILURE;
1960 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1961 if ( !pipe_hnd ) {
1962 hnd->status = NT_STATUS_INVALID_HANDLE;
1963 return CAC_FAILURE;
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 );
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 );
1982 if ( NT_STATUS_IS_OK( hnd->status )
1983 && hnd->_internal.srv_level > SRV_WIN_NT4 ) {
1984 hnd->_internal.srv_level = SRV_WIN_NT4;
1989 if ( !NT_STATUS_IS_OK( hnd->status ) )
1990 return CAC_FAILURE;
1992 return CAC_SUCCESS;
1996 int cac_SamGetUserInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1997 struct SamGetUserInfoCtr *op )
1999 struct rpc_pipe_client *pipe_hnd = NULL;
2001 SAM_USERINFO_CTR *ctr_out;
2003 if ( !hnd )
2004 return CAC_FAILURE;
2006 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2007 hnd->status = NT_STATUS_INVALID_HANDLE;
2008 return CAC_FAILURE;
2011 if ( !op->in.user_hnd || op->in.info_class == 0 || !mem_ctx ) {
2012 hnd->status = NT_STATUS_INVALID_PARAMETER;
2013 return CAC_FAILURE;
2016 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2017 if ( !pipe_hnd ) {
2018 hnd->status = NT_STATUS_INVALID_HANDLE;
2019 return CAC_FAILURE;
2022 hnd->status =
2023 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
2024 op->in.user_hnd,
2025 op->in.info_class, &ctr_out );
2027 if ( !NT_STATUS_IS_OK( hnd->status ) )
2028 return CAC_FAILURE;
2030 op->out.ctr = ctr_out;
2032 return CAC_SUCCESS;
2035 int cac_SamSetUserInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2036 struct SamSetUserInfoCtr *op )
2038 SMBCSRV *srv = NULL;
2039 struct rpc_pipe_client *pipe_hnd = NULL;
2041 if ( !hnd )
2042 return CAC_FAILURE;
2044 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2045 hnd->status = NT_STATUS_INVALID_HANDLE;
2046 return CAC_FAILURE;
2049 if ( !op->in.user_hnd || !op->in.ctr || !mem_ctx ) {
2050 hnd->status = NT_STATUS_INVALID_PARAMETER;
2051 return CAC_FAILURE;
2054 srv = cac_GetServer( hnd );
2055 if ( !srv ) {
2056 hnd->status = NT_STATUS_INVALID_CONNECTION;
2057 return CAC_FAILURE;
2060 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2061 if ( !pipe_hnd ) {
2062 hnd->status = NT_STATUS_INVALID_HANDLE;
2063 return CAC_FAILURE;
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 );
2073 if ( !NT_STATUS_IS_OK( hnd->status ) )
2074 return CAC_FAILURE;
2076 return CAC_SUCCESS;
2080 int cac_SamRenameUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2081 struct SamRenameUser *op )
2083 SMBCSRV *srv = NULL;
2084 struct rpc_pipe_client *pipe_hnd = NULL;
2086 SAM_USERINFO_CTR ctr;
2087 SAM_USER_INFO_7 info7;
2089 if ( !hnd )
2090 return CAC_FAILURE;
2092 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2093 hnd->status = NT_STATUS_INVALID_HANDLE;
2094 return CAC_FAILURE;
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;
2103 srv = cac_GetServer( hnd );
2104 if ( !srv ) {
2105 hnd->status = NT_STATUS_INVALID_CONNECTION;
2106 return CAC_FAILURE;
2109 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2110 if ( !pipe_hnd ) {
2111 hnd->status = NT_STATUS_INVALID_HANDLE;
2112 return CAC_FAILURE;
2115 ZERO_STRUCT( ctr );
2116 ZERO_STRUCT( info7 );
2118 init_sam_user_info7( &info7, op->in.new_name );
2120 ctr.switch_value = 7;
2121 ctr.info.id7 = &info7;
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 );
2128 if ( !NT_STATUS_IS_OK( hnd->status ) )
2129 return CAC_FAILURE;
2131 return CAC_SUCCESS;
2135 int cac_SamGetGroupInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2136 struct SamGetGroupInfo *op )
2138 struct rpc_pipe_client *pipe_hnd = NULL;
2140 GROUP_INFO_CTR *ctr;
2142 if ( !hnd )
2143 return CAC_FAILURE;
2145 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2146 hnd->status = NT_STATUS_INVALID_HANDLE;
2147 return CAC_FAILURE;
2150 if ( !op->in.group_hnd || !mem_ctx ) {
2151 hnd->status = NT_STATUS_INVALID_PARAMETER;
2152 return CAC_FAILURE;
2155 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2156 if ( !pipe_hnd ) {
2157 hnd->status = NT_STATUS_INVALID_HANDLE;
2158 return CAC_FAILURE;
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 );
2167 if ( !NT_STATUS_IS_OK( hnd->status ) )
2168 return CAC_FAILURE;
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;
2176 return CAC_SUCCESS;
2179 int cac_SamSetGroupInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2180 struct SamSetGroupInfo *op )
2182 struct rpc_pipe_client *pipe_hnd = NULL;
2184 GROUP_INFO_CTR *ctr = NULL;
2186 if ( !hnd )
2187 return CAC_FAILURE;
2189 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2190 hnd->status = NT_STATUS_INVALID_HANDLE;
2191 return CAC_FAILURE;
2194 if ( !op->in.group_hnd || !op->in.info || !mem_ctx ) {
2195 hnd->status = NT_STATUS_INVALID_PARAMETER;
2196 return CAC_FAILURE;
2199 ctr = cac_MakeGroupInfoCtr( mem_ctx, op->in.info );
2200 if ( !ctr ) {
2201 hnd->status = NT_STATUS_NO_MEMORY;
2202 return CAC_FAILURE;
2205 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2206 if ( !pipe_hnd ) {
2207 hnd->status = NT_STATUS_INVALID_HANDLE;
2208 return CAC_FAILURE;
2211 hnd->status =
2212 rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
2213 op->in.group_hnd, ctr );
2215 if ( !NT_STATUS_IS_OK( hnd->status ) )
2216 return CAC_FAILURE;
2218 return CAC_SUCCESS;
2221 int cac_SamRenameGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2222 struct SamRenameGroup *op )
2224 struct rpc_pipe_client *pipe_hnd = NULL;
2226 GROUP_INFO_CTR ctr;
2228 if ( !hnd )
2229 return CAC_FAILURE;
2231 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2232 hnd->status = NT_STATUS_INVALID_HANDLE;
2233 return CAC_FAILURE;
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;
2242 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2243 if ( !pipe_hnd ) {
2244 hnd->status = NT_STATUS_INVALID_HANDLE;
2245 return CAC_FAILURE;
2248 ZERO_STRUCT( ctr );
2250 init_samr_group_info2( &ctr.group.info2, op->in.new_name );
2251 ctr.switch_value1 = 2;
2253 hnd->status =
2254 rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
2255 op->in.group_hnd, &ctr );
2257 if ( !NT_STATUS_IS_OK( hnd->status ) )
2258 return CAC_FAILURE;
2260 return CAC_SUCCESS;
2263 int cac_SamGetAliasInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2264 struct SamGetAliasInfo *op )
2266 struct rpc_pipe_client *pipe_hnd = NULL;
2268 ALIAS_INFO_CTR ctr;
2270 if ( !hnd )
2271 return CAC_FAILURE;
2273 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2274 hnd->status = NT_STATUS_INVALID_HANDLE;
2275 return CAC_FAILURE;
2278 if ( !op->in.alias_hnd || !mem_ctx ) {
2279 hnd->status = NT_STATUS_INVALID_PARAMETER;
2280 return CAC_FAILURE;
2283 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2284 if ( !pipe_hnd ) {
2285 hnd->status = NT_STATUS_INVALID_HANDLE;
2286 return CAC_FAILURE;
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 );
2294 if ( !NT_STATUS_IS_OK( hnd->status ) )
2295 return CAC_FAILURE;
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;
2303 return CAC_SUCCESS;
2307 int cac_SamSetAliasInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2308 struct SamSetAliasInfo *op )
2310 struct rpc_pipe_client *pipe_hnd = NULL;
2312 ALIAS_INFO_CTR *ctr = NULL;
2314 if ( !hnd )
2315 return CAC_FAILURE;
2317 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2318 hnd->status = NT_STATUS_INVALID_HANDLE;
2319 return CAC_FAILURE;
2322 if ( !op->in.alias_hnd || !op->in.info || !mem_ctx ) {
2323 hnd->status = NT_STATUS_INVALID_PARAMETER;
2324 return CAC_FAILURE;
2327 ctr = cac_MakeAliasInfoCtr( mem_ctx, op->in.info );
2328 if ( !ctr ) {
2329 hnd->status = NT_STATUS_NO_MEMORY;
2330 return CAC_FAILURE;
2333 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2334 if ( !pipe_hnd ) {
2335 hnd->status = NT_STATUS_INVALID_HANDLE;
2336 return CAC_FAILURE;
2339 hnd->status =
2340 rpccli_samr_set_aliasinfo( pipe_hnd, mem_ctx,
2341 op->in.alias_hnd, ctr );
2343 if ( !NT_STATUS_IS_OK( hnd->status ) )
2344 return CAC_FAILURE;
2346 return CAC_SUCCESS;
2349 int cac_SamGetDomainInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2350 struct SamGetDomainInfo *op )
2352 struct rpc_pipe_client *pipe_hnd = NULL;
2354 SAM_UNK_CTR ctr;
2355 SAM_UNK_INFO_1 info1;
2356 SAM_UNK_INFO_2 info2;
2357 SAM_UNK_INFO_12 info12;
2359 /*use this to keep track of a failed call */
2360 NTSTATUS status_buf = NT_STATUS_OK;
2362 uint16 fail_count = 0;
2365 if ( !hnd )
2366 return CAC_FAILURE;
2368 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2369 hnd->status = NT_STATUS_INVALID_HANDLE;
2370 return CAC_FAILURE;
2373 if ( !op->in.dom_hnd || !mem_ctx ) {
2374 hnd->status = NT_STATUS_INVALID_PARAMETER;
2375 return CAC_FAILURE;
2378 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2379 if ( !pipe_hnd ) {
2380 hnd->status = NT_STATUS_INVALID_HANDLE;
2381 return CAC_FAILURE;
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 );
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++;
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 );
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++;
2414 /*once more */
2415 hnd->status =
2416 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2417 12, &ctr );
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++;
2427 /*return failure if all 3 calls failed */
2428 if ( fail_count == 3 )
2429 return CAC_FAILURE;
2431 op->out.info = cac_MakeDomainInfo( mem_ctx, &info1, &info2, &info12 );
2433 if ( !op->out.info ) {
2434 hnd->status = NT_STATUS_NO_MEMORY;
2435 return CAC_FAILURE;
2438 if ( fail_count > 0 ) {
2439 hnd->status = status_buf;
2440 return CAC_PARTIAL_SUCCESS;
2443 return CAC_SUCCESS;
2446 int cac_SamGetDomainInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2447 struct SamGetDomainInfoCtr *op )
2449 struct rpc_pipe_client *pipe_hnd = NULL;
2451 SAM_UNK_CTR *ctr_out;
2453 if ( !hnd )
2454 return CAC_FAILURE;
2456 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2457 hnd->status = NT_STATUS_INVALID_HANDLE;
2458 return CAC_FAILURE;
2461 if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
2462 hnd->status = NT_STATUS_INVALID_PARAMETER;
2463 return CAC_FAILURE;
2466 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2467 if ( !pipe_hnd ) {
2468 hnd->status = NT_STATUS_INVALID_HANDLE;
2469 return CAC_FAILURE;
2472 ctr_out = talloc( mem_ctx, SAM_UNK_CTR );
2473 if ( !ctr_out ) {
2474 hnd->status = NT_STATUS_NO_MEMORY;
2475 return CAC_FAILURE;
2478 hnd->status =
2479 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2480 op->in.info_class, ctr_out );
2482 if ( !NT_STATUS_IS_OK( hnd->status ) )
2483 return CAC_FAILURE;
2485 op->out.info = ctr_out;
2487 return CAC_SUCCESS;
2490 int cac_SamGetDisplayInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2491 struct SamGetDisplayInfo *op )
2493 struct rpc_pipe_client *pipe_hnd = NULL;
2495 SAM_DISPINFO_CTR ctr_out;
2497 uint32 max_entries_buf = 0;
2498 uint32 max_size_buf = 0;
2500 uint32 resume_idx_out;
2501 uint32 num_entries_out;
2503 if ( !hnd )
2504 return CAC_FAILURE;
2506 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2507 hnd->status = NT_STATUS_INVALID_HANDLE;
2508 return CAC_FAILURE;
2511 if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
2512 hnd->status = NT_STATUS_INVALID_PARAMETER;
2513 return CAC_FAILURE;
2516 if ( op->out.done == True ) /*this is done so we can use the function as a loop condition */
2517 return CAC_FAILURE;
2519 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2520 if ( !pipe_hnd ) {
2521 hnd->status = NT_STATUS_INVALID_HANDLE;
2522 return CAC_FAILURE;
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;
2533 resume_idx_out = op->out.resume_idx;
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 );
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;
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;
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++;
2560 return CAC_SUCCESS;
2563 int cac_SamLookupDomain( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2564 struct SamLookupDomain *op )
2566 struct rpc_pipe_client *pipe_hnd = NULL;
2568 DOM_SID *sid_out = NULL;
2570 if ( !hnd )
2571 return CAC_FAILURE;
2573 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2574 hnd->status = NT_STATUS_INVALID_HANDLE;
2575 return CAC_FAILURE;
2578 if ( !op->in.sam || !op->in.name || !mem_ctx ) {
2579 hnd->status = NT_STATUS_INVALID_PARAMETER;
2580 return CAC_FAILURE;
2583 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2584 if ( !pipe_hnd ) {
2585 hnd->status = NT_STATUS_INVALID_HANDLE;
2586 return CAC_FAILURE;
2589 sid_out = talloc( mem_ctx, DOM_SID );
2590 if ( !sid_out ) {
2591 hnd->status = NT_STATUS_NO_MEMORY;
2592 return CAC_FAILURE;
2595 hnd->status =
2596 rpccli_samr_lookup_domain( pipe_hnd, mem_ctx, op->in.sam,
2597 op->in.name, sid_out );
2599 if ( !NT_STATUS_IS_OK( hnd->status ) )
2600 return CAC_FAILURE;
2602 op->out.sid = sid_out;
2604 return CAC_SUCCESS;
2607 int cac_SamGetSecurityObject( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2608 struct SamGetSecurityObject *op )
2610 struct rpc_pipe_client *pipe_hnd = NULL;
2612 /*this number taken from rpcclient/cmd_samr.c, I think it is the only supported level */
2613 uint32 sec_info = DACL_SECURITY_INFORMATION;
2615 SEC_DESC_BUF *sec_out = NULL;
2617 if ( !hnd )
2618 return CAC_FAILURE;
2620 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2621 hnd->status = NT_STATUS_INVALID_HANDLE;
2622 return CAC_FAILURE;
2625 if ( !op->in.pol || !mem_ctx ) {
2626 hnd->status = NT_STATUS_INVALID_PARAMETER;
2627 return CAC_FAILURE;
2630 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2631 if ( !pipe_hnd ) {
2632 hnd->status = NT_STATUS_INVALID_HANDLE;
2633 return CAC_FAILURE;
2636 hnd->status =
2637 rpccli_samr_query_sec_obj( pipe_hnd, mem_ctx, op->in.pol,
2638 sec_info, mem_ctx, &sec_out );
2640 if ( !NT_STATUS_IS_OK( hnd->status ) )
2641 return CAC_FAILURE;
2643 op->out.sec = sec_out;
2645 return CAC_SUCCESS;
2648 int cac_SamFlush( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2649 struct SamFlush *op )
2651 struct SamOpenDomain od;
2653 if ( !hnd )
2654 return CAC_FAILURE;
2656 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2657 hnd->status = NT_STATUS_INVALID_HANDLE;
2658 return CAC_FAILURE;
2661 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
2662 hnd->status = NT_STATUS_INVALID_PARAMETER;
2663 return CAC_FAILURE;
2666 if ( !cac_SamClose( hnd, mem_ctx, op->in.dom_hnd ) )
2667 return CAC_FAILURE;
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;
2674 if ( !cac_SamOpenDomain( hnd, mem_ctx, &od ) )
2675 return CAC_FAILURE;
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;
2680 TALLOC_FREE( od.out.dom_hnd );
2682 return CAC_SUCCESS;