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 3 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 ) )
561 map_out = TALLOC_ARRAY( mem_ctx, CacLookupRidsRecord, num_names_out );
563 hnd->status = NT_STATUS_NO_MEMORY;
570 for ( i = 0; i < num_names_out; i++ ) {
571 if ( name_types_out[i] == SAMR_RID_UNKNOWN ) {
572 map_out[i].found = False;
573 map_out[i].name = NULL;
576 map_out[i].found = True;
578 talloc_strdup( mem_ctx, names_out[i] );
579 map_out[i].type = name_types_out[i];
581 map_out[i].rid = op->in.rids[i];
584 TALLOC_FREE( names_out );
585 TALLOC_FREE( name_types_out );
587 op->out.num_names = num_names_out;
588 op->out.map = map_out;
590 if ( NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
591 return CAC_PARTIAL_SUCCESS;
596 int cac_SamGetRidsFromNames( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
597 struct SamGetRidsFromNames *op )
599 struct rpc_pipe_client *pipe_hnd = NULL;
603 uint32 *rid_types_out;
607 CacLookupRidsRecord *map_out;
612 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
613 hnd->status = NT_STATUS_INVALID_HANDLE;
617 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
618 hnd->status = NT_STATUS_INVALID_PARAMETER;
622 if ( !op->in.names && op->in.num_names != 0 ) {
623 hnd->status = NT_STATUS_INVALID_PARAMETER;
627 if ( op->in.num_names == 0 ) {
628 /*then we don't have to do anything */
629 op->out.num_rids = 0;
633 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
635 hnd->status = NT_STATUS_INVALID_HANDLE;
640 rpccli_samr_lookup_names( pipe_hnd, mem_ctx, op->in.dom_hnd,
641 SAMR_LOOKUP_FLAGS, op->in.num_names,
642 ( const char ** ) op->in.names,
643 &num_rids_out, &rids_out,
646 if ( !NT_STATUS_IS_OK( hnd->status )
647 && !NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
651 map_out = TALLOC_ARRAY( mem_ctx, CacLookupRidsRecord, num_rids_out );
653 hnd->status = NT_STATUS_NO_MEMORY;
660 for ( i = 0; i < num_rids_out; i++ ) {
662 if ( rid_types_out[i] == SAMR_RID_UNKNOWN ) {
663 map_out[i].found = False;
667 map_out[i].found = True;
668 map_out[i].rid = rids_out[i];
669 map_out[i].type = rid_types_out[i];
672 map_out[i].name = talloc_strdup( mem_ctx, op->in.names[i] );
675 op->out.num_rids = num_rids_out;
676 op->out.map = map_out;
678 TALLOC_FREE( rids_out );
679 TALLOC_FREE( rid_types_out );
681 if ( NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
682 return CAC_PARTIAL_SUCCESS;
688 int cac_SamGetGroupsForUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
689 struct SamGetGroupsForUser *op )
691 struct rpc_pipe_client *pipe_hnd = NULL;
693 DOM_GID *groups = NULL;
694 uint32 num_groups_out = 0;
696 uint32 *rids_out = NULL;
697 uint32 *attr_out = NULL;
704 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
705 hnd->status = NT_STATUS_INVALID_HANDLE;
709 if ( !op || !op->in.user_hnd || !mem_ctx ) {
710 hnd->status = NT_STATUS_INVALID_PARAMETER;
714 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
716 hnd->status = NT_STATUS_INVALID_HANDLE;
721 rpccli_samr_query_usergroups( pipe_hnd, mem_ctx,
723 &num_groups_out, &groups );
725 if ( !NT_STATUS_IS_OK( hnd->status ) )
729 if (num_groups_out) {
730 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
732 hnd->status = NT_STATUS_NO_MEMORY;
735 attr_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
737 hnd->status = NT_STATUS_NO_MEMORY;
745 for ( i = 0; i < num_groups_out; i++ ) {
746 rids_out[i] = groups[i].g_rid;
747 attr_out[i] = groups[i].attr;
750 TALLOC_FREE( groups );
752 op->out.num_groups = num_groups_out;
753 op->out.rids = rids_out;
754 op->out.attributes = attr_out;
760 int cac_SamOpenGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
761 struct SamOpenGroup *op )
763 struct rpc_pipe_client *pipe_hnd = NULL;
765 POLICY_HND *group_hnd_out = NULL;
770 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
771 hnd->status = NT_STATUS_INVALID_HANDLE;
775 if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
776 hnd->status = NT_STATUS_INVALID_PARAMETER;
780 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
782 hnd->status = NT_STATUS_INVALID_HANDLE;
786 group_hnd_out = talloc( mem_ctx, POLICY_HND );
787 if ( !group_hnd_out ) {
788 hnd->status = NT_STATUS_NO_MEMORY;
793 rpccli_samr_open_group( pipe_hnd, mem_ctx, op->in.dom_hnd,
794 op->in.access, op->in.rid,
797 if ( !NT_STATUS_IS_OK( hnd->status ) )
800 op->out.group_hnd = group_hnd_out;
805 int cac_SamCreateGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
806 struct SamCreateGroup *op )
808 struct rpc_pipe_client *pipe_hnd = NULL;
810 POLICY_HND *group_hnd_out = NULL;
815 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
816 hnd->status = NT_STATUS_INVALID_HANDLE;
820 if ( !op || !op->in.name || op->in.name[0] == '\0'
821 || op->in.access == 0 || !mem_ctx ) {
822 hnd->status = NT_STATUS_INVALID_PARAMETER;
826 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
828 hnd->status = NT_STATUS_INVALID_HANDLE;
832 group_hnd_out = talloc( mem_ctx, POLICY_HND );
833 if ( !group_hnd_out ) {
834 hnd->status = NT_STATUS_NO_MEMORY;
839 rpccli_samr_create_dom_group( pipe_hnd, mem_ctx,
840 op->in.dom_hnd, op->in.name,
841 op->in.access, group_hnd_out );
843 if ( !NT_STATUS_IS_OK( hnd->status ) )
846 op->out.group_hnd = group_hnd_out;
852 int cac_SamDeleteGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
853 POLICY_HND * group_hnd )
855 struct rpc_pipe_client *pipe_hnd = NULL;
860 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
861 hnd->status = NT_STATUS_INVALID_HANDLE;
865 if ( !group_hnd || !mem_ctx ) {
866 hnd->status = NT_STATUS_INVALID_PARAMETER;
870 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
872 hnd->status = NT_STATUS_INVALID_HANDLE;
877 rpccli_samr_delete_dom_group( pipe_hnd, mem_ctx, group_hnd );
879 if ( !NT_STATUS_IS_OK( hnd->status ) )
886 int cac_SamGetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
887 struct SamGetGroupMembers *op )
889 struct rpc_pipe_client *pipe_hnd = NULL;
898 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
899 hnd->status = NT_STATUS_INVALID_HANDLE;
903 if ( !op || !op->in.group_hnd || !mem_ctx ) {
904 hnd->status = NT_STATUS_INVALID_PARAMETER;
908 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
910 hnd->status = NT_STATUS_INVALID_HANDLE;
915 rpccli_samr_query_groupmem( pipe_hnd, mem_ctx,
916 op->in.group_hnd, &num_mem_out,
917 &rids_out, &attr_out );
919 if ( !NT_STATUS_IS_OK( hnd->status ) )
922 op->out.num_members = num_mem_out;
923 op->out.rids = rids_out;
924 op->out.attributes = attr_out;
930 int cac_SamAddGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
931 struct SamAddGroupMember *op )
933 struct rpc_pipe_client *pipe_hnd = NULL;
938 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
939 hnd->status = NT_STATUS_INVALID_HANDLE;
943 if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
944 hnd->status = NT_STATUS_INVALID_PARAMETER;
948 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
950 hnd->status = NT_STATUS_INVALID_HANDLE;
955 rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
958 if ( !NT_STATUS_IS_OK( hnd->status ) )
964 int cac_SamRemoveGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
965 struct SamRemoveGroupMember *op )
967 struct rpc_pipe_client *pipe_hnd = NULL;
972 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
973 hnd->status = NT_STATUS_INVALID_HANDLE;
977 if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
978 hnd->status = NT_STATUS_INVALID_PARAMETER;
982 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
984 hnd->status = NT_STATUS_INVALID_HANDLE;
989 rpccli_samr_del_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
992 if ( !NT_STATUS_IS_OK( hnd->status ) )
998 int cac_SamClearGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
999 POLICY_HND * group_hnd )
1001 struct rpc_pipe_client *pipe_hnd = NULL;
1003 int result = CAC_SUCCESS;
1009 uint32 *attr = NULL;
1016 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1017 hnd->status = NT_STATUS_INVALID_HANDLE;
1021 if ( !group_hnd || !mem_ctx ) {
1022 hnd->status = NT_STATUS_INVALID_PARAMETER;
1026 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1028 hnd->status = NT_STATUS_INVALID_HANDLE;
1033 rpccli_samr_query_groupmem( pipe_hnd, mem_ctx, group_hnd,
1034 &num_mem, &rid, &attr );
1036 if ( !NT_STATUS_IS_OK( hnd->status ) )
1039 /*try to delete the users one by one */
1040 for ( i = 0; i < num_mem && NT_STATUS_IS_OK( hnd->status ); i++ ) {
1042 rpccli_samr_del_groupmem( pipe_hnd, mem_ctx,
1043 group_hnd, rid[i] );
1046 /*if not all members could be removed, then try to re-add the members that were already deleted */
1047 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1048 status = NT_STATUS_OK;
1050 for ( i -= 1; i >= 0 && NT_STATUS_IS_OK( status ); i-- ) {
1051 status = rpccli_samr_add_groupmem( pipe_hnd, mem_ctx,
1056 /*we return with the NTSTATUS error that we got when trying to delete users */
1057 if ( !NT_STATUS_IS_OK( status ) )
1058 result = CAC_FAILURE;
1061 TALLOC_FREE( attr );
1066 int cac_SamSetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1067 struct SamSetGroupMembers *op )
1069 struct rpc_pipe_client *pipe_hnd = NULL;
1076 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1077 hnd->status = NT_STATUS_INVALID_HANDLE;
1081 if ( !op || !op->in.group_hnd || !mem_ctx ) {
1082 hnd->status = NT_STATUS_INVALID_PARAMETER;
1086 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1088 hnd->status = NT_STATUS_INVALID_HANDLE;
1092 /*use cac_SamClearGroupMembers() to clear them */
1093 if ( !cac_SamClearGroupMembers( hnd, mem_ctx, op->in.group_hnd ) )
1094 return CAC_FAILURE; /*hnd->status is already set */
1097 for ( i = 0; i < op->in.num_members && NT_STATUS_IS_OK( hnd->status );
1100 rpccli_samr_add_groupmem( pipe_hnd, mem_ctx,
1105 if ( !NT_STATUS_IS_OK( hnd->status ) )
1112 int cac_SamEnumGroups( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1113 struct SamEnumGroups *op )
1115 struct rpc_pipe_client *pipe_hnd = NULL;
1119 uint32 resume_idx_out = 0;
1120 char **names_out = NULL;
1121 char **desc_out = NULL;
1122 uint32 *rids_out = NULL;
1123 uint32 num_groups_out = 0;
1125 struct acct_info *acct_buf = NULL;
1130 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1131 hnd->status = NT_STATUS_INVALID_HANDLE;
1135 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
1136 hnd->status = NT_STATUS_INVALID_PARAMETER;
1140 /*using this BOOL is the only reliable way to know that we are done */
1141 if ( op->out.done == True ) /*we return failure so the call will break out of a loop */
1144 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1146 hnd->status = NT_STATUS_INVALID_HANDLE;
1150 resume_idx_out = op->out.resume_idx;
1153 rpccli_samr_enum_dom_groups( pipe_hnd, mem_ctx,
1154 op->in.dom_hnd, &resume_idx_out,
1155 SAMR_ENUM_MAX_SIZE, &acct_buf,
1159 if ( NT_STATUS_IS_OK( hnd->status ) ) {
1160 op->out.done = True;
1161 } else if ( NT_STATUS_V( hnd->status ) !=
1162 NT_STATUS_V( STATUS_MORE_ENTRIES ) ) {
1163 /*if there are no more entries, the operation will return NT_STATUS_OK.
1164 * We want to return failure if no results were returned*/
1168 if (num_groups_out) {
1169 names_out = TALLOC_ARRAY( mem_ctx, char *, num_groups_out );
1171 hnd->status = NT_STATUS_NO_MEMORY;
1172 TALLOC_FREE( acct_buf );
1176 desc_out = TALLOC_ARRAY( mem_ctx, char *, num_groups_out );
1178 hnd->status = NT_STATUS_NO_MEMORY;
1179 TALLOC_FREE( acct_buf );
1180 TALLOC_FREE( names_out );
1184 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
1186 hnd->status = NT_STATUS_NO_MEMORY;
1187 TALLOC_FREE( acct_buf );
1188 TALLOC_FREE( names_out );
1189 TALLOC_FREE( desc_out );
1198 for ( i = 0; i < num_groups_out; i++ ) {
1200 talloc_strdup( mem_ctx, acct_buf[i].acct_name );
1201 desc_out[i] = talloc_strdup( mem_ctx, acct_buf[i].acct_desc );
1202 rids_out[i] = acct_buf[i].rid;
1204 if ( !names_out[i] || !desc_out[i] ) {
1205 hnd->status = NT_STATUS_NO_MEMORY;
1210 op->out.resume_idx = resume_idx_out;
1211 op->out.num_groups = num_groups_out;
1212 op->out.rids = rids_out;
1213 op->out.names = names_out;
1214 op->out.descriptions = desc_out;
1219 int cac_SamEnumAliases( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1220 struct SamEnumAliases *op )
1222 struct rpc_pipe_client *pipe_hnd = NULL;
1226 uint32 resume_idx_out = 0;
1227 char **names_out = NULL;
1228 char **desc_out = NULL;
1229 uint32 *rids_out = NULL;
1230 uint32 num_als_out = 0;
1232 struct acct_info *acct_buf = NULL;
1237 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1238 hnd->status = NT_STATUS_INVALID_HANDLE;
1242 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
1243 hnd->status = NT_STATUS_INVALID_PARAMETER;
1247 /*this is a hack.. but is the only reliable way to know if everything has been enumerated */
1248 if ( op->out.done == True ) {
1252 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1254 hnd->status = NT_STATUS_INVALID_HANDLE;
1258 resume_idx_out = op->out.resume_idx;
1261 rpccli_samr_enum_als_groups( pipe_hnd, mem_ctx,
1262 op->in.dom_hnd, &resume_idx_out,
1263 SAMR_ENUM_MAX_SIZE, &acct_buf,
1267 if ( NT_STATUS_IS_OK( hnd->status ) )
1268 op->out.done = True;
1270 /*if there are no more entries, the operation will return NT_STATUS_OK.
1271 * We want to return failure if no results were returned*/
1272 if ( !NT_STATUS_IS_OK( hnd->status )
1273 && NT_STATUS_V( hnd->status ) !=
1274 NT_STATUS_V( STATUS_MORE_ENTRIES ) )
1278 names_out = TALLOC_ARRAY( mem_ctx, char *, num_als_out );
1280 hnd->status = NT_STATUS_NO_MEMORY;
1281 TALLOC_FREE( acct_buf );
1285 desc_out = TALLOC_ARRAY( mem_ctx, char *, num_als_out );
1287 hnd->status = NT_STATUS_NO_MEMORY;
1288 TALLOC_FREE( acct_buf );
1289 TALLOC_FREE( names_out );
1293 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_als_out );
1295 hnd->status = NT_STATUS_NO_MEMORY;
1296 TALLOC_FREE( acct_buf );
1297 TALLOC_FREE( names_out );
1298 TALLOC_FREE( desc_out );
1307 for ( i = 0; i < num_als_out; i++ ) {
1309 talloc_strdup( mem_ctx, acct_buf[i].acct_name );
1310 desc_out[i] = talloc_strdup( mem_ctx, acct_buf[i].acct_desc );
1311 rids_out[i] = acct_buf[i].rid;
1313 if ( !names_out[i] || !desc_out[i] ) {
1314 hnd->status = NT_STATUS_NO_MEMORY;
1319 op->out.resume_idx = resume_idx_out;
1320 op->out.num_aliases = num_als_out;
1321 op->out.rids = rids_out;
1322 op->out.names = names_out;
1323 op->out.descriptions = desc_out;
1328 int cac_SamCreateAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1329 struct SamCreateAlias *op )
1331 struct rpc_pipe_client *pipe_hnd = NULL;
1333 POLICY_HND *als_hnd_out = NULL;
1338 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1339 hnd->status = NT_STATUS_INVALID_HANDLE;
1343 if ( !op || !op->in.name || op->in.name[0] == '\0' || !mem_ctx ) {
1344 hnd->status = NT_STATUS_INVALID_PARAMETER;
1348 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1350 hnd->status = NT_STATUS_INVALID_HANDLE;
1354 als_hnd_out = talloc( mem_ctx, POLICY_HND );
1355 if ( !als_hnd_out ) {
1356 hnd->status = NT_STATUS_NO_MEMORY;
1361 rpccli_samr_create_dom_alias( pipe_hnd, mem_ctx,
1362 op->in.dom_hnd, op->in.name,
1365 if ( !NT_STATUS_IS_OK( hnd->status ) )
1368 op->out.alias_hnd = als_hnd_out;
1374 int cac_SamOpenAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1375 struct SamOpenAlias *op )
1377 struct rpc_pipe_client *pipe_hnd = NULL;
1379 POLICY_HND *als_hnd_out = NULL;
1384 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1385 hnd->status = NT_STATUS_INVALID_HANDLE;
1389 if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
1390 hnd->status = NT_STATUS_INVALID_PARAMETER;
1394 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1396 hnd->status = NT_STATUS_INVALID_HANDLE;
1400 als_hnd_out = talloc( mem_ctx, POLICY_HND );
1401 if ( !als_hnd_out ) {
1402 hnd->status = NT_STATUS_NO_MEMORY;
1407 rpccli_samr_open_alias( pipe_hnd, mem_ctx, op->in.dom_hnd,
1408 op->in.access, op->in.rid,
1411 if ( !NT_STATUS_IS_OK( hnd->status ) )
1414 op->out.alias_hnd = als_hnd_out;
1419 int cac_SamDeleteAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1420 POLICY_HND * alias_hnd )
1422 struct rpc_pipe_client *pipe_hnd = NULL;
1427 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1428 hnd->status = NT_STATUS_INVALID_HANDLE;
1432 if ( !alias_hnd || !mem_ctx ) {
1433 hnd->status = NT_STATUS_INVALID_PARAMETER;
1437 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1439 hnd->status = NT_STATUS_INVALID_HANDLE;
1444 rpccli_samr_delete_dom_alias( pipe_hnd, mem_ctx, alias_hnd );
1446 if ( !NT_STATUS_IS_OK( hnd->status ) )
1453 int cac_SamAddAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1454 struct SamAddAliasMember *op )
1456 struct rpc_pipe_client *pipe_hnd = NULL;
1461 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1462 hnd->status = NT_STATUS_INVALID_HANDLE;
1466 if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
1467 hnd->status = NT_STATUS_INVALID_PARAMETER;
1471 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1473 hnd->status = NT_STATUS_INVALID_HANDLE;
1478 rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
1481 if ( !NT_STATUS_IS_OK( hnd->status ) )
1487 int cac_SamRemoveAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1488 struct SamRemoveAliasMember *op )
1490 struct rpc_pipe_client *pipe_hnd = NULL;
1495 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1496 hnd->status = NT_STATUS_INVALID_HANDLE;
1500 if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
1501 hnd->status = NT_STATUS_INVALID_PARAMETER;
1505 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1507 hnd->status = NT_STATUS_INVALID_HANDLE;
1512 rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
1515 if ( !NT_STATUS_IS_OK( hnd->status ) )
1521 int cac_SamGetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1522 struct SamGetAliasMembers *op )
1524 struct rpc_pipe_client *pipe_hnd = NULL;
1532 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1533 hnd->status = NT_STATUS_INVALID_HANDLE;
1537 if ( !op || !op->in.alias_hnd || !mem_ctx ) {
1538 hnd->status = NT_STATUS_INVALID_PARAMETER;
1542 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1544 hnd->status = NT_STATUS_INVALID_HANDLE;
1549 rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx,
1550 op->in.alias_hnd, &num_mem_out,
1553 if ( !NT_STATUS_IS_OK( hnd->status ) )
1556 op->out.num_members = num_mem_out;
1557 op->out.sids = sids_out;
1562 int cac_SamClearAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1563 POLICY_HND * alias_hnd )
1565 struct rpc_pipe_client *pipe_hnd = NULL;
1567 int result = CAC_SUCCESS;
1572 DOM_SID *sid = NULL;
1579 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1580 hnd->status = NT_STATUS_INVALID_HANDLE;
1584 if ( !alias_hnd || !mem_ctx ) {
1585 hnd->status = NT_STATUS_INVALID_PARAMETER;
1589 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1591 hnd->status = NT_STATUS_INVALID_HANDLE;
1596 rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx, alias_hnd,
1599 if ( !NT_STATUS_IS_OK( hnd->status ) )
1602 /*try to delete the users one by one */
1603 for ( i = 0; i < num_mem && NT_STATUS_IS_OK( hnd->status ); i++ ) {
1605 rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx,
1606 alias_hnd, &sid[i] );
1609 /*if not all members could be removed, then try to re-add the members that were already deleted */
1610 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1611 status = NT_STATUS_OK;
1613 for ( i -= 1; i >= 0 && NT_STATUS_IS_OK( status ); i-- ) {
1614 status = rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx,
1619 /*we return with the NTSTATUS error that we got when trying to delete users */
1620 if ( !NT_STATUS_IS_OK( status ) )
1621 result = CAC_FAILURE;
1628 int cac_SamSetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1629 struct SamSetAliasMembers *op )
1631 struct rpc_pipe_client *pipe_hnd = NULL;
1638 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1639 hnd->status = NT_STATUS_INVALID_HANDLE;
1643 if ( !op || !op->in.alias_hnd || !mem_ctx ) {
1644 hnd->status = NT_STATUS_INVALID_PARAMETER;
1648 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1650 hnd->status = NT_STATUS_INVALID_HANDLE;
1654 /*use cac_SamClearAliasMembers() to clear them */
1655 if ( !cac_SamClearAliasMembers( hnd, mem_ctx, op->in.alias_hnd ) )
1656 return CAC_FAILURE; /*hnd->status is already set */
1659 for ( i = 0; i < op->in.num_members && NT_STATUS_IS_OK( hnd->status );
1662 rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx,
1664 &( op->in.sids[i] ) );
1667 if ( !NT_STATUS_IS_OK( hnd->status ) )
1674 int cac_SamUserChangePasswd( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1675 struct SamUserChangePasswd *op )
1677 SMBCSRV *srv = NULL;
1678 struct rpc_pipe_client *pipe_hnd = NULL;
1683 if ( !hnd->_internal.ctx ) {
1684 hnd->status = NT_STATUS_INVALID_HANDLE;
1688 if ( !op || !op->in.username || !op->in.password
1689 || !op->in.new_password || !mem_ctx ) {
1690 hnd->status = NT_STATUS_INVALID_PARAMETER;
1694 srv = cac_GetServer( hnd );
1696 hnd->status = NT_STATUS_INVALID_CONNECTION;
1700 /*open a session on SAMR if we don't have one */
1701 if ( !hnd->_internal.pipes[PI_SAMR] ) {
1704 cli_rpc_pipe_open_noauth( srv->cli, PI_SAMR,
1705 &hnd->status ) ) ) {
1709 hnd->_internal.pipes[PI_SAMR] = True;
1712 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1714 hnd->status = NT_STATUS_INVALID_HANDLE;
1719 rpccli_samr_chgpasswd_user( pipe_hnd, mem_ctx,
1721 op->in.new_password,
1724 if ( !NT_STATUS_IS_OK( hnd->status ) )
1730 int cac_SamEnableUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1731 POLICY_HND * user_hnd )
1733 SMBCSRV *srv = NULL;
1734 struct rpc_pipe_client *pipe_hnd = NULL;
1736 SAM_USERINFO_CTR *ctr;
1741 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1742 hnd->status = NT_STATUS_INVALID_HANDLE;
1746 if ( !user_hnd || !mem_ctx ) {
1747 hnd->status = NT_STATUS_INVALID_PARAMETER;
1751 srv = cac_GetServer( hnd );
1753 hnd->status = NT_STATUS_INVALID_CONNECTION;
1757 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1759 hnd->status = NT_STATUS_INVALID_HANDLE;
1763 /*info_level = 21 is the only level that I have found to work reliably. It would be nice if user_level = 10 worked. */
1765 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10,
1768 if ( !NT_STATUS_IS_OK( hnd->status ) )
1771 /**check the ACB mask*/
1772 if ( ( ctr->info.id16->acb_info & ACB_DISABLED ) == ACB_DISABLED ) {
1773 /*toggle the disabled bit */
1774 ctr->info.id16->acb_info ^= ACB_DISABLED;
1776 /*the user is already enabled so just return success */
1780 /*now set the userinfo */
1782 rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10,
1783 &srv->cli->user_session_key, ctr );
1785 /*this will only work properly if we use set_userinfo2 - fail if it is not supported */
1786 if ( !NT_STATUS_IS_OK( hnd->status ) )
1792 int cac_SamDisableUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1793 POLICY_HND * user_hnd )
1795 SMBCSRV *srv = NULL;
1796 struct rpc_pipe_client *pipe_hnd = NULL;
1798 SAM_USERINFO_CTR *ctr;
1803 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1804 hnd->status = NT_STATUS_INVALID_HANDLE;
1808 if ( !user_hnd || !mem_ctx ) {
1809 hnd->status = NT_STATUS_INVALID_PARAMETER;
1813 srv = cac_GetServer( hnd );
1815 hnd->status = NT_STATUS_INVALID_CONNECTION;
1819 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1821 hnd->status = NT_STATUS_INVALID_HANDLE;
1826 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10,
1829 if ( !NT_STATUS_IS_OK( hnd->status ) )
1832 if ( ( ctr->info.id16->acb_info & ACB_DISABLED ) == ACB_DISABLED ) {
1833 /*then the user is already disabled */
1837 /*toggle the disabled bit */
1838 ctr->info.id16->acb_info ^= ACB_DISABLED;
1840 /*this will only work properly if we use set_userinfo2 */
1842 rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10,
1843 &srv->cli->user_session_key, ctr );
1845 /*this will only work properly if we use set_userinfo2 fail if it is not supported */
1846 if ( !NT_STATUS_IS_OK( hnd->status ) )
1852 int cac_SamSetPassword( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1853 struct SamSetPassword *op )
1855 SMBCSRV *srv = NULL;
1856 struct rpc_pipe_client *pipe_hnd = NULL;
1858 SAM_USERINFO_CTR ctr;
1859 SAM_USER_INFO_24 info24;
1865 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1866 hnd->status = NT_STATUS_INVALID_HANDLE;
1870 if ( !op->in.user_hnd || !op->in.password || !mem_ctx ) {
1871 hnd->status = NT_STATUS_INVALID_PARAMETER;
1875 srv = cac_GetServer( hnd );
1877 hnd->status = NT_STATUS_INVALID_CONNECTION;
1881 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1883 hnd->status = NT_STATUS_INVALID_HANDLE;
1888 ZERO_STRUCT( info24 );
1890 encode_pw_buffer( pw, op->in.password, STR_UNICODE );
1892 init_sam_user_info24( &info24, ( char * ) pw, 24 );
1894 ctr.switch_value = 24;
1895 ctr.info.id24 = &info24;
1898 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
1899 24, &srv->cli->user_session_key,
1902 if ( !NT_STATUS_IS_OK( hnd->status ) )
1908 int cac_SamGetUserInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1909 struct SamGetUserInfo *op )
1911 struct rpc_pipe_client *pipe_hnd = NULL;
1913 SAM_USERINFO_CTR *ctr;
1918 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1919 hnd->status = NT_STATUS_INVALID_HANDLE;
1923 if ( !op->in.user_hnd || !mem_ctx ) {
1924 hnd->status = NT_STATUS_INVALID_PARAMETER;
1928 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1930 hnd->status = NT_STATUS_INVALID_HANDLE;
1935 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
1936 op->in.user_hnd, 21, &ctr );
1938 if ( !NT_STATUS_IS_OK( hnd->status ) )
1941 op->out.info = cac_MakeUserInfo( mem_ctx, ctr );
1943 if ( !op->out.info ) {
1944 hnd->status = NT_STATUS_NO_MEMORY;
1951 int cac_SamSetUserInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1952 struct SamSetUserInfo *op )
1954 SMBCSRV *srv = NULL;
1955 struct rpc_pipe_client *pipe_hnd = NULL;
1957 SAM_USERINFO_CTR *ctr;
1962 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1963 hnd->status = NT_STATUS_INVALID_HANDLE;
1967 if ( !op->in.user_hnd || !op->in.info || !mem_ctx ) {
1968 hnd->status = NT_STATUS_INVALID_PARAMETER;
1972 ctr = cac_MakeUserInfoCtr( mem_ctx, op->in.info );
1974 hnd->status = NT_STATUS_NO_MEMORY;
1978 srv = cac_GetServer( hnd );
1980 hnd->status = NT_STATUS_INVALID_CONNECTION;
1984 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1986 hnd->status = NT_STATUS_INVALID_HANDLE;
1990 if ( hnd->_internal.srv_level >= SRV_WIN_NT4 ) {
1992 rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx,
1993 op->in.user_hnd, 21,
1995 user_session_key, ctr );
1998 if ( hnd->_internal.srv_level < SRV_WIN_NT4
1999 || !NT_STATUS_IS_OK( hnd->status ) ) {
2001 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx,
2002 op->in.user_hnd, 21,
2003 &srv->cli->user_session_key,
2006 if ( NT_STATUS_IS_OK( hnd->status )
2007 && hnd->_internal.srv_level > SRV_WIN_NT4 ) {
2008 hnd->_internal.srv_level = SRV_WIN_NT4;
2013 if ( !NT_STATUS_IS_OK( hnd->status ) )
2020 int cac_SamGetUserInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2021 struct SamGetUserInfoCtr *op )
2023 struct rpc_pipe_client *pipe_hnd = NULL;
2025 SAM_USERINFO_CTR *ctr_out;
2030 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2031 hnd->status = NT_STATUS_INVALID_HANDLE;
2035 if ( !op->in.user_hnd || op->in.info_class == 0 || !mem_ctx ) {
2036 hnd->status = NT_STATUS_INVALID_PARAMETER;
2040 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2042 hnd->status = NT_STATUS_INVALID_HANDLE;
2047 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
2049 op->in.info_class, &ctr_out );
2051 if ( !NT_STATUS_IS_OK( hnd->status ) )
2054 op->out.ctr = ctr_out;
2059 int cac_SamSetUserInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2060 struct SamSetUserInfoCtr *op )
2062 SMBCSRV *srv = NULL;
2063 struct rpc_pipe_client *pipe_hnd = NULL;
2068 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2069 hnd->status = NT_STATUS_INVALID_HANDLE;
2073 if ( !op->in.user_hnd || !op->in.ctr || !mem_ctx ) {
2074 hnd->status = NT_STATUS_INVALID_PARAMETER;
2078 srv = cac_GetServer( hnd );
2080 hnd->status = NT_STATUS_INVALID_CONNECTION;
2084 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2086 hnd->status = NT_STATUS_INVALID_HANDLE;
2092 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
2093 op->in.ctr->switch_value,
2094 &srv->cli->user_session_key,
2097 if ( !NT_STATUS_IS_OK( hnd->status ) )
2104 int cac_SamRenameUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2105 struct SamRenameUser *op )
2107 SMBCSRV *srv = NULL;
2108 struct rpc_pipe_client *pipe_hnd = NULL;
2110 SAM_USERINFO_CTR ctr;
2111 SAM_USER_INFO_7 info7;
2116 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2117 hnd->status = NT_STATUS_INVALID_HANDLE;
2121 if ( !op->in.user_hnd || !op->in.new_name
2122 || op->in.new_name[0] == '\0' || !mem_ctx ) {
2123 hnd->status = NT_STATUS_INVALID_PARAMETER;
2127 srv = cac_GetServer( hnd );
2129 hnd->status = NT_STATUS_INVALID_CONNECTION;
2133 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2135 hnd->status = NT_STATUS_INVALID_HANDLE;
2140 ZERO_STRUCT( info7 );
2142 init_sam_user_info7( &info7, op->in.new_name );
2144 ctr.switch_value = 7;
2145 ctr.info.id7 = &info7;
2148 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
2149 7, &srv->cli->user_session_key,
2152 if ( !NT_STATUS_IS_OK( hnd->status ) )
2159 int cac_SamGetGroupInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2160 struct SamGetGroupInfo *op )
2162 struct rpc_pipe_client *pipe_hnd = NULL;
2164 GROUP_INFO_CTR *ctr;
2169 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2170 hnd->status = NT_STATUS_INVALID_HANDLE;
2174 if ( !op->in.group_hnd || !mem_ctx ) {
2175 hnd->status = NT_STATUS_INVALID_PARAMETER;
2179 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2181 hnd->status = NT_STATUS_INVALID_HANDLE;
2186 /*get a GROUP_INFO_1 structure */
2188 rpccli_samr_query_groupinfo( pipe_hnd, mem_ctx,
2189 op->in.group_hnd, 1, &ctr );
2191 if ( !NT_STATUS_IS_OK( hnd->status ) )
2194 op->out.info = cac_MakeGroupInfo( mem_ctx, ctr );
2195 if ( !op->out.info ) {
2196 hnd->status = NT_STATUS_NO_MEMORY;
2203 int cac_SamSetGroupInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2204 struct SamSetGroupInfo *op )
2206 struct rpc_pipe_client *pipe_hnd = NULL;
2208 GROUP_INFO_CTR *ctr = NULL;
2213 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2214 hnd->status = NT_STATUS_INVALID_HANDLE;
2218 if ( !op->in.group_hnd || !op->in.info || !mem_ctx ) {
2219 hnd->status = NT_STATUS_INVALID_PARAMETER;
2223 ctr = cac_MakeGroupInfoCtr( mem_ctx, op->in.info );
2225 hnd->status = NT_STATUS_NO_MEMORY;
2229 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2231 hnd->status = NT_STATUS_INVALID_HANDLE;
2236 rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
2237 op->in.group_hnd, ctr );
2239 if ( !NT_STATUS_IS_OK( hnd->status ) )
2245 int cac_SamRenameGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2246 struct SamRenameGroup *op )
2248 struct rpc_pipe_client *pipe_hnd = NULL;
2255 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2256 hnd->status = NT_STATUS_INVALID_HANDLE;
2260 if ( !op->in.group_hnd || !op->in.new_name
2261 || op->in.new_name[0] == '\0' || !mem_ctx ) {
2262 hnd->status = NT_STATUS_INVALID_PARAMETER;
2266 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2268 hnd->status = NT_STATUS_INVALID_HANDLE;
2274 init_samr_group_info2( &ctr.group.info2, op->in.new_name );
2275 ctr.switch_value1 = 2;
2278 rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
2279 op->in.group_hnd, &ctr );
2281 if ( !NT_STATUS_IS_OK( hnd->status ) )
2287 int cac_SamGetAliasInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2288 struct SamGetAliasInfo *op )
2290 struct rpc_pipe_client *pipe_hnd = NULL;
2297 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2298 hnd->status = NT_STATUS_INVALID_HANDLE;
2302 if ( !op->in.alias_hnd || !mem_ctx ) {
2303 hnd->status = NT_STATUS_INVALID_PARAMETER;
2307 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2309 hnd->status = NT_STATUS_INVALID_HANDLE;
2313 /*get a GROUP_INFO_1 structure */
2315 rpccli_samr_query_alias_info( pipe_hnd, mem_ctx,
2316 op->in.alias_hnd, 1, &ctr );
2318 if ( !NT_STATUS_IS_OK( hnd->status ) )
2321 op->out.info = cac_MakeAliasInfo( mem_ctx, ctr );
2322 if ( !op->out.info ) {
2323 hnd->status = NT_STATUS_NO_MEMORY;
2331 int cac_SamSetAliasInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2332 struct SamSetAliasInfo *op )
2334 struct rpc_pipe_client *pipe_hnd = NULL;
2336 ALIAS_INFO_CTR *ctr = NULL;
2341 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2342 hnd->status = NT_STATUS_INVALID_HANDLE;
2346 if ( !op->in.alias_hnd || !op->in.info || !mem_ctx ) {
2347 hnd->status = NT_STATUS_INVALID_PARAMETER;
2351 ctr = cac_MakeAliasInfoCtr( mem_ctx, op->in.info );
2353 hnd->status = NT_STATUS_NO_MEMORY;
2357 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2359 hnd->status = NT_STATUS_INVALID_HANDLE;
2364 rpccli_samr_set_aliasinfo( pipe_hnd, mem_ctx,
2365 op->in.alias_hnd, ctr );
2367 if ( !NT_STATUS_IS_OK( hnd->status ) )
2373 int cac_SamGetDomainInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2374 struct SamGetDomainInfo *op )
2376 struct rpc_pipe_client *pipe_hnd = NULL;
2379 SAM_UNK_INFO_1 info1;
2380 SAM_UNK_INFO_2 info2;
2381 SAM_UNK_INFO_12 info12;
2383 /*use this to keep track of a failed call */
2384 NTSTATUS status_buf = NT_STATUS_OK;
2386 uint16 fail_count = 0;
2392 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2393 hnd->status = NT_STATUS_INVALID_HANDLE;
2397 if ( !op->in.dom_hnd || !mem_ctx ) {
2398 hnd->status = NT_STATUS_INVALID_PARAMETER;
2402 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2404 hnd->status = NT_STATUS_INVALID_HANDLE;
2408 /*first try with info 1 */
2410 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2413 if ( NT_STATUS_IS_OK( hnd->status ) ) {
2414 /*then we buffer the SAM_UNK_INFO_1 structure */
2415 info1 = ctr.info.inf1;
2417 /*then the call failed, store the status and ZERO out the info structure */
2418 ZERO_STRUCT( info1 );
2419 status_buf = hnd->status;
2423 /*try again for the next one */
2425 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2428 if ( NT_STATUS_IS_OK( hnd->status ) ) {
2430 info2 = ctr.info.inf2;
2432 /*ZERO out the structure and store the bad status */
2433 ZERO_STRUCT( info2 );
2434 status_buf = hnd->status;
2440 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2443 if ( NT_STATUS_IS_OK( hnd->status ) ) {
2444 info12 = ctr.info.inf12;
2446 ZERO_STRUCT( info12 );
2447 status_buf = hnd->status;
2451 /*return failure if all 3 calls failed */
2452 if ( fail_count == 3 )
2455 op->out.info = cac_MakeDomainInfo( mem_ctx, &info1, &info2, &info12 );
2457 if ( !op->out.info ) {
2458 hnd->status = NT_STATUS_NO_MEMORY;
2462 if ( fail_count > 0 ) {
2463 hnd->status = status_buf;
2464 return CAC_PARTIAL_SUCCESS;
2470 int cac_SamGetDomainInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2471 struct SamGetDomainInfoCtr *op )
2473 struct rpc_pipe_client *pipe_hnd = NULL;
2475 SAM_UNK_CTR *ctr_out;
2480 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2481 hnd->status = NT_STATUS_INVALID_HANDLE;
2485 if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
2486 hnd->status = NT_STATUS_INVALID_PARAMETER;
2490 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2492 hnd->status = NT_STATUS_INVALID_HANDLE;
2496 ctr_out = talloc( mem_ctx, SAM_UNK_CTR );
2498 hnd->status = NT_STATUS_NO_MEMORY;
2503 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2504 op->in.info_class, ctr_out );
2506 if ( !NT_STATUS_IS_OK( hnd->status ) )
2509 op->out.info = ctr_out;
2514 int cac_SamGetDisplayInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2515 struct SamGetDisplayInfo *op )
2517 struct rpc_pipe_client *pipe_hnd = NULL;
2519 SAM_DISPINFO_CTR ctr_out;
2521 uint32 max_entries_buf = 0;
2522 uint32 max_size_buf = 0;
2524 uint32 resume_idx_out;
2525 uint32 num_entries_out;
2530 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2531 hnd->status = NT_STATUS_INVALID_HANDLE;
2535 if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
2536 hnd->status = NT_STATUS_INVALID_PARAMETER;
2540 if ( op->out.done == True ) /*this is done so we can use the function as a loop condition */
2543 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2545 hnd->status = NT_STATUS_INVALID_HANDLE;
2549 if ( op->in.max_entries == 0 || op->in.max_size == 0 ) {
2550 get_query_dispinfo_params( op->out.loop_count,
2551 &max_entries_buf, &max_size_buf );
2553 max_entries_buf = op->in.max_entries;
2554 max_size_buf = op->in.max_size;
2557 resume_idx_out = op->out.resume_idx;
2560 rpccli_samr_query_dispinfo( pipe_hnd, mem_ctx, op->in.dom_hnd,
2563 &num_entries_out, max_entries_buf,
2564 max_size_buf, &ctr_out );
2566 if ( !NT_STATUS_IS_OK( hnd->status )
2567 && !NT_STATUS_EQUAL( hnd->status, STATUS_MORE_ENTRIES ) ) {
2568 /*be defensive, maybe they'll call again without zeroing the struct */
2569 op->out.loop_count = 0;
2570 op->out.resume_idx = 0;
2574 if ( NT_STATUS_IS_OK( hnd->status ) ) {
2575 /*we want to quit once the function is called next. so it can be used in a loop */
2576 op->out.done = True;
2579 op->out.resume_idx = resume_idx_out;
2580 op->out.num_entries = num_entries_out;
2581 op->out.ctr = ctr_out;
2582 op->out.loop_count++;
2587 int cac_SamLookupDomain( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2588 struct SamLookupDomain *op )
2590 struct rpc_pipe_client *pipe_hnd = NULL;
2592 DOM_SID *sid_out = NULL;
2597 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2598 hnd->status = NT_STATUS_INVALID_HANDLE;
2602 if ( !op->in.sam || !op->in.name || !mem_ctx ) {
2603 hnd->status = NT_STATUS_INVALID_PARAMETER;
2607 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2609 hnd->status = NT_STATUS_INVALID_HANDLE;
2613 sid_out = talloc( mem_ctx, DOM_SID );
2615 hnd->status = NT_STATUS_NO_MEMORY;
2620 rpccli_samr_lookup_domain( pipe_hnd, mem_ctx, op->in.sam,
2621 op->in.name, sid_out );
2623 if ( !NT_STATUS_IS_OK( hnd->status ) )
2626 op->out.sid = sid_out;
2631 int cac_SamGetSecurityObject( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2632 struct SamGetSecurityObject *op )
2634 struct rpc_pipe_client *pipe_hnd = NULL;
2636 /*this number taken from rpcclient/cmd_samr.c, I think it is the only supported level */
2637 uint32 sec_info = DACL_SECURITY_INFORMATION;
2639 SEC_DESC_BUF *sec_out = NULL;
2644 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2645 hnd->status = NT_STATUS_INVALID_HANDLE;
2649 if ( !op->in.pol || !mem_ctx ) {
2650 hnd->status = NT_STATUS_INVALID_PARAMETER;
2654 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2656 hnd->status = NT_STATUS_INVALID_HANDLE;
2661 rpccli_samr_query_sec_obj( pipe_hnd, mem_ctx, op->in.pol,
2662 sec_info, mem_ctx, &sec_out );
2664 if ( !NT_STATUS_IS_OK( hnd->status ) )
2667 op->out.sec = sec_out;
2672 int cac_SamFlush( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2673 struct SamFlush *op )
2675 struct SamOpenDomain od;
2680 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2681 hnd->status = NT_STATUS_INVALID_HANDLE;
2685 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
2686 hnd->status = NT_STATUS_INVALID_PARAMETER;
2690 if ( !cac_SamClose( hnd, mem_ctx, op->in.dom_hnd ) )
2695 ( op->in.access ) ? op->in.access : MAXIMUM_ALLOWED_ACCESS;
2696 od.in.sid = op->in.sid;
2698 if ( !cac_SamOpenDomain( hnd, mem_ctx, &od ) )
2701 /*this function does not use an output parameter to make it as convenient as possible to use */
2702 *op->in.dom_hnd = *od.out.dom_hnd;
2704 TALLOC_FREE( od.out.dom_hnd );