r10909: Give better shutdown messages
[Samba/nascimento.git] / source3 / libmsrpc / cac_samr.c
blobc6efaa2d3850e8d481d621f57a8293ffdc4e8e62
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 POLICY_HND *sam_out = NULL;
36 if(!hnd)
37 return CAC_FAILURE;
39 if(!hnd->_internal.ctx) {
40 hnd->status = NT_STATUS_INVALID_HANDLE;
41 return CAC_FAILURE;
44 if(!op || op->in.access == 0 || !mem_ctx) {
45 hnd->status = NT_STATUS_INVALID_PARAMETER;
46 return CAC_FAILURE;
49 srv = cac_GetServer(hnd);
50 if(!srv) {
51 hnd->status = NT_STATUS_INVALID_CONNECTION;
52 return CAC_FAILURE;
55 /*initialize for samr pipe if we have to*/
56 if(!hnd->_internal.pipes[PI_SAMR]) {
57 if(!cli_nt_session_open(&srv->cli, PI_SAMR)) {
58 hnd->status = NT_STATUS_UNSUCCESSFUL;
59 return CAC_FAILURE;
62 hnd->_internal.pipes[PI_SAMR] = True;
65 srv->cli.pipe_idx = PI_SAMR;
67 sam_out = talloc(mem_ctx, POLICY_HND);
68 if(!sam_out) {
69 hnd->status = NT_STATUS_NO_MEMORY;
70 return CAC_FAILURE;
73 if(hnd->_internal.srv_level >= SRV_WIN_2K_SP3) {
74 hnd->status = cli_samr_connect4( &(srv->cli), mem_ctx, op->in.access, sam_out);
77 if(hnd->_internal.srv_level < SRV_WIN_2K_SP3 || !NT_STATUS_IS_OK(hnd->status)) {
78 /*if sam_connect4 failed, the use sam_connect and lower srv_level*/
80 hnd->status = cli_samr_connect( &(srv->cli), mem_ctx, op->in.access, sam_out);
82 if(NT_STATUS_IS_OK(hnd->status) && hnd->_internal.srv_level > SRV_WIN_2K) {
83 hnd->_internal.srv_level = SRV_WIN_2K;
87 if(!NT_STATUS_IS_OK(hnd->status))
88 return CAC_FAILURE;
90 op->out.sam = sam_out;
92 return CAC_SUCCESS;
95 int cac_SamClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *sam) {
96 SMBCSRV *srv = NULL;
98 if(!hnd)
99 return CAC_FAILURE;
101 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
102 hnd->status = NT_STATUS_INVALID_HANDLE;
103 return CAC_FAILURE;
106 if(!sam || !mem_ctx) {
107 hnd->status = NT_STATUS_INVALID_PARAMETER;
108 return CAC_FAILURE;
111 srv = cac_GetServer(hnd);
112 if(!srv) {
113 hnd->status = NT_STATUS_INVALID_CONNECTION;
114 return CAC_FAILURE;
117 srv->cli.pipe_idx = PI_SAMR;
119 hnd->status = cli_samr_close( &(srv->cli), mem_ctx, sam);
121 if(!NT_STATUS_IS_OK(hnd->status))
122 return CAC_FAILURE;
124 return CAC_SUCCESS;
127 /*this is an internal function. Due to a circular dependency, it must be prototyped in libmsrpc.h (which I don't want to do)
128 * cac_SamOpenDomain() is the only function that calls it, so I just put the definition here
130 /*attempts to find the sid of the domain we are connected to*/
131 DOM_SID *cac_get_domain_sid(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, uint32 des_access) {
132 struct LsaOpenPolicy lop;
133 struct LsaFetchSid fs;
135 DOM_SID *sid;
137 ZERO_STRUCT(lop);
138 ZERO_STRUCT(fs);
140 lop.in.access = des_access;
141 lop.in.security_qos = True;
143 if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop))
144 return NULL;
146 fs.in.pol = lop.out.pol;
147 fs.in.info_class = CAC_DOMAIN_INFO;
149 if(!cac_LsaFetchSid(hnd, mem_ctx, &fs))
150 return NULL;
152 cac_LsaClosePolicy(hnd, mem_ctx, lop.out.pol);
154 if(!fs.out.domain_sid)
155 return NULL;
157 sid = talloc_memdup(mem_ctx, &(fs.out.domain_sid->sid), sizeof(DOM_SID));
159 if(!sid) {
160 hnd->status = NT_STATUS_NO_MEMORY;
163 return sid;
167 int cac_SamOpenDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenDomain *op) {
168 SMBCSRV *srv = NULL;
170 DOM_SID *sid_buf;
171 POLICY_HND *sam_out;
172 POLICY_HND *pol_out;
174 struct SamLookupDomain sld;
176 if(!hnd)
177 return CAC_FAILURE;
179 if(!hnd->_internal.ctx) {
180 hnd->status = NT_STATUS_INVALID_HANDLE;
181 return CAC_FAILURE;
184 if(!op || op->in.access == 0 || !mem_ctx) {
185 hnd->status = NT_STATUS_INVALID_PARAMETER;
186 return CAC_FAILURE;
189 srv = cac_GetServer(hnd);
190 if(!srv) {
191 hnd->status = NT_STATUS_INVALID_CONNECTION;
192 return CAC_FAILURE;
196 if(!op->in.sam) {
197 /*use cac_SamConnect() since it does the session setup*/
198 struct SamConnect sc;
199 ZERO_STRUCT(sc);
201 sc.in.access = op->in.access;
203 if(!cac_SamConnect(hnd, mem_ctx, &sc)) {
204 return CAC_FAILURE;
207 sam_out = sc.out.sam;
209 else {
210 sam_out = op->in.sam;
213 if(!op->in.sid) {
214 /*find the sid for the SAM's domain*/
216 /*try using cac_SamLookupDomain() first*/
217 ZERO_STRUCT(sld);
219 sld.in.sam = sam_out;
220 sld.in.name = hnd->domain;
222 if(cac_SamLookupDomain(hnd, mem_ctx, &sld)) {
223 /*then we got the sid*/
224 sid_buf = sld.out.sid;
226 else {
227 /*try to get it from the LSA*/
228 sid_buf = cac_get_domain_sid(hnd, mem_ctx, op->in.access);
231 else {
232 /*we already have the sid for the domain we want*/
233 sid_buf = op->in.sid;
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 = cli_samr_open_domain( &(srv->cli), 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 SMBCSRV *srv = 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 srv = cac_GetServer(hnd);
284 if(!srv) {
285 hnd->status = NT_STATUS_INVALID_CONNECTION;
286 return CAC_FAILURE;
289 srv->cli.pipe_idx = PI_SAMR;
291 if(op->in.rid == 0 && op->in.name) {
292 /*lookup the name and then set rid_buf*/
294 hnd->status = cli_samr_lookup_names( &(srv->cli), mem_ctx, op->in.dom_hnd, SAMR_LOOKUP_FLAGS, 1, (const char **)&op->in.name,
295 &num_rids, &rid_buf, &rid_types);
297 if(!NT_STATUS_IS_OK(hnd->status))
298 return CAC_FAILURE;
300 if(num_rids == 0 || rid_buf == NULL || rid_types[0] == SAMR_RID_UNKNOWN) {
301 hnd->status = NT_STATUS_INVALID_PARAMETER;
302 return CAC_FAILURE;
305 talloc_free(rid_types);
308 else {
309 rid_buf = &op->in.rid;
312 user_out = talloc(mem_ctx, POLICY_HND);
313 if(!user_out) {
314 hnd->status = NT_STATUS_NO_MEMORY;
315 return CAC_FAILURE;
318 hnd->status = cli_samr_open_user(&(srv->cli), mem_ctx, op->in.dom_hnd, op->in.access, *rid_buf, user_out);
320 if(!NT_STATUS_IS_OK(hnd->status))
321 return CAC_FAILURE;
323 op->out.user_hnd = user_out;
325 return CAC_SUCCESS;
328 int cac_SamCreateUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateUser *op) {
329 SMBCSRV *srv = NULL;
331 POLICY_HND *user_out = NULL;
332 uint32 rid_out;
334 /**found in rpcclient/cmd_samr.c*/
335 uint32 unknown = 0xe005000b;
337 if(!hnd)
338 return CAC_FAILURE;
340 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
341 hnd->status = NT_STATUS_INVALID_HANDLE;
342 return CAC_FAILURE;
345 if(!op || !op->in.dom_hnd || !op->in.name || op->in.acb_mask == 0 || !mem_ctx) {
346 hnd->status = NT_STATUS_INVALID_PARAMETER;
347 return CAC_FAILURE;
350 srv = cac_GetServer(hnd);
351 if(!srv) {
352 hnd->status = NT_STATUS_INVALID_CONNECTION;
353 return CAC_FAILURE;
356 srv->cli.pipe_idx = PI_SAMR;
358 user_out = talloc(mem_ctx, POLICY_HND);
359 if(!user_out) {
360 hnd->status = NT_STATUS_NO_MEMORY;
361 return CAC_FAILURE;
364 hnd->status = cli_samr_create_dom_user( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.name, op->in.acb_mask, unknown, user_out, &rid_out);
366 if(!NT_STATUS_IS_OK(hnd->status))
367 return CAC_FAILURE;
369 op->out.user_hnd = user_out;
370 op->out.rid = rid_out;
372 return CAC_SUCCESS;
375 int cac_SamDeleteUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) {
376 SMBCSRV *srv = NULL;
378 if(!hnd)
379 return CAC_FAILURE;
381 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
382 hnd->status = NT_STATUS_INVALID_HANDLE;
383 return CAC_FAILURE;
386 if(!user_hnd || !mem_ctx) {
387 hnd->status = NT_STATUS_INVALID_PARAMETER;
388 return CAC_FAILURE;
391 srv = cac_GetServer(hnd);
392 if(!srv) {
393 hnd->status = NT_STATUS_INVALID_CONNECTION;
394 return CAC_FAILURE;
397 srv->cli.pipe_idx = PI_SAMR;
399 hnd->status = cli_samr_delete_dom_user( &(srv->cli), mem_ctx, user_hnd);
401 if(!NT_STATUS_IS_OK(hnd->status))
402 return CAC_FAILURE;
404 return CAC_SUCCESS;
407 int cac_SamEnumUsers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumUsers *op) {
408 SMBCSRV *srv = NULL;
410 uint32 resume_idx_out = 0;
411 char **names_out = NULL;
412 uint32 *rids_out = NULL;
413 uint32 num_users_out = 0;
415 if(!hnd)
416 return CAC_FAILURE;
418 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
419 hnd->status = NT_STATUS_INVALID_HANDLE;
420 return CAC_FAILURE;
423 if(!op || !op->in.dom_hnd || !mem_ctx) {
424 hnd->status = NT_STATUS_INVALID_PARAMETER;
425 return CAC_FAILURE;
428 /*this is a hack.. but is the only reliable way to know if everything has been enumerated*/
429 if(op->out.done == True)
430 return CAC_FAILURE;
432 srv = cac_GetServer(hnd);
433 if(!srv) {
434 hnd->status = NT_STATUS_INVALID_CONNECTION;
435 return CAC_FAILURE;
438 srv->cli.pipe_idx = PI_SAMR;
440 resume_idx_out = op->out.resume_idx;
442 hnd->status = cli_samr_enum_dom_users( &(srv->cli), mem_ctx, op->in.dom_hnd, &resume_idx_out, op->in.acb_mask, SAMR_ENUM_MAX_SIZE,
443 &names_out, &rids_out, &num_users_out);
446 if(NT_STATUS_IS_OK(hnd->status))
447 op->out.done = True;
449 /*if there are no more entries, the operation will return NT_STATUS_OK.
450 * We want to return failure if no results were returned*/
451 if(!NT_STATUS_IS_OK(hnd->status) && NT_STATUS_V(hnd->status) != NT_STATUS_V(STATUS_MORE_ENTRIES))
452 return CAC_FAILURE;
454 op->out.resume_idx= resume_idx_out;
455 op->out.num_users = num_users_out;
456 op->out.rids = rids_out;
457 op->out.names = names_out;
459 return CAC_SUCCESS;
462 int cac_SamGetNamesFromRids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetNamesFromRids *op) {
463 SMBCSRV *srv = NULL;
465 uint32 num_names_out;
466 char **names_out;
467 uint32 *name_types_out;
470 uint32 i = 0;
472 CacLookupRidsRecord *map_out;
474 if(!hnd)
475 return CAC_FAILURE;
477 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
478 hnd->status = NT_STATUS_INVALID_HANDLE;
479 return CAC_FAILURE;
482 if(!op || !op->in.dom_hnd || !mem_ctx) {
483 hnd->status = NT_STATUS_INVALID_PARAMETER;
484 return CAC_FAILURE;
487 if(!op->in.rids && op->in.num_rids != 0) {
488 hnd->status = NT_STATUS_INVALID_PARAMETER;
489 return CAC_FAILURE;
492 if(op->in.num_rids == 0) {
493 /*nothing to do*/
494 op->out.num_names = 0;
495 return CAC_SUCCESS;
498 srv = cac_GetServer(hnd);
499 if(!srv) {
500 hnd->status = NT_STATUS_INVALID_CONNECTION;
501 return CAC_FAILURE;
504 srv->cli.pipe_idx = PI_SAMR;
506 hnd->status = cli_samr_lookup_rids( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.num_rids, op->in.rids, &num_names_out, &names_out, &name_types_out);
508 if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
509 return CAC_FAILURE;
511 map_out = TALLOC_ARRAY(mem_ctx, CacLookupRidsRecord, num_names_out);
512 if(!map_out) {
513 hnd->status = NT_STATUS_NO_MEMORY;
514 return CAC_FAILURE;
517 for(i = 0; i < num_names_out; i++) {
518 if(name_types_out[i] == SAMR_RID_UNKNOWN) {
519 map_out[i].found = False;
520 map_out[i].name = NULL;
521 map_out[i].type = 0;
523 else {
524 map_out[i].found = True;
525 map_out[i].name = talloc_strdup(mem_ctx, names_out[i]);
526 map_out[i].type = name_types_out[i];
528 map_out[i].rid = op->in.rids[i];
531 talloc_free(names_out);
532 talloc_free(name_types_out);
534 op->out.num_names = num_names_out;
535 op->out.map = map_out;
537 if(NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
538 return CAC_PARTIAL_SUCCESS;
540 return CAC_SUCCESS;
543 int cac_SamGetRidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetRidsFromNames *op) {
544 SMBCSRV *srv = NULL;
546 uint32 num_rids_out;
547 uint32 *rids_out;
548 uint32 *rid_types_out;
550 uint32 i = 0;
552 CacLookupRidsRecord *map_out;
554 if(!hnd)
555 return CAC_FAILURE;
557 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
558 hnd->status = NT_STATUS_INVALID_HANDLE;
559 return CAC_FAILURE;
562 if(!op || !op->in.dom_hnd || !mem_ctx) {
563 hnd->status = NT_STATUS_INVALID_PARAMETER;
564 return CAC_FAILURE;
567 if(!op->in.names && op->in.num_names != 0) {
568 hnd->status = NT_STATUS_INVALID_PARAMETER;
569 return CAC_FAILURE;
572 if(op->in.num_names == 0) {
573 /*then we don't have to do anything*/
574 op->out.num_rids = 0;
575 return CAC_SUCCESS;
578 srv = cac_GetServer(hnd);
579 if(!srv) {
580 hnd->status = NT_STATUS_INVALID_CONNECTION;
581 return CAC_FAILURE;
584 srv->cli.pipe_idx = PI_SAMR;
586 hnd->status = cli_samr_lookup_names( &(srv->cli), mem_ctx, op->in.dom_hnd, SAMR_LOOKUP_FLAGS, op->in.num_names, (const char **)op->in.names,
587 &num_rids_out, &rids_out, &rid_types_out);
589 if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
590 return CAC_FAILURE;
592 map_out = TALLOC_ARRAY(mem_ctx, CacLookupRidsRecord, num_rids_out);
593 if(!map_out) {
594 hnd->status = NT_STATUS_NO_MEMORY;
595 return CAC_FAILURE;
598 for(i = 0; i < num_rids_out; i++) {
600 if(rid_types_out[i] == SAMR_RID_UNKNOWN) {
601 map_out[i].found = False;
602 map_out[i].rid = 0;
603 map_out[i].type = 0;
605 else {
606 map_out[i].found = True;
607 map_out[i].rid = rids_out[i];
608 map_out[i].type = rid_types_out[i];
611 map_out[i].name = talloc_strdup(mem_ctx, op->in.names[i]);
614 op->out.num_rids = num_rids_out;
615 op->out.map = map_out;
617 talloc_free(rids_out);
618 talloc_free(rid_types_out);
620 if(NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
621 return CAC_PARTIAL_SUCCESS;
623 return CAC_SUCCESS;
627 int cac_SamGetGroupsForUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupsForUser *op) {
628 SMBCSRV *srv = NULL;
630 DOM_GID *groups = NULL;
631 uint32 num_groups_out = 0;
633 uint32 *rids_out = NULL;
634 uint32 *attr_out = NULL;
636 uint32 i;
638 if(!hnd)
639 return CAC_FAILURE;
641 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
642 hnd->status = NT_STATUS_INVALID_HANDLE;
643 return CAC_FAILURE;
646 if(!op || !op->in.user_hnd || !mem_ctx) {
647 hnd->status = NT_STATUS_INVALID_PARAMETER;
648 return CAC_FAILURE;
651 srv = cac_GetServer(hnd);
652 if(!srv) {
653 hnd->status = NT_STATUS_INVALID_CONNECTION;
654 return CAC_FAILURE;
657 srv->cli.pipe_idx = PI_SAMR;
659 hnd->status = cli_samr_query_usergroups(&(srv->cli), mem_ctx, op->in.user_hnd, &num_groups_out, &groups);
661 if(!NT_STATUS_IS_OK(hnd->status))
662 return CAC_FAILURE;
665 rids_out = talloc_array(mem_ctx, uint32, num_groups_out);
666 if(!rids_out) {
667 hnd->status = NT_STATUS_NO_MEMORY;
668 return CAC_FAILURE;
671 attr_out = talloc_array(mem_ctx, uint32, num_groups_out);
672 if(!attr_out) {
673 hnd->status = NT_STATUS_NO_MEMORY;
674 return CAC_FAILURE;
677 for(i = 0; i < num_groups_out; i++) {
678 rids_out[i] = groups[i].g_rid;
679 attr_out[i] = groups[i].attr;
682 talloc_free(groups);
684 op->out.num_groups = num_groups_out;
685 op->out.rids = rids_out;
686 op->out.attributes = attr_out;
688 return CAC_SUCCESS;
692 int cac_SamOpenGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenGroup *op) {
693 SMBCSRV *srv = NULL;
695 POLICY_HND *group_hnd_out = NULL;
697 if(!hnd)
698 return CAC_FAILURE;
700 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
701 hnd->status = NT_STATUS_INVALID_HANDLE;
702 return CAC_FAILURE;
705 if(!op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx) {
706 hnd->status = NT_STATUS_INVALID_PARAMETER;
707 return CAC_FAILURE;
710 srv = cac_GetServer(hnd);
711 if(!srv) {
712 hnd->status = NT_STATUS_INVALID_CONNECTION;
713 return CAC_FAILURE;
716 srv->cli.pipe_idx = PI_SAMR;
718 group_hnd_out = talloc(mem_ctx, POLICY_HND);
719 if(!group_hnd_out) {
720 hnd->status = NT_STATUS_NO_MEMORY;
721 return CAC_FAILURE;
724 hnd->status = cli_samr_open_group( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.access, op->in.rid, group_hnd_out);
726 if(!NT_STATUS_IS_OK(hnd->status))
727 return CAC_FAILURE;
729 op->out.group_hnd = group_hnd_out;
731 return CAC_SUCCESS;
734 int cac_SamCreateGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateGroup *op) {
735 SMBCSRV *srv = NULL;
737 POLICY_HND *group_hnd_out = NULL;
739 if(!hnd)
740 return CAC_FAILURE;
742 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
743 hnd->status = NT_STATUS_INVALID_HANDLE;
744 return CAC_FAILURE;
747 if(!op || !op->in.name || op->in.name[0] == '\0' || op->in.access == 0 || !mem_ctx) {
748 hnd->status = NT_STATUS_INVALID_PARAMETER;
749 return CAC_FAILURE;
752 srv = cac_GetServer(hnd);
753 if(!srv) {
754 hnd->status = NT_STATUS_INVALID_CONNECTION;
755 return CAC_FAILURE;
758 srv->cli.pipe_idx = PI_SAMR;
760 group_hnd_out = talloc(mem_ctx, POLICY_HND);
761 if(!group_hnd_out) {
762 hnd->status = NT_STATUS_NO_MEMORY;
763 return CAC_FAILURE;
766 hnd->status = cli_samr_create_dom_group( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.name, op->in.access, group_hnd_out);
768 if(!NT_STATUS_IS_OK(hnd->status))
769 return CAC_FAILURE;
771 op->out.group_hnd = group_hnd_out;
773 return CAC_SUCCESS;
777 int cac_SamDeleteGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd) {
778 SMBCSRV *srv = NULL;
780 if(!hnd)
781 return CAC_FAILURE;
783 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
784 hnd->status = NT_STATUS_INVALID_HANDLE;
785 return CAC_FAILURE;
788 if(!group_hnd || !mem_ctx) {
789 hnd->status = NT_STATUS_INVALID_PARAMETER;
790 return CAC_FAILURE;
793 srv = cac_GetServer(hnd);
794 if(!srv) {
795 hnd->status = NT_STATUS_INVALID_CONNECTION;
796 return CAC_FAILURE;
799 srv->cli.pipe_idx = PI_SAMR;
801 hnd->status = cli_samr_delete_dom_group( &(srv->cli), mem_ctx, group_hnd);
803 if(!NT_STATUS_IS_OK(hnd->status))
804 return CAC_FAILURE;
806 return CAC_SUCCESS;
810 int cac_SamGetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupMembers *op) {
811 SMBCSRV *srv = NULL;
813 uint32 num_mem_out;
814 uint32 *rids_out;
815 uint32 *attr_out;
817 if(!hnd)
818 return CAC_FAILURE;
820 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
821 hnd->status = NT_STATUS_INVALID_HANDLE;
822 return CAC_FAILURE;
825 if(!op || !op->in.group_hnd || !mem_ctx) {
826 hnd->status = NT_STATUS_INVALID_PARAMETER;
827 return CAC_FAILURE;
830 srv = cac_GetServer(hnd);
831 if(!srv) {
832 hnd->status = NT_STATUS_INVALID_CONNECTION;
833 return CAC_FAILURE;
836 srv->cli.pipe_idx = PI_SAMR;
838 hnd->status = cli_samr_query_groupmem( &(srv->cli), mem_ctx, op->in.group_hnd, &num_mem_out, &rids_out, &attr_out);
840 if(!NT_STATUS_IS_OK(hnd->status))
841 return CAC_FAILURE;
843 op->out.num_members = num_mem_out;
844 op->out.rids = rids_out;
845 op->out.attributes = attr_out;
847 return CAC_SUCCESS;
851 int cac_SamAddGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddGroupMember *op) {
852 SMBCSRV *srv = NULL;
854 if(!hnd)
855 return CAC_FAILURE;
857 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
858 hnd->status = NT_STATUS_INVALID_HANDLE;
859 return CAC_FAILURE;
862 if(!op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx) {
863 hnd->status = NT_STATUS_INVALID_PARAMETER;
864 return CAC_FAILURE;
867 srv = cac_GetServer(hnd);
868 if(!srv) {
869 hnd->status = NT_STATUS_INVALID_CONNECTION;
870 return CAC_FAILURE;
873 srv->cli.pipe_idx = PI_SAMR;
875 hnd->status = cli_samr_add_groupmem( &(srv->cli), mem_ctx, op->in.group_hnd, op->in.rid);
877 if(!NT_STATUS_IS_OK(hnd->status))
878 return CAC_FAILURE;
880 return CAC_SUCCESS;
883 int cac_SamRemoveGroupMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveGroupMember *op) {
884 SMBCSRV *srv = NULL;
886 if(!hnd)
887 return CAC_FAILURE;
889 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
890 hnd->status = NT_STATUS_INVALID_HANDLE;
891 return CAC_FAILURE;
894 if(!op || !op->in.group_hnd || op->in.rid == 0 || !mem_ctx) {
895 hnd->status = NT_STATUS_INVALID_PARAMETER;
896 return CAC_FAILURE;
899 srv = cac_GetServer(hnd);
900 if(!srv) {
901 hnd->status = NT_STATUS_INVALID_CONNECTION;
902 return CAC_FAILURE;
905 srv->cli.pipe_idx = PI_SAMR;
907 hnd->status = cli_samr_del_groupmem( &(srv->cli), mem_ctx, op->in.group_hnd, op->in.rid);
909 if(!NT_STATUS_IS_OK(hnd->status))
910 return CAC_FAILURE;
912 return CAC_SUCCESS;
915 int cac_SamClearGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *group_hnd) {
916 SMBCSRV *srv = NULL;
918 int result = CAC_SUCCESS;
920 uint32 i = 0;
922 uint32 num_mem = 0;
923 uint32 *rid = NULL;
924 uint32 *attr = NULL;
926 NTSTATUS status;
928 if(!hnd)
929 return CAC_FAILURE;
931 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
932 hnd->status = NT_STATUS_INVALID_HANDLE;
933 return CAC_FAILURE;
936 if(!group_hnd || !mem_ctx) {
937 hnd->status = NT_STATUS_INVALID_PARAMETER;
938 return CAC_FAILURE;
941 srv = cac_GetServer(hnd);
942 if(!srv) {
943 hnd->status = NT_STATUS_INVALID_CONNECTION;
944 return CAC_FAILURE;
947 srv->cli.pipe_idx = PI_SAMR;
949 hnd->status = cli_samr_query_groupmem(&(srv->cli), mem_ctx, group_hnd, &num_mem, &rid, &attr);
951 if(!NT_STATUS_IS_OK(hnd->status))
952 return CAC_FAILURE;
954 /*try to delete the users one by one*/
955 for(i = 0; i < num_mem && NT_STATUS_IS_OK(hnd->status); i++) {
956 hnd->status = cli_samr_del_groupmem(&(srv->cli), mem_ctx, group_hnd, rid[i]);
959 /*if not all members could be removed, then try to re-add the members that were already deleted*/
960 if(!NT_STATUS_IS_OK(hnd->status)) {
961 status = NT_STATUS_OK;
963 for(i -= 1; i >= 0 && NT_STATUS_IS_OK(status); i--) {
964 status = cli_samr_add_groupmem( &(srv->cli), mem_ctx, group_hnd, rid[i]);
967 /*we return with the NTSTATUS error that we got when trying to delete users*/
968 if(!NT_STATUS_IS_OK(status))
969 result = CAC_FAILURE;
972 talloc_free(attr);
974 return result;
977 int cac_SamSetGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetGroupMembers *op) {
978 SMBCSRV *srv = NULL;
980 uint32 i = 0;
982 if(!hnd)
983 return CAC_FAILURE;
985 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
986 hnd->status = NT_STATUS_INVALID_HANDLE;
987 return CAC_FAILURE;
990 if(!op || !op->in.group_hnd || !mem_ctx) {
991 hnd->status = NT_STATUS_INVALID_PARAMETER;
992 return CAC_FAILURE;
995 srv = cac_GetServer(hnd);
996 if(!srv) {
997 hnd->status = NT_STATUS_INVALID_CONNECTION;
998 return CAC_FAILURE;
1001 srv->cli.pipe_idx = PI_SAMR;
1003 /*use cac_SamClearGroupMembers() to clear them*/
1004 if(!cac_SamClearGroupMembers(hnd, mem_ctx, op->in.group_hnd))
1005 return CAC_FAILURE; /*hnd->status is already set*/
1008 for(i = 0; i < op->in.num_members && NT_STATUS_IS_OK(hnd->status); i++) {
1009 hnd->status = cli_samr_add_groupmem( &(srv->cli), mem_ctx, op->in.group_hnd, op->in.rids[i]);
1012 if(!NT_STATUS_IS_OK(hnd->status))
1013 return CAC_FAILURE;
1015 return CAC_SUCCESS;
1019 int cac_SamEnumGroups(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumGroups *op) {
1020 SMBCSRV *srv = NULL;
1022 uint32 i = 0;
1024 uint32 resume_idx_out = 0;
1025 char **names_out = NULL;
1026 char **desc_out = NULL;
1027 uint32 *rids_out = NULL;
1028 uint32 num_groups_out = 0;
1030 struct acct_info *acct_buf = NULL;
1032 if(!hnd)
1033 return CAC_FAILURE;
1035 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1036 hnd->status = NT_STATUS_INVALID_HANDLE;
1037 return CAC_FAILURE;
1040 if(!op || !op->in.dom_hnd || !mem_ctx) {
1041 hnd->status = NT_STATUS_INVALID_PARAMETER;
1042 return CAC_FAILURE;
1045 /*using this BOOL is the only reliable way to know that we are done*/
1046 if(op->out.done == True) /*we return failure so the call will break out of a loop*/
1047 return CAC_FAILURE;
1049 srv = cac_GetServer(hnd);
1050 if(!srv) {
1051 hnd->status = NT_STATUS_INVALID_CONNECTION;
1052 return CAC_FAILURE;
1055 srv->cli.pipe_idx = PI_SAMR;
1057 resume_idx_out = op->out.resume_idx;
1059 hnd->status = cli_samr_enum_dom_groups( &(srv->cli), mem_ctx, op->in.dom_hnd, &resume_idx_out, SAMR_ENUM_MAX_SIZE,
1060 &acct_buf, &num_groups_out);
1063 if(NT_STATUS_IS_OK(hnd->status)) {
1064 op->out.done = True;
1066 else if(NT_STATUS_V(hnd->status) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
1067 /*if there are no more entries, the operation will return NT_STATUS_OK.
1068 * We want to return failure if no results were returned*/
1069 return CAC_FAILURE;
1072 names_out = talloc_array(mem_ctx, char *, num_groups_out);
1073 if(!names_out) {
1074 hnd->status = NT_STATUS_NO_MEMORY;
1075 talloc_free(acct_buf);
1076 return CAC_FAILURE;
1079 desc_out = talloc_array(mem_ctx, char *, num_groups_out);
1080 if(!desc_out) {
1081 hnd->status = NT_STATUS_NO_MEMORY;
1082 talloc_free(acct_buf);
1083 talloc_free(names_out);
1084 return CAC_FAILURE;
1087 rids_out = talloc_array(mem_ctx, uint32, num_groups_out);
1088 if(!rids_out) {
1089 hnd->status = NT_STATUS_NO_MEMORY;
1090 talloc_free(acct_buf);
1091 talloc_free(names_out);
1092 talloc_free(desc_out);
1093 return CAC_FAILURE;
1096 for(i = 0; i < num_groups_out; i++) {
1097 names_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_name);
1098 desc_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_desc);
1099 rids_out[i] = acct_buf[i].rid;
1101 if(!names_out[i] || !desc_out[i]) {
1102 hnd->status = NT_STATUS_NO_MEMORY;
1103 return CAC_FAILURE;
1107 op->out.resume_idx = resume_idx_out;
1108 op->out.num_groups = num_groups_out;
1109 op->out.rids = rids_out;
1110 op->out.names = names_out;
1111 op->out.descriptions = desc_out;
1113 return CAC_SUCCESS;
1116 int cac_SamEnumAliases(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumAliases *op) {
1117 SMBCSRV *srv = NULL;
1119 uint32 i = 0;
1121 uint32 resume_idx_out = 0;
1122 char **names_out = NULL;
1123 char **desc_out = NULL;
1124 uint32 *rids_out = NULL;
1125 uint32 num_als_out = 0;
1127 struct acct_info *acct_buf = NULL;
1129 if(!hnd)
1130 return CAC_FAILURE;
1132 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1133 hnd->status = NT_STATUS_INVALID_HANDLE;
1134 return CAC_FAILURE;
1137 if(!op || !op->in.dom_hnd || !mem_ctx) {
1138 hnd->status = NT_STATUS_INVALID_PARAMETER;
1139 return CAC_FAILURE;
1142 /*this is a hack.. but is the only reliable way to know if everything has been enumerated*/
1143 if(op->out.done == True) {
1144 return CAC_FAILURE;
1147 srv = cac_GetServer(hnd);
1148 if(!srv) {
1149 hnd->status = NT_STATUS_INVALID_CONNECTION;
1150 return CAC_FAILURE;
1153 srv->cli.pipe_idx = PI_SAMR;
1155 resume_idx_out = op->out.resume_idx;
1157 hnd->status = cli_samr_enum_als_groups( &(srv->cli), mem_ctx, op->in.dom_hnd, &resume_idx_out, SAMR_ENUM_MAX_SIZE,
1158 &acct_buf, &num_als_out);
1161 if(NT_STATUS_IS_OK(hnd->status))
1162 op->out.done = True;
1164 /*if there are no more entries, the operation will return NT_STATUS_OK.
1165 * We want to return failure if no results were returned*/
1166 if(!NT_STATUS_IS_OK(hnd->status) && NT_STATUS_V(hnd->status) != NT_STATUS_V(STATUS_MORE_ENTRIES))
1167 return CAC_FAILURE;
1169 names_out = talloc_array(mem_ctx, char *, num_als_out);
1170 if(!names_out) {
1171 hnd->status = NT_STATUS_NO_MEMORY;
1172 talloc_free(acct_buf);
1173 return CAC_FAILURE;
1176 desc_out = talloc_array(mem_ctx, char *, num_als_out);
1177 if(!desc_out) {
1178 hnd->status = NT_STATUS_NO_MEMORY;
1179 talloc_free(acct_buf);
1180 talloc_free(names_out);
1181 return CAC_FAILURE;
1184 rids_out = talloc_array(mem_ctx, uint32, num_als_out);
1185 if(!rids_out) {
1186 hnd->status = NT_STATUS_NO_MEMORY;
1187 talloc_free(acct_buf);
1188 talloc_free(names_out);
1189 talloc_free(desc_out);
1190 return CAC_FAILURE;
1193 for(i = 0; i < num_als_out; i++) {
1194 names_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_name);
1195 desc_out[i] = talloc_strdup(mem_ctx, acct_buf[i].acct_desc);
1196 rids_out[i] = acct_buf[i].rid;
1198 if(!names_out[i] || !desc_out[i]) {
1199 hnd->status = NT_STATUS_NO_MEMORY;
1200 return CAC_FAILURE;
1204 op->out.resume_idx = resume_idx_out;
1205 op->out.num_aliases = num_als_out;
1206 op->out.rids = rids_out;
1207 op->out.names = names_out;
1208 op->out.descriptions = desc_out;
1210 return CAC_SUCCESS;
1213 int cac_SamCreateAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamCreateAlias *op) {
1214 SMBCSRV *srv = NULL;
1216 POLICY_HND *als_hnd_out = NULL;
1218 if(!hnd)
1219 return CAC_FAILURE;
1221 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1222 hnd->status = NT_STATUS_INVALID_HANDLE;
1223 return CAC_FAILURE;
1226 if(!op || !op->in.name || op->in.name[0] == '\0' || !mem_ctx) {
1227 hnd->status = NT_STATUS_INVALID_PARAMETER;
1228 return CAC_FAILURE;
1231 srv = cac_GetServer(hnd);
1232 if(!srv) {
1233 hnd->status = NT_STATUS_INVALID_CONNECTION;
1234 return CAC_FAILURE;
1237 srv->cli.pipe_idx = PI_SAMR;
1239 als_hnd_out = talloc(mem_ctx, POLICY_HND);
1240 if(!als_hnd_out) {
1241 hnd->status = NT_STATUS_NO_MEMORY;
1242 return CAC_FAILURE;
1245 hnd->status = cli_samr_create_dom_alias( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.name, als_hnd_out);
1247 if(!NT_STATUS_IS_OK(hnd->status))
1248 return CAC_FAILURE;
1250 op->out.alias_hnd = als_hnd_out;
1252 return CAC_SUCCESS;
1256 int cac_SamOpenAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenAlias *op) {
1257 SMBCSRV *srv = NULL;
1259 POLICY_HND *als_hnd_out = NULL;
1261 if(!hnd)
1262 return CAC_FAILURE;
1264 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1265 hnd->status = NT_STATUS_INVALID_HANDLE;
1266 return CAC_FAILURE;
1269 if(!op || op->in.access == 0 || op->in.rid == 0 || !mem_ctx) {
1270 hnd->status = NT_STATUS_INVALID_PARAMETER;
1271 return CAC_FAILURE;
1274 srv = cac_GetServer(hnd);
1275 if(!srv) {
1276 hnd->status = NT_STATUS_INVALID_CONNECTION;
1277 return CAC_FAILURE;
1280 srv->cli.pipe_idx = PI_SAMR;
1282 als_hnd_out = talloc(mem_ctx, POLICY_HND);
1283 if(!als_hnd_out) {
1284 hnd->status = NT_STATUS_NO_MEMORY;
1285 return CAC_FAILURE;
1288 hnd->status = cli_samr_open_alias( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.access, op->in.rid, als_hnd_out);
1290 if(!NT_STATUS_IS_OK(hnd->status))
1291 return CAC_FAILURE;
1293 op->out.alias_hnd = als_hnd_out;
1295 return CAC_SUCCESS;
1298 int cac_SamDeleteAlias(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *alias_hnd) {
1299 SMBCSRV *srv = NULL;
1301 if(!hnd)
1302 return CAC_FAILURE;
1304 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1305 hnd->status = NT_STATUS_INVALID_HANDLE;
1306 return CAC_FAILURE;
1309 if(!alias_hnd || !mem_ctx) {
1310 hnd->status = NT_STATUS_INVALID_PARAMETER;
1311 return CAC_FAILURE;
1314 srv = cac_GetServer(hnd);
1315 if(!srv) {
1316 hnd->status = NT_STATUS_INVALID_CONNECTION;
1317 return CAC_FAILURE;
1320 srv->cli.pipe_idx = PI_SAMR;
1322 hnd->status = cli_samr_delete_dom_alias( &(srv->cli), mem_ctx, alias_hnd);
1324 if(!NT_STATUS_IS_OK(hnd->status))
1325 return CAC_FAILURE;
1327 return CAC_SUCCESS;
1331 int cac_SamAddAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamAddAliasMember *op) {
1332 SMBCSRV *srv = NULL;
1334 if(!hnd)
1335 return CAC_FAILURE;
1337 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1338 hnd->status = NT_STATUS_INVALID_HANDLE;
1339 return CAC_FAILURE;
1342 if(!op || !op->in.alias_hnd || !op->in.sid || !mem_ctx) {
1343 hnd->status = NT_STATUS_INVALID_PARAMETER;
1344 return CAC_FAILURE;
1347 srv = cac_GetServer(hnd);
1348 if(!srv) {
1349 hnd->status = NT_STATUS_INVALID_CONNECTION;
1350 return CAC_FAILURE;
1353 srv->cli.pipe_idx = PI_SAMR;
1355 hnd->status = cli_samr_add_aliasmem( &(srv->cli), mem_ctx, op->in.alias_hnd, op->in.sid);
1357 if(!NT_STATUS_IS_OK(hnd->status))
1358 return CAC_FAILURE;
1360 return CAC_SUCCESS;
1363 int cac_SamRemoveAliasMember(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRemoveAliasMember *op) {
1364 SMBCSRV *srv = NULL;
1366 if(!hnd)
1367 return CAC_FAILURE;
1369 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1370 hnd->status = NT_STATUS_INVALID_HANDLE;
1371 return CAC_FAILURE;
1374 if(!op || !op->in.alias_hnd || !op->in.sid || !mem_ctx) {
1375 hnd->status = NT_STATUS_INVALID_PARAMETER;
1376 return CAC_FAILURE;
1379 srv = cac_GetServer(hnd);
1380 if(!srv) {
1381 hnd->status = NT_STATUS_INVALID_CONNECTION;
1382 return CAC_FAILURE;
1385 srv->cli.pipe_idx = PI_SAMR;
1387 hnd->status = cli_samr_del_aliasmem( &(srv->cli), mem_ctx, op->in.alias_hnd, op->in.sid);
1389 if(!NT_STATUS_IS_OK(hnd->status))
1390 return CAC_FAILURE;
1392 return CAC_SUCCESS;
1395 int cac_SamGetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasMembers *op) {
1396 SMBCSRV *srv = NULL;
1398 uint32 num_mem_out;
1399 DOM_SID *sids_out;
1401 if(!hnd)
1402 return CAC_FAILURE;
1404 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1405 hnd->status = NT_STATUS_INVALID_HANDLE;
1406 return CAC_FAILURE;
1409 if(!op || !op->in.alias_hnd || !mem_ctx) {
1410 hnd->status = NT_STATUS_INVALID_PARAMETER;
1411 return CAC_FAILURE;
1414 srv = cac_GetServer(hnd);
1415 if(!srv) {
1416 hnd->status = NT_STATUS_INVALID_CONNECTION;
1417 return CAC_FAILURE;
1420 srv->cli.pipe_idx = PI_SAMR;
1422 hnd->status = cli_samr_query_aliasmem( &(srv->cli), mem_ctx, op->in.alias_hnd, &num_mem_out, &sids_out);
1424 if(!NT_STATUS_IS_OK(hnd->status))
1425 return CAC_FAILURE;
1427 op->out.num_members = num_mem_out;
1428 op->out.sids = sids_out;
1430 return CAC_SUCCESS;
1433 int cac_SamClearAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *alias_hnd) {
1434 SMBCSRV *srv = NULL;
1436 int result = CAC_SUCCESS;
1438 uint32 i = 0;
1440 uint32 num_mem = 0;
1441 DOM_SID *sid = NULL;
1443 NTSTATUS status;
1445 if(!hnd)
1446 return CAC_FAILURE;
1448 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1449 hnd->status = NT_STATUS_INVALID_HANDLE;
1450 return CAC_FAILURE;
1453 if(!alias_hnd || !mem_ctx) {
1454 hnd->status = NT_STATUS_INVALID_PARAMETER;
1455 return CAC_FAILURE;
1458 srv = cac_GetServer(hnd);
1459 if(!srv) {
1460 hnd->status = NT_STATUS_INVALID_CONNECTION;
1461 return CAC_FAILURE;
1464 srv->cli.pipe_idx = PI_SAMR;
1466 hnd->status = cli_samr_query_aliasmem(&(srv->cli), mem_ctx, alias_hnd, &num_mem, &sid);
1468 if(!NT_STATUS_IS_OK(hnd->status))
1469 return CAC_FAILURE;
1471 /*try to delete the users one by one*/
1472 for(i = 0; i < num_mem && NT_STATUS_IS_OK(hnd->status); i++) {
1473 hnd->status = cli_samr_del_aliasmem(&(srv->cli), mem_ctx, alias_hnd, &sid[i]);
1476 /*if not all members could be removed, then try to re-add the members that were already deleted*/
1477 if(!NT_STATUS_IS_OK(hnd->status)) {
1478 status = NT_STATUS_OK;
1480 for(i -= 1; i >= 0 && NT_STATUS_IS_OK(status); i--) {
1481 status = cli_samr_add_aliasmem( &(srv->cli), mem_ctx, alias_hnd, &sid[i]);
1484 /*we return with the NTSTATUS error that we got when trying to delete users*/
1485 if(!NT_STATUS_IS_OK(status))
1486 result = CAC_FAILURE;
1489 talloc_free(sid);
1490 return result;
1493 int cac_SamSetAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetAliasMembers *op) {
1494 SMBCSRV *srv = NULL;
1496 uint32 i = 0;
1498 if(!hnd)
1499 return CAC_FAILURE;
1501 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1502 hnd->status = NT_STATUS_INVALID_HANDLE;
1503 return CAC_FAILURE;
1506 if(!op || !op->in.alias_hnd || !mem_ctx) {
1507 hnd->status = NT_STATUS_INVALID_PARAMETER;
1508 return CAC_FAILURE;
1511 srv = cac_GetServer(hnd);
1512 if(!srv) {
1513 hnd->status = NT_STATUS_INVALID_CONNECTION;
1514 return CAC_FAILURE;
1517 srv->cli.pipe_idx = PI_SAMR;
1519 /*use cac_SamClearAliasMembers() to clear them*/
1520 if(!cac_SamClearAliasMembers(hnd, mem_ctx, op->in.alias_hnd))
1521 return CAC_FAILURE; /*hnd->status is already set*/
1524 for(i = 0; i < op->in.num_members && NT_STATUS_IS_OK(hnd->status); i++) {
1525 hnd->status = cli_samr_add_aliasmem( &(srv->cli), mem_ctx, op->in.alias_hnd, &(op->in.sids[i]));
1528 if(!NT_STATUS_IS_OK(hnd->status))
1529 return CAC_FAILURE;
1531 return CAC_SUCCESS;
1535 int cac_SamUserChangePasswd(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamUserChangePasswd *op) {
1536 SMBCSRV *srv = NULL;
1538 if(!hnd)
1539 return CAC_FAILURE;
1541 if(!hnd->_internal.ctx) {
1542 hnd->status = NT_STATUS_INVALID_HANDLE;
1543 return CAC_FAILURE;
1546 if(!op || !op->in.username || !op->in.password || !op->in.new_password || !mem_ctx) {
1547 hnd->status = NT_STATUS_INVALID_PARAMETER;
1548 return CAC_FAILURE;
1551 srv = cac_GetServer(hnd);
1552 if(!srv) {
1553 hnd->status = NT_STATUS_INVALID_CONNECTION;
1554 return CAC_FAILURE;
1557 /*open a session on SAMR if we don't have one*/
1558 if(!hnd->_internal.pipes[PI_SAMR]) {
1559 if(!cli_nt_session_open(&srv->cli, PI_SAMR)) {
1560 hnd->status = NT_STATUS_UNSUCCESSFUL;
1561 return CAC_FAILURE;
1564 hnd->_internal.pipes[PI_SAMR] = True;
1567 srv->cli.pipe_idx = PI_SAMR;
1569 hnd->status = cli_samr_chgpasswd_user(&(srv->cli), mem_ctx, op->in.username, op->in.new_password, op->in.password);
1571 if(!NT_STATUS_IS_OK(hnd->status))
1572 return CAC_FAILURE;
1574 return CAC_SUCCESS;
1577 int cac_SamEnableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) {
1578 SMBCSRV *srv = NULL;
1580 SAM_USERINFO_CTR *ctr;
1582 if(!hnd)
1583 return CAC_FAILURE;
1585 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1586 hnd->status = NT_STATUS_INVALID_HANDLE;
1587 return CAC_FAILURE;
1590 if(!user_hnd || !mem_ctx) {
1591 hnd->status = NT_STATUS_INVALID_PARAMETER;
1592 return CAC_FAILURE;
1595 srv = cac_GetServer(hnd);
1596 if(!srv) {
1597 hnd->status = NT_STATUS_INVALID_CONNECTION;
1598 return CAC_FAILURE;
1601 srv->cli.pipe_idx = PI_SAMR;
1603 /*info_level = 21 is the only level that I have found to work reliably. It would be nice if user_level = 10 worked.*/
1604 hnd->status = cli_samr_query_userinfo( &(srv->cli), mem_ctx, user_hnd, 0x10, &ctr);
1606 if(!NT_STATUS_IS_OK(hnd->status))
1607 return CAC_FAILURE;
1609 /**check the ACB mask*/
1610 if((ctr->info.id16->acb_info & ACB_DISABLED) == ACB_DISABLED) {
1611 /*toggle the disabled bit*/
1612 ctr->info.id16->acb_info ^= ACB_DISABLED;
1614 else {
1615 /*the user is already enabled so just return success*/
1616 return CAC_SUCCESS;
1619 /*now set the userinfo*/
1620 hnd->status = cli_samr_set_userinfo2( &(srv->cli), mem_ctx, user_hnd, 0x10, &(srv->cli.user_session_key), ctr);
1622 /*this will only work properly if we use set_userinfo2 - fail if it is not supported*/
1623 if(!NT_STATUS_IS_OK(hnd->status))
1624 return CAC_FAILURE;
1626 return CAC_SUCCESS;
1629 int cac_SamDisableUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *user_hnd) {
1630 SMBCSRV *srv = NULL;
1632 SAM_USERINFO_CTR *ctr;
1634 if(!hnd)
1635 return CAC_FAILURE;
1637 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1638 hnd->status = NT_STATUS_INVALID_HANDLE;
1639 return CAC_FAILURE;
1642 if(!user_hnd || !mem_ctx) {
1643 hnd->status = NT_STATUS_INVALID_PARAMETER;
1644 return CAC_FAILURE;
1647 srv = cac_GetServer(hnd);
1648 if(!srv) {
1649 hnd->status = NT_STATUS_INVALID_CONNECTION;
1650 return CAC_FAILURE;
1653 srv->cli.pipe_idx = PI_SAMR;
1655 hnd->status = cli_samr_query_userinfo( &(srv->cli), mem_ctx, user_hnd, 0x10, &ctr);
1657 if(!NT_STATUS_IS_OK(hnd->status))
1658 return CAC_FAILURE;
1660 if((ctr->info.id16->acb_info & ACB_DISABLED) == ACB_DISABLED) {
1661 /*then the user is already disabled*/
1662 return CAC_SUCCESS;
1665 /*toggle the disabled bit*/
1666 ctr->info.id16->acb_info ^= ACB_DISABLED;
1668 /*this will only work properly if we use set_userinfo2*/
1669 hnd->status = cli_samr_set_userinfo2( &(srv->cli), mem_ctx, user_hnd, 0x10, &(srv->cli.user_session_key), ctr);
1671 /*this will only work properly if we use set_userinfo2 fail if it is not supported*/
1672 if(!NT_STATUS_IS_OK(hnd->status))
1673 return CAC_FAILURE;
1675 return CAC_SUCCESS;
1678 int cac_SamSetPassword(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetPassword *op) {
1679 SMBCSRV *srv = NULL;
1681 SAM_USERINFO_CTR ctr;
1682 SAM_USER_INFO_24 info24;
1683 uint8 pw[516];
1685 if(!hnd)
1686 return CAC_FAILURE;
1688 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1689 hnd->status = NT_STATUS_INVALID_HANDLE;
1690 return CAC_FAILURE;
1693 if(!op->in.user_hnd || !op->in.password || !mem_ctx) {
1694 hnd->status = NT_STATUS_INVALID_PARAMETER;
1695 return CAC_FAILURE;
1698 srv = cac_GetServer(hnd);
1699 if(!srv) {
1700 hnd->status = NT_STATUS_INVALID_CONNECTION;
1701 return CAC_FAILURE;
1704 srv->cli.pipe_idx = PI_SAMR;
1706 ZERO_STRUCT(ctr);
1707 ZERO_STRUCT(info24);
1709 encode_pw_buffer(pw, op->in.password, STR_UNICODE);
1711 init_sam_user_info24(&info24, (char *)pw, 24);
1713 ctr.switch_value = 24;
1714 ctr.info.id24 = &info24;
1716 hnd->status = cli_samr_set_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, 24, &(srv->cli.user_session_key), &ctr);
1718 if(!NT_STATUS_IS_OK(hnd->status))
1719 return CAC_FAILURE;
1721 return CAC_SUCCESS;
1724 int cac_SamGetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetUserInfo *op) {
1725 SMBCSRV *srv = NULL;
1727 SAM_USERINFO_CTR *ctr;
1729 if(!hnd)
1730 return CAC_FAILURE;
1732 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1733 hnd->status = NT_STATUS_INVALID_HANDLE;
1734 return CAC_FAILURE;
1737 if(!op->in.user_hnd || !mem_ctx) {
1738 hnd->status = NT_STATUS_INVALID_PARAMETER;
1739 return CAC_FAILURE;
1742 srv = cac_GetServer(hnd);
1743 if(!srv) {
1744 hnd->status = NT_STATUS_INVALID_CONNECTION;
1745 return CAC_FAILURE;
1748 srv->cli.pipe_idx = PI_SAMR;
1750 hnd->status = cli_samr_query_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, 21, &ctr);
1752 if(!NT_STATUS_IS_OK(hnd->status))
1753 return CAC_FAILURE;
1755 op->out.info = cac_MakeUserInfo(mem_ctx, ctr);
1757 if(!op->out.info) {
1758 hnd->status = NT_STATUS_NO_MEMORY;
1759 return CAC_FAILURE;
1762 return CAC_SUCCESS;
1765 int cac_SamSetUserInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetUserInfo *op) {
1766 SMBCSRV *srv = NULL;
1768 SAM_USERINFO_CTR *ctr;
1770 if(!hnd)
1771 return CAC_FAILURE;
1773 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1774 hnd->status = NT_STATUS_INVALID_HANDLE;
1775 return CAC_FAILURE;
1778 if(!op->in.user_hnd || !op->in.info || !mem_ctx) {
1779 hnd->status = NT_STATUS_INVALID_PARAMETER;
1780 return CAC_FAILURE;
1783 ctr = cac_MakeUserInfoCtr(mem_ctx, op->in.info);
1784 if(!ctr) {
1785 hnd->status = NT_STATUS_NO_MEMORY;
1786 return CAC_FAILURE;
1789 srv = cac_GetServer(hnd);
1790 if(!srv) {
1791 hnd->status = NT_STATUS_INVALID_CONNECTION;
1792 return CAC_FAILURE;
1795 srv->cli.pipe_idx = PI_SAMR;
1797 if(hnd->_internal.srv_level >= SRV_WIN_NT4) {
1798 hnd->status = cli_samr_set_userinfo2( &(srv->cli), mem_ctx, op->in.user_hnd, 21, &(srv->cli.user_session_key), ctr);
1801 if(hnd->_internal.srv_level < SRV_WIN_NT4 || !NT_STATUS_IS_OK(hnd->status)) {
1802 hnd->status = cli_samr_set_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, 21, &(srv->cli.user_session_key), ctr);
1804 if(NT_STATUS_IS_OK(hnd->status) && hnd->_internal.srv_level > SRV_WIN_NT4) {
1805 hnd->_internal.srv_level = SRV_WIN_NT4;
1810 if(!NT_STATUS_IS_OK(hnd->status))
1811 return CAC_FAILURE;
1813 return CAC_SUCCESS;
1817 int cac_SamGetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetUserInfoCtr *op) {
1818 SMBCSRV *srv = NULL;
1820 SAM_USERINFO_CTR *ctr_out;
1822 if(!hnd)
1823 return CAC_FAILURE;
1825 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1826 hnd->status = NT_STATUS_INVALID_HANDLE;
1827 return CAC_FAILURE;
1830 if(!op->in.user_hnd || op->in.info_class == 0 || !mem_ctx) {
1831 hnd->status = NT_STATUS_INVALID_PARAMETER;
1832 return CAC_FAILURE;
1835 srv = cac_GetServer(hnd);
1836 if(!srv) {
1837 hnd->status = NT_STATUS_INVALID_CONNECTION;
1838 return CAC_FAILURE;
1841 srv->cli.pipe_idx = PI_SAMR;
1843 hnd->status = cli_samr_query_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, op->in.info_class, &ctr_out);
1845 if(!NT_STATUS_IS_OK(hnd->status))
1846 return CAC_FAILURE;
1848 op->out.ctr = ctr_out;
1850 return CAC_SUCCESS;
1853 int cac_SamSetUserInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetUserInfoCtr *op) {
1854 SMBCSRV *srv = NULL;
1856 if(!hnd)
1857 return CAC_FAILURE;
1859 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1860 hnd->status = NT_STATUS_INVALID_HANDLE;
1861 return CAC_FAILURE;
1864 if(!op->in.user_hnd || !op->in.ctr || !mem_ctx) {
1865 hnd->status = NT_STATUS_INVALID_PARAMETER;
1866 return CAC_FAILURE;
1869 srv = cac_GetServer(hnd);
1870 if(!srv) {
1871 hnd->status = NT_STATUS_INVALID_CONNECTION;
1872 return CAC_FAILURE;
1875 srv->cli.pipe_idx = PI_SAMR;
1878 hnd->status = cli_samr_set_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, op->in.ctr->switch_value, &(srv->cli.user_session_key), op->in.ctr);
1880 if(!NT_STATUS_IS_OK(hnd->status))
1881 return CAC_FAILURE;
1883 return CAC_SUCCESS;
1887 int cac_SamRenameUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenameUser *op) {
1888 SMBCSRV *srv = NULL;
1890 SAM_USERINFO_CTR ctr;
1891 SAM_USER_INFO_7 info7;
1893 if(!hnd)
1894 return CAC_FAILURE;
1896 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1897 hnd->status = NT_STATUS_INVALID_HANDLE;
1898 return CAC_FAILURE;
1901 if(!op->in.user_hnd || !op->in.new_name || op->in.new_name[0] == '\0' || !mem_ctx) {
1902 hnd->status = NT_STATUS_INVALID_PARAMETER;
1903 return CAC_FAILURE;
1906 srv = cac_GetServer(hnd);
1907 if(!srv) {
1908 hnd->status = NT_STATUS_INVALID_CONNECTION;
1909 return CAC_FAILURE;
1912 srv->cli.pipe_idx = PI_SAMR;
1914 ZERO_STRUCT(ctr);
1915 ZERO_STRUCT(info7);
1917 init_sam_user_info7(&info7, op->in.new_name);
1919 ctr.switch_value = 7;
1920 ctr.info.id7 = &info7;
1922 hnd->status = cli_samr_set_userinfo( &(srv->cli), mem_ctx, op->in.user_hnd, 7, &(srv->cli.user_session_key), &ctr);
1924 if(!NT_STATUS_IS_OK(hnd->status))
1925 return CAC_FAILURE;
1927 return CAC_SUCCESS;
1931 int cac_SamGetGroupInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetGroupInfo *op) {
1932 SMBCSRV *srv = NULL;
1934 GROUP_INFO_CTR *ctr;
1936 if(!hnd)
1937 return CAC_FAILURE;
1939 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1940 hnd->status = NT_STATUS_INVALID_HANDLE;
1941 return CAC_FAILURE;
1944 if(!op->in.group_hnd || !mem_ctx) {
1945 hnd->status = NT_STATUS_INVALID_PARAMETER;
1946 return CAC_FAILURE;
1949 srv = cac_GetServer(hnd);
1950 if(!srv) {
1951 hnd->status = NT_STATUS_INVALID_CONNECTION;
1952 return CAC_FAILURE;
1955 srv->cli.pipe_idx = PI_SAMR;
1957 /*get a GROUP_INFO_1 structure*/
1958 hnd->status = cli_samr_query_groupinfo( &(srv->cli), mem_ctx, op->in.group_hnd, 1, &ctr);
1960 if(!NT_STATUS_IS_OK(hnd->status))
1961 return CAC_FAILURE;
1963 op->out.info = cac_MakeGroupInfo(mem_ctx, ctr);
1964 if(!op->out.info) {
1965 hnd->status = NT_STATUS_NO_MEMORY;
1966 return CAC_FAILURE;
1969 return CAC_SUCCESS;
1972 int cac_SamSetGroupInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetGroupInfo *op) {
1973 SMBCSRV *srv = NULL;
1975 GROUP_INFO_CTR *ctr = NULL;
1977 if(!hnd)
1978 return CAC_FAILURE;
1980 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
1981 hnd->status = NT_STATUS_INVALID_HANDLE;
1982 return CAC_FAILURE;
1985 if(!op->in.group_hnd || !op->in.info || !mem_ctx) {
1986 hnd->status = NT_STATUS_INVALID_PARAMETER;
1987 return CAC_FAILURE;
1990 ctr = cac_MakeGroupInfoCtr(mem_ctx, op->in.info);
1991 if(!ctr) {
1992 hnd->status = NT_STATUS_NO_MEMORY;
1993 return CAC_FAILURE;
1996 srv = cac_GetServer(hnd);
1997 if(!srv) {
1998 hnd->status = NT_STATUS_INVALID_CONNECTION;
1999 return CAC_FAILURE;
2002 srv->cli.pipe_idx = PI_SAMR;
2004 hnd->status = cli_samr_set_groupinfo(&(srv->cli), mem_ctx, op->in.group_hnd, ctr);
2006 if(!NT_STATUS_IS_OK(hnd->status))
2007 return CAC_FAILURE;
2009 return CAC_SUCCESS;
2012 int cac_SamRenameGroup(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamRenameGroup *op) {
2013 SMBCSRV *srv = NULL;
2015 GROUP_INFO_CTR ctr;
2017 if(!hnd)
2018 return CAC_FAILURE;
2020 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2021 hnd->status = NT_STATUS_INVALID_HANDLE;
2022 return CAC_FAILURE;
2025 if(!op->in.group_hnd || !op->in.new_name || op->in.new_name[0] == '\0' || !mem_ctx) {
2026 hnd->status = NT_STATUS_INVALID_PARAMETER;
2027 return CAC_FAILURE;
2030 srv = cac_GetServer(hnd);
2031 if(!srv) {
2032 hnd->status = NT_STATUS_INVALID_CONNECTION;
2033 return CAC_FAILURE;
2036 srv->cli.pipe_idx = PI_SAMR;
2038 ZERO_STRUCT(ctr);
2040 init_samr_group_info2(&ctr.group.info2, op->in.new_name);
2041 ctr.switch_value1 = 2;
2043 hnd->status = cli_samr_set_groupinfo( &(srv->cli), mem_ctx, op->in.group_hnd, &ctr);
2045 if(!NT_STATUS_IS_OK(hnd->status))
2046 return CAC_FAILURE;
2048 return CAC_SUCCESS;
2051 int cac_SamGetAliasInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetAliasInfo *op) {
2052 SMBCSRV *srv = NULL;
2054 ALIAS_INFO_CTR ctr;
2056 if(!hnd)
2057 return CAC_FAILURE;
2059 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2060 hnd->status = NT_STATUS_INVALID_HANDLE;
2061 return CAC_FAILURE;
2064 if(!op->in.alias_hnd || !mem_ctx) {
2065 hnd->status = NT_STATUS_INVALID_PARAMETER;
2066 return CAC_FAILURE;
2069 srv = cac_GetServer(hnd);
2070 if(!srv) {
2071 hnd->status = NT_STATUS_INVALID_CONNECTION;
2072 return CAC_FAILURE;
2075 srv->cli.pipe_idx = PI_SAMR;
2077 /*get a GROUP_INFO_1 structure*/
2078 hnd->status = cli_samr_query_alias_info( &(srv->cli), mem_ctx, op->in.alias_hnd, 1, &ctr);
2080 if(!NT_STATUS_IS_OK(hnd->status))
2081 return CAC_FAILURE;
2083 op->out.info = cac_MakeAliasInfo(mem_ctx, ctr);
2084 if(!op->out.info) {
2085 hnd->status = NT_STATUS_NO_MEMORY;
2086 return CAC_FAILURE;
2089 return CAC_SUCCESS;
2093 int cac_SamSetAliasInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamSetAliasInfo *op) {
2094 SMBCSRV *srv = NULL;
2096 ALIAS_INFO_CTR *ctr = NULL;
2098 if(!hnd)
2099 return CAC_FAILURE;
2101 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2102 hnd->status = NT_STATUS_INVALID_HANDLE;
2103 return CAC_FAILURE;
2106 if(!op->in.alias_hnd || !op->in.info || !mem_ctx) {
2107 hnd->status = NT_STATUS_INVALID_PARAMETER;
2108 return CAC_FAILURE;
2111 ctr = cac_MakeAliasInfoCtr(mem_ctx, op->in.info);
2112 if(!ctr) {
2113 hnd->status = NT_STATUS_NO_MEMORY;
2114 return CAC_FAILURE;
2117 srv = cac_GetServer(hnd);
2118 if(!srv) {
2119 hnd->status = NT_STATUS_INVALID_CONNECTION;
2120 return CAC_FAILURE;
2123 srv->cli.pipe_idx = PI_SAMR;
2125 hnd->status = cli_samr_set_aliasinfo(&(srv->cli), mem_ctx, op->in.alias_hnd, ctr);
2127 if(!NT_STATUS_IS_OK(hnd->status))
2128 return CAC_FAILURE;
2130 return CAC_SUCCESS;
2133 int cac_SamGetDomainInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDomainInfo *op) {
2134 SMBCSRV *srv = NULL;
2136 SAM_UNK_CTR ctr;
2137 SAM_UNK_INFO_1 info1;
2138 SAM_UNK_INFO_2 info2;
2139 SAM_UNK_INFO_12 info12;
2141 /*use this to keep track of a failed call*/
2142 NTSTATUS status_buf = NT_STATUS_OK;
2144 uint16 fail_count = 0;
2147 if(!hnd)
2148 return CAC_FAILURE;
2150 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2151 hnd->status = NT_STATUS_INVALID_HANDLE;
2152 return CAC_FAILURE;
2155 if(!op->in.dom_hnd || !mem_ctx) {
2156 hnd->status = NT_STATUS_INVALID_PARAMETER;
2157 return CAC_FAILURE;
2160 srv = cac_GetServer(hnd);
2161 if(!srv) {
2162 hnd->status = NT_STATUS_INVALID_CONNECTION;
2163 return CAC_FAILURE;
2166 srv->cli.pipe_idx = PI_SAMR;
2168 /*first try with info 1*/
2169 hnd->status = cli_samr_query_dom_info( &(srv->cli), mem_ctx, op->in.dom_hnd, 1, &ctr);
2171 if(NT_STATUS_IS_OK(hnd->status)) {
2172 /*then we buffer the SAM_UNK_INFO_1 structure*/
2173 info1 = ctr.info.inf1;
2175 else {
2176 /*then the call failed, store the status and ZERO out the info structure*/
2177 ZERO_STRUCT(info1);
2178 status_buf = hnd->status;
2179 fail_count++;
2182 /*try again for the next one*/
2183 hnd->status = cli_samr_query_dom_info( &(srv->cli), mem_ctx, op->in.dom_hnd, 2, &ctr);
2185 if(NT_STATUS_IS_OK(hnd->status)) {
2186 /*store the info*/
2187 info2 = ctr.info.inf2;
2189 else {
2190 /*ZERO out the structure and store the bad status*/
2191 ZERO_STRUCT(info2);
2192 status_buf = hnd->status;
2193 fail_count++;
2196 /*once more*/
2197 hnd->status = cli_samr_query_dom_info( &(srv->cli), mem_ctx, op->in.dom_hnd, 12, &ctr);
2199 if(NT_STATUS_IS_OK(hnd->status)) {
2200 info12 = ctr.info.inf12;
2202 else {
2203 ZERO_STRUCT(info12);
2204 status_buf = hnd->status;
2205 fail_count++;
2208 /*return failure if all 3 calls failed*/
2209 if(fail_count == 3)
2210 return CAC_FAILURE;
2212 op->out.info = cac_MakeDomainInfo(mem_ctx, &info1, &info2, &info12);
2214 if(!op->out.info) {
2215 hnd->status = NT_STATUS_NO_MEMORY;
2216 return CAC_FAILURE;
2219 if(fail_count > 0) {
2220 hnd->status = status_buf;
2221 return CAC_PARTIAL_SUCCESS;
2224 return CAC_SUCCESS;
2227 int cac_SamGetDomainInfoCtr(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDomainInfoCtr *op) {
2228 SMBCSRV *srv = NULL;
2230 SAM_UNK_CTR *ctr_out;
2232 if(!hnd)
2233 return CAC_FAILURE;
2235 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2236 hnd->status = NT_STATUS_INVALID_HANDLE;
2237 return CAC_FAILURE;
2240 if(!op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx) {
2241 hnd->status = NT_STATUS_INVALID_PARAMETER;
2242 return CAC_FAILURE;
2245 srv = cac_GetServer(hnd);
2246 if(!srv) {
2247 hnd->status = NT_STATUS_INVALID_CONNECTION;
2248 return CAC_FAILURE;
2251 srv->cli.pipe_idx = PI_SAMR;
2253 ctr_out = talloc(mem_ctx, SAM_UNK_CTR);
2254 if(!ctr_out) {
2255 hnd->status = NT_STATUS_NO_MEMORY;
2256 return CAC_FAILURE;
2259 hnd->status = cli_samr_query_dom_info( &(srv->cli), mem_ctx, op->in.dom_hnd, op->in.info_class, ctr_out);
2261 if(!NT_STATUS_IS_OK(hnd->status))
2262 return CAC_FAILURE;
2264 op->out.info = ctr_out;
2266 return CAC_SUCCESS;
2269 int cac_SamGetDisplayInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetDisplayInfo *op) {
2270 SMBCSRV *srv = NULL;
2272 SAM_DISPINFO_CTR ctr_out;
2274 uint32 max_entries_buf = 0;
2275 uint32 max_size_buf = 0;
2277 uint32 resume_idx_out;
2278 uint32 num_entries_out;
2280 if(!hnd)
2281 return CAC_FAILURE;
2283 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2284 hnd->status = NT_STATUS_INVALID_HANDLE;
2285 return CAC_FAILURE;
2288 if(!op->in.dom_hnd || op->in.info_class == 0 || !mem_ctx) {
2289 hnd->status = NT_STATUS_INVALID_PARAMETER;
2290 return CAC_FAILURE;
2293 if(op->out.done == True) /*this is done so we can use the function as a loop condition*/
2294 return CAC_FAILURE;
2296 srv = cac_GetServer(hnd);
2297 if(!srv) {
2298 hnd->status = NT_STATUS_INVALID_CONNECTION;
2299 return CAC_FAILURE;
2302 srv->cli.pipe_idx = PI_SAMR;
2304 if(op->in.max_entries == 0 || op->in.max_size == 0) {
2305 get_query_dispinfo_params(op->out.loop_count, &max_entries_buf, &max_size_buf);
2307 else {
2308 max_entries_buf = op->in.max_entries;
2309 max_size_buf = op->in.max_size;
2312 resume_idx_out = op->out.resume_idx;
2314 hnd->status = cli_samr_query_dispinfo( &(srv->cli), mem_ctx, op->in.dom_hnd, &resume_idx_out, op->in.info_class,
2315 &num_entries_out, max_entries_buf, max_size_buf, &ctr_out);
2317 if(!NT_STATUS_IS_OK(hnd->status) && !NT_STATUS_EQUAL(hnd->status, STATUS_MORE_ENTRIES)) {
2318 /*be defensive, maybe they'll call again without zeroing the struct*/
2319 op->out.loop_count = 0;
2320 op->out.resume_idx = 0;
2321 return CAC_FAILURE;
2324 if(NT_STATUS_IS_OK(hnd->status)) {
2325 /*we want to quit once the function is called next. so it can be used in a loop*/
2326 op->out.done = True;
2329 op->out.resume_idx = resume_idx_out;
2330 op->out.num_entries = num_entries_out;
2331 op->out.ctr = ctr_out;
2332 op->out.loop_count++;
2334 return CAC_SUCCESS;
2337 int cac_SamLookupDomain(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamLookupDomain *op) {
2338 SMBCSRV *srv = NULL;
2340 DOM_SID *sid_out = NULL;
2342 if(!hnd)
2343 return CAC_FAILURE;
2345 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2346 hnd->status = NT_STATUS_INVALID_HANDLE;
2347 return CAC_FAILURE;
2350 if(!op->in.sam || !op->in.name || !mem_ctx) {
2351 hnd->status = NT_STATUS_INVALID_PARAMETER;
2352 return CAC_FAILURE;
2355 srv = cac_GetServer(hnd);
2356 if(!srv) {
2357 hnd->status = NT_STATUS_INVALID_CONNECTION;
2358 return CAC_FAILURE;
2361 srv->cli.pipe_idx = PI_SAMR;
2363 sid_out = talloc(mem_ctx, DOM_SID);
2364 if(!sid_out) {
2365 hnd->status = NT_STATUS_NO_MEMORY;
2366 return CAC_FAILURE;
2369 hnd->status = cli_samr_lookup_domain( &(srv->cli), mem_ctx, op->in.sam, op->in.name, sid_out);
2371 if(!NT_STATUS_IS_OK(hnd->status))
2372 return CAC_FAILURE;
2374 op->out.sid = sid_out;
2376 return CAC_SUCCESS;
2379 int cac_SamGetSecurityObject(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamGetSecurityObject *op) {
2380 SMBCSRV *srv = NULL;
2382 /*this number taken from rpcclient/cmd_samr.c, I think it is the only supported level*/
2383 uint16 info_level = 4;
2385 SEC_DESC_BUF *sec_out = NULL;
2387 if(!hnd)
2388 return CAC_FAILURE;
2390 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2391 hnd->status = NT_STATUS_INVALID_HANDLE;
2392 return CAC_FAILURE;
2395 if(!op->in.pol || !mem_ctx) {
2396 hnd->status = NT_STATUS_INVALID_PARAMETER;
2397 return CAC_FAILURE;
2400 srv = cac_GetServer(hnd);
2401 if(!srv) {
2402 hnd->status = NT_STATUS_INVALID_CONNECTION;
2403 return CAC_FAILURE;
2406 srv->cli.pipe_idx = PI_SAMR;
2408 hnd->status = cli_samr_query_sec_obj(&(srv->cli), mem_ctx, op->in.pol, info_level, mem_ctx, &sec_out);
2410 if(!NT_STATUS_IS_OK(hnd->status))
2411 return CAC_FAILURE;
2413 op->out.sec = sec_out;
2415 return CAC_SUCCESS;
2418 int cac_SamFlush(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamFlush *op) {
2419 SMBCSRV *srv = NULL;
2421 struct SamOpenDomain od;
2423 if(!hnd)
2424 return CAC_FAILURE;
2426 if(!hnd->_internal.ctx || !hnd->_internal.pipes[PI_SAMR]) {
2427 hnd->status = NT_STATUS_INVALID_HANDLE;
2428 return CAC_FAILURE;
2431 if(!op || !op->in.dom_hnd || !mem_ctx) {
2432 hnd->status = NT_STATUS_INVALID_PARAMETER;
2433 return CAC_FAILURE;
2436 srv = cac_GetServer(hnd);
2437 if(!srv) {
2438 hnd->status = NT_STATUS_INVALID_CONNECTION;
2439 return CAC_FAILURE;
2442 srv->cli.pipe_idx = PI_SAMR;
2444 if(!cac_SamClose(hnd, mem_ctx, op->in.dom_hnd))
2445 return CAC_FAILURE;
2447 ZERO_STRUCT(od);
2448 od.in.access = (op->in.access) ? op->in.access : MAXIMUM_ALLOWED_ACCESS;
2449 od.in.sid = op->in.sid;
2451 if(!cac_SamOpenDomain(hnd, mem_ctx, &od))
2452 return CAC_FAILURE;
2454 /*this function does not use an output parameter to make it as convenient as possible to use*/
2455 *op->in.dom_hnd = *od.out.dom_hnd;
2457 talloc_free(od.out.dom_hnd);
2459 return CAC_SUCCESS;