2 * Unix SMB/CIFS implementation.
3 * MS-RPC client library implementation (SAMR pipe)
4 * Copyright (C) Chris Nicholls 2005.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 int cac_SamConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamConnect *op) {
34 struct rpc_pipe_client *pipe_hnd = NULL;
35 POLICY_HND *sam_out = NULL;
40 if(!hnd->_internal.ctx) {
41 hnd->status = NT_STATUS_INVALID_HANDLE;
45 if(!op || op->in.access == 0 || !mem_ctx) {
46 hnd->status = NT_STATUS_INVALID_PARAMETER;
50 srv = cac_GetServer(hnd);
52 hnd->status = NT_STATUS_INVALID_CONNECTION;
56 /*initialize for samr pipe if we have to*/
57 if(!hnd->_internal.pipes[PI_SAMR]) {
58 if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_SAMR, &hnd->status))) {
62 hnd->_internal.pipes[PI_SAMR] = True;
65 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
67 hnd->status = NT_STATUS_INVALID_HANDLE;
71 sam_out = talloc(mem_ctx, POLICY_HND);
73 hnd->status = NT_STATUS_NO_MEMORY;
77 if(hnd->_internal.srv_level >= SRV_WIN_2K_SP3) {
78 hnd->status = rpccli_samr_connect4( pipe_hnd, mem_ctx, op->in.access, sam_out);
81 if(hnd->_internal.srv_level < SRV_WIN_2K_SP3 || !NT_STATUS_IS_OK(hnd->status)) {
82 /*if sam_connect4 failed, the use sam_connect and lower srv_level*/
84 hnd->status = rpccli_samr_connect( pipe_hnd, mem_ctx, op->in.access, sam_out);
86 if(NT_STATUS_IS_OK(hnd->status) && hnd->_internal.srv_level > SRV_WIN_2K) {
87 hnd->_internal.srv_level = SRV_WIN_2K;
91 if(!NT_STATUS_IS_OK(hnd->status))
94 op->out.sam = sam_out;
99 int cac_SamClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *sam) {
100 struct rpc_pipe_client *pipe_hnd = NULL;
105 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
106 hnd->status = NT_STATUS_INVALID_HANDLE;
110 if(!sam || !mem_ctx) {
111 hnd->status = NT_STATUS_INVALID_PARAMETER;
115 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
117 hnd->status = NT_STATUS_INVALID_HANDLE;
121 hnd->status = rpccli_samr_close( pipe_hnd, mem_ctx, sam);
123 if(!NT_STATUS_IS_OK(hnd->status))
129 /*this is an internal function. Due to a circular dependency, it must be prototyped in libmsrpc.h (which I don't want to do)
130 * cac_SamOpenDomain() is the only function that calls it, so I just put the definition here
132 /*attempts to find the sid of the domain we are connected to*/
133 DOM_SID *cac_get_domain_sid(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, uint32 des_access) {
134 struct LsaOpenPolicy lop;
135 struct LsaFetchSid fs;
142 lop.in.access = des_access;
143 lop.in.security_qos = True;
145 if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop))
148 fs.in.pol = lop.out.pol;
149 fs.in.info_class = CAC_DOMAIN_INFO;
151 if(!cac_LsaFetchSid(hnd, mem_ctx, &fs))
154 cac_LsaClosePolicy(hnd, mem_ctx, lop.out.pol);
156 if(!fs.out.domain_sid)
159 sid = talloc_memdup(mem_ctx, &(fs.out.domain_sid->sid), sizeof(DOM_SID));
162 hnd->status = NT_STATUS_NO_MEMORY;
169 int cac_SamOpenDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenDomain *op) {
170 struct rpc_pipe_client *pipe_hnd = NULL;
176 struct SamLookupDomain sld;
181 if(!hnd->_internal.ctx) {
182 hnd->status = NT_STATUS_INVALID_HANDLE;
186 if(!op || op->in.access == 0 || !mem_ctx) {
187 hnd->status = NT_STATUS_INVALID_PARAMETER;
192 /*use cac_SamConnect() since it does the session setup*/
193 struct SamConnect sc;
196 sc.in.access = op->in.access;
198 if(!cac_SamConnect(hnd, mem_ctx, &sc)) {
202 sam_out = sc.out.sam;
205 sam_out = op->in.sam;
209 /*find the sid for the SAM's domain*/
211 /*try using cac_SamLookupDomain() first*/
214 sld.in.sam = sam_out;
215 sld.in.name = hnd->domain;
217 if(cac_SamLookupDomain(hnd, mem_ctx, &sld)) {
218 /*then we got the sid*/
219 sid_buf = sld.out.sid;
222 /*try to get it from the LSA*/
223 sid_buf = cac_get_domain_sid(hnd, mem_ctx, op->in.access);
227 /*we already have the sid for the domain we want*/
228 sid_buf = op->in.sid;
231 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
233 hnd->status = NT_STATUS_INVALID_HANDLE;
237 pol_out = talloc(mem_ctx, POLICY_HND);
239 hnd->status = NT_STATUS_NO_MEMORY;
243 /*now open the domain*/
244 hnd->status = rpccli_samr_open_domain( pipe_hnd, mem_ctx, sam_out, op->in.access, sid_buf, pol_out);
246 if(!NT_STATUS_IS_OK(hnd->status))
249 op->out.sam = sam_out;
250 op->out.dom_hnd = pol_out;
255 int cac_SamOpenUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenUser *op) {
256 struct rpc_pipe_client *pipe_hnd = NULL;
258 uint32 *rid_buf = NULL;
261 uint32 *rid_types = NULL;
263 POLICY_HND *user_out = NULL;
268 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
269 hnd->status = NT_STATUS_INVALID_HANDLE;
273 if(!op || !op->in.dom_hnd || op->in.access == 0 || !mem_ctx) {
274 hnd->status = NT_STATUS_INVALID_PARAMETER;
278 if(op->in.rid == 0 && op->in.name == NULL) {
279 hnd->status = NT_STATUS_INVALID_PARAMETER;
283 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
285 hnd->status = NT_STATUS_INVALID_HANDLE;
289 if(op->in.rid == 0 && op->in.name) {
290 /*lookup the name and then set rid_buf*/
292 hnd->status = rpccli_samr_lookup_names( pipe_hnd, mem_ctx, op->in.dom_hnd, SAMR_LOOKUP_FLAGS, 1, (const char **)&op->in.name,
293 &num_rids, &rid_buf, &rid_types);
295 if(!NT_STATUS_IS_OK(hnd->status))
298 if(num_rids == 0 || rid_buf == NULL || rid_types[0] == SAMR_RID_UNKNOWN) {
299 hnd->status = NT_STATUS_INVALID_PARAMETER;
303 TALLOC_FREE(rid_types);
307 rid_buf = &op->in.rid;
310 user_out = talloc(mem_ctx, POLICY_HND);
312 hnd->status = NT_STATUS_NO_MEMORY;
316 hnd->status = rpccli_samr_open_user(pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.access, *rid_buf, user_out);
318 if(!NT_STATUS_IS_OK(hnd->status))
321 op->out.user_hnd = user_out;
326 int cac_SamCreateUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateUser *op) {
327 struct rpc_pipe_client *pipe_hnd = NULL;
329 POLICY_HND *user_out = NULL;
332 /**found in rpcclient/cmd_samr.c*/
333 uint32 unknown = 0xe005000b;
338 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
339 hnd->status = NT_STATUS_INVALID_HANDLE;
343 if(!op || !op->in.dom_hnd || !op->in.name || op->in.acb_mask == 0 || !mem_ctx) {
344 hnd->status = NT_STATUS_INVALID_PARAMETER;
348 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
350 hnd->status = NT_STATUS_INVALID_HANDLE;
354 user_out = talloc(mem_ctx, POLICY_HND);
356 hnd->status = NT_STATUS_NO_MEMORY;
360 hnd->status = rpccli_samr_create_dom_user( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.name, op->in.acb_mask, unknown, user_out, &rid_out);
362 if(!NT_STATUS_IS_OK(hnd->status))
365 op->out.user_hnd = user_out;
366 op->out.rid = rid_out;
371 int cac_SamDeleteUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) {
372 struct rpc_pipe_client *pipe_hnd = NULL;
377 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
378 hnd->status = NT_STATUS_INVALID_HANDLE;
382 if(!user_hnd || !mem_ctx) {
383 hnd->status = NT_STATUS_INVALID_PARAMETER;
387 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
389 hnd->status = NT_STATUS_INVALID_HANDLE;
393 hnd->status = rpccli_samr_delete_dom_user( pipe_hnd, mem_ctx, user_hnd);
395 if(!NT_STATUS_IS_OK(hnd->status))
401 int cac_SamEnumUsers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumUsers *op) {
402 struct rpc_pipe_client *pipe_hnd = NULL;
404 uint32 resume_idx_out = 0;
405 char **names_out = NULL;
406 uint32 *rids_out = NULL;
407 uint32 num_users_out = 0;
412 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
413 hnd->status = NT_STATUS_INVALID_HANDLE;
417 if(!op || !op->in.dom_hnd || !mem_ctx) {
418 hnd->status = NT_STATUS_INVALID_PARAMETER;
422 /*this is a hack.. but is the only reliable way to know if everything has been enumerated*/
423 if(op->out.done == True)
426 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
428 hnd->status = NT_STATUS_INVALID_HANDLE;
432 resume_idx_out = op->out.resume_idx;
434 hnd->status = rpccli_samr_enum_dom_users( pipe_hnd, mem_ctx, op->in.dom_hnd, &resume_idx_out, op->in.acb_mask, SAMR_ENUM_MAX_SIZE,
435 &names_out, &rids_out, &num_users_out);
438 if(NT_STATUS_IS_OK(hnd->status))
441 /*if there are no more entries, the operation will return NT_STATUS_OK.
442 * We want to return failure if no results were returned*/
443 if(!NT_STATUS_IS_OK(hnd->status) && NT_STATUS_V(hnd->status) != NT_STATUS_V(STATUS_MORE_ENTRIES))
446 op->out.resume_idx= resume_idx_out;
447 op->out.num_users = num_users_out;
448 op->out.rids = rids_out;
449 op->out.names = names_out;
454 int cac_SamGetNamesFromRids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetNamesFromRids *op) {
455 struct rpc_pipe_client *pipe_hnd = NULL;
457 uint32 num_names_out;
459 uint32 *name_types_out;
464 CacLookupRidsRecord *map_out;
469 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
470 hnd->status = NT_STATUS_INVALID_HANDLE;
474 if(!op || !op->in.dom_hnd || !mem_ctx) {
475 hnd->status = NT_STATUS_INVALID_PARAMETER;
479 if(!op->in.rids && op->in.num_rids != 0) {
480 hnd->status = NT_STATUS_INVALID_PARAMETER;
484 if(op->in.num_rids == 0) {
486 op->out.num_names = 0;
490 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
492 hnd->status = NT_STATUS_INVALID_HANDLE;
496 hnd->status = rpccli_samr_lookup_rids( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.num_rids, op->in.rids, &num_names_out, &names_out, &name_types_out);
498 if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
501 map_out = TALLOC_ARRAY(mem_ctx, CacLookupRidsRecord, num_names_out);
503 hnd->status = NT_STATUS_NO_MEMORY;
507 for(i = 0; i < num_names_out; i++) {
508 if(name_types_out[i] == SAMR_RID_UNKNOWN) {
509 map_out[i].found = False;
510 map_out[i].name = NULL;
514 map_out[i].found = True;
515 map_out[i].name = talloc_strdup(mem_ctx, names_out[i]);
516 map_out[i].type = name_types_out[i];
518 map_out[i].rid = op->in.rids[i];
521 TALLOC_FREE(names_out);
522 TALLOC_FREE(name_types_out);
524 op->out.num_names = num_names_out;
525 op->out.map = map_out;
527 if(NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
528 return CAC_PARTIAL_SUCCESS;
533 int cac_SamGetRidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetRidsFromNames *op) {
534 struct rpc_pipe_client *pipe_hnd = NULL;
538 uint32 *rid_types_out;
542 CacLookupRidsRecord *map_out;
547 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
548 hnd->status = NT_STATUS_INVALID_HANDLE;
552 if(!op || !op->in.dom_hnd || !mem_ctx) {
553 hnd->status = NT_STATUS_INVALID_PARAMETER;
557 if(!op->in.names && op->in.num_names != 0) {
558 hnd->status = NT_STATUS_INVALID_PARAMETER;
562 if(op->in.num_names == 0) {
563 /*then we don't have to do anything*/
564 op->out.num_rids = 0;
568 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
570 hnd->status = NT_STATUS_INVALID_HANDLE;
574 hnd->status = rpccli_samr_lookup_names( pipe_hnd, mem_ctx, op->in.dom_hnd, SAMR_LOOKUP_FLAGS, op->in.num_names, (const char **)op->in.names,
575 &num_rids_out, &rids_out, &rid_types_out);
577 if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
580 map_out = TALLOC_ARRAY(mem_ctx, CacLookupRidsRecord, num_rids_out);
582 hnd->status = NT_STATUS_NO_MEMORY;
586 for(i = 0; i < num_rids_out; i++) {
588 if(rid_types_out[i] == SAMR_RID_UNKNOWN) {
589 map_out[i].found = False;
594 map_out[i].found = True;
595 map_out[i].rid = rids_out[i];
596 map_out[i].type = rid_types_out[i];
599 map_out[i].name = talloc_strdup(mem_ctx, op->in.names[i]);
602 op->out.num_rids = num_rids_out;
603 op->out.map = map_out;
605 TALLOC_FREE(rids_out);
606 TALLOC_FREE(rid_types_out);
608 if(NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
609 return CAC_PARTIAL_SUCCESS;
615 int cac_SamGetGroupsForUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupsForUser *op) {
616 struct rpc_pipe_client *pipe_hnd = NULL;
618 DOM_GID *groups = NULL;
619 uint32 num_groups_out = 0;
621 uint32 *rids_out = NULL;
622 uint32 *attr_out = NULL;
629 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
630 hnd->status = NT_STATUS_INVALID_HANDLE;
634 if(!op || !op->in.user_hnd || !mem_ctx) {
635 hnd->status = NT_STATUS_INVALID_PARAMETER;
639 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
641 hnd->status = NT_STATUS_INVALID_HANDLE;
645 hnd->status = rpccli_samr_query_usergroups(pipe_hnd, mem_ctx, op->in.user_hnd, &num_groups_out, &groups);
647 if(!NT_STATUS_IS_OK(hnd->status))
651 rids_out = talloc_array(mem_ctx, uint32, num_groups_out);
653 hnd->status = NT_STATUS_NO_MEMORY;
657 attr_out = talloc_array(mem_ctx, uint32, num_groups_out);
659 hnd->status = NT_STATUS_NO_MEMORY;
663 for(i = 0; i < num_groups_out; i++) {
664 rids_out[i] = groups[i].g_rid;
665 attr_out[i] = groups[i].attr;
670 op->out.num_groups = num_groups_out;
671 op->out.rids = rids_out;
672 op->out.attributes = attr_out;
678 int cac_SamOpenGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenGroup *op) {
679 struct rpc_pipe_client *pipe_hnd = NULL;
681 POLICY_HND *group_hnd_out = NULL;
686 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
687 hnd->status = NT_STATUS_INVALID_HANDLE;
691 if(!op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx) {
692 hnd->status = NT_STATUS_INVALID_PARAMETER;
696 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
698 hnd->status = NT_STATUS_INVALID_HANDLE;
702 group_hnd_out = talloc(mem_ctx, POLICY_HND);
704 hnd->status = NT_STATUS_NO_MEMORY;
708 hnd->status = rpccli_samr_open_group( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.access, op->in.rid, group_hnd_out);
710 if(!NT_STATUS_IS_OK(hnd->status))
713 op->out.group_hnd = group_hnd_out;
718 int cac_SamCreateGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateGroup *op) {
719 struct rpc_pipe_client *pipe_hnd = NULL;
721 POLICY_HND *group_hnd_out = NULL;
726 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
727 hnd->status = NT_STATUS_INVALID_HANDLE;
731 if(!op || !op->in.name || op->in.name[0] == '\0' || op->in.access == 0 || !mem_ctx) {
732 hnd->status = NT_STATUS_INVALID_PARAMETER;
736 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
738 hnd->status = NT_STATUS_INVALID_HANDLE;
742 group_hnd_out = talloc(mem_ctx, POLICY_HND);
744 hnd->status = NT_STATUS_NO_MEMORY;
748 hnd->status = rpccli_samr_create_dom_group( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.name, op->in.access, group_hnd_out);
750 if(!NT_STATUS_IS_OK(hnd->status))
753 op->out.group_hnd = group_hnd_out;
759 int cac_SamDeleteGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd) {
760 struct rpc_pipe_client *pipe_hnd = NULL;
765 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
766 hnd->status = NT_STATUS_INVALID_HANDLE;
770 if(!group_hnd || !mem_ctx) {
771 hnd->status = NT_STATUS_INVALID_PARAMETER;
775 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
777 hnd->status = NT_STATUS_INVALID_HANDLE;
781 hnd->status = rpccli_samr_delete_dom_group( pipe_hnd, mem_ctx, group_hnd);
783 if(!NT_STATUS_IS_OK(hnd->status))
790 int cac_SamGetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupMembers *op) {
791 struct rpc_pipe_client *pipe_hnd = NULL;
800 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
801 hnd->status = NT_STATUS_INVALID_HANDLE;
805 if(!op || !op->in.group_hnd || !mem_ctx) {
806 hnd->status = NT_STATUS_INVALID_PARAMETER;
810 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
812 hnd->status = NT_STATUS_INVALID_HANDLE;
816 hnd->status = rpccli_samr_query_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd, &num_mem_out, &rids_out, &attr_out);
818 if(!NT_STATUS_IS_OK(hnd->status))
821 op->out.num_members = num_mem_out;
822 op->out.rids = rids_out;
823 op->out.attributes = attr_out;
829 int cac_SamAddGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddGroupMember *op) {
830 struct rpc_pipe_client *pipe_hnd = NULL;
835 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
836 hnd->status = NT_STATUS_INVALID_HANDLE;
840 if(!op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx) {
841 hnd->status = NT_STATUS_INVALID_PARAMETER;
845 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
847 hnd->status = NT_STATUS_INVALID_HANDLE;
851 hnd->status = rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd, op->in.rid);
853 if(!NT_STATUS_IS_OK(hnd->status))
859 int cac_SamRemoveGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveGroupMember *op) {
860 struct rpc_pipe_client *pipe_hnd = NULL;
865 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
866 hnd->status = NT_STATUS_INVALID_HANDLE;
870 if(!op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx) {
871 hnd->status = NT_STATUS_INVALID_PARAMETER;
875 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
877 hnd->status = NT_STATUS_INVALID_HANDLE;
881 hnd->status = rpccli_samr_del_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd, op->in.rid);
883 if(!NT_STATUS_IS_OK(hnd->status))
889 int cac_SamClearGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd) {
890 struct rpc_pipe_client *pipe_hnd = NULL;
892 int result = CAC_SUCCESS;
905 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
906 hnd->status = NT_STATUS_INVALID_HANDLE;
910 if(!group_hnd || !mem_ctx) {
911 hnd->status = NT_STATUS_INVALID_PARAMETER;
915 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
917 hnd->status = NT_STATUS_INVALID_HANDLE;
921 hnd->status = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, group_hnd, &num_mem, &rid, &attr);
923 if(!NT_STATUS_IS_OK(hnd->status))
926 /*try to delete the users one by one*/
927 for(i = 0; i < num_mem && NT_STATUS_IS_OK(hnd->status); i++) {
928 hnd->status = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, group_hnd, rid[i]);
931 /*if not all members could be removed, then try to re-add the members that were already deleted*/
932 if(!NT_STATUS_IS_OK(hnd->status)) {
933 status = NT_STATUS_OK;
935 for(i -= 1; i >= 0 && NT_STATUS_IS_OK(status); i--) {
936 status = rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, group_hnd, rid[i]);
939 /*we return with the NTSTATUS error that we got when trying to delete users*/
940 if(!NT_STATUS_IS_OK(status))
941 result = CAC_FAILURE;
949 int cac_SamSetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetGroupMembers *op) {
950 struct rpc_pipe_client *pipe_hnd = NULL;
957 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
958 hnd->status = NT_STATUS_INVALID_HANDLE;
962 if(!op || !op->in.group_hnd || !mem_ctx) {
963 hnd->status = NT_STATUS_INVALID_PARAMETER;
967 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
969 hnd->status = NT_STATUS_INVALID_HANDLE;
973 /*use cac_SamClearGroupMembers() to clear them*/
974 if(!cac_SamClearGroupMembers(hnd, mem_ctx, op->in.group_hnd))
975 return CAC_FAILURE; /*hnd->status is already set*/
978 for(i = 0; i < op->in.num_members && NT_STATUS_IS_OK(hnd->status); i++) {
979 hnd->status = rpccli_samr_add_groupmem( pipe_hnd, mem_ctx, op->in.group_hnd, op->in.rids[i]);
982 if(!NT_STATUS_IS_OK(hnd->status))
989 int cac_SamEnumGroups(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumGroups *op) {
990 struct rpc_pipe_client *pipe_hnd = NULL;
994 uint32 resume_idx_out = 0;
995 char **names_out = NULL;
996 char **desc_out = NULL;
997 uint32 *rids_out = NULL;
998 uint32 num_groups_out = 0;
1000 struct acct_info *acct_buf = NULL;
1005 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1006 hnd->status = NT_STATUS_INVALID_HANDLE;
1010 if(!op || !op->in.dom_hnd || !mem_ctx) {
1011 hnd->status = NT_STATUS_INVALID_PARAMETER;
1015 /*using this BOOL is the only reliable way to know that we are done*/
1016 if(op->out.done == True) /*we return failure so the call will break out of a loop*/
1019 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1021 hnd->status = NT_STATUS_INVALID_HANDLE;
1025 resume_idx_out = op->out.resume_idx;
1027 hnd->status = rpccli_samr_enum_dom_groups( pipe_hnd, mem_ctx, op->in.dom_hnd, &resume_idx_out, SAMR_ENUM_MAX_SIZE,
1028 &acct_buf, &num_groups_out);
1031 if(NT_STATUS_IS_OK(hnd->status)) {
1032 op->out.done = True;
1034 else if(NT_STATUS_V(hnd->status) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1035 /*if there are no more entries, the operation will return NT_STATUS_OK.
1036 * We want to return failure if no results were returned*/
1040 names_out = talloc_array(mem_ctx, char *, num_groups_out);
1042 hnd->status = NT_STATUS_NO_MEMORY;
1043 TALLOC_FREE(acct_buf);
1047 desc_out = talloc_array(mem_ctx, char *, num_groups_out);
1049 hnd->status = NT_STATUS_NO_MEMORY;
1050 TALLOC_FREE(acct_buf);
1051 TALLOC_FREE(names_out);
1055 rids_out = talloc_array(mem_ctx, uint32, num_groups_out);
1057 hnd->status = NT_STATUS_NO_MEMORY;
1058 TALLOC_FREE(acct_buf);
1059 TALLOC_FREE(names_out);
1060 TALLOC_FREE(desc_out);
1064 for(i = 0; i < num_groups_out; i++) {
1065 names_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_name);
1066 desc_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_desc);
1067 rids_out[i] = acct_buf[i].rid;
1069 if(!names_out[i] || !desc_out[i]) {
1070 hnd->status = NT_STATUS_NO_MEMORY;
1075 op->out.resume_idx = resume_idx_out;
1076 op->out.num_groups = num_groups_out;
1077 op->out.rids = rids_out;
1078 op->out.names = names_out;
1079 op->out.descriptions = desc_out;
1084 int cac_SamEnumAliases(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumAliases *op) {
1085 struct rpc_pipe_client *pipe_hnd = NULL;
1089 uint32 resume_idx_out = 0;
1090 char **names_out = NULL;
1091 char **desc_out = NULL;
1092 uint32 *rids_out = NULL;
1093 uint32 num_als_out = 0;
1095 struct acct_info *acct_buf = NULL;
1100 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1101 hnd->status = NT_STATUS_INVALID_HANDLE;
1105 if(!op || !op->in.dom_hnd || !mem_ctx) {
1106 hnd->status = NT_STATUS_INVALID_PARAMETER;
1110 /*this is a hack.. but is the only reliable way to know if everything has been enumerated*/
1111 if(op->out.done == True) {
1115 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1117 hnd->status = NT_STATUS_INVALID_HANDLE;
1121 resume_idx_out = op->out.resume_idx;
1123 hnd->status = rpccli_samr_enum_als_groups( pipe_hnd, mem_ctx, op->in.dom_hnd, &resume_idx_out, SAMR_ENUM_MAX_SIZE,
1124 &acct_buf, &num_als_out);
1127 if(NT_STATUS_IS_OK(hnd->status))
1128 op->out.done = True;
1130 /*if there are no more entries, the operation will return NT_STATUS_OK.
1131 * We want to return failure if no results were returned*/
1132 if(!NT_STATUS_IS_OK(hnd->status) && NT_STATUS_V(hnd->status) != NT_STATUS_V(STATUS_MORE_ENTRIES))
1135 names_out = talloc_array(mem_ctx, char *, num_als_out);
1137 hnd->status = NT_STATUS_NO_MEMORY;
1138 TALLOC_FREE(acct_buf);
1142 desc_out = talloc_array(mem_ctx, char *, num_als_out);
1144 hnd->status = NT_STATUS_NO_MEMORY;
1145 TALLOC_FREE(acct_buf);
1146 TALLOC_FREE(names_out);
1150 rids_out = talloc_array(mem_ctx, uint32, num_als_out);
1152 hnd->status = NT_STATUS_NO_MEMORY;
1153 TALLOC_FREE(acct_buf);
1154 TALLOC_FREE(names_out);
1155 TALLOC_FREE(desc_out);
1159 for(i = 0; i < num_als_out; i++) {
1160 names_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_name);
1161 desc_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_desc);
1162 rids_out[i] = acct_buf[i].rid;
1164 if(!names_out[i] || !desc_out[i]) {
1165 hnd->status = NT_STATUS_NO_MEMORY;
1170 op->out.resume_idx = resume_idx_out;
1171 op->out.num_aliases = num_als_out;
1172 op->out.rids = rids_out;
1173 op->out.names = names_out;
1174 op->out.descriptions = desc_out;
1179 int cac_SamCreateAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateAlias *op) {
1180 struct rpc_pipe_client *pipe_hnd = NULL;
1182 POLICY_HND *als_hnd_out = NULL;
1187 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1188 hnd->status = NT_STATUS_INVALID_HANDLE;
1192 if(!op || !op->in.name || op->in.name[0] == '\0' || !mem_ctx) {
1193 hnd->status = NT_STATUS_INVALID_PARAMETER;
1197 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1199 hnd->status = NT_STATUS_INVALID_HANDLE;
1203 als_hnd_out = talloc(mem_ctx, POLICY_HND);
1205 hnd->status = NT_STATUS_NO_MEMORY;
1209 hnd->status = rpccli_samr_create_dom_alias( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.name, als_hnd_out);
1211 if(!NT_STATUS_IS_OK(hnd->status))
1214 op->out.alias_hnd = als_hnd_out;
1220 int cac_SamOpenAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenAlias *op) {
1221 struct rpc_pipe_client *pipe_hnd = NULL;
1223 POLICY_HND *als_hnd_out = NULL;
1228 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1229 hnd->status = NT_STATUS_INVALID_HANDLE;
1233 if(!op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx) {
1234 hnd->status = NT_STATUS_INVALID_PARAMETER;
1238 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1240 hnd->status = NT_STATUS_INVALID_HANDLE;
1244 als_hnd_out = talloc(mem_ctx, POLICY_HND);
1246 hnd->status = NT_STATUS_NO_MEMORY;
1250 hnd->status = rpccli_samr_open_alias( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.access, op->in.rid, als_hnd_out);
1252 if(!NT_STATUS_IS_OK(hnd->status))
1255 op->out.alias_hnd = als_hnd_out;
1260 int cac_SamDeleteAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *alias_hnd) {
1261 struct rpc_pipe_client *pipe_hnd = NULL;
1266 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1267 hnd->status = NT_STATUS_INVALID_HANDLE;
1271 if(!alias_hnd || !mem_ctx) {
1272 hnd->status = NT_STATUS_INVALID_PARAMETER;
1276 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1278 hnd->status = NT_STATUS_INVALID_HANDLE;
1282 hnd->status = rpccli_samr_delete_dom_alias( pipe_hnd, mem_ctx, alias_hnd);
1284 if(!NT_STATUS_IS_OK(hnd->status))
1291 int cac_SamAddAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddAliasMember *op) {
1292 struct rpc_pipe_client *pipe_hnd = NULL;
1297 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1298 hnd->status = NT_STATUS_INVALID_HANDLE;
1302 if(!op || !op->in.alias_hnd || !op->in.sid || !mem_ctx) {
1303 hnd->status = NT_STATUS_INVALID_PARAMETER;
1307 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1309 hnd->status = NT_STATUS_INVALID_HANDLE;
1313 hnd->status = rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd, op->in.sid);
1315 if(!NT_STATUS_IS_OK(hnd->status))
1321 int cac_SamRemoveAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveAliasMember *op) {
1322 struct rpc_pipe_client *pipe_hnd = NULL;
1327 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1328 hnd->status = NT_STATUS_INVALID_HANDLE;
1332 if(!op || !op->in.alias_hnd || !op->in.sid || !mem_ctx) {
1333 hnd->status = NT_STATUS_INVALID_PARAMETER;
1337 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1339 hnd->status = NT_STATUS_INVALID_HANDLE;
1343 hnd->status = rpccli_samr_del_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd, op->in.sid);
1345 if(!NT_STATUS_IS_OK(hnd->status))
1351 int cac_SamGetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasMembers *op) {
1352 struct rpc_pipe_client *pipe_hnd = NULL;
1360 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1361 hnd->status = NT_STATUS_INVALID_HANDLE;
1365 if(!op || !op->in.alias_hnd || !mem_ctx) {
1366 hnd->status = NT_STATUS_INVALID_PARAMETER;
1370 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1372 hnd->status = NT_STATUS_INVALID_HANDLE;
1376 hnd->status = rpccli_samr_query_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd, &num_mem_out, &sids_out);
1378 if(!NT_STATUS_IS_OK(hnd->status))
1381 op->out.num_members = num_mem_out;
1382 op->out.sids = sids_out;
1387 int cac_SamClearAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *alias_hnd) {
1388 struct rpc_pipe_client *pipe_hnd = NULL;
1390 int result = CAC_SUCCESS;
1395 DOM_SID *sid = NULL;
1402 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1403 hnd->status = NT_STATUS_INVALID_HANDLE;
1407 if(!alias_hnd || !mem_ctx) {
1408 hnd->status = NT_STATUS_INVALID_PARAMETER;
1412 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1414 hnd->status = NT_STATUS_INVALID_HANDLE;
1418 hnd->status = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx, alias_hnd, &num_mem, &sid);
1420 if(!NT_STATUS_IS_OK(hnd->status))
1423 /*try to delete the users one by one*/
1424 for(i = 0; i < num_mem && NT_STATUS_IS_OK(hnd->status); i++) {
1425 hnd->status = rpccli_samr_del_aliasmem(pipe_hnd, mem_ctx, alias_hnd, &sid[i]);
1428 /*if not all members could be removed, then try to re-add the members that were already deleted*/
1429 if(!NT_STATUS_IS_OK(hnd->status)) {
1430 status = NT_STATUS_OK;
1432 for(i -= 1; i >= 0 && NT_STATUS_IS_OK(status); i--) {
1433 status = rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, alias_hnd, &sid[i]);
1436 /*we return with the NTSTATUS error that we got when trying to delete users*/
1437 if(!NT_STATUS_IS_OK(status))
1438 result = CAC_FAILURE;
1445 int cac_SamSetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetAliasMembers *op) {
1446 struct rpc_pipe_client *pipe_hnd = NULL;
1453 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1454 hnd->status = NT_STATUS_INVALID_HANDLE;
1458 if(!op || !op->in.alias_hnd || !mem_ctx) {
1459 hnd->status = NT_STATUS_INVALID_PARAMETER;
1463 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1465 hnd->status = NT_STATUS_INVALID_HANDLE;
1469 /*use cac_SamClearAliasMembers() to clear them*/
1470 if(!cac_SamClearAliasMembers(hnd, mem_ctx, op->in.alias_hnd))
1471 return CAC_FAILURE; /*hnd->status is already set*/
1474 for(i = 0; i < op->in.num_members && NT_STATUS_IS_OK(hnd->status); i++) {
1475 hnd->status = rpccli_samr_add_aliasmem( pipe_hnd, mem_ctx, op->in.alias_hnd, &(op->in.sids[i]));
1478 if(!NT_STATUS_IS_OK(hnd->status))
1485 int cac_SamUserChangePasswd(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamUserChangePasswd *op) {
1486 SMBCSRV *srv = NULL;
1487 struct rpc_pipe_client *pipe_hnd = NULL;
1492 if(!hnd->_internal.ctx) {
1493 hnd->status = NT_STATUS_INVALID_HANDLE;
1497 if(!op || !op->in.username || !op->in.password || !op->in.new_password || !mem_ctx) {
1498 hnd->status = NT_STATUS_INVALID_PARAMETER;
1502 srv = cac_GetServer(hnd);
1504 hnd->status = NT_STATUS_INVALID_CONNECTION;
1508 /*open a session on SAMR if we don't have one*/
1509 if(!hnd->_internal.pipes[PI_SAMR]) {
1510 if(!(pipe_hnd = cli_rpc_pipe_open_noauth(srv->cli, PI_SAMR, &hnd->status))) {
1514 hnd->_internal.pipes[PI_SAMR] = True;
1517 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1519 hnd->status = NT_STATUS_INVALID_HANDLE;
1523 hnd->status = rpccli_samr_chgpasswd_user(pipe_hnd, mem_ctx, op->in.username, op->in.new_password, op->in.password);
1525 if(!NT_STATUS_IS_OK(hnd->status))
1531 int cac_SamEnableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) {
1532 SMBCSRV *srv = NULL;
1533 struct rpc_pipe_client *pipe_hnd = NULL;
1535 SAM_USERINFO_CTR *ctr;
1540 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1541 hnd->status = NT_STATUS_INVALID_HANDLE;
1545 if(!user_hnd || !mem_ctx) {
1546 hnd->status = NT_STATUS_INVALID_PARAMETER;
1550 srv = cac_GetServer(hnd);
1552 hnd->status = NT_STATUS_INVALID_CONNECTION;
1556 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1558 hnd->status = NT_STATUS_INVALID_HANDLE;
1562 /*info_level = 21 is the only level that I have found to work reliably. It would be nice if user_level = 10 worked.*/
1563 hnd->status = rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10, &ctr);
1565 if(!NT_STATUS_IS_OK(hnd->status))
1568 /**check the ACB mask*/
1569 if((ctr->info.id16->acb_info & ACB_DISABLED) == ACB_DISABLED) {
1570 /*toggle the disabled bit*/
1571 ctr->info.id16->acb_info ^= ACB_DISABLED;
1574 /*the user is already enabled so just return success*/
1578 /*now set the userinfo*/
1579 hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &srv->cli->user_session_key, ctr);
1581 /*this will only work properly if we use set_userinfo2 - fail if it is not supported*/
1582 if(!NT_STATUS_IS_OK(hnd->status))
1588 int cac_SamDisableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) {
1589 SMBCSRV *srv = NULL;
1590 struct rpc_pipe_client *pipe_hnd = NULL;
1592 SAM_USERINFO_CTR *ctr;
1597 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1598 hnd->status = NT_STATUS_INVALID_HANDLE;
1602 if(!user_hnd || !mem_ctx) {
1603 hnd->status = NT_STATUS_INVALID_PARAMETER;
1607 srv = cac_GetServer(hnd);
1609 hnd->status = NT_STATUS_INVALID_CONNECTION;
1613 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1615 hnd->status = NT_STATUS_INVALID_HANDLE;
1619 hnd->status = rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10, &ctr);
1621 if(!NT_STATUS_IS_OK(hnd->status))
1624 if((ctr->info.id16->acb_info & ACB_DISABLED) == ACB_DISABLED) {
1625 /*then the user is already disabled*/
1629 /*toggle the disabled bit*/
1630 ctr->info.id16->acb_info ^= ACB_DISABLED;
1632 /*this will only work properly if we use set_userinfo2*/
1633 hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, user_hnd, 0x10, &srv->cli->user_session_key, ctr);
1635 /*this will only work properly if we use set_userinfo2 fail if it is not supported*/
1636 if(!NT_STATUS_IS_OK(hnd->status))
1642 int cac_SamSetPassword(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetPassword *op) {
1643 SMBCSRV *srv = NULL;
1644 struct rpc_pipe_client *pipe_hnd = NULL;
1646 SAM_USERINFO_CTR ctr;
1647 SAM_USER_INFO_24 info24;
1653 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1654 hnd->status = NT_STATUS_INVALID_HANDLE;
1658 if(!op->in.user_hnd || !op->in.password || !mem_ctx) {
1659 hnd->status = NT_STATUS_INVALID_PARAMETER;
1663 srv = cac_GetServer(hnd);
1665 hnd->status = NT_STATUS_INVALID_CONNECTION;
1669 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1671 hnd->status = NT_STATUS_INVALID_HANDLE;
1676 ZERO_STRUCT(info24);
1678 encode_pw_buffer(pw, op->in.password, STR_UNICODE);
1680 init_sam_user_info24(&info24, (char *)pw, 24);
1682 ctr.switch_value = 24;
1683 ctr.info.id24 = &info24;
1685 hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 24, &srv->cli->user_session_key, &ctr);
1687 if(!NT_STATUS_IS_OK(hnd->status))
1693 int cac_SamGetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetUserInfo *op) {
1694 struct rpc_pipe_client *pipe_hnd = NULL;
1696 SAM_USERINFO_CTR *ctr;
1701 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1702 hnd->status = NT_STATUS_INVALID_HANDLE;
1706 if(!op->in.user_hnd || !mem_ctx) {
1707 hnd->status = NT_STATUS_INVALID_PARAMETER;
1711 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1713 hnd->status = NT_STATUS_INVALID_HANDLE;
1717 hnd->status = rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &ctr);
1719 if(!NT_STATUS_IS_OK(hnd->status))
1722 op->out.info = cac_MakeUserInfo(mem_ctx, ctr);
1725 hnd->status = NT_STATUS_NO_MEMORY;
1732 int cac_SamSetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetUserInfo *op) {
1733 SMBCSRV *srv = NULL;
1734 struct rpc_pipe_client *pipe_hnd = NULL;
1736 SAM_USERINFO_CTR *ctr;
1741 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1742 hnd->status = NT_STATUS_INVALID_HANDLE;
1746 if(!op->in.user_hnd || !op->in.info || !mem_ctx) {
1747 hnd->status = NT_STATUS_INVALID_PARAMETER;
1751 ctr = cac_MakeUserInfoCtr(mem_ctx, op->in.info);
1753 hnd->status = NT_STATUS_NO_MEMORY;
1757 srv = cac_GetServer(hnd);
1759 hnd->status = NT_STATUS_INVALID_CONNECTION;
1763 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1765 hnd->status = NT_STATUS_INVALID_HANDLE;
1769 if(hnd->_internal.srv_level >= SRV_WIN_NT4) {
1770 hnd->status = rpccli_samr_set_userinfo2( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &srv->cli->user_session_key, ctr);
1773 if(hnd->_internal.srv_level < SRV_WIN_NT4 || !NT_STATUS_IS_OK(hnd->status)) {
1774 hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 21, &srv->cli->user_session_key, ctr);
1776 if(NT_STATUS_IS_OK(hnd->status) && hnd->_internal.srv_level > SRV_WIN_NT4) {
1777 hnd->_internal.srv_level = SRV_WIN_NT4;
1782 if(!NT_STATUS_IS_OK(hnd->status))
1789 int cac_SamGetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetUserInfoCtr *op) {
1790 struct rpc_pipe_client *pipe_hnd = NULL;
1792 SAM_USERINFO_CTR *ctr_out;
1797 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1798 hnd->status = NT_STATUS_INVALID_HANDLE;
1802 if(!op->in.user_hnd || op->in.info_class == 0 || !mem_ctx) {
1803 hnd->status = NT_STATUS_INVALID_PARAMETER;
1807 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1809 hnd->status = NT_STATUS_INVALID_HANDLE;
1813 hnd->status = rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, op->in.info_class, &ctr_out);
1815 if(!NT_STATUS_IS_OK(hnd->status))
1818 op->out.ctr = ctr_out;
1823 int cac_SamSetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetUserInfoCtr *op) {
1824 SMBCSRV *srv = NULL;
1825 struct rpc_pipe_client *pipe_hnd = NULL;
1830 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1831 hnd->status = NT_STATUS_INVALID_HANDLE;
1835 if(!op->in.user_hnd || !op->in.ctr || !mem_ctx) {
1836 hnd->status = NT_STATUS_INVALID_PARAMETER;
1840 srv = cac_GetServer(hnd);
1842 hnd->status = NT_STATUS_INVALID_CONNECTION;
1846 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1848 hnd->status = NT_STATUS_INVALID_HANDLE;
1853 hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, op->in.ctr->switch_value, &srv->cli->user_session_key, op->in.ctr);
1855 if(!NT_STATUS_IS_OK(hnd->status))
1862 int cac_SamRenameUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenameUser *op) {
1863 SMBCSRV *srv = NULL;
1864 struct rpc_pipe_client *pipe_hnd = NULL;
1866 SAM_USERINFO_CTR ctr;
1867 SAM_USER_INFO_7 info7;
1872 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1873 hnd->status = NT_STATUS_INVALID_HANDLE;
1877 if(!op->in.user_hnd || !op->in.new_name || op->in.new_name[0] == '\0' || !mem_ctx) {
1878 hnd->status = NT_STATUS_INVALID_PARAMETER;
1882 srv = cac_GetServer(hnd);
1884 hnd->status = NT_STATUS_INVALID_CONNECTION;
1888 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1890 hnd->status = NT_STATUS_INVALID_HANDLE;
1897 init_sam_user_info7(&info7, op->in.new_name);
1899 ctr.switch_value = 7;
1900 ctr.info.id7 = &info7;
1902 hnd->status = rpccli_samr_set_userinfo( pipe_hnd, mem_ctx, op->in.user_hnd, 7, &srv->cli->user_session_key, &ctr);
1904 if(!NT_STATUS_IS_OK(hnd->status))
1911 int cac_SamGetGroupInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupInfo *op) {
1912 struct rpc_pipe_client *pipe_hnd = NULL;
1914 GROUP_INFO_CTR *ctr;
1919 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1920 hnd->status = NT_STATUS_INVALID_HANDLE;
1924 if(!op->in.group_hnd || !mem_ctx) {
1925 hnd->status = NT_STATUS_INVALID_PARAMETER;
1929 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1931 hnd->status = NT_STATUS_INVALID_HANDLE;
1936 /*get a GROUP_INFO_1 structure*/
1937 hnd->status = rpccli_samr_query_groupinfo( pipe_hnd, mem_ctx, op->in.group_hnd, 1, &ctr);
1939 if(!NT_STATUS_IS_OK(hnd->status))
1942 op->out.info = cac_MakeGroupInfo(mem_ctx, ctr);
1944 hnd->status = NT_STATUS_NO_MEMORY;
1951 int cac_SamSetGroupInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetGroupInfo *op) {
1952 struct rpc_pipe_client *pipe_hnd = NULL;
1954 GROUP_INFO_CTR *ctr = NULL;
1959 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1960 hnd->status = NT_STATUS_INVALID_HANDLE;
1964 if(!op->in.group_hnd || !op->in.info || !mem_ctx) {
1965 hnd->status = NT_STATUS_INVALID_PARAMETER;
1969 ctr = cac_MakeGroupInfoCtr(mem_ctx, op->in.info);
1971 hnd->status = NT_STATUS_NO_MEMORY;
1975 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1977 hnd->status = NT_STATUS_INVALID_HANDLE;
1981 hnd->status = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, op->in.group_hnd, ctr);
1983 if(!NT_STATUS_IS_OK(hnd->status))
1989 int cac_SamRenameGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenameGroup *op) {
1990 struct rpc_pipe_client *pipe_hnd = NULL;
1997 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1998 hnd->status = NT_STATUS_INVALID_HANDLE;
2002 if(!op->in.group_hnd || !op->in.new_name || op->in.new_name[0] == '\0' || !mem_ctx) {
2003 hnd->status = NT_STATUS_INVALID_PARAMETER;
2007 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2009 hnd->status = NT_STATUS_INVALID_HANDLE;
2015 init_samr_group_info2(&ctr.group.info2, op->in.new_name);
2016 ctr.switch_value1 = 2;
2018 hnd->status = rpccli_samr_set_groupinfo( pipe_hnd, mem_ctx, op->in.group_hnd, &ctr);
2020 if(!NT_STATUS_IS_OK(hnd->status))
2026 int cac_SamGetAliasInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasInfo *op) {
2027 struct rpc_pipe_client *pipe_hnd = NULL;
2034 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2035 hnd->status = NT_STATUS_INVALID_HANDLE;
2039 if(!op->in.alias_hnd || !mem_ctx) {
2040 hnd->status = NT_STATUS_INVALID_PARAMETER;
2044 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2046 hnd->status = NT_STATUS_INVALID_HANDLE;
2050 /*get a GROUP_INFO_1 structure*/
2051 hnd->status = rpccli_samr_query_alias_info( pipe_hnd, mem_ctx, op->in.alias_hnd, 1, &ctr);
2053 if(!NT_STATUS_IS_OK(hnd->status))
2056 op->out.info = cac_MakeAliasInfo(mem_ctx, ctr);
2058 hnd->status = NT_STATUS_NO_MEMORY;
2066 int cac_SamSetAliasInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetAliasInfo *op) {
2067 struct rpc_pipe_client *pipe_hnd = NULL;
2069 ALIAS_INFO_CTR *ctr = NULL;
2074 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2075 hnd->status = NT_STATUS_INVALID_HANDLE;
2079 if(!op->in.alias_hnd || !op->in.info || !mem_ctx) {
2080 hnd->status = NT_STATUS_INVALID_PARAMETER;
2084 ctr = cac_MakeAliasInfoCtr(mem_ctx, op->in.info);
2086 hnd->status = NT_STATUS_NO_MEMORY;
2090 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2092 hnd->status = NT_STATUS_INVALID_HANDLE;
2096 hnd->status = rpccli_samr_set_aliasinfo(pipe_hnd, mem_ctx, op->in.alias_hnd, ctr);
2098 if(!NT_STATUS_IS_OK(hnd->status))
2104 int cac_SamGetDomainInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDomainInfo *op) {
2105 struct rpc_pipe_client *pipe_hnd = NULL;
2108 SAM_UNK_INFO_1 info1;
2109 SAM_UNK_INFO_2 info2;
2110 SAM_UNK_INFO_12 info12;
2112 /*use this to keep track of a failed call*/
2113 NTSTATUS status_buf = NT_STATUS_OK;
2115 uint16 fail_count = 0;
2121 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2122 hnd->status = NT_STATUS_INVALID_HANDLE;
2126 if(!op->in.dom_hnd || !mem_ctx) {
2127 hnd->status = NT_STATUS_INVALID_PARAMETER;
2131 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2133 hnd->status = NT_STATUS_INVALID_HANDLE;
2137 /*first try with info 1*/
2138 hnd->status = rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd, 1, &ctr);
2140 if(NT_STATUS_IS_OK(hnd->status)) {
2141 /*then we buffer the SAM_UNK_INFO_1 structure*/
2142 info1 = ctr.info.inf1;
2145 /*then the call failed, store the status and ZERO out the info structure*/
2147 status_buf = hnd->status;
2151 /*try again for the next one*/
2152 hnd->status = rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd, 2, &ctr);
2154 if(NT_STATUS_IS_OK(hnd->status)) {
2156 info2 = ctr.info.inf2;
2159 /*ZERO out the structure and store the bad status*/
2161 status_buf = hnd->status;
2166 hnd->status = rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd, 12, &ctr);
2168 if(NT_STATUS_IS_OK(hnd->status)) {
2169 info12 = ctr.info.inf12;
2172 ZERO_STRUCT(info12);
2173 status_buf = hnd->status;
2177 /*return failure if all 3 calls failed*/
2181 op->out.info = cac_MakeDomainInfo(mem_ctx, &info1, &info2, &info12);
2184 hnd->status = NT_STATUS_NO_MEMORY;
2188 if(fail_count > 0) {
2189 hnd->status = status_buf;
2190 return CAC_PARTIAL_SUCCESS;
2196 int cac_SamGetDomainInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDomainInfoCtr *op) {
2197 struct rpc_pipe_client *pipe_hnd = NULL;
2199 SAM_UNK_CTR *ctr_out;
2204 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2205 hnd->status = NT_STATUS_INVALID_HANDLE;
2209 if(!op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx) {
2210 hnd->status = NT_STATUS_INVALID_PARAMETER;
2214 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2216 hnd->status = NT_STATUS_INVALID_HANDLE;
2220 ctr_out = talloc(mem_ctx, SAM_UNK_CTR);
2222 hnd->status = NT_STATUS_NO_MEMORY;
2226 hnd->status = rpccli_samr_query_dom_info( pipe_hnd, mem_ctx, op->in.dom_hnd, op->in.info_class, ctr_out);
2228 if(!NT_STATUS_IS_OK(hnd->status))
2231 op->out.info = ctr_out;
2236 int cac_SamGetDisplayInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDisplayInfo *op) {
2237 struct rpc_pipe_client *pipe_hnd = NULL;
2239 SAM_DISPINFO_CTR ctr_out;
2241 uint32 max_entries_buf = 0;
2242 uint32 max_size_buf = 0;
2244 uint32 resume_idx_out;
2245 uint32 num_entries_out;
2250 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2251 hnd->status = NT_STATUS_INVALID_HANDLE;
2255 if(!op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx) {
2256 hnd->status = NT_STATUS_INVALID_PARAMETER;
2260 if(op->out.done == True) /*this is done so we can use the function as a loop condition*/
2263 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2265 hnd->status = NT_STATUS_INVALID_HANDLE;
2269 if(op->in.max_entries == 0 || op->in.max_size == 0) {
2270 get_query_dispinfo_params(op->out.loop_count, &max_entries_buf, &max_size_buf);
2273 max_entries_buf = op->in.max_entries;
2274 max_size_buf = op->in.max_size;
2277 resume_idx_out = op->out.resume_idx;
2279 hnd->status = rpccli_samr_query_dispinfo( pipe_hnd, mem_ctx, op->in.dom_hnd, &resume_idx_out, op->in.info_class,
2280 &num_entries_out, max_entries_buf, max_size_buf, &ctr_out);
2282 if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_MORE_ENTRIES)) {
2283 /*be defensive, maybe they'll call again without zeroing the struct*/
2284 op->out.loop_count = 0;
2285 op->out.resume_idx = 0;
2289 if(NT_STATUS_IS_OK(hnd->status)) {
2290 /*we want to quit once the function is called next. so it can be used in a loop*/
2291 op->out.done = True;
2294 op->out.resume_idx = resume_idx_out;
2295 op->out.num_entries = num_entries_out;
2296 op->out.ctr = ctr_out;
2297 op->out.loop_count++;
2302 int cac_SamLookupDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamLookupDomain *op) {
2303 struct rpc_pipe_client *pipe_hnd = NULL;
2305 DOM_SID *sid_out = NULL;
2310 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2311 hnd->status = NT_STATUS_INVALID_HANDLE;
2315 if(!op->in.sam || !op->in.name || !mem_ctx) {
2316 hnd->status = NT_STATUS_INVALID_PARAMETER;
2320 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2322 hnd->status = NT_STATUS_INVALID_HANDLE;
2326 sid_out = talloc(mem_ctx, DOM_SID);
2328 hnd->status = NT_STATUS_NO_MEMORY;
2332 hnd->status = rpccli_samr_lookup_domain( pipe_hnd, mem_ctx, op->in.sam, op->in.name, sid_out);
2334 if(!NT_STATUS_IS_OK(hnd->status))
2337 op->out.sid = sid_out;
2342 int cac_SamGetSecurityObject(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetSecurityObject *op) {
2343 struct rpc_pipe_client *pipe_hnd = NULL;
2345 /*this number taken from rpcclient/cmd_samr.c, I think it is the only supported level*/
2346 uint32 sec_info = DACL_SECURITY_INFORMATION;
2348 SEC_DESC_BUF *sec_out = NULL;
2353 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2354 hnd->status = NT_STATUS_INVALID_HANDLE;
2358 if(!op->in.pol || !mem_ctx) {
2359 hnd->status = NT_STATUS_INVALID_PARAMETER;
2363 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2365 hnd->status = NT_STATUS_INVALID_HANDLE;
2369 hnd->status = rpccli_samr_query_sec_obj(pipe_hnd, mem_ctx, op->in.pol, sec_info, mem_ctx, &sec_out);
2371 if(!NT_STATUS_IS_OK(hnd->status))
2374 op->out.sec = sec_out;
2379 int cac_SamFlush(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamFlush *op) {
2380 struct SamOpenDomain od;
2385 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2386 hnd->status = NT_STATUS_INVALID_HANDLE;
2390 if(!op || !op->in.dom_hnd || !mem_ctx) {
2391 hnd->status = NT_STATUS_INVALID_PARAMETER;
2395 if(!cac_SamClose(hnd, mem_ctx, op->in.dom_hnd))
2399 od.in.access = (op->in.access) ? op->in.access : MAXIMUM_ALLOWED_ACCESS;
2400 od.in.sid = op->in.sid;
2402 if(!cac_SamOpenDomain(hnd, mem_ctx, &od))
2405 /*this function does not use an output parameter to make it as convenient as possible to use*/
2406 *op->in.dom_hnd = *od.out.dom_hnd;
2408 TALLOC_FREE(od.out.dom_hnd);