s3:g_lock: reorder the logic in g_lock_lock_simple_fn()
[Samba.git] / source3 / lib / netapi / group.c
blob5258549ce66a98ba1c7d83a568f901b7bd99d8b0
1 /*
2 * Unix SMB/CIFS implementation.
3 * NetApi Group Support
4 * Copyright (C) Guenther Deschner 2008
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 3 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, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
26 #include "rpc_client/rpc_client.h"
27 #include "../librpc/gen_ndr/ndr_samr_c.h"
28 #include "rpc_client/init_lsa.h"
29 #include "../libcli/security/security.h"
31 /****************************************************************
32 ****************************************************************/
34 WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
35 struct NetGroupAdd *r)
37 struct rpc_pipe_client *pipe_cli = NULL;
38 NTSTATUS status, result;
39 WERROR werr;
40 struct policy_handle connect_handle, domain_handle, group_handle;
41 struct lsa_String lsa_group_name;
42 struct dom_sid2 *domain_sid = NULL;
43 uint32_t rid = 0;
44 struct dcerpc_binding_handle *b = NULL;
46 struct GROUP_INFO_0 *info0 = NULL;
47 struct GROUP_INFO_1 *info1 = NULL;
48 struct GROUP_INFO_2 *info2 = NULL;
49 struct GROUP_INFO_3 *info3 = NULL;
50 union samr_GroupInfo info;
52 ZERO_STRUCT(connect_handle);
53 ZERO_STRUCT(domain_handle);
54 ZERO_STRUCT(group_handle);
56 if (!r->in.buffer) {
57 return WERR_INVALID_PARAMETER;
60 switch (r->in.level) {
61 case 0:
62 info0 = (struct GROUP_INFO_0 *)r->in.buffer;
63 break;
64 case 1:
65 info1 = (struct GROUP_INFO_1 *)r->in.buffer;
66 break;
67 case 2:
68 info2 = (struct GROUP_INFO_2 *)r->in.buffer;
69 break;
70 case 3:
71 info3 = (struct GROUP_INFO_3 *)r->in.buffer;
72 break;
73 default:
74 werr = WERR_INVALID_LEVEL;
75 goto done;
78 werr = libnetapi_open_pipe(ctx, r->in.server_name,
79 &ndr_table_samr,
80 &pipe_cli);
81 if (!W_ERROR_IS_OK(werr)) {
82 goto done;
85 b = pipe_cli->binding_handle;
87 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
88 SAMR_ACCESS_ENUM_DOMAINS |
89 SAMR_ACCESS_LOOKUP_DOMAIN,
90 SAMR_DOMAIN_ACCESS_CREATE_GROUP |
91 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
92 &connect_handle,
93 &domain_handle,
94 &domain_sid);
95 if (!W_ERROR_IS_OK(werr)) {
96 goto done;
99 switch (r->in.level) {
100 case 0:
101 init_lsa_String(&lsa_group_name, info0->grpi0_name);
102 break;
103 case 1:
104 init_lsa_String(&lsa_group_name, info1->grpi1_name);
105 break;
106 case 2:
107 init_lsa_String(&lsa_group_name, info2->grpi2_name);
108 break;
109 case 3:
110 init_lsa_String(&lsa_group_name, info3->grpi3_name);
111 break;
114 status = dcerpc_samr_CreateDomainGroup(b, talloc_tos(),
115 &domain_handle,
116 &lsa_group_name,
117 SEC_STD_DELETE |
118 SAMR_GROUP_ACCESS_SET_INFO,
119 &group_handle,
120 &rid,
121 &result);
123 if (any_nt_status_not_ok(status, result, &status)) {
124 werr = ntstatus_to_werror(status);
125 goto done;
128 switch (r->in.level) {
129 case 1:
130 if (info1->grpi1_comment) {
131 init_lsa_String(&info.description,
132 info1->grpi1_comment);
134 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
135 &group_handle,
136 GROUPINFODESCRIPTION,
137 &info,
138 &result);
140 break;
141 case 2:
142 if (info2->grpi2_comment) {
143 init_lsa_String(&info.description,
144 info2->grpi2_comment);
146 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
147 &group_handle,
148 GROUPINFODESCRIPTION,
149 &info,
150 &result);
151 if (any_nt_status_not_ok(
152 status, result, &status)) {
153 werr = ntstatus_to_werror(status);
154 goto failed;
158 if (info2->grpi2_attributes != 0) {
159 info.attributes.attributes = info2->grpi2_attributes;
160 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
161 &group_handle,
162 GROUPINFOATTRIBUTES,
163 &info,
164 &result);
167 break;
168 case 3:
169 if (info3->grpi3_comment) {
170 init_lsa_String(&info.description,
171 info3->grpi3_comment);
173 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
174 &group_handle,
175 GROUPINFODESCRIPTION,
176 &info,
177 &result);
178 if (any_nt_status_not_ok(
179 status, result, &status)) {
180 werr = ntstatus_to_werror(status);
181 goto failed;
185 if (info3->grpi3_attributes != 0) {
186 info.attributes.attributes = info3->grpi3_attributes;
187 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
188 &group_handle,
189 GROUPINFOATTRIBUTES,
190 &info,
191 &result);
193 break;
194 default:
195 break;
198 if (any_nt_status_not_ok(status, result, &status)) {
199 werr = ntstatus_to_werror(status);
200 goto failed;
203 werr = WERR_OK;
204 goto done;
206 failed:
207 dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
208 &group_handle, &result);
210 done:
211 if (is_valid_policy_hnd(&group_handle)) {
212 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
215 if (ctx->disable_policy_handle_cache) {
216 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
217 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
220 return werr;
223 /****************************************************************
224 ****************************************************************/
226 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
227 struct NetGroupAdd *r)
229 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
232 /****************************************************************
233 ****************************************************************/
235 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
236 struct NetGroupDel *r)
238 struct rpc_pipe_client *pipe_cli = NULL;
239 NTSTATUS status, result;
240 WERROR werr;
241 struct policy_handle connect_handle, domain_handle, group_handle;
242 struct lsa_String lsa_group_name;
243 struct dom_sid2 *domain_sid = NULL;
244 int i = 0;
245 struct dcerpc_binding_handle *b = NULL;
247 struct samr_Ids rids;
248 struct samr_Ids types;
249 union samr_GroupInfo *info = NULL;
250 struct samr_RidAttrArray *rid_array = NULL;
252 ZERO_STRUCT(connect_handle);
253 ZERO_STRUCT(domain_handle);
254 ZERO_STRUCT(group_handle);
256 if (!r->in.group_name) {
257 return WERR_INVALID_PARAMETER;
260 werr = libnetapi_open_pipe(ctx, r->in.server_name,
261 &ndr_table_samr,
262 &pipe_cli);
263 if (!W_ERROR_IS_OK(werr)) {
264 goto done;
267 b = pipe_cli->binding_handle;
269 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
270 SAMR_ACCESS_ENUM_DOMAINS |
271 SAMR_ACCESS_LOOKUP_DOMAIN,
272 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
273 &connect_handle,
274 &domain_handle,
275 &domain_sid);
276 if (!W_ERROR_IS_OK(werr)) {
277 goto done;
280 init_lsa_String(&lsa_group_name, r->in.group_name);
282 status = dcerpc_samr_LookupNames(b, talloc_tos(),
283 &domain_handle,
285 &lsa_group_name,
286 &rids,
287 &types,
288 &result);
289 if (any_nt_status_not_ok(status, result, &status)) {
290 werr = ntstatus_to_werror(status);
291 goto done;
294 if (rids.count != 1) {
295 werr = WERR_BAD_NET_RESP;
296 goto done;
298 if (types.count != 1) {
299 werr = WERR_BAD_NET_RESP;
300 goto done;
303 if (types.ids[0] != SID_NAME_DOM_GRP) {
304 werr = WERR_INVALID_DATATYPE;
305 goto done;
308 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
309 &domain_handle,
310 SEC_STD_DELETE |
311 SAMR_GROUP_ACCESS_GET_MEMBERS |
312 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
313 SAMR_GROUP_ACCESS_ADD_MEMBER |
314 SAMR_GROUP_ACCESS_LOOKUP_INFO,
315 rids.ids[0],
316 &group_handle,
317 &result);
318 if (any_nt_status_not_ok(status, result, &status)) {
319 werr = ntstatus_to_werror(status);
320 goto done;
323 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
324 &group_handle,
325 GROUPINFOATTRIBUTES,
326 &info,
327 &result);
328 if (any_nt_status_not_ok(status, result, &status)) {
329 werr = ntstatus_to_werror(status);
330 goto done;
333 #if 0
334 /* breaks against NT4 */
335 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
336 werr = WERR_ACCESS_DENIED;
337 goto done;
339 #endif
340 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
341 &group_handle,
342 &rid_array,
343 &result);
344 if (any_nt_status_not_ok(status, result, &status)) {
345 werr = ntstatus_to_werror(status);
346 goto done;
350 struct lsa_Strings names;
351 struct samr_Ids member_types;
353 status = dcerpc_samr_LookupRids(b, talloc_tos(),
354 &domain_handle,
355 rid_array->count,
356 rid_array->rids,
357 &names,
358 &member_types,
359 &result);
360 if (any_nt_status_not_ok(status, result, &status)) {
361 werr = ntstatus_to_werror(status);
362 goto done;
364 if (names.count != rid_array->count) {
365 werr = WERR_BAD_NET_RESP;
366 goto done;
368 if (member_types.count != rid_array->count) {
369 werr = WERR_BAD_NET_RESP;
370 goto done;
374 for (i=0; i < rid_array->count; i++) {
376 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
377 &group_handle,
378 rid_array->rids[i],
379 &result);
380 if (any_nt_status_not_ok(status, result, &status)) {
381 werr = ntstatus_to_werror(status);
382 goto done;
386 status = dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
387 &group_handle,
388 &result);
389 if (any_nt_status_not_ok(status, result, &status)) {
390 werr = ntstatus_to_werror(status);
391 goto done;
394 ZERO_STRUCT(group_handle);
396 werr = WERR_OK;
398 done:
399 if (is_valid_policy_hnd(&group_handle)) {
400 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
403 if (ctx->disable_policy_handle_cache) {
404 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
405 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
408 return werr;
411 /****************************************************************
412 ****************************************************************/
414 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
415 struct NetGroupDel *r)
417 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
420 /****************************************************************
421 ****************************************************************/
423 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
424 struct NetGroupSetInfo *r)
426 struct rpc_pipe_client *pipe_cli = NULL;
427 NTSTATUS status, result;
428 WERROR werr;
429 struct policy_handle connect_handle, domain_handle, group_handle;
430 struct lsa_String lsa_group_name;
431 struct dom_sid2 *domain_sid = NULL;
432 struct dcerpc_binding_handle *b = NULL;
434 struct samr_Ids rids;
435 struct samr_Ids types;
436 union samr_GroupInfo info;
437 struct GROUP_INFO_0 *g0;
438 struct GROUP_INFO_1 *g1;
439 struct GROUP_INFO_2 *g2;
440 struct GROUP_INFO_3 *g3;
441 struct GROUP_INFO_1002 *g1002;
442 struct GROUP_INFO_1005 *g1005;
444 ZERO_STRUCT(connect_handle);
445 ZERO_STRUCT(domain_handle);
446 ZERO_STRUCT(group_handle);
448 if (!r->in.group_name) {
449 return WERR_INVALID_PARAMETER;
452 werr = libnetapi_open_pipe(ctx, r->in.server_name,
453 &ndr_table_samr,
454 &pipe_cli);
455 if (!W_ERROR_IS_OK(werr)) {
456 goto done;
459 b = pipe_cli->binding_handle;
461 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
462 SAMR_ACCESS_ENUM_DOMAINS |
463 SAMR_ACCESS_LOOKUP_DOMAIN,
464 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
465 &connect_handle,
466 &domain_handle,
467 &domain_sid);
468 if (!W_ERROR_IS_OK(werr)) {
469 goto done;
472 init_lsa_String(&lsa_group_name, r->in.group_name);
474 status = dcerpc_samr_LookupNames(b, talloc_tos(),
475 &domain_handle,
477 &lsa_group_name,
478 &rids,
479 &types,
480 &result);
481 if (any_nt_status_not_ok(status, result, &status)) {
482 werr = ntstatus_to_werror(status);
483 goto done;
485 if (rids.count != 1) {
486 werr = WERR_BAD_NET_RESP;
487 goto done;
489 if (types.count != 1) {
490 werr = WERR_BAD_NET_RESP;
491 goto done;
494 if (types.ids[0] != SID_NAME_DOM_GRP) {
495 werr = WERR_INVALID_DATATYPE;
496 goto done;
499 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
500 &domain_handle,
501 SAMR_GROUP_ACCESS_SET_INFO |
502 SAMR_GROUP_ACCESS_LOOKUP_INFO,
503 rids.ids[0],
504 &group_handle,
505 &result);
506 if (any_nt_status_not_ok(status, result, &status)) {
507 werr = ntstatus_to_werror(status);
508 goto done;
511 switch (r->in.level) {
512 case 0:
513 g0 = (struct GROUP_INFO_0 *)r->in.buffer;
514 init_lsa_String(&info.name, g0->grpi0_name);
515 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
516 &group_handle,
517 GROUPINFONAME,
518 &info,
519 &result);
520 break;
521 case 1:
522 g1 = (struct GROUP_INFO_1 *)r->in.buffer;
523 init_lsa_String(&info.description, g1->grpi1_comment);
524 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
525 &group_handle,
526 GROUPINFODESCRIPTION,
527 &info,
528 &result);
529 break;
530 case 2:
531 g2 = (struct GROUP_INFO_2 *)r->in.buffer;
532 init_lsa_String(&info.description, g2->grpi2_comment);
533 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
534 &group_handle,
535 GROUPINFODESCRIPTION,
536 &info,
537 &result);
538 if (any_nt_status_not_ok(status, result, &status)) {
539 werr = ntstatus_to_werror(status);
540 goto done;
543 info.attributes.attributes = g2->grpi2_attributes;
544 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
545 &group_handle,
546 GROUPINFOATTRIBUTES,
547 &info,
548 &result);
549 break;
550 case 3:
551 g3 = (struct GROUP_INFO_3 *)r->in.buffer;
552 init_lsa_String(&info.description, g3->grpi3_comment);
553 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
554 &group_handle,
555 GROUPINFODESCRIPTION,
556 &info,
557 &result);
558 if (any_nt_status_not_ok(status, result, &status)) {
559 werr = ntstatus_to_werror(status);
560 goto done;
563 info.attributes.attributes = g3->grpi3_attributes;
564 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
565 &group_handle,
566 GROUPINFOATTRIBUTES,
567 &info,
568 &result);
569 break;
570 case 1002:
571 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
572 init_lsa_String(&info.description, g1002->grpi1002_comment);
573 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
574 &group_handle,
575 GROUPINFODESCRIPTION,
576 &info,
577 &result);
578 break;
579 case 1005:
580 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
581 info.attributes.attributes = g1005->grpi1005_attributes;
582 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
583 &group_handle,
584 GROUPINFOATTRIBUTES,
585 &info,
586 &result);
587 break;
588 default:
589 status = NT_STATUS_INVALID_LEVEL;
590 break;
593 if (any_nt_status_not_ok(status, result, &status)) {
594 werr = ntstatus_to_werror(status);
595 goto done;
598 werr = WERR_OK;
600 done:
601 if (is_valid_policy_hnd(&group_handle)) {
602 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
605 if (ctx->disable_policy_handle_cache) {
606 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
607 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
610 return werr;
613 /****************************************************************
614 ****************************************************************/
616 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
617 struct NetGroupSetInfo *r)
619 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
622 /****************************************************************
623 ****************************************************************/
625 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
626 uint32_t level,
627 struct samr_GroupInfoAll *info,
628 struct dom_sid2 *domain_sid,
629 uint32_t rid,
630 uint8_t **buffer)
632 struct GROUP_INFO_0 info0;
633 struct GROUP_INFO_1 info1;
634 struct GROUP_INFO_2 info2;
635 struct GROUP_INFO_3 info3;
636 struct dom_sid sid;
638 switch (level) {
639 case 0:
640 info0.grpi0_name = info->name.string;
642 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
644 break;
645 case 1:
646 info1.grpi1_name = info->name.string;
647 info1.grpi1_comment = info->description.string;
649 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
651 break;
652 case 2:
653 info2.grpi2_name = info->name.string;
654 info2.grpi2_comment = info->description.string;
655 info2.grpi2_group_id = rid;
656 info2.grpi2_attributes = info->attributes;
658 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
660 break;
661 case 3:
662 if (!sid_compose(&sid, domain_sid, rid)) {
663 return WERR_NOT_ENOUGH_MEMORY;
666 info3.grpi3_name = info->name.string;
667 info3.grpi3_comment = info->description.string;
668 info3.grpi3_attributes = info->attributes;
669 info3.grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
671 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
673 break;
674 default:
675 return WERR_INVALID_LEVEL;
678 W_ERROR_HAVE_NO_MEMORY(*buffer);
680 return WERR_OK;
683 /****************************************************************
684 ****************************************************************/
686 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
687 struct NetGroupGetInfo *r)
689 struct rpc_pipe_client *pipe_cli = NULL;
690 NTSTATUS status, result;
691 WERROR werr;
692 struct policy_handle connect_handle, domain_handle, group_handle;
693 struct lsa_String lsa_group_name;
694 struct dom_sid2 *domain_sid = NULL;
695 struct dcerpc_binding_handle *b = NULL;
697 struct samr_Ids rids;
698 struct samr_Ids types;
699 union samr_GroupInfo *info = NULL;
700 bool group_info_all = false;
702 ZERO_STRUCT(connect_handle);
703 ZERO_STRUCT(domain_handle);
704 ZERO_STRUCT(group_handle);
706 if (!r->in.group_name) {
707 return WERR_INVALID_PARAMETER;
710 werr = libnetapi_open_pipe(ctx, r->in.server_name,
711 &ndr_table_samr,
712 &pipe_cli);
713 if (!W_ERROR_IS_OK(werr)) {
714 goto done;
717 b = pipe_cli->binding_handle;
719 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
720 SAMR_ACCESS_ENUM_DOMAINS |
721 SAMR_ACCESS_LOOKUP_DOMAIN,
722 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
723 &connect_handle,
724 &domain_handle,
725 &domain_sid);
726 if (!W_ERROR_IS_OK(werr)) {
727 goto done;
730 init_lsa_String(&lsa_group_name, r->in.group_name);
732 status = dcerpc_samr_LookupNames(b, talloc_tos(),
733 &domain_handle,
735 &lsa_group_name,
736 &rids,
737 &types,
738 &result);
739 if (any_nt_status_not_ok(status, result, &status)) {
740 werr = ntstatus_to_werror(status);
741 goto done;
743 if (rids.count != 1) {
744 werr = WERR_BAD_NET_RESP;
745 goto done;
747 if (types.count != 1) {
748 werr = WERR_BAD_NET_RESP;
749 goto done;
752 if (types.ids[0] != SID_NAME_DOM_GRP) {
753 werr = WERR_INVALID_DATATYPE;
754 goto done;
757 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
758 &domain_handle,
759 SAMR_GROUP_ACCESS_LOOKUP_INFO,
760 rids.ids[0],
761 &group_handle,
762 &result);
763 if (any_nt_status_not_ok(status, result, &status)) {
764 werr = ntstatus_to_werror(status);
765 goto done;
768 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
769 &group_handle,
770 GROUPINFOALL2,
771 &info,
772 &result);
773 if (!NT_STATUS_IS_OK(status)) {
774 werr = ntstatus_to_werror(status);
775 goto done;
778 if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS)) {
779 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
780 &group_handle,
781 GROUPINFOALL,
782 &info,
783 &result);
784 group_info_all = true;
785 if (!NT_STATUS_IS_OK(status)) {
786 werr = ntstatus_to_werror(status);
787 goto done;
791 if (!NT_STATUS_IS_OK(result)) {
792 werr = ntstatus_to_werror(result);
793 goto done;
796 werr = map_group_info_to_buffer(ctx, r->in.level,
797 group_info_all ? &info->all : &info->all2,
798 domain_sid, rids.ids[0],
799 r->out.buffer);
800 if (!W_ERROR_IS_OK(werr)) {
801 goto done;
803 done:
804 if (is_valid_policy_hnd(&group_handle)) {
805 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
808 if (ctx->disable_policy_handle_cache) {
809 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
810 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
813 return werr;
816 /****************************************************************
817 ****************************************************************/
819 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
820 struct NetGroupGetInfo *r)
822 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
825 /****************************************************************
826 ****************************************************************/
828 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
829 struct NetGroupAddUser *r)
831 struct rpc_pipe_client *pipe_cli = NULL;
832 NTSTATUS status, result;
833 WERROR werr;
834 struct policy_handle connect_handle, domain_handle, group_handle;
835 struct lsa_String lsa_group_name, lsa_user_name;
836 struct dom_sid2 *domain_sid = NULL;
837 struct dcerpc_binding_handle *b = NULL;
839 struct samr_Ids rids;
840 struct samr_Ids types;
842 ZERO_STRUCT(connect_handle);
843 ZERO_STRUCT(domain_handle);
844 ZERO_STRUCT(group_handle);
846 if (!r->in.group_name) {
847 return WERR_INVALID_PARAMETER;
850 werr = libnetapi_open_pipe(ctx, r->in.server_name,
851 &ndr_table_samr,
852 &pipe_cli);
853 if (!W_ERROR_IS_OK(werr)) {
854 goto done;
857 b = pipe_cli->binding_handle;
859 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
860 SAMR_ACCESS_ENUM_DOMAINS |
861 SAMR_ACCESS_LOOKUP_DOMAIN,
862 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
863 &connect_handle,
864 &domain_handle,
865 &domain_sid);
866 if (!W_ERROR_IS_OK(werr)) {
867 goto done;
870 init_lsa_String(&lsa_group_name, r->in.group_name);
872 status = dcerpc_samr_LookupNames(b, talloc_tos(),
873 &domain_handle,
875 &lsa_group_name,
876 &rids,
877 &types,
878 &result);
879 if (!NT_STATUS_IS_OK(status)) {
880 werr = ntstatus_to_werror(status);
881 goto done;
883 if (!NT_STATUS_IS_OK(result)) {
884 werr = WERR_NERR_GROUPNOTFOUND;
885 goto done;
887 if (rids.count != 1) {
888 werr = WERR_BAD_NET_RESP;
889 goto done;
891 if (types.count != 1) {
892 werr = WERR_BAD_NET_RESP;
893 goto done;
896 if (types.ids[0] != SID_NAME_DOM_GRP) {
897 werr = WERR_NERR_GROUPNOTFOUND;
898 goto done;
901 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
902 &domain_handle,
903 SAMR_GROUP_ACCESS_ADD_MEMBER,
904 rids.ids[0],
905 &group_handle,
906 &result);
907 if (any_nt_status_not_ok(status, result, &status)) {
908 werr = ntstatus_to_werror(status);
909 goto done;
912 init_lsa_String(&lsa_user_name, r->in.user_name);
914 status = dcerpc_samr_LookupNames(b, talloc_tos(),
915 &domain_handle,
917 &lsa_user_name,
918 &rids,
919 &types,
920 &result);
921 if (!NT_STATUS_IS_OK(status)) {
922 werr = ntstatus_to_werror(status);
923 goto done;
925 if (!NT_STATUS_IS_OK(result)) {
926 werr = WERR_NERR_USERNOTFOUND;
927 goto done;
929 if (rids.count != 1) {
930 werr = WERR_BAD_NET_RESP;
931 goto done;
933 if (types.count != 1) {
934 werr = WERR_BAD_NET_RESP;
935 goto done;
938 if (types.ids[0] != SID_NAME_USER) {
939 werr = WERR_NERR_USERNOTFOUND;
940 goto done;
943 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
944 &group_handle,
945 rids.ids[0],
946 7, /* why ? */
947 &result);
948 if (any_nt_status_not_ok(status, result, &status)) {
949 werr = ntstatus_to_werror(status);
950 goto done;
953 werr = WERR_OK;
955 done:
956 if (is_valid_policy_hnd(&group_handle)) {
957 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
960 if (ctx->disable_policy_handle_cache) {
961 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
962 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
965 return werr;
968 /****************************************************************
969 ****************************************************************/
971 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
972 struct NetGroupAddUser *r)
974 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
977 /****************************************************************
978 ****************************************************************/
980 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
981 struct NetGroupDelUser *r)
983 struct rpc_pipe_client *pipe_cli = NULL;
984 NTSTATUS status, result;
985 WERROR werr;
986 struct policy_handle connect_handle, domain_handle, group_handle;
987 struct lsa_String lsa_group_name, lsa_user_name;
988 struct dom_sid2 *domain_sid = NULL;
989 struct dcerpc_binding_handle *b = NULL;
991 struct samr_Ids rids;
992 struct samr_Ids types;
994 ZERO_STRUCT(connect_handle);
995 ZERO_STRUCT(domain_handle);
996 ZERO_STRUCT(group_handle);
998 if (!r->in.group_name) {
999 return WERR_INVALID_PARAMETER;
1002 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1003 &ndr_table_samr,
1004 &pipe_cli);
1005 if (!W_ERROR_IS_OK(werr)) {
1006 goto done;
1009 b = pipe_cli->binding_handle;
1011 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1012 SAMR_ACCESS_ENUM_DOMAINS |
1013 SAMR_ACCESS_LOOKUP_DOMAIN,
1014 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1015 &connect_handle,
1016 &domain_handle,
1017 &domain_sid);
1018 if (!W_ERROR_IS_OK(werr)) {
1019 goto done;
1022 init_lsa_String(&lsa_group_name, r->in.group_name);
1024 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1025 &domain_handle,
1027 &lsa_group_name,
1028 &rids,
1029 &types,
1030 &result);
1031 if (!NT_STATUS_IS_OK(status)) {
1032 werr = ntstatus_to_werror(status);
1033 goto done;
1035 if (!NT_STATUS_IS_OK(result)) {
1036 werr = WERR_NERR_GROUPNOTFOUND;
1037 goto done;
1039 if (rids.count != 1) {
1040 werr = WERR_BAD_NET_RESP;
1041 goto done;
1043 if (types.count != 1) {
1044 werr = WERR_BAD_NET_RESP;
1045 goto done;
1048 if (types.ids[0] != SID_NAME_DOM_GRP) {
1049 werr = WERR_NERR_GROUPNOTFOUND;
1050 goto done;
1053 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1054 &domain_handle,
1055 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
1056 rids.ids[0],
1057 &group_handle,
1058 &result);
1059 if (any_nt_status_not_ok(status, result, &status)) {
1060 werr = ntstatus_to_werror(status);
1061 goto done;
1064 init_lsa_String(&lsa_user_name, r->in.user_name);
1066 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1067 &domain_handle,
1069 &lsa_user_name,
1070 &rids,
1071 &types,
1072 &result);
1073 if (!NT_STATUS_IS_OK(status)) {
1074 werr = ntstatus_to_werror(status);
1075 goto done;
1078 if (!NT_STATUS_IS_OK(result)) {
1079 werr = WERR_NERR_USERNOTFOUND;
1080 goto done;
1082 if (rids.count != 1) {
1083 werr = WERR_BAD_NET_RESP;
1084 goto done;
1086 if (types.count != 1) {
1087 werr = WERR_BAD_NET_RESP;
1088 goto done;
1091 if (types.ids[0] != SID_NAME_USER) {
1092 werr = WERR_NERR_USERNOTFOUND;
1093 goto done;
1096 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1097 &group_handle,
1098 rids.ids[0],
1099 &result);
1100 if (any_nt_status_not_ok(status, result, &status)) {
1101 werr = ntstatus_to_werror(status);
1102 goto done;
1105 werr = WERR_OK;
1107 done:
1108 if (is_valid_policy_hnd(&group_handle)) {
1109 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1112 if (ctx->disable_policy_handle_cache) {
1113 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1114 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1117 return werr;
1120 /****************************************************************
1121 ****************************************************************/
1123 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1124 struct NetGroupDelUser *r)
1126 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
1129 /****************************************************************
1130 ****************************************************************/
1132 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
1133 struct samr_DispInfoFullGroups *groups,
1134 uint8_t **buffer)
1136 struct GROUP_INFO_0 *g0;
1137 int i;
1139 g0 = talloc_zero_array(mem_ctx, struct GROUP_INFO_0, groups->count);
1140 W_ERROR_HAVE_NO_MEMORY(g0);
1142 for (i=0; i<groups->count; i++) {
1143 g0[i].grpi0_name = talloc_strdup(mem_ctx,
1144 groups->entries[i].account_name.string);
1145 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
1148 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
1149 sizeof(struct GROUP_INFO_0) * groups->count);
1150 W_ERROR_HAVE_NO_MEMORY(*buffer);
1152 return WERR_OK;
1155 /****************************************************************
1156 ****************************************************************/
1158 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1159 struct samr_DispInfoFullGroups *groups,
1160 uint8_t **buffer)
1162 struct GROUP_INFO_1 *g1;
1163 int i;
1165 g1 = talloc_zero_array(mem_ctx, struct GROUP_INFO_1, groups->count);
1166 W_ERROR_HAVE_NO_MEMORY(g1);
1168 for (i=0; i<groups->count; i++) {
1169 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1170 groups->entries[i].account_name.string);
1171 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1172 groups->entries[i].description.string);
1173 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1176 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1177 sizeof(struct GROUP_INFO_1) * groups->count);
1178 W_ERROR_HAVE_NO_MEMORY(*buffer);
1180 return WERR_OK;
1183 /****************************************************************
1184 ****************************************************************/
1186 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1187 struct samr_DispInfoFullGroups *groups,
1188 uint8_t **buffer)
1190 struct GROUP_INFO_2 *g2;
1191 int i;
1193 g2 = talloc_zero_array(mem_ctx, struct GROUP_INFO_2, groups->count);
1194 W_ERROR_HAVE_NO_MEMORY(g2);
1196 for (i=0; i<groups->count; i++) {
1197 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1198 groups->entries[i].account_name.string);
1199 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1200 groups->entries[i].description.string);
1201 g2[i].grpi2_group_id = groups->entries[i].rid;
1202 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1203 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1206 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1207 sizeof(struct GROUP_INFO_2) * groups->count);
1208 W_ERROR_HAVE_NO_MEMORY(*buffer);
1210 return WERR_OK;
1213 /****************************************************************
1214 ****************************************************************/
1216 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1217 struct samr_DispInfoFullGroups *groups,
1218 const struct dom_sid *domain_sid,
1219 uint8_t **buffer)
1221 struct GROUP_INFO_3 *g3;
1222 int i;
1224 g3 = talloc_zero_array(mem_ctx, struct GROUP_INFO_3, groups->count);
1225 W_ERROR_HAVE_NO_MEMORY(g3);
1227 for (i=0; i<groups->count; i++) {
1229 struct dom_sid sid;
1231 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1232 return WERR_NOT_ENOUGH_MEMORY;
1235 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1236 groups->entries[i].account_name.string);
1237 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1238 groups->entries[i].description.string);
1239 g3[i].grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
1240 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1241 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1244 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1245 sizeof(struct GROUP_INFO_3) * groups->count);
1246 W_ERROR_HAVE_NO_MEMORY(*buffer);
1248 return WERR_OK;
1251 /****************************************************************
1252 ****************************************************************/
1254 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1255 uint32_t level,
1256 struct samr_DispInfoFullGroups *groups,
1257 const struct dom_sid *domain_sid,
1258 uint32_t *entries_read,
1259 uint8_t **buffer)
1261 if (entries_read) {
1262 *entries_read = groups->count;
1265 switch (level) {
1266 case 0:
1267 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1268 case 1:
1269 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1270 case 2:
1271 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1272 case 3:
1273 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1274 default:
1275 return WERR_INVALID_LEVEL;
1279 /****************************************************************
1280 ****************************************************************/
1282 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1283 struct NetGroupEnum *r)
1285 struct rpc_pipe_client *pipe_cli = NULL;
1286 struct policy_handle connect_handle;
1287 struct dom_sid2 *domain_sid = NULL;
1288 struct policy_handle domain_handle;
1289 union samr_DispInfo info;
1290 union samr_DomainInfo *domain_info = NULL;
1291 struct dcerpc_binding_handle *b = NULL;
1293 uint32_t total_size = 0;
1294 uint32_t returned_size = 0;
1296 NTSTATUS result = NT_STATUS_OK;
1297 NTSTATUS status;
1298 WERROR werr, tmp_werr;
1300 ZERO_STRUCT(connect_handle);
1301 ZERO_STRUCT(domain_handle);
1303 switch (r->in.level) {
1304 case 0:
1305 case 1:
1306 case 2:
1307 case 3:
1308 break;
1309 default:
1310 return WERR_INVALID_LEVEL;
1313 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1314 &ndr_table_samr,
1315 &pipe_cli);
1316 if (!W_ERROR_IS_OK(werr)) {
1317 goto done;
1320 b = pipe_cli->binding_handle;
1322 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1323 SAMR_ACCESS_ENUM_DOMAINS |
1324 SAMR_ACCESS_LOOKUP_DOMAIN,
1325 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1326 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1327 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1328 &connect_handle,
1329 &domain_handle,
1330 &domain_sid);
1331 if (!W_ERROR_IS_OK(werr)) {
1332 goto done;
1335 status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
1336 &domain_handle,
1338 &domain_info,
1339 &result);
1340 if (any_nt_status_not_ok(status, result, &status)) {
1341 werr = ntstatus_to_werror(status);
1342 goto done;
1345 if (r->out.total_entries) {
1346 *r->out.total_entries = domain_info->general.num_groups;
1349 status = dcerpc_samr_QueryDisplayInfo2(b,
1350 ctx,
1351 &domain_handle,
1353 r->in.resume_handle ?
1354 *r->in.resume_handle : 0,
1355 (uint32_t)-1,
1356 r->in.prefmaxlen,
1357 &total_size,
1358 &returned_size,
1359 &info,
1360 &result);
1361 if (!NT_STATUS_IS_OK(status)) {
1362 werr = ntstatus_to_werror(status);
1363 goto done;
1366 werr = ntstatus_to_werror(result);
1367 if (NT_STATUS_IS_ERR(result)) {
1368 goto done;
1371 if (r->out.resume_handle && info.info3.count > 0) {
1372 *r->out.resume_handle =
1373 info.info3.entries[info.info3.count-1].idx;
1376 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1377 r->in.level,
1378 &info.info3,
1379 domain_sid,
1380 r->out.entries_read,
1381 r->out.buffer);
1382 if (!W_ERROR_IS_OK(tmp_werr)) {
1383 werr = tmp_werr;
1384 goto done;
1387 done:
1388 /* if last query */
1389 if (NT_STATUS_IS_OK(result) ||
1390 NT_STATUS_IS_ERR(result)) {
1392 if (ctx->disable_policy_handle_cache) {
1393 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1394 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1398 return werr;
1401 /****************************************************************
1402 ****************************************************************/
1404 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1405 struct NetGroupEnum *r)
1407 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1410 /****************************************************************
1411 ****************************************************************/
1413 WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1414 struct NetGroupGetUsers *r)
1416 /* FIXME: this call needs to cope with large replies */
1418 struct rpc_pipe_client *pipe_cli = NULL;
1419 struct policy_handle connect_handle, domain_handle, group_handle;
1420 struct lsa_String lsa_account_name;
1421 struct dom_sid2 *domain_sid = NULL;
1422 struct samr_Ids group_rids, name_types;
1423 struct samr_RidAttrArray *rid_array = NULL;
1424 struct lsa_Strings names;
1425 struct samr_Ids member_types;
1426 struct dcerpc_binding_handle *b = NULL;
1428 int i;
1429 uint32_t entries_read = 0;
1431 NTSTATUS status;
1432 NTSTATUS result = NT_STATUS_OK;
1433 WERROR werr;
1435 ZERO_STRUCT(connect_handle);
1436 ZERO_STRUCT(domain_handle);
1437 ZERO_STRUCT(group_handle);
1439 if (!r->out.buffer) {
1440 return WERR_INVALID_PARAMETER;
1443 *r->out.buffer = NULL;
1444 *r->out.entries_read = 0;
1445 *r->out.total_entries = 0;
1447 switch (r->in.level) {
1448 case 0:
1449 case 1:
1450 break;
1451 default:
1452 return WERR_INVALID_LEVEL;
1456 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1457 &ndr_table_samr,
1458 &pipe_cli);
1459 if (!W_ERROR_IS_OK(werr)) {
1460 goto done;
1463 b = pipe_cli->binding_handle;
1465 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1466 SAMR_ACCESS_ENUM_DOMAINS |
1467 SAMR_ACCESS_LOOKUP_DOMAIN,
1468 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1469 &connect_handle,
1470 &domain_handle,
1471 &domain_sid);
1472 if (!W_ERROR_IS_OK(werr)) {
1473 goto done;
1476 init_lsa_String(&lsa_account_name, r->in.group_name);
1478 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1479 &domain_handle,
1481 &lsa_account_name,
1482 &group_rids,
1483 &name_types,
1484 &result);
1485 if (any_nt_status_not_ok(status, result, &status)) {
1486 werr = ntstatus_to_werror(status);
1487 goto done;
1489 if (group_rids.count != 1) {
1490 werr = WERR_BAD_NET_RESP;
1491 goto done;
1493 if (name_types.count != 1) {
1494 werr = WERR_BAD_NET_RESP;
1495 goto done;
1498 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1499 &domain_handle,
1500 SAMR_GROUP_ACCESS_GET_MEMBERS,
1501 group_rids.ids[0],
1502 &group_handle,
1503 &result);
1504 if (any_nt_status_not_ok(status, result, &status)) {
1505 werr = ntstatus_to_werror(status);
1506 goto done;
1509 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1510 &group_handle,
1511 &rid_array,
1512 &result);
1513 if (any_nt_status_not_ok(status, result, &status)) {
1514 werr = ntstatus_to_werror(status);
1515 goto done;
1518 status = dcerpc_samr_LookupRids(b, talloc_tos(),
1519 &domain_handle,
1520 rid_array->count,
1521 rid_array->rids,
1522 &names,
1523 &member_types,
1524 &result);
1525 if (any_nt_status_not_ok(status, result, &status)) {
1526 werr = ntstatus_to_werror(status);
1527 goto done;
1529 if (names.count != rid_array->count) {
1530 werr = WERR_BAD_NET_RESP;
1531 goto done;
1533 if (member_types.count != rid_array->count) {
1534 werr = WERR_BAD_NET_RESP;
1535 goto done;
1538 for (i=0; i < names.count; i++) {
1540 if (member_types.ids[i] != SID_NAME_USER) {
1541 continue;
1544 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1545 r->in.level,
1546 names.names[i].string,
1548 r->out.buffer,
1549 &entries_read);
1550 if (!NT_STATUS_IS_OK(status)) {
1551 werr = ntstatus_to_werror(status);
1552 goto done;
1556 *r->out.entries_read = entries_read;
1557 *r->out.total_entries = entries_read;
1559 werr = WERR_OK;
1561 done:
1562 if (is_valid_policy_hnd(&group_handle)) {
1563 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1566 if (ctx->disable_policy_handle_cache) {
1567 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1568 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1571 return werr;
1574 /****************************************************************
1575 ****************************************************************/
1577 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1578 struct NetGroupGetUsers *r)
1580 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1583 /****************************************************************
1584 ****************************************************************/
1586 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1587 struct NetGroupSetUsers *r)
1589 struct rpc_pipe_client *pipe_cli = NULL;
1590 struct policy_handle connect_handle, domain_handle, group_handle;
1591 struct lsa_String lsa_account_name;
1592 struct dom_sid2 *domain_sid = NULL;
1593 union samr_GroupInfo *group_info = NULL;
1594 struct samr_Ids user_rids, name_types;
1595 struct samr_Ids group_rids, group_types;
1596 struct samr_RidAttrArray *rid_array = NULL;
1597 struct lsa_String *lsa_names = NULL;
1598 struct dcerpc_binding_handle *b = NULL;
1600 uint32_t *add_rids = NULL;
1601 uint32_t *del_rids = NULL;
1602 size_t num_add_rids = 0;
1603 size_t num_del_rids = 0;
1605 uint32_t *member_rids = NULL;
1607 struct GROUP_USERS_INFO_0 *i0 = NULL;
1608 struct GROUP_USERS_INFO_1 *i1 = NULL;
1610 int i, k;
1612 NTSTATUS status;
1613 NTSTATUS result = NT_STATUS_OK;
1614 WERROR werr;
1616 ZERO_STRUCT(connect_handle);
1617 ZERO_STRUCT(domain_handle);
1618 ZERO_STRUCT(group_handle);
1620 if (!r->in.buffer) {
1621 return WERR_INVALID_PARAMETER;
1624 switch (r->in.level) {
1625 case 0:
1626 case 1:
1627 break;
1628 default:
1629 return WERR_INVALID_LEVEL;
1632 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1633 &ndr_table_samr,
1634 &pipe_cli);
1635 if (!W_ERROR_IS_OK(werr)) {
1636 goto done;
1639 b = pipe_cli->binding_handle;
1641 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1642 SAMR_ACCESS_ENUM_DOMAINS |
1643 SAMR_ACCESS_LOOKUP_DOMAIN,
1644 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1645 &connect_handle,
1646 &domain_handle,
1647 &domain_sid);
1648 if (!W_ERROR_IS_OK(werr)) {
1649 goto done;
1652 init_lsa_String(&lsa_account_name, r->in.group_name);
1654 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1655 &domain_handle,
1657 &lsa_account_name,
1658 &group_rids,
1659 &group_types,
1660 &result);
1661 if (any_nt_status_not_ok(status, result, &status)) {
1662 werr = ntstatus_to_werror(status);
1663 goto done;
1665 if (group_rids.count != 1) {
1666 werr = WERR_BAD_NET_RESP;
1667 goto done;
1669 if (group_types.count != 1) {
1670 werr = WERR_BAD_NET_RESP;
1671 goto done;
1674 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1675 &domain_handle,
1676 SAMR_GROUP_ACCESS_GET_MEMBERS |
1677 SAMR_GROUP_ACCESS_ADD_MEMBER |
1678 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1679 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1680 group_rids.ids[0],
1681 &group_handle,
1682 &result);
1683 if (any_nt_status_not_ok(status, result, &status)) {
1684 werr = ntstatus_to_werror(status);
1685 goto done;
1688 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
1689 &group_handle,
1690 GROUPINFOATTRIBUTES,
1691 &group_info,
1692 &result);
1693 if (any_nt_status_not_ok(status, result, &status)) {
1694 werr = ntstatus_to_werror(status);
1695 goto done;
1698 switch (r->in.level) {
1699 case 0:
1700 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1701 break;
1702 case 1:
1703 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1704 break;
1707 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1708 if (!lsa_names) {
1709 werr = WERR_NOT_ENOUGH_MEMORY;
1710 goto done;
1713 for (i=0; i < r->in.num_entries; i++) {
1715 switch (r->in.level) {
1716 case 0:
1717 init_lsa_String(&lsa_names[i], i0->grui0_name);
1718 i0++;
1719 break;
1720 case 1:
1721 init_lsa_String(&lsa_names[i], i1->grui1_name);
1722 i1++;
1723 break;
1727 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1728 &domain_handle,
1729 r->in.num_entries,
1730 lsa_names,
1731 &user_rids,
1732 &name_types,
1733 &result);
1734 if (any_nt_status_not_ok(status, result, &status)) {
1735 werr = ntstatus_to_werror(status);
1736 goto done;
1739 if (r->in.num_entries != user_rids.count) {
1740 werr = WERR_BAD_NET_RESP;
1741 goto done;
1743 if (r->in.num_entries != name_types.count) {
1744 werr = WERR_BAD_NET_RESP;
1745 goto done;
1748 member_rids = user_rids.ids;
1750 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1751 &group_handle,
1752 &rid_array,
1753 &result);
1754 if (any_nt_status_not_ok(status, result, &status)) {
1755 werr = ntstatus_to_werror(status);
1756 goto done;
1759 /* add list */
1761 for (i=0; i < r->in.num_entries; i++) {
1762 bool already_member = false;
1763 for (k=0; k < rid_array->count; k++) {
1764 if (member_rids[i] == rid_array->rids[k]) {
1765 already_member = true;
1766 break;
1769 if (!already_member) {
1770 if (!add_rid_to_array_unique(ctx,
1771 member_rids[i],
1772 &add_rids, &num_add_rids)) {
1773 werr = WERR_GEN_FAILURE;
1774 goto done;
1779 /* del list */
1781 for (k=0; k < rid_array->count; k++) {
1782 bool keep_member = false;
1783 for (i=0; i < r->in.num_entries; i++) {
1784 if (member_rids[i] == rid_array->rids[k]) {
1785 keep_member = true;
1786 break;
1789 if (!keep_member) {
1790 if (!add_rid_to_array_unique(ctx,
1791 rid_array->rids[k],
1792 &del_rids, &num_del_rids)) {
1793 werr = WERR_GEN_FAILURE;
1794 goto done;
1799 /* add list */
1801 for (i=0; i < num_add_rids; i++) {
1802 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
1803 &group_handle,
1804 add_rids[i],
1805 7 /* ? */,
1806 &result);
1807 if (any_nt_status_not_ok(status, result, &status)) {
1808 werr = ntstatus_to_werror(status);
1809 goto done;
1813 /* del list */
1815 for (i=0; i < num_del_rids; i++) {
1816 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1817 &group_handle,
1818 del_rids[i],
1819 &result);
1820 if (any_nt_status_not_ok(status, result, &status)) {
1821 werr = ntstatus_to_werror(status);
1822 goto done;
1826 werr = WERR_OK;
1828 done:
1829 if (is_valid_policy_hnd(&group_handle)) {
1830 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1833 if (ctx->disable_policy_handle_cache) {
1834 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1835 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1838 return werr;
1841 /****************************************************************
1842 ****************************************************************/
1844 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1845 struct NetGroupSetUsers *r)
1847 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);