r12199: grabbing some low risk fixes from 3.0
[Samba.git] / source / libmsrpc / cac_samr.c
blob65141ca31955f5a2d9fd761d9f4fe2fb8a902c7c
1 /*
2 * Unix SMB/CIFS implementation.
3 * MS-RPC client library implementation (SAMR pipe)
4 * Copyright (C) Chris Nicholls 2005.
5 *
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.
21 #include "libmsrpc.h"
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) {
33 SMBCSRV *srv = NULL;
34 struct rpc_pipe_client *pipe_hnd = NULL;
35 POLICY_HND *sam_out = NULL;
37 if(!hnd)
38 return CAC_FAILURE;
40 if(!hnd->_internal.ctx) {
41 hnd->status = NT_STATUS_INVALID_HANDLE;
42 return CAC_FAILURE;
45 if(!op || op->in.access == 0 || !mem_ctx) {
46 hnd->status = NT_STATUS_INVALID_PARAMETER;
47 return CAC_FAILURE;
50 srv = cac_GetServer(hnd);
51 if(!srv) {
52 hnd->status = NT_STATUS_INVALID_CONNECTION;
53 return CAC_FAILURE;
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)))) {
59 return CAC_FAILURE;
62 hnd->_internal.pipes[PI_SAMR] = True;
65 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
66 if(!pipe_hnd) {
67 hnd->status = NT_STATUS_INVALID_HANDLE;
68 return CAC_FAILURE;
71 sam_out = talloc(mem_ctx, POLICY_HND);
72 if(!sam_out) {
73 hnd->status = NT_STATUS_NO_MEMORY;
74 return CAC_FAILURE;
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))
92 return CAC_FAILURE;
94 op->out.sam = sam_out;
96 return CAC_SUCCESS;
99 int cac_SamClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *sam) {
100 struct rpc_pipe_client *pipe_hnd = NULL;
102 if(!hnd)
103 return CAC_FAILURE;
105 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
106 hnd->status = NT_STATUS_INVALID_HANDLE;
107 return CAC_FAILURE;
110 if(!sam || !mem_ctx) {
111 hnd->status = NT_STATUS_INVALID_PARAMETER;
112 return CAC_FAILURE;
115 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
116 if(!pipe_hnd) {
117 hnd->status = NT_STATUS_INVALID_HANDLE;
118 return CAC_FAILURE;
121 hnd->status = rpccli_samr_close( pipe_hnd, mem_ctx, sam);
123 if(!NT_STATUS_IS_OK(hnd->status))
124 return CAC_FAILURE;
126 return CAC_SUCCESS;
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;
137 DOM_SID *sid;
139 ZERO_STRUCT(lop);
140 ZERO_STRUCT(fs);
142 lop.in.access = des_access;
143 lop.in.security_qos = True;
145 if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop))
146 return NULL;
148 fs.in.pol = lop.out.pol;
149 fs.in.info_class = CAC_DOMAIN_INFO;
151 if(!cac_LsaFetchSid(hnd, mem_ctx, &fs))
152 return NULL;
154 cac_LsaClosePolicy(hnd, mem_ctx, lop.out.pol);
156 if(!fs.out.domain_sid)
157 return NULL;
159 sid = talloc_memdup(mem_ctx, &(fs.out.domain_sid->sid), sizeof(DOM_SID));
161 if(!sid) {
162 hnd->status = NT_STATUS_NO_MEMORY;
165 return sid;
169 int cac_SamOpenDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenDomain *op) {
170 struct rpc_pipe_client *pipe_hnd = NULL;
172 DOM_SID *sid_buf;
173 POLICY_HND *sam_out;
174 POLICY_HND *pol_out;
176 struct SamLookupDomain sld;
178 if(!hnd)
179 return CAC_FAILURE;
181 if(!hnd->_internal.ctx) {
182 hnd->status = NT_STATUS_INVALID_HANDLE;
183 return CAC_FAILURE;
186 if(!op || op->in.access == 0 || !mem_ctx) {
187 hnd->status = NT_STATUS_INVALID_PARAMETER;
188 return CAC_FAILURE;
191 if(!op->in.sam) {
192 /*use cac_SamConnect() since it does the session setup*/
193 struct SamConnect sc;
194 ZERO_STRUCT(sc);
196 sc.in.access = op->in.access;
198 if(!cac_SamConnect(hnd, mem_ctx, &sc)) {
199 return CAC_FAILURE;
202 sam_out = sc.out.sam;
204 else {
205 sam_out = op->in.sam;
208 if(!op->in.sid) {
209 /*find the sid for the SAM's domain*/
211 /*try using cac_SamLookupDomain() first*/
212 ZERO_STRUCT(sld);
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;
221 else {
222 /*try to get it from the LSA*/
223 sid_buf = cac_get_domain_sid(hnd, mem_ctx, op->in.access);
226 else {
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);
232 if(!pipe_hnd) {
233 hnd->status = NT_STATUS_INVALID_HANDLE;
234 return CAC_FAILURE;
237 pol_out = talloc(mem_ctx, POLICY_HND);
238 if(!pol_out) {
239 hnd->status = NT_STATUS_NO_MEMORY;
240 return CAC_FAILURE;
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))
247 return CAC_FAILURE;
249 op->out.sam = sam_out;
250 op->out.dom_hnd = pol_out;
252 return CAC_SUCCESS;
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;
260 uint32 num_rids = 0;
261 uint32 *rid_types = NULL;
263 POLICY_HND *user_out = NULL;
265 if(!hnd)
266 return CAC_FAILURE;
268 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
269 hnd->status = NT_STATUS_INVALID_HANDLE;
270 return CAC_FAILURE;
273 if(!op || !op->in.dom_hnd || op->in.access == 0 || !mem_ctx) {
274 hnd->status = NT_STATUS_INVALID_PARAMETER;
275 return CAC_FAILURE;
278 if(op->in.rid == 0 && op->in.name == NULL) {
279 hnd->status = NT_STATUS_INVALID_PARAMETER;
280 return CAC_FAILURE;
283 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
284 if(!pipe_hnd) {
285 hnd->status = NT_STATUS_INVALID_HANDLE;
286 return CAC_FAILURE;
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))
296 return CAC_FAILURE;
298 if(num_rids == 0 || rid_buf == NULL || rid_types[0] == SAMR_RID_UNKNOWN) {
299 hnd->status = NT_STATUS_INVALID_PARAMETER;
300 return CAC_FAILURE;
303 talloc_free(rid_types);
306 else {
307 rid_buf = &op->in.rid;
310 user_out = talloc(mem_ctx, POLICY_HND);
311 if(!user_out) {
312 hnd->status = NT_STATUS_NO_MEMORY;
313 return CAC_FAILURE;
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))
319 return CAC_FAILURE;
321 op->out.user_hnd = user_out;
323 return CAC_SUCCESS;
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;
330 uint32 rid_out;
332 /**found in rpcclient/cmd_samr.c*/
333 uint32 unknown = 0xe005000b;
335 if(!hnd)
336 return CAC_FAILURE;
338 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
339 hnd->status = NT_STATUS_INVALID_HANDLE;
340 return CAC_FAILURE;
343 if(!op || !op->in.dom_hnd || !op->in.name || op->in.acb_mask == 0 || !mem_ctx) {
344 hnd->status = NT_STATUS_INVALID_PARAMETER;
345 return CAC_FAILURE;
348 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
349 if(!pipe_hnd) {
350 hnd->status = NT_STATUS_INVALID_HANDLE;
351 return CAC_FAILURE;
354 user_out = talloc(mem_ctx, POLICY_HND);
355 if(!user_out) {
356 hnd->status = NT_STATUS_NO_MEMORY;
357 return CAC_FAILURE;
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))
363 return CAC_FAILURE;
365 op->out.user_hnd = user_out;
366 op->out.rid = rid_out;
368 return CAC_SUCCESS;
371 int cac_SamDeleteUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) {
372 struct rpc_pipe_client *pipe_hnd = NULL;
374 if(!hnd)
375 return CAC_FAILURE;
377 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
378 hnd->status = NT_STATUS_INVALID_HANDLE;
379 return CAC_FAILURE;
382 if(!user_hnd || !mem_ctx) {
383 hnd->status = NT_STATUS_INVALID_PARAMETER;
384 return CAC_FAILURE;
387 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
388 if(!pipe_hnd) {
389 hnd->status = NT_STATUS_INVALID_HANDLE;
390 return CAC_FAILURE;
393 hnd->status = rpccli_samr_delete_dom_user( pipe_hnd, mem_ctx, user_hnd);
395 if(!NT_STATUS_IS_OK(hnd->status))
396 return CAC_FAILURE;
398 return CAC_SUCCESS;
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;
409 if(!hnd)
410 return CAC_FAILURE;
412 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
413 hnd->status = NT_STATUS_INVALID_HANDLE;
414 return CAC_FAILURE;
417 if(!op || !op->in.dom_hnd || !mem_ctx) {
418 hnd->status = NT_STATUS_INVALID_PARAMETER;
419 return CAC_FAILURE;
422 /*this is a hack.. but is the only reliable way to know if everything has been enumerated*/
423 if(op->out.done == True)
424 return CAC_FAILURE;
426 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
427 if(!pipe_hnd) {
428 hnd->status = NT_STATUS_INVALID_HANDLE;
429 return CAC_FAILURE;
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))
439 op->out.done = True;
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))
444 return CAC_FAILURE;
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;
451 return CAC_SUCCESS;
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;
458 char **names_out;
459 uint32 *name_types_out;
462 uint32 i = 0;
464 CacLookupRidsRecord *map_out;
466 if(!hnd)
467 return CAC_FAILURE;
469 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
470 hnd->status = NT_STATUS_INVALID_HANDLE;
471 return CAC_FAILURE;
474 if(!op || !op->in.dom_hnd || !mem_ctx) {
475 hnd->status = NT_STATUS_INVALID_PARAMETER;
476 return CAC_FAILURE;
479 if(!op->in.rids && op->in.num_rids != 0) {
480 hnd->status = NT_STATUS_INVALID_PARAMETER;
481 return CAC_FAILURE;
484 if(op->in.num_rids == 0) {
485 /*nothing to do*/
486 op->out.num_names = 0;
487 return CAC_SUCCESS;
490 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
491 if(!pipe_hnd) {
492 hnd->status = NT_STATUS_INVALID_HANDLE;
493 return CAC_FAILURE;
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))
499 return CAC_FAILURE;
501 map_out = TALLOC_ARRAY(mem_ctx, CacLookupRidsRecord, num_names_out);
502 if(!map_out) {
503 hnd->status = NT_STATUS_NO_MEMORY;
504 return CAC_FAILURE;
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;
511 map_out[i].type = 0;
513 else {
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;
530 return CAC_SUCCESS;
533 int cac_SamGetRidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetRidsFromNames *op) {
534 struct rpc_pipe_client *pipe_hnd = NULL;
536 uint32 num_rids_out;
537 uint32 *rids_out;
538 uint32 *rid_types_out;
540 uint32 i = 0;
542 CacLookupRidsRecord *map_out;
544 if(!hnd)
545 return CAC_FAILURE;
547 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
548 hnd->status = NT_STATUS_INVALID_HANDLE;
549 return CAC_FAILURE;
552 if(!op || !op->in.dom_hnd || !mem_ctx) {
553 hnd->status = NT_STATUS_INVALID_PARAMETER;
554 return CAC_FAILURE;
557 if(!op->in.names && op->in.num_names != 0) {
558 hnd->status = NT_STATUS_INVALID_PARAMETER;
559 return CAC_FAILURE;
562 if(op->in.num_names == 0) {
563 /*then we don't have to do anything*/
564 op->out.num_rids = 0;
565 return CAC_SUCCESS;
568 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
569 if(!pipe_hnd) {
570 hnd->status = NT_STATUS_INVALID_HANDLE;
571 return CAC_FAILURE;
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))
578 return CAC_FAILURE;
580 map_out = TALLOC_ARRAY(mem_ctx, CacLookupRidsRecord, num_rids_out);
581 if(!map_out) {
582 hnd->status = NT_STATUS_NO_MEMORY;
583 return CAC_FAILURE;
586 for(i = 0; i < num_rids_out; i++) {
588 if(rid_types_out[i] == SAMR_RID_UNKNOWN) {
589 map_out[i].found = False;
590 map_out[i].rid = 0;
591 map_out[i].type = 0;
593 else {
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;
611 return CAC_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;
624 uint32 i;
626 if(!hnd)
627 return CAC_FAILURE;
629 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
630 hnd->status = NT_STATUS_INVALID_HANDLE;
631 return CAC_FAILURE;
634 if(!op || !op->in.user_hnd || !mem_ctx) {
635 hnd->status = NT_STATUS_INVALID_PARAMETER;
636 return CAC_FAILURE;
639 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
640 if(!pipe_hnd) {
641 hnd->status = NT_STATUS_INVALID_HANDLE;
642 return CAC_FAILURE;
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))
648 return CAC_FAILURE;
651 rids_out = talloc_array(mem_ctx, uint32, num_groups_out);
652 if(!rids_out) {
653 hnd->status = NT_STATUS_NO_MEMORY;
654 return CAC_FAILURE;
657 attr_out = talloc_array(mem_ctx, uint32, num_groups_out);
658 if(!attr_out) {
659 hnd->status = NT_STATUS_NO_MEMORY;
660 return CAC_FAILURE;
663 for(i = 0; i < num_groups_out; i++) {
664 rids_out[i] = groups[i].g_rid;
665 attr_out[i] = groups[i].attr;
668 talloc_free(groups);
670 op->out.num_groups = num_groups_out;
671 op->out.rids = rids_out;
672 op->out.attributes = attr_out;
674 return CAC_SUCCESS;
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;
683 if(!hnd)
684 return CAC_FAILURE;
686 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
687 hnd->status = NT_STATUS_INVALID_HANDLE;
688 return CAC_FAILURE;
691 if(!op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx) {
692 hnd->status = NT_STATUS_INVALID_PARAMETER;
693 return CAC_FAILURE;
696 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
697 if(!pipe_hnd) {
698 hnd->status = NT_STATUS_INVALID_HANDLE;
699 return CAC_FAILURE;
702 group_hnd_out = talloc(mem_ctx, POLICY_HND);
703 if(!group_hnd_out) {
704 hnd->status = NT_STATUS_NO_MEMORY;
705 return CAC_FAILURE;
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))
711 return CAC_FAILURE;
713 op->out.group_hnd = group_hnd_out;
715 return CAC_SUCCESS;
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;
723 if(!hnd)
724 return CAC_FAILURE;
726 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
727 hnd->status = NT_STATUS_INVALID_HANDLE;
728 return CAC_FAILURE;
731 if(!op || !op->in.name || op->in.name[0] == '\0' || op->in.access == 0 || !mem_ctx) {
732 hnd->status = NT_STATUS_INVALID_PARAMETER;
733 return CAC_FAILURE;
736 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
737 if(!pipe_hnd) {
738 hnd->status = NT_STATUS_INVALID_HANDLE;
739 return CAC_FAILURE;
742 group_hnd_out = talloc(mem_ctx, POLICY_HND);
743 if(!group_hnd_out) {
744 hnd->status = NT_STATUS_NO_MEMORY;
745 return CAC_FAILURE;
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))
751 return CAC_FAILURE;
753 op->out.group_hnd = group_hnd_out;
755 return CAC_SUCCESS;
759 int cac_SamDeleteGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd) {
760 struct rpc_pipe_client *pipe_hnd = NULL;
762 if(!hnd)
763 return CAC_FAILURE;
765 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
766 hnd->status = NT_STATUS_INVALID_HANDLE;
767 return CAC_FAILURE;
770 if(!group_hnd || !mem_ctx) {
771 hnd->status = NT_STATUS_INVALID_PARAMETER;
772 return CAC_FAILURE;
775 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
776 if(!pipe_hnd) {
777 hnd->status = NT_STATUS_INVALID_HANDLE;
778 return CAC_FAILURE;
781 hnd->status = rpccli_samr_delete_dom_group( pipe_hnd, mem_ctx, group_hnd);
783 if(!NT_STATUS_IS_OK(hnd->status))
784 return CAC_FAILURE;
786 return CAC_SUCCESS;
790 int cac_SamGetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupMembers *op) {
791 struct rpc_pipe_client *pipe_hnd = NULL;
793 uint32 num_mem_out;
794 uint32 *rids_out;
795 uint32 *attr_out;
797 if(!hnd)
798 return CAC_FAILURE;
800 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
801 hnd->status = NT_STATUS_INVALID_HANDLE;
802 return CAC_FAILURE;
805 if(!op || !op->in.group_hnd || !mem_ctx) {
806 hnd->status = NT_STATUS_INVALID_PARAMETER;
807 return CAC_FAILURE;
810 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
811 if(!pipe_hnd) {
812 hnd->status = NT_STATUS_INVALID_HANDLE;
813 return CAC_FAILURE;
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))
819 return CAC_FAILURE;
821 op->out.num_members = num_mem_out;
822 op->out.rids = rids_out;
823 op->out.attributes = attr_out;
825 return CAC_SUCCESS;
829 int cac_SamAddGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddGroupMember *op) {
830 struct rpc_pipe_client *pipe_hnd = NULL;
832 if(!hnd)
833 return CAC_FAILURE;
835 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
836 hnd->status = NT_STATUS_INVALID_HANDLE;
837 return CAC_FAILURE;
840 if(!op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx) {
841 hnd->status = NT_STATUS_INVALID_PARAMETER;
842 return CAC_FAILURE;
845 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
846 if(!pipe_hnd) {
847 hnd->status = NT_STATUS_INVALID_HANDLE;
848 return CAC_FAILURE;
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))
854 return CAC_FAILURE;
856 return CAC_SUCCESS;
859 int cac_SamRemoveGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveGroupMember *op) {
860 struct rpc_pipe_client *pipe_hnd = NULL;
862 if(!hnd)
863 return CAC_FAILURE;
865 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
866 hnd->status = NT_STATUS_INVALID_HANDLE;
867 return CAC_FAILURE;
870 if(!op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx) {
871 hnd->status = NT_STATUS_INVALID_PARAMETER;
872 return CAC_FAILURE;
875 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
876 if(!pipe_hnd) {
877 hnd->status = NT_STATUS_INVALID_HANDLE;
878 return CAC_FAILURE;
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))
884 return CAC_FAILURE;
886 return CAC_SUCCESS;
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;
894 uint32 i = 0;
896 uint32 num_mem = 0;
897 uint32 *rid = NULL;
898 uint32 *attr = NULL;
900 NTSTATUS status;
902 if(!hnd)
903 return CAC_FAILURE;
905 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
906 hnd->status = NT_STATUS_INVALID_HANDLE;
907 return CAC_FAILURE;
910 if(!group_hnd || !mem_ctx) {
911 hnd->status = NT_STATUS_INVALID_PARAMETER;
912 return CAC_FAILURE;
915 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
916 if(!pipe_hnd) {
917 hnd->status = NT_STATUS_INVALID_HANDLE;
918 return CAC_FAILURE;
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))
924 return CAC_FAILURE;
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;
944 talloc_free(attr);
946 return result;
949 int cac_SamSetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetGroupMembers *op) {
950 struct rpc_pipe_client *pipe_hnd = NULL;
952 uint32 i = 0;
954 if(!hnd)
955 return CAC_FAILURE;
957 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
958 hnd->status = NT_STATUS_INVALID_HANDLE;
959 return CAC_FAILURE;
962 if(!op || !op->in.group_hnd || !mem_ctx) {
963 hnd->status = NT_STATUS_INVALID_PARAMETER;
964 return CAC_FAILURE;
967 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
968 if(!pipe_hnd) {
969 hnd->status = NT_STATUS_INVALID_HANDLE;
970 return CAC_FAILURE;
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))
983 return CAC_FAILURE;
985 return CAC_SUCCESS;
989 int cac_SamEnumGroups(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumGroups *op) {
990 struct rpc_pipe_client *pipe_hnd = NULL;
992 uint32 i = 0;
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;
1002 if(!hnd)
1003 return CAC_FAILURE;
1005 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1006 hnd->status = NT_STATUS_INVALID_HANDLE;
1007 return CAC_FAILURE;
1010 if(!op || !op->in.dom_hnd || !mem_ctx) {
1011 hnd->status = NT_STATUS_INVALID_PARAMETER;
1012 return CAC_FAILURE;
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*/
1017 return CAC_FAILURE;
1019 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1020 if(!pipe_hnd) {
1021 hnd->status = NT_STATUS_INVALID_HANDLE;
1022 return CAC_FAILURE;
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*/
1037 return CAC_FAILURE;
1040 names_out = talloc_array(mem_ctx, char *, num_groups_out);
1041 if(!names_out) {
1042 hnd->status = NT_STATUS_NO_MEMORY;
1043 talloc_free(acct_buf);
1044 return CAC_FAILURE;
1047 desc_out = talloc_array(mem_ctx, char *, num_groups_out);
1048 if(!desc_out) {
1049 hnd->status = NT_STATUS_NO_MEMORY;
1050 talloc_free(acct_buf);
1051 talloc_free(names_out);
1052 return CAC_FAILURE;
1055 rids_out = talloc_array(mem_ctx, uint32, num_groups_out);
1056 if(!rids_out) {
1057 hnd->status = NT_STATUS_NO_MEMORY;
1058 talloc_free(acct_buf);
1059 talloc_free(names_out);
1060 talloc_free(desc_out);
1061 return CAC_FAILURE;
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;
1071 return CAC_FAILURE;
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;
1081 return CAC_SUCCESS;
1084 int cac_SamEnumAliases(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumAliases *op) {
1085 struct rpc_pipe_client *pipe_hnd = NULL;
1087 uint32 i = 0;
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;
1097 if(!hnd)
1098 return CAC_FAILURE;
1100 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1101 hnd->status = NT_STATUS_INVALID_HANDLE;
1102 return CAC_FAILURE;
1105 if(!op || !op->in.dom_hnd || !mem_ctx) {
1106 hnd->status = NT_STATUS_INVALID_PARAMETER;
1107 return CAC_FAILURE;
1110 /*this is a hack.. but is the only reliable way to know if everything has been enumerated*/
1111 if(op->out.done == True) {
1112 return CAC_FAILURE;
1115 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1116 if(!pipe_hnd) {
1117 hnd->status = NT_STATUS_INVALID_HANDLE;
1118 return CAC_FAILURE;
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))
1133 return CAC_FAILURE;
1135 names_out = talloc_array(mem_ctx, char *, num_als_out);
1136 if(!names_out) {
1137 hnd->status = NT_STATUS_NO_MEMORY;
1138 talloc_free(acct_buf);
1139 return CAC_FAILURE;
1142 desc_out = talloc_array(mem_ctx, char *, num_als_out);
1143 if(!desc_out) {
1144 hnd->status = NT_STATUS_NO_MEMORY;
1145 talloc_free(acct_buf);
1146 talloc_free(names_out);
1147 return CAC_FAILURE;
1150 rids_out = talloc_array(mem_ctx, uint32, num_als_out);
1151 if(!rids_out) {
1152 hnd->status = NT_STATUS_NO_MEMORY;
1153 talloc_free(acct_buf);
1154 talloc_free(names_out);
1155 talloc_free(desc_out);
1156 return CAC_FAILURE;
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;
1166 return CAC_FAILURE;
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;
1176 return CAC_SUCCESS;
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;
1184 if(!hnd)
1185 return CAC_FAILURE;
1187 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1188 hnd->status = NT_STATUS_INVALID_HANDLE;
1189 return CAC_FAILURE;
1192 if(!op || !op->in.name || op->in.name[0] == '\0' || !mem_ctx) {
1193 hnd->status = NT_STATUS_INVALID_PARAMETER;
1194 return CAC_FAILURE;
1197 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1198 if(!pipe_hnd) {
1199 hnd->status = NT_STATUS_INVALID_HANDLE;
1200 return CAC_FAILURE;
1203 als_hnd_out = talloc(mem_ctx, POLICY_HND);
1204 if(!als_hnd_out) {
1205 hnd->status = NT_STATUS_NO_MEMORY;
1206 return CAC_FAILURE;
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))
1212 return CAC_FAILURE;
1214 op->out.alias_hnd = als_hnd_out;
1216 return CAC_SUCCESS;
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;
1225 if(!hnd)
1226 return CAC_FAILURE;
1228 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1229 hnd->status = NT_STATUS_INVALID_HANDLE;
1230 return CAC_FAILURE;
1233 if(!op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx) {
1234 hnd->status = NT_STATUS_INVALID_PARAMETER;
1235 return CAC_FAILURE;
1238 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1239 if(!pipe_hnd) {
1240 hnd->status = NT_STATUS_INVALID_HANDLE;
1241 return CAC_FAILURE;
1244 als_hnd_out = talloc(mem_ctx, POLICY_HND);
1245 if(!als_hnd_out) {
1246 hnd->status = NT_STATUS_NO_MEMORY;
1247 return CAC_FAILURE;
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))
1253 return CAC_FAILURE;
1255 op->out.alias_hnd = als_hnd_out;
1257 return CAC_SUCCESS;
1260 int cac_SamDeleteAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *alias_hnd) {
1261 struct rpc_pipe_client *pipe_hnd = NULL;
1263 if(!hnd)
1264 return CAC_FAILURE;
1266 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1267 hnd->status = NT_STATUS_INVALID_HANDLE;
1268 return CAC_FAILURE;
1271 if(!alias_hnd || !mem_ctx) {
1272 hnd->status = NT_STATUS_INVALID_PARAMETER;
1273 return CAC_FAILURE;
1276 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1277 if(!pipe_hnd) {
1278 hnd->status = NT_STATUS_INVALID_HANDLE;
1279 return CAC_FAILURE;
1282 hnd->status = rpccli_samr_delete_dom_alias( pipe_hnd, mem_ctx, alias_hnd);
1284 if(!NT_STATUS_IS_OK(hnd->status))
1285 return CAC_FAILURE;
1287 return CAC_SUCCESS;
1291 int cac_SamAddAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddAliasMember *op) {
1292 struct rpc_pipe_client *pipe_hnd = NULL;
1294 if(!hnd)
1295 return CAC_FAILURE;
1297 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1298 hnd->status = NT_STATUS_INVALID_HANDLE;
1299 return CAC_FAILURE;
1302 if(!op || !op->in.alias_hnd || !op->in.sid || !mem_ctx) {
1303 hnd->status = NT_STATUS_INVALID_PARAMETER;
1304 return CAC_FAILURE;
1307 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1308 if(!pipe_hnd) {
1309 hnd->status = NT_STATUS_INVALID_HANDLE;
1310 return CAC_FAILURE;
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))
1316 return CAC_FAILURE;
1318 return CAC_SUCCESS;
1321 int cac_SamRemoveAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveAliasMember *op) {
1322 struct rpc_pipe_client *pipe_hnd = NULL;
1324 if(!hnd)
1325 return CAC_FAILURE;
1327 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1328 hnd->status = NT_STATUS_INVALID_HANDLE;
1329 return CAC_FAILURE;
1332 if(!op || !op->in.alias_hnd || !op->in.sid || !mem_ctx) {
1333 hnd->status = NT_STATUS_INVALID_PARAMETER;
1334 return CAC_FAILURE;
1337 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1338 if(!pipe_hnd) {
1339 hnd->status = NT_STATUS_INVALID_HANDLE;
1340 return CAC_FAILURE;
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))
1346 return CAC_FAILURE;
1348 return CAC_SUCCESS;
1351 int cac_SamGetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasMembers *op) {
1352 struct rpc_pipe_client *pipe_hnd = NULL;
1354 uint32 num_mem_out;
1355 DOM_SID *sids_out;
1357 if(!hnd)
1358 return CAC_FAILURE;
1360 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1361 hnd->status = NT_STATUS_INVALID_HANDLE;
1362 return CAC_FAILURE;
1365 if(!op || !op->in.alias_hnd || !mem_ctx) {
1366 hnd->status = NT_STATUS_INVALID_PARAMETER;
1367 return CAC_FAILURE;
1370 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1371 if(!pipe_hnd) {
1372 hnd->status = NT_STATUS_INVALID_HANDLE;
1373 return CAC_FAILURE;
1376 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))
1379 return CAC_FAILURE;
1381 op->out.num_members = num_mem_out;
1382 op->out.sids = sids_out;
1384 return CAC_SUCCESS;
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;
1392 uint32 i = 0;
1394 uint32 num_mem = 0;
1395 DOM_SID *sid = NULL;
1397 NTSTATUS status;
1399 if(!hnd)
1400 return CAC_FAILURE;
1402 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1403 hnd->status = NT_STATUS_INVALID_HANDLE;
1404 return CAC_FAILURE;
1407 if(!alias_hnd || !mem_ctx) {
1408 hnd->status = NT_STATUS_INVALID_PARAMETER;
1409 return CAC_FAILURE;
1412 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1413 if(!pipe_hnd) {
1414 hnd->status = NT_STATUS_INVALID_HANDLE;
1415 return CAC_FAILURE;
1418 hnd->status = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx, alias_hnd, &num_mem, &sid);
1420 if(!NT_STATUS_IS_OK(hnd->status))
1421 return CAC_FAILURE;
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;
1441 talloc_free(sid);
1442 return result;
1445 int cac_SamSetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetAliasMembers *op) {
1446 struct rpc_pipe_client *pipe_hnd = NULL;
1448 uint32 i = 0;
1450 if(!hnd)
1451 return CAC_FAILURE;
1453 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1454 hnd->status = NT_STATUS_INVALID_HANDLE;
1455 return CAC_FAILURE;
1458 if(!op || !op->in.alias_hnd || !mem_ctx) {
1459 hnd->status = NT_STATUS_INVALID_PARAMETER;
1460 return CAC_FAILURE;
1463 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1464 if(!pipe_hnd) {
1465 hnd->status = NT_STATUS_INVALID_HANDLE;
1466 return CAC_FAILURE;
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))
1479 return CAC_FAILURE;
1481 return CAC_SUCCESS;
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;
1489 if(!hnd)
1490 return CAC_FAILURE;
1492 if(!hnd->_internal.ctx) {
1493 hnd->status = NT_STATUS_INVALID_HANDLE;
1494 return CAC_FAILURE;
1497 if(!op || !op->in.username || !op->in.password || !op->in.new_password || !mem_ctx) {
1498 hnd->status = NT_STATUS_INVALID_PARAMETER;
1499 return CAC_FAILURE;
1502 srv = cac_GetServer(hnd);
1503 if(!srv) {
1504 hnd->status = NT_STATUS_INVALID_CONNECTION;
1505 return CAC_FAILURE;
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)))) {
1511 return CAC_FAILURE;
1514 hnd->_internal.pipes[PI_SAMR] = True;
1517 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1518 if(!pipe_hnd) {
1519 hnd->status = NT_STATUS_INVALID_HANDLE;
1520 return CAC_FAILURE;
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))
1526 return CAC_FAILURE;
1528 return CAC_SUCCESS;
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;
1537 if(!hnd)
1538 return CAC_FAILURE;
1540 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1541 hnd->status = NT_STATUS_INVALID_HANDLE;
1542 return CAC_FAILURE;
1545 if(!user_hnd || !mem_ctx) {
1546 hnd->status = NT_STATUS_INVALID_PARAMETER;
1547 return CAC_FAILURE;
1550 srv = cac_GetServer(hnd);
1551 if(!srv) {
1552 hnd->status = NT_STATUS_INVALID_CONNECTION;
1553 return CAC_FAILURE;
1556 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1557 if(!pipe_hnd) {
1558 hnd->status = NT_STATUS_INVALID_HANDLE;
1559 return CAC_FAILURE;
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))
1566 return CAC_FAILURE;
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;
1573 else {
1574 /*the user is already enabled so just return success*/
1575 return CAC_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))
1583 return CAC_FAILURE;
1585 return CAC_SUCCESS;
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;
1594 if(!hnd)
1595 return CAC_FAILURE;
1597 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1598 hnd->status = NT_STATUS_INVALID_HANDLE;
1599 return CAC_FAILURE;
1602 if(!user_hnd || !mem_ctx) {
1603 hnd->status = NT_STATUS_INVALID_PARAMETER;
1604 return CAC_FAILURE;
1607 srv = cac_GetServer(hnd);
1608 if(!srv) {
1609 hnd->status = NT_STATUS_INVALID_CONNECTION;
1610 return CAC_FAILURE;
1613 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1614 if(!pipe_hnd) {
1615 hnd->status = NT_STATUS_INVALID_HANDLE;
1616 return CAC_FAILURE;
1619 hnd->status = rpccli_samr_query_userinfo( pipe_hnd, mem_ctx, user_hnd, 0x10, &ctr);
1621 if(!NT_STATUS_IS_OK(hnd->status))
1622 return CAC_FAILURE;
1624 if((ctr->info.id16->acb_info & ACB_DISABLED) == ACB_DISABLED) {
1625 /*then the user is already disabled*/
1626 return CAC_SUCCESS;
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))
1637 return CAC_FAILURE;
1639 return CAC_SUCCESS;
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;
1648 uint8 pw[516];
1650 if(!hnd)
1651 return CAC_FAILURE;
1653 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1654 hnd->status = NT_STATUS_INVALID_HANDLE;
1655 return CAC_FAILURE;
1658 if(!op->in.user_hnd || !op->in.password || !mem_ctx) {
1659 hnd->status = NT_STATUS_INVALID_PARAMETER;
1660 return CAC_FAILURE;
1663 srv = cac_GetServer(hnd);
1664 if(!srv) {
1665 hnd->status = NT_STATUS_INVALID_CONNECTION;
1666 return CAC_FAILURE;
1669 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1670 if(!pipe_hnd) {
1671 hnd->status = NT_STATUS_INVALID_HANDLE;
1672 return CAC_FAILURE;
1675 ZERO_STRUCT(ctr);
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))
1688 return CAC_FAILURE;
1690 return CAC_SUCCESS;
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;
1698 if(!hnd)
1699 return CAC_FAILURE;
1701 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1702 hnd->status = NT_STATUS_INVALID_HANDLE;
1703 return CAC_FAILURE;
1706 if(!op->in.user_hnd || !mem_ctx) {
1707 hnd->status = NT_STATUS_INVALID_PARAMETER;
1708 return CAC_FAILURE;
1711 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1712 if(!pipe_hnd) {
1713 hnd->status = NT_STATUS_INVALID_HANDLE;
1714 return CAC_FAILURE;
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))
1720 return CAC_FAILURE;
1722 op->out.info = cac_MakeUserInfo(mem_ctx, ctr);
1724 if(!op->out.info) {
1725 hnd->status = NT_STATUS_NO_MEMORY;
1726 return CAC_FAILURE;
1729 return CAC_SUCCESS;
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;
1738 if(!hnd)
1739 return CAC_FAILURE;
1741 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1742 hnd->status = NT_STATUS_INVALID_HANDLE;
1743 return CAC_FAILURE;
1746 if(!op->in.user_hnd || !op->in.info || !mem_ctx) {
1747 hnd->status = NT_STATUS_INVALID_PARAMETER;
1748 return CAC_FAILURE;
1751 ctr = cac_MakeUserInfoCtr(mem_ctx, op->in.info);
1752 if(!ctr) {
1753 hnd->status = NT_STATUS_NO_MEMORY;
1754 return CAC_FAILURE;
1757 srv = cac_GetServer(hnd);
1758 if(!srv) {
1759 hnd->status = NT_STATUS_INVALID_CONNECTION;
1760 return CAC_FAILURE;
1763 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1764 if(!pipe_hnd) {
1765 hnd->status = NT_STATUS_INVALID_HANDLE;
1766 return CAC_FAILURE;
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))
1783 return CAC_FAILURE;
1785 return CAC_SUCCESS;
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;
1794 if(!hnd)
1795 return CAC_FAILURE;
1797 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1798 hnd->status = NT_STATUS_INVALID_HANDLE;
1799 return CAC_FAILURE;
1802 if(!op->in.user_hnd || op->in.info_class == 0 || !mem_ctx) {
1803 hnd->status = NT_STATUS_INVALID_PARAMETER;
1804 return CAC_FAILURE;
1807 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1808 if(!pipe_hnd) {
1809 hnd->status = NT_STATUS_INVALID_HANDLE;
1810 return CAC_FAILURE;
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))
1816 return CAC_FAILURE;
1818 op->out.ctr = ctr_out;
1820 return CAC_SUCCESS;
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;
1827 if(!hnd)
1828 return CAC_FAILURE;
1830 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1831 hnd->status = NT_STATUS_INVALID_HANDLE;
1832 return CAC_FAILURE;
1835 if(!op->in.user_hnd || !op->in.ctr || !mem_ctx) {
1836 hnd->status = NT_STATUS_INVALID_PARAMETER;
1837 return CAC_FAILURE;
1840 srv = cac_GetServer(hnd);
1841 if(!srv) {
1842 hnd->status = NT_STATUS_INVALID_CONNECTION;
1843 return CAC_FAILURE;
1846 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1847 if(!pipe_hnd) {
1848 hnd->status = NT_STATUS_INVALID_HANDLE;
1849 return CAC_FAILURE;
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))
1856 return CAC_FAILURE;
1858 return CAC_SUCCESS;
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;
1869 if(!hnd)
1870 return CAC_FAILURE;
1872 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1873 hnd->status = NT_STATUS_INVALID_HANDLE;
1874 return CAC_FAILURE;
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;
1879 return CAC_FAILURE;
1882 srv = cac_GetServer(hnd);
1883 if(!srv) {
1884 hnd->status = NT_STATUS_INVALID_CONNECTION;
1885 return CAC_FAILURE;
1888 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1889 if(!pipe_hnd) {
1890 hnd->status = NT_STATUS_INVALID_HANDLE;
1891 return CAC_FAILURE;
1894 ZERO_STRUCT(ctr);
1895 ZERO_STRUCT(info7);
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))
1905 return CAC_FAILURE;
1907 return CAC_SUCCESS;
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;
1916 if(!hnd)
1917 return CAC_FAILURE;
1919 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1920 hnd->status = NT_STATUS_INVALID_HANDLE;
1921 return CAC_FAILURE;
1924 if(!op->in.group_hnd || !mem_ctx) {
1925 hnd->status = NT_STATUS_INVALID_PARAMETER;
1926 return CAC_FAILURE;
1929 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1930 if(!pipe_hnd) {
1931 hnd->status = NT_STATUS_INVALID_HANDLE;
1932 return CAC_FAILURE;
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))
1940 return CAC_FAILURE;
1942 op->out.info = cac_MakeGroupInfo(mem_ctx, ctr);
1943 if(!op->out.info) {
1944 hnd->status = NT_STATUS_NO_MEMORY;
1945 return CAC_FAILURE;
1948 return CAC_SUCCESS;
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;
1956 if(!hnd)
1957 return CAC_FAILURE;
1959 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1960 hnd->status = NT_STATUS_INVALID_HANDLE;
1961 return CAC_FAILURE;
1964 if(!op->in.group_hnd || !op->in.info || !mem_ctx) {
1965 hnd->status = NT_STATUS_INVALID_PARAMETER;
1966 return CAC_FAILURE;
1969 ctr = cac_MakeGroupInfoCtr(mem_ctx, op->in.info);
1970 if(!ctr) {
1971 hnd->status = NT_STATUS_NO_MEMORY;
1972 return CAC_FAILURE;
1975 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
1976 if(!pipe_hnd) {
1977 hnd->status = NT_STATUS_INVALID_HANDLE;
1978 return CAC_FAILURE;
1981 hnd->status = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, op->in.group_hnd, ctr);
1983 if(!NT_STATUS_IS_OK(hnd->status))
1984 return CAC_FAILURE;
1986 return CAC_SUCCESS;
1989 int cac_SamRenameGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenameGroup *op) {
1990 struct rpc_pipe_client *pipe_hnd = NULL;
1992 GROUP_INFO_CTR ctr;
1994 if(!hnd)
1995 return CAC_FAILURE;
1997 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1998 hnd->status = NT_STATUS_INVALID_HANDLE;
1999 return CAC_FAILURE;
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;
2004 return CAC_FAILURE;
2007 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2008 if(!pipe_hnd) {
2009 hnd->status = NT_STATUS_INVALID_HANDLE;
2010 return CAC_FAILURE;
2013 ZERO_STRUCT(ctr);
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))
2021 return CAC_FAILURE;
2023 return CAC_SUCCESS;
2026 int cac_SamGetAliasInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasInfo *op) {
2027 struct rpc_pipe_client *pipe_hnd = NULL;
2029 ALIAS_INFO_CTR ctr;
2031 if(!hnd)
2032 return CAC_FAILURE;
2034 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2035 hnd->status = NT_STATUS_INVALID_HANDLE;
2036 return CAC_FAILURE;
2039 if(!op->in.alias_hnd || !mem_ctx) {
2040 hnd->status = NT_STATUS_INVALID_PARAMETER;
2041 return CAC_FAILURE;
2044 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2045 if(!pipe_hnd) {
2046 hnd->status = NT_STATUS_INVALID_HANDLE;
2047 return CAC_FAILURE;
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))
2054 return CAC_FAILURE;
2056 op->out.info = cac_MakeAliasInfo(mem_ctx, ctr);
2057 if(!op->out.info) {
2058 hnd->status = NT_STATUS_NO_MEMORY;
2059 return CAC_FAILURE;
2062 return CAC_SUCCESS;
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;
2071 if(!hnd)
2072 return CAC_FAILURE;
2074 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2075 hnd->status = NT_STATUS_INVALID_HANDLE;
2076 return CAC_FAILURE;
2079 if(!op->in.alias_hnd || !op->in.info || !mem_ctx) {
2080 hnd->status = NT_STATUS_INVALID_PARAMETER;
2081 return CAC_FAILURE;
2084 ctr = cac_MakeAliasInfoCtr(mem_ctx, op->in.info);
2085 if(!ctr) {
2086 hnd->status = NT_STATUS_NO_MEMORY;
2087 return CAC_FAILURE;
2090 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2091 if(!pipe_hnd) {
2092 hnd->status = NT_STATUS_INVALID_HANDLE;
2093 return CAC_FAILURE;
2096 hnd->status = rpccli_samr_set_aliasinfo(pipe_hnd, mem_ctx, op->in.alias_hnd, ctr);
2098 if(!NT_STATUS_IS_OK(hnd->status))
2099 return CAC_FAILURE;
2101 return CAC_SUCCESS;
2104 int cac_SamGetDomainInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDomainInfo *op) {
2105 struct rpc_pipe_client *pipe_hnd = NULL;
2107 SAM_UNK_CTR ctr;
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;
2118 if(!hnd)
2119 return CAC_FAILURE;
2121 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2122 hnd->status = NT_STATUS_INVALID_HANDLE;
2123 return CAC_FAILURE;
2126 if(!op->in.dom_hnd || !mem_ctx) {
2127 hnd->status = NT_STATUS_INVALID_PARAMETER;
2128 return CAC_FAILURE;
2131 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2132 if(!pipe_hnd) {
2133 hnd->status = NT_STATUS_INVALID_HANDLE;
2134 return CAC_FAILURE;
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;
2144 else {
2145 /*then the call failed, store the status and ZERO out the info structure*/
2146 ZERO_STRUCT(info1);
2147 status_buf = hnd->status;
2148 fail_count++;
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)) {
2155 /*store the info*/
2156 info2 = ctr.info.inf2;
2158 else {
2159 /*ZERO out the structure and store the bad status*/
2160 ZERO_STRUCT(info2);
2161 status_buf = hnd->status;
2162 fail_count++;
2165 /*once more*/
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;
2171 else {
2172 ZERO_STRUCT(info12);
2173 status_buf = hnd->status;
2174 fail_count++;
2177 /*return failure if all 3 calls failed*/
2178 if(fail_count == 3)
2179 return CAC_FAILURE;
2181 op->out.info = cac_MakeDomainInfo(mem_ctx, &info1, &info2, &info12);
2183 if(!op->out.info) {
2184 hnd->status = NT_STATUS_NO_MEMORY;
2185 return CAC_FAILURE;
2188 if(fail_count > 0) {
2189 hnd->status = status_buf;
2190 return CAC_PARTIAL_SUCCESS;
2193 return CAC_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;
2201 if(!hnd)
2202 return CAC_FAILURE;
2204 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2205 hnd->status = NT_STATUS_INVALID_HANDLE;
2206 return CAC_FAILURE;
2209 if(!op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx) {
2210 hnd->status = NT_STATUS_INVALID_PARAMETER;
2211 return CAC_FAILURE;
2214 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2215 if(!pipe_hnd) {
2216 hnd->status = NT_STATUS_INVALID_HANDLE;
2217 return CAC_FAILURE;
2220 ctr_out = talloc(mem_ctx, SAM_UNK_CTR);
2221 if(!ctr_out) {
2222 hnd->status = NT_STATUS_NO_MEMORY;
2223 return CAC_FAILURE;
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))
2229 return CAC_FAILURE;
2231 op->out.info = ctr_out;
2233 return CAC_SUCCESS;
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;
2247 if(!hnd)
2248 return CAC_FAILURE;
2250 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2251 hnd->status = NT_STATUS_INVALID_HANDLE;
2252 return CAC_FAILURE;
2255 if(!op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx) {
2256 hnd->status = NT_STATUS_INVALID_PARAMETER;
2257 return CAC_FAILURE;
2260 if(op->out.done == True) /*this is done so we can use the function as a loop condition*/
2261 return CAC_FAILURE;
2263 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2264 if(!pipe_hnd) {
2265 hnd->status = NT_STATUS_INVALID_HANDLE;
2266 return CAC_FAILURE;
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);
2272 else {
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;
2286 return CAC_FAILURE;
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++;
2299 return CAC_SUCCESS;
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;
2307 if(!hnd)
2308 return CAC_FAILURE;
2310 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2311 hnd->status = NT_STATUS_INVALID_HANDLE;
2312 return CAC_FAILURE;
2315 if(!op->in.sam || !op->in.name || !mem_ctx) {
2316 hnd->status = NT_STATUS_INVALID_PARAMETER;
2317 return CAC_FAILURE;
2320 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2321 if(!pipe_hnd) {
2322 hnd->status = NT_STATUS_INVALID_HANDLE;
2323 return CAC_FAILURE;
2326 sid_out = talloc(mem_ctx, DOM_SID);
2327 if(!sid_out) {
2328 hnd->status = NT_STATUS_NO_MEMORY;
2329 return CAC_FAILURE;
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))
2335 return CAC_FAILURE;
2337 op->out.sid = sid_out;
2339 return CAC_SUCCESS;
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 uint16 info_level = 4;
2348 SEC_DESC_BUF *sec_out = NULL;
2350 if(!hnd)
2351 return CAC_FAILURE;
2353 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2354 hnd->status = NT_STATUS_INVALID_HANDLE;
2355 return CAC_FAILURE;
2358 if(!op->in.pol || !mem_ctx) {
2359 hnd->status = NT_STATUS_INVALID_PARAMETER;
2360 return CAC_FAILURE;
2363 pipe_hnd = cac_GetPipe(hnd, PI_SAMR);
2364 if(!pipe_hnd) {
2365 hnd->status = NT_STATUS_INVALID_HANDLE;
2366 return CAC_FAILURE;
2369 hnd->status = rpccli_samr_query_sec_obj(pipe_hnd, mem_ctx, op->in.pol, info_level, mem_ctx, &sec_out);
2371 if(!NT_STATUS_IS_OK(hnd->status))
2372 return CAC_FAILURE;
2374 op->out.sec = sec_out;
2376 return CAC_SUCCESS;
2379 int cac_SamFlush(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamFlush *op) {
2380 struct SamOpenDomain od;
2382 if(!hnd)
2383 return CAC_FAILURE;
2385 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2386 hnd->status = NT_STATUS_INVALID_HANDLE;
2387 return CAC_FAILURE;
2390 if(!op || !op->in.dom_hnd || !mem_ctx) {
2391 hnd->status = NT_STATUS_INVALID_PARAMETER;
2392 return CAC_FAILURE;
2395 if(!cac_SamClose(hnd, mem_ctx, op->in.dom_hnd))
2396 return CAC_FAILURE;
2398 ZERO_STRUCT(od);
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))
2403 return CAC_FAILURE;
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);
2410 return CAC_SUCCESS;