3 * Unix SMB/CIFS implementation.
4 * MS-RPC client library implementation (SAMR pipe)
5 * Copyright (C) Chris Nicholls 2005.
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.
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,
36 int cac_SamConnect( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
37 struct SamConnect *op )
40 struct rpc_pipe_client *pipe_hnd = NULL;
41 POLICY_HND *sam_out = NULL;
46 if ( !hnd->_internal.ctx ) {
47 hnd->status = NT_STATUS_INVALID_HANDLE;
51 if ( !op || op->in.access == 0 || !mem_ctx ) {
52 hnd->status = NT_STATUS_INVALID_PARAMETER;
56 srv = cac_GetServer( hnd );
58 hnd->status = NT_STATUS_INVALID_CONNECTION;
62 /*initialize for samr pipe if we have to */
63 if ( !hnd->_internal.pipes[PI_SAMR] ) {
66 cli_rpc_pipe_open_noauth( srv->cli, PI_SAMR,
71 hnd->_internal.pipes[PI_SAMR] = True;
74 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
76 hnd->status = NT_STATUS_INVALID_HANDLE;
80 sam_out = talloc( mem_ctx, POLICY_HND );
82 hnd->status = NT_STATUS_NO_MEMORY;
86 if ( hnd->_internal.srv_level >= SRV_WIN_2K_SP3 ) {
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 */
97 rpccli_samr_connect( pipe_hnd, mem_ctx, op->in.access,
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 ) )
109 op->out.sam = sam_out;
114 int cac_SamClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
117 struct rpc_pipe_client *pipe_hnd = NULL;
122 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
123 hnd->status = NT_STATUS_INVALID_HANDLE;
127 if ( !sam || !mem_ctx ) {
128 hnd->status = NT_STATUS_INVALID_PARAMETER;
132 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
134 hnd->status = NT_STATUS_INVALID_HANDLE;
138 hnd->status = rpccli_samr_close( pipe_hnd, mem_ctx, sam );
140 if ( !NT_STATUS_IS_OK( hnd->status ) )
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,
154 struct LsaOpenPolicy lop;
155 struct LsaFetchSid fs;
162 lop.in.access = des_access;
163 lop.in.security_qos = True;
165 if ( !cac_LsaOpenPolicy( hnd, mem_ctx, &lop ) )
168 fs.in.pol = lop.out.pol;
169 fs.in.info_class = CAC_DOMAIN_INFO;
171 if ( !cac_LsaFetchSid( hnd, mem_ctx, &fs ) )
174 cac_LsaClosePolicy( hnd, mem_ctx, lop.out.pol );
176 if ( !fs.out.domain_sid )
179 sid = ( DOM_SID * ) TALLOC_MEMDUP( mem_ctx,
180 &( fs.out.domain_sid->sid ),
184 hnd->status = NT_STATUS_NO_MEMORY;
191 int cac_SamOpenDomain( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
192 struct SamOpenDomain *op )
194 struct rpc_pipe_client *pipe_hnd = NULL;
200 struct SamLookupDomain sld;
205 if ( !hnd->_internal.ctx ) {
206 hnd->status = NT_STATUS_INVALID_HANDLE;
210 if ( !op || op->in.access == 0 || !mem_ctx ) {
211 hnd->status = NT_STATUS_INVALID_PARAMETER;
216 /*use cac_SamConnect() since it does the session setup */
217 struct SamConnect sc;
221 sc.in.access = op->in.access;
223 if ( !cac_SamConnect( hnd, mem_ctx, &sc ) ) {
227 sam_out = sc.out.sam;
229 sam_out = op->in.sam;
233 /*find the sid for the SAM's domain */
235 /*try using cac_SamLookupDomain() first */
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;
245 /*try to get it from the LSA */
247 cac_get_domain_sid( hnd, mem_ctx,
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 );
257 hnd->status = NT_STATUS_INVALID_HANDLE;
261 pol_out = talloc( mem_ctx, POLICY_HND );
263 hnd->status = NT_STATUS_NO_MEMORY;
267 /*now open the domain */
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 ) )
275 op->out.sam = sam_out;
276 op->out.dom_hnd = pol_out;
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;
289 uint32 *rid_types = NULL;
291 POLICY_HND *user_out = NULL;
296 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
297 hnd->status = NT_STATUS_INVALID_HANDLE;
301 if ( !op || !op->in.dom_hnd || op->in.access == 0 || !mem_ctx ) {
302 hnd->status = NT_STATUS_INVALID_PARAMETER;
306 if ( op->in.rid == 0 && op->in.name == NULL ) {
307 hnd->status = NT_STATUS_INVALID_PARAMETER;
311 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
313 hnd->status = NT_STATUS_INVALID_HANDLE;
317 if ( op->in.rid == 0 && op->in.name ) {
318 /*lookup the name and then set rid_buf */
321 rpccli_samr_lookup_names( pipe_hnd, mem_ctx,
323 SAMR_LOOKUP_FLAGS, 1,
324 ( const char ** ) &op->in.
325 name, &num_rids, &rid_buf,
328 if ( !NT_STATUS_IS_OK( hnd->status ) )
331 if ( num_rids == 0 || rid_buf == NULL
332 || rid_types[0] == SAMR_RID_UNKNOWN ) {
333 hnd->status = NT_STATUS_INVALID_PARAMETER;
337 TALLOC_FREE( rid_types );
340 rid_buf = &op->in.rid;
343 user_out = talloc( mem_ctx, POLICY_HND );
345 hnd->status = NT_STATUS_NO_MEMORY;
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 ) )
356 op->out.user_hnd = user_out;
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;
369 /**found in rpcclient/cmd_samr.c*/
370 uint32 unknown = 0xe005000b;
375 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
376 hnd->status = NT_STATUS_INVALID_HANDLE;
380 if ( !op || !op->in.dom_hnd || !op->in.name || op->in.acb_mask == 0
382 hnd->status = NT_STATUS_INVALID_PARAMETER;
386 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
388 hnd->status = NT_STATUS_INVALID_HANDLE;
392 user_out = talloc( mem_ctx, POLICY_HND );
394 hnd->status = NT_STATUS_NO_MEMORY;
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 ) )
407 op->out.user_hnd = user_out;
408 op->out.rid = rid_out;
413 int cac_SamDeleteUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
414 POLICY_HND * user_hnd )
416 struct rpc_pipe_client *pipe_hnd = NULL;
421 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
422 hnd->status = NT_STATUS_INVALID_HANDLE;
426 if ( !user_hnd || !mem_ctx ) {
427 hnd->status = NT_STATUS_INVALID_PARAMETER;
431 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
433 hnd->status = NT_STATUS_INVALID_HANDLE;
438 rpccli_samr_delete_dom_user( pipe_hnd, mem_ctx, user_hnd );
440 if ( !NT_STATUS_IS_OK( hnd->status ) )
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;
459 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
460 hnd->status = NT_STATUS_INVALID_HANDLE;
464 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
465 hnd->status = NT_STATUS_INVALID_PARAMETER;
469 /*this is a hack.. but is the only reliable way to know if everything has been enumerated */
470 if ( op->out.done == True )
473 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
475 hnd->status = NT_STATUS_INVALID_HANDLE;
479 resume_idx_out = op->out.resume_idx;
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 ) )
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 ) )
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;
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;
513 uint32 *name_types_out;
518 CacLookupRidsRecord *map_out;
523 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
524 hnd->status = NT_STATUS_INVALID_HANDLE;
528 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
529 hnd->status = NT_STATUS_INVALID_PARAMETER;
533 if ( !op->in.rids && op->in.num_rids != 0 ) {
534 hnd->status = NT_STATUS_INVALID_PARAMETER;
538 if ( op->in.num_rids == 0 ) {
540 op->out.num_names = 0;
544 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
546 hnd->status = NT_STATUS_INVALID_HANDLE;
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,
556 if ( !NT_STATUS_IS_OK( hnd->status )
557 && !NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
560 map_out = TALLOC_ARRAY( mem_ctx, CacLookupRidsRecord, num_names_out );
562 hnd->status = NT_STATUS_NO_MEMORY;
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;
572 map_out[i].found = True;
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;
592 int cac_SamGetRidsFromNames( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
593 struct SamGetRidsFromNames *op )
595 struct rpc_pipe_client *pipe_hnd = NULL;
599 uint32 *rid_types_out;
603 CacLookupRidsRecord *map_out;
608 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
609 hnd->status = NT_STATUS_INVALID_HANDLE;
613 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
614 hnd->status = NT_STATUS_INVALID_PARAMETER;
618 if ( !op->in.names && op->in.num_names != 0 ) {
619 hnd->status = NT_STATUS_INVALID_PARAMETER;
623 if ( op->in.num_names == 0 ) {
624 /*then we don't have to do anything */
625 op->out.num_rids = 0;
629 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
631 hnd->status = NT_STATUS_INVALID_HANDLE;
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,
642 if ( !NT_STATUS_IS_OK( hnd->status )
643 && !NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
646 map_out = TALLOC_ARRAY( mem_ctx, CacLookupRidsRecord, num_rids_out );
648 hnd->status = NT_STATUS_NO_MEMORY;
652 for ( i = 0; i < num_rids_out; i++ ) {
654 if ( rid_types_out[i] == SAMR_RID_UNKNOWN ) {
655 map_out[i].found = False;
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;
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;
696 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
697 hnd->status = NT_STATUS_INVALID_HANDLE;
701 if ( !op || !op->in.user_hnd || !mem_ctx ) {
702 hnd->status = NT_STATUS_INVALID_PARAMETER;
706 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
708 hnd->status = NT_STATUS_INVALID_HANDLE;
713 rpccli_samr_query_usergroups( pipe_hnd, mem_ctx,
715 &num_groups_out, &groups );
717 if ( !NT_STATUS_IS_OK( hnd->status ) )
721 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
723 hnd->status = NT_STATUS_NO_MEMORY;
727 attr_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
729 hnd->status = NT_STATUS_NO_MEMORY;
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;
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;
758 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
759 hnd->status = NT_STATUS_INVALID_HANDLE;
763 if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
764 hnd->status = NT_STATUS_INVALID_PARAMETER;
768 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
770 hnd->status = NT_STATUS_INVALID_HANDLE;
774 group_hnd_out = talloc( mem_ctx, POLICY_HND );
775 if ( !group_hnd_out ) {
776 hnd->status = NT_STATUS_NO_MEMORY;
781 rpccli_samr_open_group( pipe_hnd, mem_ctx, op->in.dom_hnd,
782 op->in.access, op->in.rid,
785 if ( !NT_STATUS_IS_OK( hnd->status ) )
788 op->out.group_hnd = group_hnd_out;
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;
803 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
804 hnd->status = NT_STATUS_INVALID_HANDLE;
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;
814 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
816 hnd->status = NT_STATUS_INVALID_HANDLE;
820 group_hnd_out = talloc( mem_ctx, POLICY_HND );
821 if ( !group_hnd_out ) {
822 hnd->status = NT_STATUS_NO_MEMORY;
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 ) )
834 op->out.group_hnd = group_hnd_out;
840 int cac_SamDeleteGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
841 POLICY_HND * group_hnd )
843 struct rpc_pipe_client *pipe_hnd = NULL;
848 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
849 hnd->status = NT_STATUS_INVALID_HANDLE;
853 if ( !group_hnd || !mem_ctx ) {
854 hnd->status = NT_STATUS_INVALID_PARAMETER;
858 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
860 hnd->status = NT_STATUS_INVALID_HANDLE;
865 rpccli_samr_delete_dom_group( pipe_hnd, mem_ctx, group_hnd );
867 if ( !NT_STATUS_IS_OK( hnd->status ) )
874 int cac_SamGetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
875 struct SamGetGroupMembers *op )
877 struct rpc_pipe_client *pipe_hnd = NULL;
886 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
887 hnd->status = NT_STATUS_INVALID_HANDLE;
891 if ( !op || !op->in.group_hnd || !mem_ctx ) {
892 hnd->status = NT_STATUS_INVALID_PARAMETER;
896 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
898 hnd->status = NT_STATUS_INVALID_HANDLE;
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 ) )
910 op->out.num_members = num_mem_out;
911 op->out.rids = rids_out;
912 op->out.attributes = attr_out;
918 int cac_SamAddGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
919 struct SamAddGroupMember *op )
921 struct rpc_pipe_client *pipe_hnd = NULL;
926 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
927 hnd->status = NT_STATUS_INVALID_HANDLE;
931 if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
932 hnd->status = NT_STATUS_INVALID_PARAMETER;
936 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
938 hnd->status = NT_STATUS_INVALID_HANDLE;
943 rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
946 if ( !NT_STATUS_IS_OK( hnd->status ) )
952 int cac_SamRemoveGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
953 struct SamRemoveGroupMember *op )
955 struct rpc_pipe_client *pipe_hnd = NULL;
960 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
961 hnd->status = NT_STATUS_INVALID_HANDLE;
965 if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
966 hnd->status = NT_STATUS_INVALID_PARAMETER;
970 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
972 hnd->status = NT_STATUS_INVALID_HANDLE;
977 rpccli_samr_del_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
980 if ( !NT_STATUS_IS_OK( hnd->status ) )
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;
1004 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1005 hnd->status = NT_STATUS_INVALID_HANDLE;
1009 if ( !group_hnd || !mem_ctx ) {
1010 hnd->status = NT_STATUS_INVALID_PARAMETER;
1014 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1016 hnd->status = NT_STATUS_INVALID_HANDLE;
1021 rpccli_samr_query_groupmem( pipe_hnd, mem_ctx, group_hnd,
1022 &num_mem, &rid, &attr );
1024 if ( !NT_STATUS_IS_OK( hnd->status ) )
1027 /*try to delete the users one by one */
1028 for ( i = 0; i < num_mem && NT_STATUS_IS_OK( hnd->status ); i++ ) {
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,
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 );
1054 int cac_SamSetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1055 struct SamSetGroupMembers *op )
1057 struct rpc_pipe_client *pipe_hnd = NULL;
1064 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1065 hnd->status = NT_STATUS_INVALID_HANDLE;
1069 if ( !op || !op->in.group_hnd || !mem_ctx ) {
1070 hnd->status = NT_STATUS_INVALID_PARAMETER;
1074 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1076 hnd->status = NT_STATUS_INVALID_HANDLE;
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 );
1088 rpccli_samr_add_groupmem( pipe_hnd, mem_ctx,
1093 if ( !NT_STATUS_IS_OK( hnd->status ) )
1100 int cac_SamEnumGroups( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1101 struct SamEnumGroups *op )
1103 struct rpc_pipe_client *pipe_hnd = NULL;
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;
1118 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1119 hnd->status = NT_STATUS_INVALID_HANDLE;
1123 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
1124 hnd->status = NT_STATUS_INVALID_PARAMETER;
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 */
1132 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1134 hnd->status = NT_STATUS_INVALID_HANDLE;
1138 resume_idx_out = op->out.resume_idx;
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,
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*/
1156 names_out = TALLOC_ARRAY( mem_ctx, char *, num_groups_out );
1158 hnd->status = NT_STATUS_NO_MEMORY;
1159 TALLOC_FREE( acct_buf );
1163 desc_out = TALLOC_ARRAY( mem_ctx, char *, num_groups_out );
1165 hnd->status = NT_STATUS_NO_MEMORY;
1166 TALLOC_FREE( acct_buf );
1167 TALLOC_FREE( names_out );
1171 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
1173 hnd->status = NT_STATUS_NO_MEMORY;
1174 TALLOC_FREE( acct_buf );
1175 TALLOC_FREE( names_out );
1176 TALLOC_FREE( desc_out );
1180 for ( i = 0; i < num_groups_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;
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;
1201 int cac_SamEnumAliases( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1202 struct SamEnumAliases *op )
1204 struct rpc_pipe_client *pipe_hnd = NULL;
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;
1219 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1220 hnd->status = NT_STATUS_INVALID_HANDLE;
1224 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
1225 hnd->status = NT_STATUS_INVALID_PARAMETER;
1229 /*this is a hack.. but is the only reliable way to know if everything has been enumerated */
1230 if ( op->out.done == True ) {
1234 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1236 hnd->status = NT_STATUS_INVALID_HANDLE;
1240 resume_idx_out = op->out.resume_idx;
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,
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 ) )
1259 names_out = TALLOC_ARRAY( mem_ctx, char *, num_als_out );
1261 hnd->status = NT_STATUS_NO_MEMORY;
1262 TALLOC_FREE( acct_buf );
1266 desc_out = TALLOC_ARRAY( mem_ctx, char *, num_als_out );
1268 hnd->status = NT_STATUS_NO_MEMORY;
1269 TALLOC_FREE( acct_buf );
1270 TALLOC_FREE( names_out );
1274 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_als_out );
1276 hnd->status = NT_STATUS_NO_MEMORY;
1277 TALLOC_FREE( acct_buf );
1278 TALLOC_FREE( names_out );
1279 TALLOC_FREE( desc_out );
1283 for ( i = 0; i < num_als_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;
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;
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;
1314 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1315 hnd->status = NT_STATUS_INVALID_HANDLE;
1319 if ( !op || !op->in.name || op->in.name[0] == '\0' || !mem_ctx ) {
1320 hnd->status = NT_STATUS_INVALID_PARAMETER;
1324 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1326 hnd->status = NT_STATUS_INVALID_HANDLE;
1330 als_hnd_out = talloc( mem_ctx, POLICY_HND );
1331 if ( !als_hnd_out ) {
1332 hnd->status = NT_STATUS_NO_MEMORY;
1337 rpccli_samr_create_dom_alias( pipe_hnd, mem_ctx,
1338 op->in.dom_hnd, op->in.name,
1341 if ( !NT_STATUS_IS_OK( hnd->status ) )
1344 op->out.alias_hnd = als_hnd_out;
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;
1360 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1361 hnd->status = NT_STATUS_INVALID_HANDLE;
1365 if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
1366 hnd->status = NT_STATUS_INVALID_PARAMETER;
1370 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1372 hnd->status = NT_STATUS_INVALID_HANDLE;
1376 als_hnd_out = talloc( mem_ctx, POLICY_HND );
1377 if ( !als_hnd_out ) {
1378 hnd->status = NT_STATUS_NO_MEMORY;
1383 rpccli_samr_open_alias( pipe_hnd, mem_ctx, op->in.dom_hnd,
1384 op->in.access, op->in.rid,
1387 if ( !NT_STATUS_IS_OK( hnd->status ) )
1390 op->out.alias_hnd = als_hnd_out;
1395 int cac_SamDeleteAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1396 POLICY_HND * alias_hnd )
1398 struct rpc_pipe_client *pipe_hnd = NULL;
1403 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1404 hnd->status = NT_STATUS_INVALID_HANDLE;
1408 if ( !alias_hnd || !mem_ctx ) {
1409 hnd->status = NT_STATUS_INVALID_PARAMETER;
1413 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1415 hnd->status = NT_STATUS_INVALID_HANDLE;
1420 rpccli_samr_delete_dom_alias( pipe_hnd, mem_ctx, alias_hnd );
1422 if ( !NT_STATUS_IS_OK( hnd->status ) )
1429 int cac_SamAddAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1430 struct SamAddAliasMember *op )
1432 struct rpc_pipe_client *pipe_hnd = NULL;
1437 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1438 hnd->status = NT_STATUS_INVALID_HANDLE;
1442 if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
1443 hnd->status = NT_STATUS_INVALID_PARAMETER;
1447 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1449 hnd->status = NT_STATUS_INVALID_HANDLE;
1454 rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
1457 if ( !NT_STATUS_IS_OK( hnd->status ) )
1463 int cac_SamRemoveAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1464 struct SamRemoveAliasMember *op )
1466 struct rpc_pipe_client *pipe_hnd = NULL;
1471 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1472 hnd->status = NT_STATUS_INVALID_HANDLE;
1476 if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
1477 hnd->status = NT_STATUS_INVALID_PARAMETER;
1481 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1483 hnd->status = NT_STATUS_INVALID_HANDLE;
1488 rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
1491 if ( !NT_STATUS_IS_OK( hnd->status ) )
1497 int cac_SamGetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1498 struct SamGetAliasMembers *op )
1500 struct rpc_pipe_client *pipe_hnd = NULL;
1508 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1509 hnd->status = NT_STATUS_INVALID_HANDLE;
1513 if ( !op || !op->in.alias_hnd || !mem_ctx ) {
1514 hnd->status = NT_STATUS_INVALID_PARAMETER;
1518 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1520 hnd->status = NT_STATUS_INVALID_HANDLE;
1525 rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx,
1526 op->in.alias_hnd, &num_mem_out,
1529 if ( !NT_STATUS_IS_OK( hnd->status ) )
1532 op->out.num_members = num_mem_out;
1533 op->out.sids = sids_out;
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;
1548 DOM_SID *sid = NULL;
1555 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1556 hnd->status = NT_STATUS_INVALID_HANDLE;
1560 if ( !alias_hnd || !mem_ctx ) {
1561 hnd->status = NT_STATUS_INVALID_PARAMETER;
1565 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1567 hnd->status = NT_STATUS_INVALID_HANDLE;
1572 rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx, alias_hnd,
1575 if ( !NT_STATUS_IS_OK( hnd->status ) )
1578 /*try to delete the users one by one */
1579 for ( i = 0; i < num_mem && NT_STATUS_IS_OK( hnd->status ); i++ ) {
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,
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;
1604 int cac_SamSetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1605 struct SamSetAliasMembers *op )
1607 struct rpc_pipe_client *pipe_hnd = NULL;
1614 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1615 hnd->status = NT_STATUS_INVALID_HANDLE;
1619 if ( !op || !op->in.alias_hnd || !mem_ctx ) {
1620 hnd->status = NT_STATUS_INVALID_PARAMETER;
1624 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1626 hnd->status = NT_STATUS_INVALID_HANDLE;
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 );
1638 rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx,
1640 &( op->in.sids[i] ) );
1643 if ( !NT_STATUS_IS_OK( hnd->status ) )
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;
1659 if ( !hnd->_internal.ctx ) {
1660 hnd->status = NT_STATUS_INVALID_HANDLE;
1664 if ( !op || !op->in.username || !op->in.password
1665 || !op->in.new_password || !mem_ctx ) {
1666 hnd->status = NT_STATUS_INVALID_PARAMETER;
1670 srv = cac_GetServer( hnd );
1672 hnd->status = NT_STATUS_INVALID_CONNECTION;
1676 /*open a session on SAMR if we don't have one */
1677 if ( !hnd->_internal.pipes[PI_SAMR] ) {
1680 cli_rpc_pipe_open_noauth( srv->cli, PI_SAMR,
1681 &hnd->status ) ) ) {
1685 hnd->_internal.pipes[PI_SAMR] = True;
1688 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1690 hnd->status = NT_STATUS_INVALID_HANDLE;
1695 rpccli_samr_chgpasswd_user( pipe_hnd, mem_ctx,
1697 op->in.new_password,
1700 if ( !NT_STATUS_IS_OK( hnd->status ) )
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;
1717 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1718 hnd->status = NT_STATUS_INVALID_HANDLE;
1722 if ( !user_hnd || !mem_ctx ) {
1723 hnd->status = NT_STATUS_INVALID_PARAMETER;
1727 srv = cac_GetServer( hnd );
1729 hnd->status = NT_STATUS_INVALID_CONNECTION;
1733 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1735 hnd->status = NT_STATUS_INVALID_HANDLE;
1739 /*info_level = 21 is the only level that I have found to work reliably. It would be nice if user_level = 10 worked. */
1741 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10,
1744 if ( !NT_STATUS_IS_OK( hnd->status ) )
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;
1752 /*the user is already enabled so just return success */
1756 /*now set the userinfo */
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 ) )
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;
1779 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1780 hnd->status = NT_STATUS_INVALID_HANDLE;
1784 if ( !user_hnd || !mem_ctx ) {
1785 hnd->status = NT_STATUS_INVALID_PARAMETER;
1789 srv = cac_GetServer( hnd );
1791 hnd->status = NT_STATUS_INVALID_CONNECTION;
1795 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1797 hnd->status = NT_STATUS_INVALID_HANDLE;
1802 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10,
1805 if ( !NT_STATUS_IS_OK( hnd->status ) )
1808 if ( ( ctr->info.id16->acb_info & ACB_DISABLED ) == ACB_DISABLED ) {
1809 /*then the user is already disabled */
1813 /*toggle the disabled bit */
1814 ctr->info.id16->acb_info ^= ACB_DISABLED;
1816 /*this will only work properly if we use set_userinfo2 */
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 ) )
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;
1841 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1842 hnd->status = NT_STATUS_INVALID_HANDLE;
1846 if ( !op->in.user_hnd || !op->in.password || !mem_ctx ) {
1847 hnd->status = NT_STATUS_INVALID_PARAMETER;
1851 srv = cac_GetServer( hnd );
1853 hnd->status = NT_STATUS_INVALID_CONNECTION;
1857 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1859 hnd->status = NT_STATUS_INVALID_HANDLE;
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;
1874 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
1875 24, &srv->cli->user_session_key,
1878 if ( !NT_STATUS_IS_OK( hnd->status ) )
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;
1894 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1895 hnd->status = NT_STATUS_INVALID_HANDLE;
1899 if ( !op->in.user_hnd || !mem_ctx ) {
1900 hnd->status = NT_STATUS_INVALID_PARAMETER;
1904 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1906 hnd->status = NT_STATUS_INVALID_HANDLE;
1911 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
1912 op->in.user_hnd, 21, &ctr );
1914 if ( !NT_STATUS_IS_OK( hnd->status ) )
1917 op->out.info = cac_MakeUserInfo( mem_ctx, ctr );
1919 if ( !op->out.info ) {
1920 hnd->status = NT_STATUS_NO_MEMORY;
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;
1938 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1939 hnd->status = NT_STATUS_INVALID_HANDLE;
1943 if ( !op->in.user_hnd || !op->in.info || !mem_ctx ) {
1944 hnd->status = NT_STATUS_INVALID_PARAMETER;
1948 ctr = cac_MakeUserInfoCtr( mem_ctx, op->in.info );
1950 hnd->status = NT_STATUS_NO_MEMORY;
1954 srv = cac_GetServer( hnd );
1956 hnd->status = NT_STATUS_INVALID_CONNECTION;
1960 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1962 hnd->status = NT_STATUS_INVALID_HANDLE;
1966 if ( hnd->_internal.srv_level >= SRV_WIN_NT4 ) {
1968 rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx,
1969 op->in.user_hnd, 21,
1971 user_session_key, ctr );
1974 if ( hnd->_internal.srv_level < SRV_WIN_NT4
1975 || !NT_STATUS_IS_OK( hnd->status ) ) {
1977 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx,
1978 op->in.user_hnd, 21,
1979 &srv->cli->user_session_key,
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 ) )
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;
2006 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2007 hnd->status = NT_STATUS_INVALID_HANDLE;
2011 if ( !op->in.user_hnd || op->in.info_class == 0 || !mem_ctx ) {
2012 hnd->status = NT_STATUS_INVALID_PARAMETER;
2016 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2018 hnd->status = NT_STATUS_INVALID_HANDLE;
2023 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
2025 op->in.info_class, &ctr_out );
2027 if ( !NT_STATUS_IS_OK( hnd->status ) )
2030 op->out.ctr = ctr_out;
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;
2044 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2045 hnd->status = NT_STATUS_INVALID_HANDLE;
2049 if ( !op->in.user_hnd || !op->in.ctr || !mem_ctx ) {
2050 hnd->status = NT_STATUS_INVALID_PARAMETER;
2054 srv = cac_GetServer( hnd );
2056 hnd->status = NT_STATUS_INVALID_CONNECTION;
2060 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2062 hnd->status = NT_STATUS_INVALID_HANDLE;
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,
2073 if ( !NT_STATUS_IS_OK( hnd->status ) )
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;
2092 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2093 hnd->status = NT_STATUS_INVALID_HANDLE;
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;
2103 srv = cac_GetServer( hnd );
2105 hnd->status = NT_STATUS_INVALID_CONNECTION;
2109 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2111 hnd->status = NT_STATUS_INVALID_HANDLE;
2116 ZERO_STRUCT( info7 );
2118 init_sam_user_info7( &info7, op->in.new_name );
2120 ctr.switch_value = 7;
2121 ctr.info.id7 = &info7;
2124 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
2125 7, &srv->cli->user_session_key,
2128 if ( !NT_STATUS_IS_OK( hnd->status ) )
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;
2145 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2146 hnd->status = NT_STATUS_INVALID_HANDLE;
2150 if ( !op->in.group_hnd || !mem_ctx ) {
2151 hnd->status = NT_STATUS_INVALID_PARAMETER;
2155 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2157 hnd->status = NT_STATUS_INVALID_HANDLE;
2162 /*get a GROUP_INFO_1 structure */
2164 rpccli_samr_query_groupinfo( pipe_hnd, mem_ctx,
2165 op->in.group_hnd, 1, &ctr );
2167 if ( !NT_STATUS_IS_OK( hnd->status ) )
2170 op->out.info = cac_MakeGroupInfo( mem_ctx, ctr );
2171 if ( !op->out.info ) {
2172 hnd->status = NT_STATUS_NO_MEMORY;
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;
2189 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2190 hnd->status = NT_STATUS_INVALID_HANDLE;
2194 if ( !op->in.group_hnd || !op->in.info || !mem_ctx ) {
2195 hnd->status = NT_STATUS_INVALID_PARAMETER;
2199 ctr = cac_MakeGroupInfoCtr( mem_ctx, op->in.info );
2201 hnd->status = NT_STATUS_NO_MEMORY;
2205 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2207 hnd->status = NT_STATUS_INVALID_HANDLE;
2212 rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
2213 op->in.group_hnd, ctr );
2215 if ( !NT_STATUS_IS_OK( hnd->status ) )
2221 int cac_SamRenameGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2222 struct SamRenameGroup *op )
2224 struct rpc_pipe_client *pipe_hnd = NULL;
2231 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2232 hnd->status = NT_STATUS_INVALID_HANDLE;
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;
2242 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2244 hnd->status = NT_STATUS_INVALID_HANDLE;
2250 init_samr_group_info2( &ctr.group.info2, op->in.new_name );
2251 ctr.switch_value1 = 2;
2254 rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
2255 op->in.group_hnd, &ctr );
2257 if ( !NT_STATUS_IS_OK( hnd->status ) )
2263 int cac_SamGetAliasInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2264 struct SamGetAliasInfo *op )
2266 struct rpc_pipe_client *pipe_hnd = NULL;
2273 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2274 hnd->status = NT_STATUS_INVALID_HANDLE;
2278 if ( !op->in.alias_hnd || !mem_ctx ) {
2279 hnd->status = NT_STATUS_INVALID_PARAMETER;
2283 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2285 hnd->status = NT_STATUS_INVALID_HANDLE;
2289 /*get a GROUP_INFO_1 structure */
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 ) )
2297 op->out.info = cac_MakeAliasInfo( mem_ctx, ctr );
2298 if ( !op->out.info ) {
2299 hnd->status = NT_STATUS_NO_MEMORY;
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;
2317 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2318 hnd->status = NT_STATUS_INVALID_HANDLE;
2322 if ( !op->in.alias_hnd || !op->in.info || !mem_ctx ) {
2323 hnd->status = NT_STATUS_INVALID_PARAMETER;
2327 ctr = cac_MakeAliasInfoCtr( mem_ctx, op->in.info );
2329 hnd->status = NT_STATUS_NO_MEMORY;
2333 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2335 hnd->status = NT_STATUS_INVALID_HANDLE;
2340 rpccli_samr_set_aliasinfo( pipe_hnd, mem_ctx,
2341 op->in.alias_hnd, ctr );
2343 if ( !NT_STATUS_IS_OK( hnd->status ) )
2349 int cac_SamGetDomainInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2350 struct SamGetDomainInfo *op )
2352 struct rpc_pipe_client *pipe_hnd = NULL;
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;
2368 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2369 hnd->status = NT_STATUS_INVALID_HANDLE;
2373 if ( !op->in.dom_hnd || !mem_ctx ) {
2374 hnd->status = NT_STATUS_INVALID_PARAMETER;
2378 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2380 hnd->status = NT_STATUS_INVALID_HANDLE;
2384 /*first try with info 1 */
2386 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2389 if ( NT_STATUS_IS_OK( hnd->status ) ) {
2390 /*then we buffer the SAM_UNK_INFO_1 structure */
2391 info1 = ctr.info.inf1;
2393 /*then the call failed, store the status and ZERO out the info structure */
2394 ZERO_STRUCT( info1 );
2395 status_buf = hnd->status;
2399 /*try again for the next one */
2401 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2404 if ( NT_STATUS_IS_OK( hnd->status ) ) {
2406 info2 = ctr.info.inf2;
2408 /*ZERO out the structure and store the bad status */
2409 ZERO_STRUCT( info2 );
2410 status_buf = hnd->status;
2416 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2419 if ( NT_STATUS_IS_OK( hnd->status ) ) {
2420 info12 = ctr.info.inf12;
2422 ZERO_STRUCT( info12 );
2423 status_buf = hnd->status;
2427 /*return failure if all 3 calls failed */
2428 if ( fail_count == 3 )
2431 op->out.info = cac_MakeDomainInfo( mem_ctx, &info1, &info2, &info12 );
2433 if ( !op->out.info ) {
2434 hnd->status = NT_STATUS_NO_MEMORY;
2438 if ( fail_count > 0 ) {
2439 hnd->status = status_buf;
2440 return CAC_PARTIAL_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;
2456 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2457 hnd->status = NT_STATUS_INVALID_HANDLE;
2461 if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
2462 hnd->status = NT_STATUS_INVALID_PARAMETER;
2466 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2468 hnd->status = NT_STATUS_INVALID_HANDLE;
2472 ctr_out = talloc( mem_ctx, SAM_UNK_CTR );
2474 hnd->status = NT_STATUS_NO_MEMORY;
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 ) )
2485 op->out.info = ctr_out;
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;
2506 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2507 hnd->status = NT_STATUS_INVALID_HANDLE;
2511 if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
2512 hnd->status = NT_STATUS_INVALID_PARAMETER;
2516 if ( op->out.done == True ) /*this is done so we can use the function as a loop condition */
2519 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2521 hnd->status = NT_STATUS_INVALID_HANDLE;
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 );
2529 max_entries_buf = op->in.max_entries;
2530 max_size_buf = op->in.max_size;
2533 resume_idx_out = op->out.resume_idx;
2536 rpccli_samr_query_dispinfo( pipe_hnd, mem_ctx, op->in.dom_hnd,
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;
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++;
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;
2573 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2574 hnd->status = NT_STATUS_INVALID_HANDLE;
2578 if ( !op->in.sam || !op->in.name || !mem_ctx ) {
2579 hnd->status = NT_STATUS_INVALID_PARAMETER;
2583 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2585 hnd->status = NT_STATUS_INVALID_HANDLE;
2589 sid_out = talloc( mem_ctx, DOM_SID );
2591 hnd->status = NT_STATUS_NO_MEMORY;
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 ) )
2602 op->out.sid = sid_out;
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;
2620 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2621 hnd->status = NT_STATUS_INVALID_HANDLE;
2625 if ( !op->in.pol || !mem_ctx ) {
2626 hnd->status = NT_STATUS_INVALID_PARAMETER;
2630 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2632 hnd->status = NT_STATUS_INVALID_HANDLE;
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 ) )
2643 op->out.sec = sec_out;
2648 int cac_SamFlush( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2649 struct SamFlush *op )
2651 struct SamOpenDomain od;
2656 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2657 hnd->status = NT_STATUS_INVALID_HANDLE;
2661 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
2662 hnd->status = NT_STATUS_INVALID_PARAMETER;
2666 if ( !cac_SamClose( hnd, mem_ctx, op->in.dom_hnd ) )
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 ) )
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 );