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, see <http://www.gnu.org/licenses/>.
22 #include "libmsrpc_internal.h"
24 /*used by cac_SamGetNamesFromRids*/
25 #define SAMR_RID_UNKNOWN 8
27 #define SAMR_ENUM_MAX_SIZE 0xffff
29 /*not sure what this is.. taken from rpcclient/cmd_samr.c*/
30 #define SAMR_LOOKUP_FLAGS 0x000003e8
32 DOM_SID *cac_get_domain_sid( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
35 int cac_SamConnect( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
36 struct SamConnect *op )
39 struct rpc_pipe_client *pipe_hnd = NULL;
40 POLICY_HND *sam_out = NULL;
45 if ( !hnd->_internal.ctx ) {
46 hnd->status = NT_STATUS_INVALID_HANDLE;
50 if ( !op || op->in.access == 0 || !mem_ctx ) {
51 hnd->status = NT_STATUS_INVALID_PARAMETER;
55 srv = cac_GetServer( hnd );
57 hnd->status = NT_STATUS_INVALID_CONNECTION;
61 /*initialize for samr pipe if we have to */
62 if ( !hnd->_internal.pipes[PI_SAMR] ) {
65 cli_rpc_pipe_open_noauth( srv->cli, PI_SAMR,
70 hnd->_internal.pipes[PI_SAMR] = True;
73 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
75 hnd->status = NT_STATUS_INVALID_HANDLE;
79 sam_out = talloc( mem_ctx, POLICY_HND );
81 hnd->status = NT_STATUS_NO_MEMORY;
85 if ( hnd->_internal.srv_level >= SRV_WIN_2K_SP3 ) {
87 rpccli_samr_connect4( pipe_hnd, mem_ctx,
88 op->in.access, sam_out );
91 if ( hnd->_internal.srv_level < SRV_WIN_2K_SP3
92 || !NT_STATUS_IS_OK( hnd->status ) ) {
93 /*if sam_connect4 failed, the use sam_connect and lower srv_level */
96 rpccli_samr_connect( pipe_hnd, mem_ctx, op->in.access,
99 if ( NT_STATUS_IS_OK( hnd->status )
100 && hnd->_internal.srv_level > SRV_WIN_2K ) {
101 hnd->_internal.srv_level = SRV_WIN_2K;
105 if ( !NT_STATUS_IS_OK( hnd->status ) )
108 op->out.sam = sam_out;
113 int cac_SamClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
116 struct rpc_pipe_client *pipe_hnd = NULL;
121 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
122 hnd->status = NT_STATUS_INVALID_HANDLE;
126 if ( !sam || !mem_ctx ) {
127 hnd->status = NT_STATUS_INVALID_PARAMETER;
131 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
133 hnd->status = NT_STATUS_INVALID_HANDLE;
137 hnd->status = rpccli_samr_close( pipe_hnd, mem_ctx, sam );
139 if ( !NT_STATUS_IS_OK( hnd->status ) )
145 /*this is an internal function. Due to a circular dependency, it must be prototyped in libmsrpc.h (which I don't want to do)
146 * cac_SamOpenDomain() is the only function that calls it, so I just put the definition here
149 /*attempts to find the sid of the domain we are connected to*/
150 DOM_SID *cac_get_domain_sid( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
153 struct LsaOpenPolicy lop;
154 struct LsaFetchSid fs;
161 lop.in.access = des_access;
162 lop.in.security_qos = True;
164 if ( !cac_LsaOpenPolicy( hnd, mem_ctx, &lop ) )
167 fs.in.pol = lop.out.pol;
168 fs.in.info_class = CAC_DOMAIN_INFO;
170 if ( !cac_LsaFetchSid( hnd, mem_ctx, &fs ) )
173 cac_LsaClosePolicy( hnd, mem_ctx, lop.out.pol );
175 if ( !fs.out.domain_sid )
178 sid = ( DOM_SID * ) TALLOC_MEMDUP( mem_ctx,
179 &( fs.out.domain_sid->sid ),
183 hnd->status = NT_STATUS_NO_MEMORY;
190 int cac_SamOpenDomain( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
191 struct SamOpenDomain *op )
193 struct rpc_pipe_client *pipe_hnd = NULL;
199 struct SamLookupDomain sld;
204 if ( !hnd->_internal.ctx ) {
205 hnd->status = NT_STATUS_INVALID_HANDLE;
209 if ( !op || op->in.access == 0 || !mem_ctx ) {
210 hnd->status = NT_STATUS_INVALID_PARAMETER;
215 /*use cac_SamConnect() since it does the session setup */
216 struct SamConnect sc;
220 sc.in.access = op->in.access;
222 if ( !cac_SamConnect( hnd, mem_ctx, &sc ) ) {
226 sam_out = sc.out.sam;
228 sam_out = op->in.sam;
232 /*find the sid for the SAM's domain */
234 /*try using cac_SamLookupDomain() first */
237 sld.in.sam = sam_out;
238 sld.in.name = hnd->domain;
240 if ( cac_SamLookupDomain( hnd, mem_ctx, &sld ) ) {
241 /*then we got the sid */
242 sid_buf = sld.out.sid;
244 /*try to get it from the LSA */
246 cac_get_domain_sid( hnd, mem_ctx,
250 /*we already have the sid for the domain we want */
251 sid_buf = op->in.sid;
254 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
256 hnd->status = NT_STATUS_INVALID_HANDLE;
260 pol_out = talloc( mem_ctx, POLICY_HND );
262 hnd->status = NT_STATUS_NO_MEMORY;
266 /*now open the domain */
268 rpccli_samr_open_domain( pipe_hnd, mem_ctx, sam_out,
269 op->in.access, sid_buf, pol_out );
271 if ( !NT_STATUS_IS_OK( hnd->status ) )
274 op->out.sam = sam_out;
275 op->out.dom_hnd = pol_out;
280 int cac_SamOpenUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
281 struct SamOpenUser *op )
283 struct rpc_pipe_client *pipe_hnd = NULL;
285 uint32 *rid_buf = NULL;
288 uint32 *rid_types = NULL;
290 POLICY_HND *user_out = NULL;
295 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
296 hnd->status = NT_STATUS_INVALID_HANDLE;
300 if ( !op || !op->in.dom_hnd || op->in.access == 0 || !mem_ctx ) {
301 hnd->status = NT_STATUS_INVALID_PARAMETER;
305 if ( op->in.rid == 0 && op->in.name == NULL ) {
306 hnd->status = NT_STATUS_INVALID_PARAMETER;
310 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
312 hnd->status = NT_STATUS_INVALID_HANDLE;
316 if ( op->in.rid == 0 && op->in.name ) {
317 /*lookup the name and then set rid_buf */
320 rpccli_samr_lookup_names( pipe_hnd, mem_ctx,
322 SAMR_LOOKUP_FLAGS, 1,
323 ( const char ** ) &op->in.
324 name, &num_rids, &rid_buf,
327 if ( !NT_STATUS_IS_OK( hnd->status ) )
330 if ( num_rids == 0 || rid_buf == NULL
331 || rid_types[0] == SAMR_RID_UNKNOWN ) {
332 hnd->status = NT_STATUS_INVALID_PARAMETER;
336 TALLOC_FREE( rid_types );
339 rid_buf = &op->in.rid;
342 user_out = talloc( mem_ctx, POLICY_HND );
344 hnd->status = NT_STATUS_NO_MEMORY;
349 rpccli_samr_open_user( pipe_hnd, mem_ctx, op->in.dom_hnd,
350 op->in.access, *rid_buf, user_out );
352 if ( !NT_STATUS_IS_OK( hnd->status ) )
355 op->out.user_hnd = user_out;
360 int cac_SamCreateUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
361 struct SamCreateUser *op )
363 struct rpc_pipe_client *pipe_hnd = NULL;
365 POLICY_HND *user_out = NULL;
368 /**found in rpcclient/cmd_samr.c*/
369 uint32 unknown = 0xe005000b;
374 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
375 hnd->status = NT_STATUS_INVALID_HANDLE;
379 if ( !op || !op->in.dom_hnd || !op->in.name || op->in.acb_mask == 0
381 hnd->status = NT_STATUS_INVALID_PARAMETER;
385 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
387 hnd->status = NT_STATUS_INVALID_HANDLE;
391 user_out = talloc( mem_ctx, POLICY_HND );
393 hnd->status = NT_STATUS_NO_MEMORY;
398 rpccli_samr_create_dom_user( pipe_hnd, mem_ctx,
399 op->in.dom_hnd, op->in.name,
400 op->in.acb_mask, unknown,
401 user_out, &rid_out );
403 if ( !NT_STATUS_IS_OK( hnd->status ) )
406 op->out.user_hnd = user_out;
407 op->out.rid = rid_out;
412 int cac_SamDeleteUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
413 POLICY_HND * user_hnd )
415 struct rpc_pipe_client *pipe_hnd = NULL;
420 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
421 hnd->status = NT_STATUS_INVALID_HANDLE;
425 if ( !user_hnd || !mem_ctx ) {
426 hnd->status = NT_STATUS_INVALID_PARAMETER;
430 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
432 hnd->status = NT_STATUS_INVALID_HANDLE;
437 rpccli_samr_delete_dom_user( pipe_hnd, mem_ctx, user_hnd );
439 if ( !NT_STATUS_IS_OK( hnd->status ) )
445 int cac_SamEnumUsers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
446 struct SamEnumUsers *op )
448 struct rpc_pipe_client *pipe_hnd = NULL;
450 uint32 resume_idx_out = 0;
451 char **names_out = NULL;
452 uint32 *rids_out = NULL;
453 uint32 num_users_out = 0;
458 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
459 hnd->status = NT_STATUS_INVALID_HANDLE;
463 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
464 hnd->status = NT_STATUS_INVALID_PARAMETER;
468 /*this is a hack.. but is the only reliable way to know if everything has been enumerated */
469 if ( op->out.done == True )
472 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
474 hnd->status = NT_STATUS_INVALID_HANDLE;
478 resume_idx_out = op->out.resume_idx;
481 rpccli_samr_enum_dom_users( pipe_hnd, mem_ctx, op->in.dom_hnd,
482 &resume_idx_out, op->in.acb_mask,
483 SAMR_ENUM_MAX_SIZE, &names_out,
484 &rids_out, &num_users_out );
487 if ( NT_STATUS_IS_OK( hnd->status ) )
490 /*if there are no more entries, the operation will return NT_STATUS_OK.
491 * We want to return failure if no results were returned*/
492 if ( !NT_STATUS_IS_OK( hnd->status )
493 && NT_STATUS_V( hnd->status ) !=
494 NT_STATUS_V( STATUS_MORE_ENTRIES ) )
497 op->out.resume_idx = resume_idx_out;
498 op->out.num_users = num_users_out;
499 op->out.rids = rids_out;
500 op->out.names = names_out;
505 int cac_SamGetNamesFromRids( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
506 struct SamGetNamesFromRids *op )
508 struct rpc_pipe_client *pipe_hnd = NULL;
510 uint32 num_names_out;
512 uint32 *name_types_out;
517 CacLookupRidsRecord *map_out;
522 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
523 hnd->status = NT_STATUS_INVALID_HANDLE;
527 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
528 hnd->status = NT_STATUS_INVALID_PARAMETER;
532 if ( !op->in.rids && op->in.num_rids != 0 ) {
533 hnd->status = NT_STATUS_INVALID_PARAMETER;
537 if ( op->in.num_rids == 0 ) {
539 op->out.num_names = 0;
543 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
545 hnd->status = NT_STATUS_INVALID_HANDLE;
550 rpccli_samr_lookup_rids( pipe_hnd, mem_ctx, op->in.dom_hnd,
551 op->in.num_rids, op->in.rids,
552 &num_names_out, &names_out,
555 if ( !NT_STATUS_IS_OK( hnd->status )
556 && !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;
569 for ( i = 0; i < num_names_out; i++ ) {
570 if ( name_types_out[i] == SAMR_RID_UNKNOWN ) {
571 map_out[i].found = False;
572 map_out[i].name = NULL;
575 map_out[i].found = True;
577 talloc_strdup( mem_ctx, names_out[i] );
578 map_out[i].type = name_types_out[i];
580 map_out[i].rid = op->in.rids[i];
583 TALLOC_FREE( names_out );
584 TALLOC_FREE( name_types_out );
586 op->out.num_names = num_names_out;
587 op->out.map = map_out;
589 if ( NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
590 return CAC_PARTIAL_SUCCESS;
595 int cac_SamGetRidsFromNames( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
596 struct SamGetRidsFromNames *op )
598 struct rpc_pipe_client *pipe_hnd = NULL;
602 uint32 *rid_types_out;
606 CacLookupRidsRecord *map_out;
611 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
612 hnd->status = NT_STATUS_INVALID_HANDLE;
616 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
617 hnd->status = NT_STATUS_INVALID_PARAMETER;
621 if ( !op->in.names && op->in.num_names != 0 ) {
622 hnd->status = NT_STATUS_INVALID_PARAMETER;
626 if ( op->in.num_names == 0 ) {
627 /*then we don't have to do anything */
628 op->out.num_rids = 0;
632 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
634 hnd->status = NT_STATUS_INVALID_HANDLE;
639 rpccli_samr_lookup_names( pipe_hnd, mem_ctx, op->in.dom_hnd,
640 SAMR_LOOKUP_FLAGS, op->in.num_names,
641 ( const char ** ) op->in.names,
642 &num_rids_out, &rids_out,
645 if ( !NT_STATUS_IS_OK( hnd->status )
646 && !NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
650 map_out = TALLOC_ARRAY( mem_ctx, CacLookupRidsRecord, num_rids_out );
652 hnd->status = NT_STATUS_NO_MEMORY;
659 for ( i = 0; i < num_rids_out; i++ ) {
661 if ( rid_types_out[i] == SAMR_RID_UNKNOWN ) {
662 map_out[i].found = False;
666 map_out[i].found = True;
667 map_out[i].rid = rids_out[i];
668 map_out[i].type = rid_types_out[i];
671 map_out[i].name = talloc_strdup( mem_ctx, op->in.names[i] );
674 op->out.num_rids = num_rids_out;
675 op->out.map = map_out;
677 TALLOC_FREE( rids_out );
678 TALLOC_FREE( rid_types_out );
680 if ( NT_STATUS_EQUAL( hnd->status, STATUS_SOME_UNMAPPED ) )
681 return CAC_PARTIAL_SUCCESS;
687 int cac_SamGetGroupsForUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
688 struct SamGetGroupsForUser *op )
690 struct rpc_pipe_client *pipe_hnd = NULL;
692 DOM_GID *groups = NULL;
693 uint32 num_groups_out = 0;
695 uint32 *rids_out = NULL;
696 uint32 *attr_out = NULL;
703 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
704 hnd->status = NT_STATUS_INVALID_HANDLE;
708 if ( !op || !op->in.user_hnd || !mem_ctx ) {
709 hnd->status = NT_STATUS_INVALID_PARAMETER;
713 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
715 hnd->status = NT_STATUS_INVALID_HANDLE;
720 rpccli_samr_query_usergroups( pipe_hnd, mem_ctx,
722 &num_groups_out, &groups );
724 if ( !NT_STATUS_IS_OK( hnd->status ) )
728 if (num_groups_out) {
729 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
731 hnd->status = NT_STATUS_NO_MEMORY;
734 attr_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
736 hnd->status = NT_STATUS_NO_MEMORY;
744 for ( i = 0; i < num_groups_out; i++ ) {
745 rids_out[i] = groups[i].g_rid;
746 attr_out[i] = groups[i].attr;
749 TALLOC_FREE( groups );
751 op->out.num_groups = num_groups_out;
752 op->out.rids = rids_out;
753 op->out.attributes = attr_out;
759 int cac_SamOpenGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
760 struct SamOpenGroup *op )
762 struct rpc_pipe_client *pipe_hnd = NULL;
764 POLICY_HND *group_hnd_out = NULL;
769 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
770 hnd->status = NT_STATUS_INVALID_HANDLE;
774 if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
775 hnd->status = NT_STATUS_INVALID_PARAMETER;
779 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
781 hnd->status = NT_STATUS_INVALID_HANDLE;
785 group_hnd_out = talloc( mem_ctx, POLICY_HND );
786 if ( !group_hnd_out ) {
787 hnd->status = NT_STATUS_NO_MEMORY;
792 rpccli_samr_open_group( pipe_hnd, mem_ctx, op->in.dom_hnd,
793 op->in.access, op->in.rid,
796 if ( !NT_STATUS_IS_OK( hnd->status ) )
799 op->out.group_hnd = group_hnd_out;
804 int cac_SamCreateGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
805 struct SamCreateGroup *op )
807 struct rpc_pipe_client *pipe_hnd = NULL;
809 POLICY_HND *group_hnd_out = NULL;
814 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
815 hnd->status = NT_STATUS_INVALID_HANDLE;
819 if ( !op || !op->in.name || op->in.name[0] == '\0'
820 || op->in.access == 0 || !mem_ctx ) {
821 hnd->status = NT_STATUS_INVALID_PARAMETER;
825 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
827 hnd->status = NT_STATUS_INVALID_HANDLE;
831 group_hnd_out = talloc( mem_ctx, POLICY_HND );
832 if ( !group_hnd_out ) {
833 hnd->status = NT_STATUS_NO_MEMORY;
838 rpccli_samr_create_dom_group( pipe_hnd, mem_ctx,
839 op->in.dom_hnd, op->in.name,
840 op->in.access, group_hnd_out );
842 if ( !NT_STATUS_IS_OK( hnd->status ) )
845 op->out.group_hnd = group_hnd_out;
851 int cac_SamDeleteGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
852 POLICY_HND * group_hnd )
854 struct rpc_pipe_client *pipe_hnd = NULL;
859 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
860 hnd->status = NT_STATUS_INVALID_HANDLE;
864 if ( !group_hnd || !mem_ctx ) {
865 hnd->status = NT_STATUS_INVALID_PARAMETER;
869 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
871 hnd->status = NT_STATUS_INVALID_HANDLE;
876 rpccli_samr_delete_dom_group( pipe_hnd, mem_ctx, group_hnd );
878 if ( !NT_STATUS_IS_OK( hnd->status ) )
885 int cac_SamGetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
886 struct SamGetGroupMembers *op )
888 struct rpc_pipe_client *pipe_hnd = NULL;
897 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
898 hnd->status = NT_STATUS_INVALID_HANDLE;
902 if ( !op || !op->in.group_hnd || !mem_ctx ) {
903 hnd->status = NT_STATUS_INVALID_PARAMETER;
907 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
909 hnd->status = NT_STATUS_INVALID_HANDLE;
914 rpccli_samr_query_groupmem( pipe_hnd, mem_ctx,
915 op->in.group_hnd, &num_mem_out,
916 &rids_out, &attr_out );
918 if ( !NT_STATUS_IS_OK( hnd->status ) )
921 op->out.num_members = num_mem_out;
922 op->out.rids = rids_out;
923 op->out.attributes = attr_out;
929 int cac_SamAddGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
930 struct SamAddGroupMember *op )
932 struct rpc_pipe_client *pipe_hnd = NULL;
937 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
938 hnd->status = NT_STATUS_INVALID_HANDLE;
942 if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
943 hnd->status = NT_STATUS_INVALID_PARAMETER;
947 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
949 hnd->status = NT_STATUS_INVALID_HANDLE;
954 rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
957 if ( !NT_STATUS_IS_OK( hnd->status ) )
963 int cac_SamRemoveGroupMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
964 struct SamRemoveGroupMember *op )
966 struct rpc_pipe_client *pipe_hnd = NULL;
971 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
972 hnd->status = NT_STATUS_INVALID_HANDLE;
976 if ( !op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx ) {
977 hnd->status = NT_STATUS_INVALID_PARAMETER;
981 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
983 hnd->status = NT_STATUS_INVALID_HANDLE;
988 rpccli_samr_del_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd,
991 if ( !NT_STATUS_IS_OK( hnd->status ) )
997 int cac_SamClearGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
998 POLICY_HND * group_hnd )
1000 struct rpc_pipe_client *pipe_hnd = NULL;
1002 int result = CAC_SUCCESS;
1008 uint32 *attr = NULL;
1015 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1016 hnd->status = NT_STATUS_INVALID_HANDLE;
1020 if ( !group_hnd || !mem_ctx ) {
1021 hnd->status = NT_STATUS_INVALID_PARAMETER;
1025 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1027 hnd->status = NT_STATUS_INVALID_HANDLE;
1032 rpccli_samr_query_groupmem( pipe_hnd, mem_ctx, group_hnd,
1033 &num_mem, &rid, &attr );
1035 if ( !NT_STATUS_IS_OK( hnd->status ) )
1038 /*try to delete the users one by one */
1039 for ( i = 0; i < num_mem && NT_STATUS_IS_OK( hnd->status ); i++ ) {
1041 rpccli_samr_del_groupmem( pipe_hnd, mem_ctx,
1042 group_hnd, rid[i] );
1045 /*if not all members could be removed, then try to re-add the members that were already deleted */
1046 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1047 status = NT_STATUS_OK;
1049 for ( i -= 1; i >= 0 && NT_STATUS_IS_OK( status ); i-- ) {
1050 status = rpccli_samr_add_groupmem( pipe_hnd, mem_ctx,
1055 /*we return with the NTSTATUS error that we got when trying to delete users */
1056 if ( !NT_STATUS_IS_OK( status ) )
1057 result = CAC_FAILURE;
1060 TALLOC_FREE( attr );
1065 int cac_SamSetGroupMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1066 struct SamSetGroupMembers *op )
1068 struct rpc_pipe_client *pipe_hnd = NULL;
1075 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1076 hnd->status = NT_STATUS_INVALID_HANDLE;
1080 if ( !op || !op->in.group_hnd || !mem_ctx ) {
1081 hnd->status = NT_STATUS_INVALID_PARAMETER;
1085 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1087 hnd->status = NT_STATUS_INVALID_HANDLE;
1091 /*use cac_SamClearGroupMembers() to clear them */
1092 if ( !cac_SamClearGroupMembers( hnd, mem_ctx, op->in.group_hnd ) )
1093 return CAC_FAILURE; /*hnd->status is already set */
1096 for ( i = 0; i < op->in.num_members && NT_STATUS_IS_OK( hnd->status );
1099 rpccli_samr_add_groupmem( pipe_hnd, mem_ctx,
1104 if ( !NT_STATUS_IS_OK( hnd->status ) )
1111 int cac_SamEnumGroups( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1112 struct SamEnumGroups *op )
1114 struct rpc_pipe_client *pipe_hnd = NULL;
1118 uint32 resume_idx_out = 0;
1119 char **names_out = NULL;
1120 char **desc_out = NULL;
1121 uint32 *rids_out = NULL;
1122 uint32 num_groups_out = 0;
1124 struct acct_info *acct_buf = NULL;
1129 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1130 hnd->status = NT_STATUS_INVALID_HANDLE;
1134 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
1135 hnd->status = NT_STATUS_INVALID_PARAMETER;
1139 /*using this BOOL is the only reliable way to know that we are done */
1140 if ( op->out.done == True ) /*we return failure so the call will break out of a loop */
1143 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1145 hnd->status = NT_STATUS_INVALID_HANDLE;
1149 resume_idx_out = op->out.resume_idx;
1152 rpccli_samr_enum_dom_groups( pipe_hnd, mem_ctx,
1153 op->in.dom_hnd, &resume_idx_out,
1154 SAMR_ENUM_MAX_SIZE, &acct_buf,
1158 if ( NT_STATUS_IS_OK( hnd->status ) ) {
1159 op->out.done = True;
1160 } else if ( NT_STATUS_V( hnd->status ) !=
1161 NT_STATUS_V( STATUS_MORE_ENTRIES ) ) {
1162 /*if there are no more entries, the operation will return NT_STATUS_OK.
1163 * We want to return failure if no results were returned*/
1167 if (num_groups_out) {
1168 names_out = TALLOC_ARRAY( mem_ctx, char *, num_groups_out );
1170 hnd->status = NT_STATUS_NO_MEMORY;
1171 TALLOC_FREE( acct_buf );
1175 desc_out = TALLOC_ARRAY( mem_ctx, char *, num_groups_out );
1177 hnd->status = NT_STATUS_NO_MEMORY;
1178 TALLOC_FREE( acct_buf );
1179 TALLOC_FREE( names_out );
1183 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_groups_out );
1185 hnd->status = NT_STATUS_NO_MEMORY;
1186 TALLOC_FREE( acct_buf );
1187 TALLOC_FREE( names_out );
1188 TALLOC_FREE( desc_out );
1197 for ( i = 0; i < num_groups_out; i++ ) {
1199 talloc_strdup( mem_ctx, acct_buf[i].acct_name );
1200 desc_out[i] = talloc_strdup( mem_ctx, acct_buf[i].acct_desc );
1201 rids_out[i] = acct_buf[i].rid;
1203 if ( !names_out[i] || !desc_out[i] ) {
1204 hnd->status = NT_STATUS_NO_MEMORY;
1209 op->out.resume_idx = resume_idx_out;
1210 op->out.num_groups = num_groups_out;
1211 op->out.rids = rids_out;
1212 op->out.names = names_out;
1213 op->out.descriptions = desc_out;
1218 int cac_SamEnumAliases( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1219 struct SamEnumAliases *op )
1221 struct rpc_pipe_client *pipe_hnd = NULL;
1225 uint32 resume_idx_out = 0;
1226 char **names_out = NULL;
1227 char **desc_out = NULL;
1228 uint32 *rids_out = NULL;
1229 uint32 num_als_out = 0;
1231 struct acct_info *acct_buf = NULL;
1236 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1237 hnd->status = NT_STATUS_INVALID_HANDLE;
1241 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
1242 hnd->status = NT_STATUS_INVALID_PARAMETER;
1246 /*this is a hack.. but is the only reliable way to know if everything has been enumerated */
1247 if ( op->out.done == True ) {
1251 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1253 hnd->status = NT_STATUS_INVALID_HANDLE;
1257 resume_idx_out = op->out.resume_idx;
1260 rpccli_samr_enum_als_groups( pipe_hnd, mem_ctx,
1261 op->in.dom_hnd, &resume_idx_out,
1262 SAMR_ENUM_MAX_SIZE, &acct_buf,
1266 if ( NT_STATUS_IS_OK( hnd->status ) )
1267 op->out.done = True;
1269 /*if there are no more entries, the operation will return NT_STATUS_OK.
1270 * We want to return failure if no results were returned*/
1271 if ( !NT_STATUS_IS_OK( hnd->status )
1272 && NT_STATUS_V( hnd->status ) !=
1273 NT_STATUS_V( STATUS_MORE_ENTRIES ) )
1277 names_out = TALLOC_ARRAY( mem_ctx, char *, num_als_out );
1279 hnd->status = NT_STATUS_NO_MEMORY;
1280 TALLOC_FREE( acct_buf );
1284 desc_out = TALLOC_ARRAY( mem_ctx, char *, num_als_out );
1286 hnd->status = NT_STATUS_NO_MEMORY;
1287 TALLOC_FREE( acct_buf );
1288 TALLOC_FREE( names_out );
1292 rids_out = TALLOC_ARRAY( mem_ctx, uint32, num_als_out );
1294 hnd->status = NT_STATUS_NO_MEMORY;
1295 TALLOC_FREE( acct_buf );
1296 TALLOC_FREE( names_out );
1297 TALLOC_FREE( desc_out );
1306 for ( i = 0; i < num_als_out; i++ ) {
1308 talloc_strdup( mem_ctx, acct_buf[i].acct_name );
1309 desc_out[i] = talloc_strdup( mem_ctx, acct_buf[i].acct_desc );
1310 rids_out[i] = acct_buf[i].rid;
1312 if ( !names_out[i] || !desc_out[i] ) {
1313 hnd->status = NT_STATUS_NO_MEMORY;
1318 op->out.resume_idx = resume_idx_out;
1319 op->out.num_aliases = num_als_out;
1320 op->out.rids = rids_out;
1321 op->out.names = names_out;
1322 op->out.descriptions = desc_out;
1327 int cac_SamCreateAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1328 struct SamCreateAlias *op )
1330 struct rpc_pipe_client *pipe_hnd = NULL;
1332 POLICY_HND *als_hnd_out = NULL;
1337 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1338 hnd->status = NT_STATUS_INVALID_HANDLE;
1342 if ( !op || !op->in.name || op->in.name[0] == '\0' || !mem_ctx ) {
1343 hnd->status = NT_STATUS_INVALID_PARAMETER;
1347 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1349 hnd->status = NT_STATUS_INVALID_HANDLE;
1353 als_hnd_out = talloc( mem_ctx, POLICY_HND );
1354 if ( !als_hnd_out ) {
1355 hnd->status = NT_STATUS_NO_MEMORY;
1360 rpccli_samr_create_dom_alias( pipe_hnd, mem_ctx,
1361 op->in.dom_hnd, op->in.name,
1364 if ( !NT_STATUS_IS_OK( hnd->status ) )
1367 op->out.alias_hnd = als_hnd_out;
1373 int cac_SamOpenAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1374 struct SamOpenAlias *op )
1376 struct rpc_pipe_client *pipe_hnd = NULL;
1378 POLICY_HND *als_hnd_out = NULL;
1383 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1384 hnd->status = NT_STATUS_INVALID_HANDLE;
1388 if ( !op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx ) {
1389 hnd->status = NT_STATUS_INVALID_PARAMETER;
1393 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1395 hnd->status = NT_STATUS_INVALID_HANDLE;
1399 als_hnd_out = talloc( mem_ctx, POLICY_HND );
1400 if ( !als_hnd_out ) {
1401 hnd->status = NT_STATUS_NO_MEMORY;
1406 rpccli_samr_open_alias( pipe_hnd, mem_ctx, op->in.dom_hnd,
1407 op->in.access, op->in.rid,
1410 if ( !NT_STATUS_IS_OK( hnd->status ) )
1413 op->out.alias_hnd = als_hnd_out;
1418 int cac_SamDeleteAlias( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1419 POLICY_HND * alias_hnd )
1421 struct rpc_pipe_client *pipe_hnd = NULL;
1426 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1427 hnd->status = NT_STATUS_INVALID_HANDLE;
1431 if ( !alias_hnd || !mem_ctx ) {
1432 hnd->status = NT_STATUS_INVALID_PARAMETER;
1436 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1438 hnd->status = NT_STATUS_INVALID_HANDLE;
1443 rpccli_samr_delete_dom_alias( pipe_hnd, mem_ctx, alias_hnd );
1445 if ( !NT_STATUS_IS_OK( hnd->status ) )
1452 int cac_SamAddAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1453 struct SamAddAliasMember *op )
1455 struct rpc_pipe_client *pipe_hnd = NULL;
1460 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1461 hnd->status = NT_STATUS_INVALID_HANDLE;
1465 if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
1466 hnd->status = NT_STATUS_INVALID_PARAMETER;
1470 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1472 hnd->status = NT_STATUS_INVALID_HANDLE;
1477 rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
1480 if ( !NT_STATUS_IS_OK( hnd->status ) )
1486 int cac_SamRemoveAliasMember( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1487 struct SamRemoveAliasMember *op )
1489 struct rpc_pipe_client *pipe_hnd = NULL;
1494 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1495 hnd->status = NT_STATUS_INVALID_HANDLE;
1499 if ( !op || !op->in.alias_hnd || !op->in.sid || !mem_ctx ) {
1500 hnd->status = NT_STATUS_INVALID_PARAMETER;
1504 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1506 hnd->status = NT_STATUS_INVALID_HANDLE;
1511 rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd,
1514 if ( !NT_STATUS_IS_OK( hnd->status ) )
1520 int cac_SamGetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1521 struct SamGetAliasMembers *op )
1523 struct rpc_pipe_client *pipe_hnd = NULL;
1531 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1532 hnd->status = NT_STATUS_INVALID_HANDLE;
1536 if ( !op || !op->in.alias_hnd || !mem_ctx ) {
1537 hnd->status = NT_STATUS_INVALID_PARAMETER;
1541 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1543 hnd->status = NT_STATUS_INVALID_HANDLE;
1548 rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx,
1549 op->in.alias_hnd, &num_mem_out,
1552 if ( !NT_STATUS_IS_OK( hnd->status ) )
1555 op->out.num_members = num_mem_out;
1556 op->out.sids = sids_out;
1561 int cac_SamClearAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1562 POLICY_HND * alias_hnd )
1564 struct rpc_pipe_client *pipe_hnd = NULL;
1566 int result = CAC_SUCCESS;
1571 DOM_SID *sid = NULL;
1578 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1579 hnd->status = NT_STATUS_INVALID_HANDLE;
1583 if ( !alias_hnd || !mem_ctx ) {
1584 hnd->status = NT_STATUS_INVALID_PARAMETER;
1588 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1590 hnd->status = NT_STATUS_INVALID_HANDLE;
1595 rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx, alias_hnd,
1598 if ( !NT_STATUS_IS_OK( hnd->status ) )
1601 /*try to delete the users one by one */
1602 for ( i = 0; i < num_mem && NT_STATUS_IS_OK( hnd->status ); i++ ) {
1604 rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx,
1605 alias_hnd, &sid[i] );
1608 /*if not all members could be removed, then try to re-add the members that were already deleted */
1609 if ( !NT_STATUS_IS_OK( hnd->status ) ) {
1610 status = NT_STATUS_OK;
1612 for ( i -= 1; i >= 0 && NT_STATUS_IS_OK( status ); i-- ) {
1613 status = rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx,
1618 /*we return with the NTSTATUS error that we got when trying to delete users */
1619 if ( !NT_STATUS_IS_OK( status ) )
1620 result = CAC_FAILURE;
1627 int cac_SamSetAliasMembers( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1628 struct SamSetAliasMembers *op )
1630 struct rpc_pipe_client *pipe_hnd = NULL;
1637 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1638 hnd->status = NT_STATUS_INVALID_HANDLE;
1642 if ( !op || !op->in.alias_hnd || !mem_ctx ) {
1643 hnd->status = NT_STATUS_INVALID_PARAMETER;
1647 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1649 hnd->status = NT_STATUS_INVALID_HANDLE;
1653 /*use cac_SamClearAliasMembers() to clear them */
1654 if ( !cac_SamClearAliasMembers( hnd, mem_ctx, op->in.alias_hnd ) )
1655 return CAC_FAILURE; /*hnd->status is already set */
1658 for ( i = 0; i < op->in.num_members && NT_STATUS_IS_OK( hnd->status );
1661 rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx,
1663 &( op->in.sids[i] ) );
1666 if ( !NT_STATUS_IS_OK( hnd->status ) )
1673 int cac_SamUserChangePasswd( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1674 struct SamUserChangePasswd *op )
1676 SMBCSRV *srv = NULL;
1677 struct rpc_pipe_client *pipe_hnd = NULL;
1682 if ( !hnd->_internal.ctx ) {
1683 hnd->status = NT_STATUS_INVALID_HANDLE;
1687 if ( !op || !op->in.username || !op->in.password
1688 || !op->in.new_password || !mem_ctx ) {
1689 hnd->status = NT_STATUS_INVALID_PARAMETER;
1693 srv = cac_GetServer( hnd );
1695 hnd->status = NT_STATUS_INVALID_CONNECTION;
1699 /*open a session on SAMR if we don't have one */
1700 if ( !hnd->_internal.pipes[PI_SAMR] ) {
1703 cli_rpc_pipe_open_noauth( srv->cli, PI_SAMR,
1704 &hnd->status ) ) ) {
1708 hnd->_internal.pipes[PI_SAMR] = True;
1711 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1713 hnd->status = NT_STATUS_INVALID_HANDLE;
1718 rpccli_samr_chgpasswd_user( pipe_hnd, mem_ctx,
1720 op->in.new_password,
1723 if ( !NT_STATUS_IS_OK( hnd->status ) )
1729 int cac_SamEnableUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1730 POLICY_HND * user_hnd )
1732 SMBCSRV *srv = NULL;
1733 struct rpc_pipe_client *pipe_hnd = NULL;
1735 SAM_USERINFO_CTR *ctr;
1740 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1741 hnd->status = NT_STATUS_INVALID_HANDLE;
1745 if ( !user_hnd || !mem_ctx ) {
1746 hnd->status = NT_STATUS_INVALID_PARAMETER;
1750 srv = cac_GetServer( hnd );
1752 hnd->status = NT_STATUS_INVALID_CONNECTION;
1756 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1758 hnd->status = NT_STATUS_INVALID_HANDLE;
1762 /*info_level = 21 is the only level that I have found to work reliably. It would be nice if user_level = 10 worked. */
1764 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10,
1767 if ( !NT_STATUS_IS_OK( hnd->status ) )
1770 /**check the ACB mask*/
1771 if ( ( ctr->info.id16->acb_info & ACB_DISABLED ) == ACB_DISABLED ) {
1772 /*toggle the disabled bit */
1773 ctr->info.id16->acb_info ^= ACB_DISABLED;
1775 /*the user is already enabled so just return success */
1779 /*now set the userinfo */
1781 rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10,
1782 &srv->cli->user_session_key, ctr );
1784 /*this will only work properly if we use set_userinfo2 - fail if it is not supported */
1785 if ( !NT_STATUS_IS_OK( hnd->status ) )
1791 int cac_SamDisableUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1792 POLICY_HND * user_hnd )
1794 SMBCSRV *srv = NULL;
1795 struct rpc_pipe_client *pipe_hnd = NULL;
1797 SAM_USERINFO_CTR *ctr;
1802 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1803 hnd->status = NT_STATUS_INVALID_HANDLE;
1807 if ( !user_hnd || !mem_ctx ) {
1808 hnd->status = NT_STATUS_INVALID_PARAMETER;
1812 srv = cac_GetServer( hnd );
1814 hnd->status = NT_STATUS_INVALID_CONNECTION;
1818 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1820 hnd->status = NT_STATUS_INVALID_HANDLE;
1825 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10,
1828 if ( !NT_STATUS_IS_OK( hnd->status ) )
1831 if ( ( ctr->info.id16->acb_info & ACB_DISABLED ) == ACB_DISABLED ) {
1832 /*then the user is already disabled */
1836 /*toggle the disabled bit */
1837 ctr->info.id16->acb_info ^= ACB_DISABLED;
1839 /*this will only work properly if we use set_userinfo2 */
1841 rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10,
1842 &srv->cli->user_session_key, ctr );
1844 /*this will only work properly if we use set_userinfo2 fail if it is not supported */
1845 if ( !NT_STATUS_IS_OK( hnd->status ) )
1851 int cac_SamSetPassword( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1852 struct SamSetPassword *op )
1854 SMBCSRV *srv = NULL;
1855 struct rpc_pipe_client *pipe_hnd = NULL;
1857 SAM_USERINFO_CTR ctr;
1858 SAM_USER_INFO_24 info24;
1864 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1865 hnd->status = NT_STATUS_INVALID_HANDLE;
1869 if ( !op->in.user_hnd || !op->in.password || !mem_ctx ) {
1870 hnd->status = NT_STATUS_INVALID_PARAMETER;
1874 srv = cac_GetServer( hnd );
1876 hnd->status = NT_STATUS_INVALID_CONNECTION;
1880 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1882 hnd->status = NT_STATUS_INVALID_HANDLE;
1887 ZERO_STRUCT( info24 );
1889 encode_pw_buffer( pw, op->in.password, STR_UNICODE );
1891 init_sam_user_info24( &info24, ( char * ) pw, 24 );
1893 ctr.switch_value = 24;
1894 ctr.info.id24 = &info24;
1897 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
1898 24, &srv->cli->user_session_key,
1901 if ( !NT_STATUS_IS_OK( hnd->status ) )
1907 int cac_SamGetUserInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1908 struct SamGetUserInfo *op )
1910 struct rpc_pipe_client *pipe_hnd = NULL;
1912 SAM_USERINFO_CTR *ctr;
1917 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1918 hnd->status = NT_STATUS_INVALID_HANDLE;
1922 if ( !op->in.user_hnd || !mem_ctx ) {
1923 hnd->status = NT_STATUS_INVALID_PARAMETER;
1927 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1929 hnd->status = NT_STATUS_INVALID_HANDLE;
1934 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
1935 op->in.user_hnd, 21, &ctr );
1937 if ( !NT_STATUS_IS_OK( hnd->status ) )
1940 op->out.info = cac_MakeUserInfo( mem_ctx, ctr );
1942 if ( !op->out.info ) {
1943 hnd->status = NT_STATUS_NO_MEMORY;
1950 int cac_SamSetUserInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
1951 struct SamSetUserInfo *op )
1953 SMBCSRV *srv = NULL;
1954 struct rpc_pipe_client *pipe_hnd = NULL;
1956 SAM_USERINFO_CTR *ctr;
1961 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
1962 hnd->status = NT_STATUS_INVALID_HANDLE;
1966 if ( !op->in.user_hnd || !op->in.info || !mem_ctx ) {
1967 hnd->status = NT_STATUS_INVALID_PARAMETER;
1971 ctr = cac_MakeUserInfoCtr( mem_ctx, op->in.info );
1973 hnd->status = NT_STATUS_NO_MEMORY;
1977 srv = cac_GetServer( hnd );
1979 hnd->status = NT_STATUS_INVALID_CONNECTION;
1983 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
1985 hnd->status = NT_STATUS_INVALID_HANDLE;
1989 if ( hnd->_internal.srv_level >= SRV_WIN_NT4 ) {
1991 rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx,
1992 op->in.user_hnd, 21,
1994 user_session_key, ctr );
1997 if ( hnd->_internal.srv_level < SRV_WIN_NT4
1998 || !NT_STATUS_IS_OK( hnd->status ) ) {
2000 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx,
2001 op->in.user_hnd, 21,
2002 &srv->cli->user_session_key,
2005 if ( NT_STATUS_IS_OK( hnd->status )
2006 && hnd->_internal.srv_level > SRV_WIN_NT4 ) {
2007 hnd->_internal.srv_level = SRV_WIN_NT4;
2012 if ( !NT_STATUS_IS_OK( hnd->status ) )
2019 int cac_SamGetUserInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2020 struct SamGetUserInfoCtr *op )
2022 struct rpc_pipe_client *pipe_hnd = NULL;
2024 SAM_USERINFO_CTR *ctr_out;
2029 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2030 hnd->status = NT_STATUS_INVALID_HANDLE;
2034 if ( !op->in.user_hnd || op->in.info_class == 0 || !mem_ctx ) {
2035 hnd->status = NT_STATUS_INVALID_PARAMETER;
2039 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2041 hnd->status = NT_STATUS_INVALID_HANDLE;
2046 rpccli_samr_query_userinfo( pipe_hnd, mem_ctx,
2048 op->in.info_class, &ctr_out );
2050 if ( !NT_STATUS_IS_OK( hnd->status ) )
2053 op->out.ctr = ctr_out;
2058 int cac_SamSetUserInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2059 struct SamSetUserInfoCtr *op )
2061 SMBCSRV *srv = NULL;
2062 struct rpc_pipe_client *pipe_hnd = NULL;
2067 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2068 hnd->status = NT_STATUS_INVALID_HANDLE;
2072 if ( !op->in.user_hnd || !op->in.ctr || !mem_ctx ) {
2073 hnd->status = NT_STATUS_INVALID_PARAMETER;
2077 srv = cac_GetServer( hnd );
2079 hnd->status = NT_STATUS_INVALID_CONNECTION;
2083 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2085 hnd->status = NT_STATUS_INVALID_HANDLE;
2091 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
2092 op->in.ctr->switch_value,
2093 &srv->cli->user_session_key,
2096 if ( !NT_STATUS_IS_OK( hnd->status ) )
2103 int cac_SamRenameUser( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2104 struct SamRenameUser *op )
2106 SMBCSRV *srv = NULL;
2107 struct rpc_pipe_client *pipe_hnd = NULL;
2109 SAM_USERINFO_CTR ctr;
2110 SAM_USER_INFO_7 info7;
2115 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2116 hnd->status = NT_STATUS_INVALID_HANDLE;
2120 if ( !op->in.user_hnd || !op->in.new_name
2121 || op->in.new_name[0] == '\0' || !mem_ctx ) {
2122 hnd->status = NT_STATUS_INVALID_PARAMETER;
2126 srv = cac_GetServer( hnd );
2128 hnd->status = NT_STATUS_INVALID_CONNECTION;
2132 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2134 hnd->status = NT_STATUS_INVALID_HANDLE;
2139 ZERO_STRUCT( info7 );
2141 init_sam_user_info7( &info7, op->in.new_name );
2143 ctr.switch_value = 7;
2144 ctr.info.id7 = &info7;
2147 rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd,
2148 7, &srv->cli->user_session_key,
2151 if ( !NT_STATUS_IS_OK( hnd->status ) )
2158 int cac_SamGetGroupInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2159 struct SamGetGroupInfo *op )
2161 struct rpc_pipe_client *pipe_hnd = NULL;
2163 GROUP_INFO_CTR *ctr;
2168 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2169 hnd->status = NT_STATUS_INVALID_HANDLE;
2173 if ( !op->in.group_hnd || !mem_ctx ) {
2174 hnd->status = NT_STATUS_INVALID_PARAMETER;
2178 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2180 hnd->status = NT_STATUS_INVALID_HANDLE;
2185 /*get a GROUP_INFO_1 structure */
2187 rpccli_samr_query_groupinfo( pipe_hnd, mem_ctx,
2188 op->in.group_hnd, 1, &ctr );
2190 if ( !NT_STATUS_IS_OK( hnd->status ) )
2193 op->out.info = cac_MakeGroupInfo( mem_ctx, ctr );
2194 if ( !op->out.info ) {
2195 hnd->status = NT_STATUS_NO_MEMORY;
2202 int cac_SamSetGroupInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2203 struct SamSetGroupInfo *op )
2205 struct rpc_pipe_client *pipe_hnd = NULL;
2207 GROUP_INFO_CTR *ctr = NULL;
2212 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2213 hnd->status = NT_STATUS_INVALID_HANDLE;
2217 if ( !op->in.group_hnd || !op->in.info || !mem_ctx ) {
2218 hnd->status = NT_STATUS_INVALID_PARAMETER;
2222 ctr = cac_MakeGroupInfoCtr( mem_ctx, op->in.info );
2224 hnd->status = NT_STATUS_NO_MEMORY;
2228 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2230 hnd->status = NT_STATUS_INVALID_HANDLE;
2235 rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
2236 op->in.group_hnd, ctr );
2238 if ( !NT_STATUS_IS_OK( hnd->status ) )
2244 int cac_SamRenameGroup( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2245 struct SamRenameGroup *op )
2247 struct rpc_pipe_client *pipe_hnd = NULL;
2254 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2255 hnd->status = NT_STATUS_INVALID_HANDLE;
2259 if ( !op->in.group_hnd || !op->in.new_name
2260 || op->in.new_name[0] == '\0' || !mem_ctx ) {
2261 hnd->status = NT_STATUS_INVALID_PARAMETER;
2265 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2267 hnd->status = NT_STATUS_INVALID_HANDLE;
2273 init_samr_group_info2( &ctr.group.info2, op->in.new_name );
2274 ctr.switch_value1 = 2;
2277 rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx,
2278 op->in.group_hnd, &ctr );
2280 if ( !NT_STATUS_IS_OK( hnd->status ) )
2286 int cac_SamGetAliasInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2287 struct SamGetAliasInfo *op )
2289 struct rpc_pipe_client *pipe_hnd = NULL;
2296 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2297 hnd->status = NT_STATUS_INVALID_HANDLE;
2301 if ( !op->in.alias_hnd || !mem_ctx ) {
2302 hnd->status = NT_STATUS_INVALID_PARAMETER;
2306 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2308 hnd->status = NT_STATUS_INVALID_HANDLE;
2312 /*get a GROUP_INFO_1 structure */
2314 rpccli_samr_query_alias_info( pipe_hnd, mem_ctx,
2315 op->in.alias_hnd, 1, &ctr );
2317 if ( !NT_STATUS_IS_OK( hnd->status ) )
2320 op->out.info = cac_MakeAliasInfo( mem_ctx, ctr );
2321 if ( !op->out.info ) {
2322 hnd->status = NT_STATUS_NO_MEMORY;
2330 int cac_SamSetAliasInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2331 struct SamSetAliasInfo *op )
2333 struct rpc_pipe_client *pipe_hnd = NULL;
2335 ALIAS_INFO_CTR *ctr = NULL;
2340 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2341 hnd->status = NT_STATUS_INVALID_HANDLE;
2345 if ( !op->in.alias_hnd || !op->in.info || !mem_ctx ) {
2346 hnd->status = NT_STATUS_INVALID_PARAMETER;
2350 ctr = cac_MakeAliasInfoCtr( mem_ctx, op->in.info );
2352 hnd->status = NT_STATUS_NO_MEMORY;
2356 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2358 hnd->status = NT_STATUS_INVALID_HANDLE;
2363 rpccli_samr_set_aliasinfo( pipe_hnd, mem_ctx,
2364 op->in.alias_hnd, ctr );
2366 if ( !NT_STATUS_IS_OK( hnd->status ) )
2372 int cac_SamGetDomainInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2373 struct SamGetDomainInfo *op )
2375 struct rpc_pipe_client *pipe_hnd = NULL;
2378 SAM_UNK_INFO_1 info1;
2379 SAM_UNK_INFO_2 info2;
2380 SAM_UNK_INFO_12 info12;
2382 /*use this to keep track of a failed call */
2383 NTSTATUS status_buf = NT_STATUS_OK;
2385 uint16 fail_count = 0;
2391 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2392 hnd->status = NT_STATUS_INVALID_HANDLE;
2396 if ( !op->in.dom_hnd || !mem_ctx ) {
2397 hnd->status = NT_STATUS_INVALID_PARAMETER;
2401 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2403 hnd->status = NT_STATUS_INVALID_HANDLE;
2407 /*first try with info 1 */
2409 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2412 if ( NT_STATUS_IS_OK( hnd->status ) ) {
2413 /*then we buffer the SAM_UNK_INFO_1 structure */
2414 info1 = ctr.info.inf1;
2416 /*then the call failed, store the status and ZERO out the info structure */
2417 ZERO_STRUCT( info1 );
2418 status_buf = hnd->status;
2422 /*try again for the next one */
2424 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2427 if ( NT_STATUS_IS_OK( hnd->status ) ) {
2429 info2 = ctr.info.inf2;
2431 /*ZERO out the structure and store the bad status */
2432 ZERO_STRUCT( info2 );
2433 status_buf = hnd->status;
2439 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2442 if ( NT_STATUS_IS_OK( hnd->status ) ) {
2443 info12 = ctr.info.inf12;
2445 ZERO_STRUCT( info12 );
2446 status_buf = hnd->status;
2450 /*return failure if all 3 calls failed */
2451 if ( fail_count == 3 )
2454 op->out.info = cac_MakeDomainInfo( mem_ctx, &info1, &info2, &info12 );
2456 if ( !op->out.info ) {
2457 hnd->status = NT_STATUS_NO_MEMORY;
2461 if ( fail_count > 0 ) {
2462 hnd->status = status_buf;
2463 return CAC_PARTIAL_SUCCESS;
2469 int cac_SamGetDomainInfoCtr( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2470 struct SamGetDomainInfoCtr *op )
2472 struct rpc_pipe_client *pipe_hnd = NULL;
2474 SAM_UNK_CTR *ctr_out;
2479 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2480 hnd->status = NT_STATUS_INVALID_HANDLE;
2484 if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
2485 hnd->status = NT_STATUS_INVALID_PARAMETER;
2489 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2491 hnd->status = NT_STATUS_INVALID_HANDLE;
2495 ctr_out = talloc( mem_ctx, SAM_UNK_CTR );
2497 hnd->status = NT_STATUS_NO_MEMORY;
2502 rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd,
2503 op->in.info_class, ctr_out );
2505 if ( !NT_STATUS_IS_OK( hnd->status ) )
2508 op->out.info = ctr_out;
2513 int cac_SamGetDisplayInfo( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2514 struct SamGetDisplayInfo *op )
2516 struct rpc_pipe_client *pipe_hnd = NULL;
2518 SAM_DISPINFO_CTR ctr_out;
2520 uint32 max_entries_buf = 0;
2521 uint32 max_size_buf = 0;
2523 uint32 resume_idx_out;
2524 uint32 num_entries_out;
2529 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2530 hnd->status = NT_STATUS_INVALID_HANDLE;
2534 if ( !op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx ) {
2535 hnd->status = NT_STATUS_INVALID_PARAMETER;
2539 if ( op->out.done == True ) /*this is done so we can use the function as a loop condition */
2542 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2544 hnd->status = NT_STATUS_INVALID_HANDLE;
2548 if ( op->in.max_entries == 0 || op->in.max_size == 0 ) {
2549 get_query_dispinfo_params( op->out.loop_count,
2550 &max_entries_buf, &max_size_buf );
2552 max_entries_buf = op->in.max_entries;
2553 max_size_buf = op->in.max_size;
2556 resume_idx_out = op->out.resume_idx;
2559 rpccli_samr_query_dispinfo( pipe_hnd, mem_ctx, op->in.dom_hnd,
2562 &num_entries_out, max_entries_buf,
2563 max_size_buf, &ctr_out );
2565 if ( !NT_STATUS_IS_OK( hnd->status )
2566 && !NT_STATUS_EQUAL( hnd->status, STATUS_MORE_ENTRIES ) ) {
2567 /*be defensive, maybe they'll call again without zeroing the struct */
2568 op->out.loop_count = 0;
2569 op->out.resume_idx = 0;
2573 if ( NT_STATUS_IS_OK( hnd->status ) ) {
2574 /*we want to quit once the function is called next. so it can be used in a loop */
2575 op->out.done = True;
2578 op->out.resume_idx = resume_idx_out;
2579 op->out.num_entries = num_entries_out;
2580 op->out.ctr = ctr_out;
2581 op->out.loop_count++;
2586 int cac_SamLookupDomain( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2587 struct SamLookupDomain *op )
2589 struct rpc_pipe_client *pipe_hnd = NULL;
2591 DOM_SID *sid_out = NULL;
2596 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2597 hnd->status = NT_STATUS_INVALID_HANDLE;
2601 if ( !op->in.sam || !op->in.name || !mem_ctx ) {
2602 hnd->status = NT_STATUS_INVALID_PARAMETER;
2606 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2608 hnd->status = NT_STATUS_INVALID_HANDLE;
2612 sid_out = talloc( mem_ctx, DOM_SID );
2614 hnd->status = NT_STATUS_NO_MEMORY;
2619 rpccli_samr_lookup_domain( pipe_hnd, mem_ctx, op->in.sam,
2620 op->in.name, sid_out );
2622 if ( !NT_STATUS_IS_OK( hnd->status ) )
2625 op->out.sid = sid_out;
2630 int cac_SamGetSecurityObject( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2631 struct SamGetSecurityObject *op )
2633 struct rpc_pipe_client *pipe_hnd = NULL;
2635 /*this number taken from rpcclient/cmd_samr.c, I think it is the only supported level */
2636 uint32 sec_info = DACL_SECURITY_INFORMATION;
2638 SEC_DESC_BUF *sec_out = NULL;
2643 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2644 hnd->status = NT_STATUS_INVALID_HANDLE;
2648 if ( !op->in.pol || !mem_ctx ) {
2649 hnd->status = NT_STATUS_INVALID_PARAMETER;
2653 pipe_hnd = cac_GetPipe( hnd, PI_SAMR );
2655 hnd->status = NT_STATUS_INVALID_HANDLE;
2660 rpccli_samr_query_sec_obj( pipe_hnd, mem_ctx, op->in.pol,
2661 sec_info, mem_ctx, &sec_out );
2663 if ( !NT_STATUS_IS_OK( hnd->status ) )
2666 op->out.sec = sec_out;
2671 int cac_SamFlush( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
2672 struct SamFlush *op )
2674 struct SamOpenDomain od;
2679 if ( !hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR] ) {
2680 hnd->status = NT_STATUS_INVALID_HANDLE;
2684 if ( !op || !op->in.dom_hnd || !mem_ctx ) {
2685 hnd->status = NT_STATUS_INVALID_PARAMETER;
2689 if ( !cac_SamClose( hnd, mem_ctx, op->in.dom_hnd ) )
2694 ( op->in.access ) ? op->in.access : MAXIMUM_ALLOWED_ACCESS;
2695 od.in.sid = op->in.sid;
2697 if ( !cac_SamOpenDomain( hnd, mem_ctx, &od ) )
2700 /*this function does not use an output parameter to make it as convenient as possible to use */
2701 *op->in.dom_hnd = *od.out.dom_hnd;
2703 TALLOC_FREE( od.out.dom_hnd );