Fix bug #6089 - Winbind samr_OpenDomain not possible with Samba 3.2.6+
[Samba.git] / source / lib / netapi / group.c
blob6dcf2e13f38da554f344d0f833bb53e75dd1bc86
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"
27 /****************************************************************
28 ****************************************************************/
30 WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
31 struct NetGroupAdd *r)
33 struct cli_state *cli = NULL;
34 struct rpc_pipe_client *pipe_cli = NULL;
35 NTSTATUS status;
36 WERROR werr;
37 POLICY_HND connect_handle, domain_handle, group_handle;
38 struct lsa_String lsa_group_name;
39 struct dom_sid2 *domain_sid = NULL;
40 uint32_t rid = 0;
42 struct GROUP_INFO_0 *info0 = NULL;
43 struct GROUP_INFO_1 *info1 = NULL;
44 struct GROUP_INFO_2 *info2 = NULL;
45 struct GROUP_INFO_3 *info3 = NULL;
46 union samr_GroupInfo info;
48 ZERO_STRUCT(connect_handle);
49 ZERO_STRUCT(domain_handle);
50 ZERO_STRUCT(group_handle);
52 if (!r->in.buffer) {
53 return WERR_INVALID_PARAM;
56 switch (r->in.level) {
57 case 0:
58 info0 = (struct GROUP_INFO_0 *)r->in.buffer;
59 break;
60 case 1:
61 info1 = (struct GROUP_INFO_1 *)r->in.buffer;
62 break;
63 case 2:
64 info2 = (struct GROUP_INFO_2 *)r->in.buffer;
65 break;
66 case 3:
67 info3 = (struct GROUP_INFO_3 *)r->in.buffer;
68 break;
69 default:
70 werr = WERR_UNKNOWN_LEVEL;
71 goto done;
74 werr = libnetapi_open_pipe(ctx, r->in.server_name,
75 &ndr_table_samr.syntax_id,
76 &cli,
77 &pipe_cli);
78 if (!W_ERROR_IS_OK(werr)) {
79 goto done;
82 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
83 SAMR_ACCESS_ENUM_DOMAINS |
84 SAMR_ACCESS_LOOKUP_DOMAIN,
85 SAMR_DOMAIN_ACCESS_CREATE_GROUP |
86 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
87 &connect_handle,
88 &domain_handle,
89 &domain_sid);
90 if (!W_ERROR_IS_OK(werr)) {
91 goto done;
94 switch (r->in.level) {
95 case 0:
96 init_lsa_String(&lsa_group_name, info0->grpi0_name);
97 break;
98 case 1:
99 init_lsa_String(&lsa_group_name, info1->grpi1_name);
100 break;
101 case 2:
102 init_lsa_String(&lsa_group_name, info2->grpi2_name);
103 break;
104 case 3:
105 init_lsa_String(&lsa_group_name, info3->grpi3_name);
106 break;
109 status = rpccli_samr_CreateDomainGroup(pipe_cli, ctx,
110 &domain_handle,
111 &lsa_group_name,
112 SEC_STD_DELETE |
113 SAMR_GROUP_ACCESS_SET_INFO,
114 &group_handle,
115 &rid);
117 if (!NT_STATUS_IS_OK(status)) {
118 werr = ntstatus_to_werror(status);
119 goto done;
122 switch (r->in.level) {
123 case 1:
124 if (info1->grpi1_comment) {
125 init_lsa_String(&info.description,
126 info1->grpi1_comment);
128 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
129 &group_handle,
130 GROUPINFODESCRIPTION,
131 &info);
133 break;
134 case 2:
135 if (info2->grpi2_comment) {
136 init_lsa_String(&info.description,
137 info2->grpi2_comment);
139 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
140 &group_handle,
141 GROUPINFODESCRIPTION,
142 &info);
143 if (!NT_STATUS_IS_OK(status)) {
144 werr = ntstatus_to_werror(status);
145 goto failed;
149 if (info2->grpi2_attributes != 0) {
150 info.attributes.attributes = info2->grpi2_attributes;
151 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
152 &group_handle,
153 GROUPINFOATTRIBUTES,
154 &info);
157 break;
158 case 3:
159 if (info3->grpi3_comment) {
160 init_lsa_String(&info.description,
161 info3->grpi3_comment);
163 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
164 &group_handle,
165 GROUPINFODESCRIPTION,
166 &info);
167 if (!NT_STATUS_IS_OK(status)) {
168 werr = ntstatus_to_werror(status);
169 goto failed;
173 if (info3->grpi3_attributes != 0) {
174 info.attributes.attributes = info3->grpi3_attributes;
175 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
176 &group_handle,
177 GROUPINFOATTRIBUTES,
178 &info);
180 break;
181 default:
182 break;
185 if (!NT_STATUS_IS_OK(status)) {
186 werr = ntstatus_to_werror(status);
187 goto failed;
190 werr = WERR_OK;
191 goto done;
193 failed:
194 rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
195 &group_handle);
197 done:
198 if (!cli) {
199 return werr;
202 if (is_valid_policy_hnd(&group_handle)) {
203 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
206 if (ctx->disable_policy_handle_cache) {
207 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
208 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
211 return werr;
214 /****************************************************************
215 ****************************************************************/
217 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
218 struct NetGroupAdd *r)
220 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
223 /****************************************************************
224 ****************************************************************/
226 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
227 struct NetGroupDel *r)
229 struct cli_state *cli = NULL;
230 struct rpc_pipe_client *pipe_cli = NULL;
231 NTSTATUS status;
232 WERROR werr;
233 POLICY_HND connect_handle, domain_handle, group_handle;
234 struct lsa_String lsa_group_name;
235 struct dom_sid2 *domain_sid = NULL;
236 int i = 0;
238 struct samr_Ids rids;
239 struct samr_Ids types;
240 union samr_GroupInfo *info = NULL;
241 struct samr_RidTypeArray *rid_array = NULL;
243 ZERO_STRUCT(connect_handle);
244 ZERO_STRUCT(domain_handle);
245 ZERO_STRUCT(group_handle);
247 if (!r->in.group_name) {
248 return WERR_INVALID_PARAM;
251 werr = libnetapi_open_pipe(ctx, r->in.server_name,
252 &ndr_table_samr.syntax_id,
253 &cli,
254 &pipe_cli);
255 if (!W_ERROR_IS_OK(werr)) {
256 goto done;
259 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
260 SAMR_ACCESS_ENUM_DOMAINS |
261 SAMR_ACCESS_LOOKUP_DOMAIN,
262 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
263 &connect_handle,
264 &domain_handle,
265 &domain_sid);
266 if (!W_ERROR_IS_OK(werr)) {
267 goto done;
270 init_lsa_String(&lsa_group_name, r->in.group_name);
272 status = rpccli_samr_LookupNames(pipe_cli, ctx,
273 &domain_handle,
275 &lsa_group_name,
276 &rids,
277 &types);
278 if (!NT_STATUS_IS_OK(status)) {
279 werr = ntstatus_to_werror(status);
280 goto done;
283 if (types.ids[0] != SID_NAME_DOM_GRP) {
284 werr = WERR_INVALID_DATATYPE;
285 goto done;
288 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
289 &domain_handle,
290 SEC_STD_DELETE |
291 SAMR_GROUP_ACCESS_GET_MEMBERS |
292 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
293 SAMR_GROUP_ACCESS_ADD_MEMBER |
294 SAMR_GROUP_ACCESS_LOOKUP_INFO,
295 rids.ids[0],
296 &group_handle);
297 if (!NT_STATUS_IS_OK(status)) {
298 werr = ntstatus_to_werror(status);
299 goto done;
302 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
303 &group_handle,
304 GROUPINFOATTRIBUTES,
305 &info);
306 if (!NT_STATUS_IS_OK(status)) {
307 werr = ntstatus_to_werror(status);
308 goto done;
311 #if 0
312 /* breaks against NT4 */
313 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
314 werr = WERR_ACCESS_DENIED;
315 goto done;
317 #endif
318 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
319 &group_handle,
320 &rid_array);
321 if (!NT_STATUS_IS_OK(status)) {
322 werr = ntstatus_to_werror(status);
323 goto done;
327 struct lsa_Strings names;
328 struct samr_Ids member_types;
330 status = rpccli_samr_LookupRids(pipe_cli, ctx,
331 &domain_handle,
332 rid_array->count,
333 rid_array->rids,
334 &names,
335 &member_types);
336 if (!NT_STATUS_IS_OK(status)) {
337 werr = ntstatus_to_werror(status);
338 goto done;
342 for (i=0; i < rid_array->count; i++) {
344 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
345 &group_handle,
346 rid_array->rids[i]);
347 if (!NT_STATUS_IS_OK(status)) {
348 werr = ntstatus_to_werror(status);
349 goto done;
353 status = rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
354 &group_handle);
355 if (!NT_STATUS_IS_OK(status)) {
356 werr = ntstatus_to_werror(status);
357 goto done;
360 ZERO_STRUCT(group_handle);
362 werr = WERR_OK;
364 done:
365 if (!cli) {
366 return werr;
369 if (is_valid_policy_hnd(&group_handle)) {
370 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
373 if (ctx->disable_policy_handle_cache) {
374 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
375 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
378 return werr;
381 /****************************************************************
382 ****************************************************************/
384 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
385 struct NetGroupDel *r)
387 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
390 /****************************************************************
391 ****************************************************************/
393 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
394 struct NetGroupSetInfo *r)
396 struct cli_state *cli = NULL;
397 struct rpc_pipe_client *pipe_cli = NULL;
398 NTSTATUS status;
399 WERROR werr;
400 POLICY_HND connect_handle, domain_handle, group_handle;
401 struct lsa_String lsa_group_name;
402 struct dom_sid2 *domain_sid = NULL;
404 struct samr_Ids rids;
405 struct samr_Ids types;
406 union samr_GroupInfo info;
407 struct GROUP_INFO_0 *g0;
408 struct GROUP_INFO_1 *g1;
409 struct GROUP_INFO_2 *g2;
410 struct GROUP_INFO_3 *g3;
411 struct GROUP_INFO_1002 *g1002;
412 struct GROUP_INFO_1005 *g1005;
414 ZERO_STRUCT(connect_handle);
415 ZERO_STRUCT(domain_handle);
416 ZERO_STRUCT(group_handle);
418 if (!r->in.group_name) {
419 return WERR_INVALID_PARAM;
422 werr = libnetapi_open_pipe(ctx, r->in.server_name,
423 &ndr_table_samr.syntax_id,
424 &cli,
425 &pipe_cli);
426 if (!W_ERROR_IS_OK(werr)) {
427 goto done;
430 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
431 SAMR_ACCESS_ENUM_DOMAINS |
432 SAMR_ACCESS_LOOKUP_DOMAIN,
433 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
434 &connect_handle,
435 &domain_handle,
436 &domain_sid);
437 if (!W_ERROR_IS_OK(werr)) {
438 goto done;
441 init_lsa_String(&lsa_group_name, r->in.group_name);
443 status = rpccli_samr_LookupNames(pipe_cli, ctx,
444 &domain_handle,
446 &lsa_group_name,
447 &rids,
448 &types);
449 if (!NT_STATUS_IS_OK(status)) {
450 werr = ntstatus_to_werror(status);
451 goto done;
454 if (types.ids[0] != SID_NAME_DOM_GRP) {
455 werr = WERR_INVALID_DATATYPE;
456 goto done;
459 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
460 &domain_handle,
461 SAMR_GROUP_ACCESS_SET_INFO |
462 SAMR_GROUP_ACCESS_LOOKUP_INFO,
463 rids.ids[0],
464 &group_handle);
465 if (!NT_STATUS_IS_OK(status)) {
466 werr = ntstatus_to_werror(status);
467 goto done;
470 switch (r->in.level) {
471 case 0:
472 g0 = (struct GROUP_INFO_0 *)r->in.buffer;
473 init_lsa_String(&info.name, g0->grpi0_name);
474 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
475 &group_handle,
476 GROUPINFONAME,
477 &info);
478 break;
479 case 1:
480 g1 = (struct GROUP_INFO_1 *)r->in.buffer;
481 init_lsa_String(&info.description, g1->grpi1_comment);
482 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
483 &group_handle,
484 GROUPINFODESCRIPTION,
485 &info);
486 break;
487 case 2:
488 g2 = (struct GROUP_INFO_2 *)r->in.buffer;
489 init_lsa_String(&info.description, g2->grpi2_comment);
490 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
491 &group_handle,
492 GROUPINFODESCRIPTION,
493 &info);
494 if (!NT_STATUS_IS_OK(status)) {
495 werr = ntstatus_to_werror(status);
496 goto done;
498 info.attributes.attributes = g2->grpi2_attributes;
499 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
500 &group_handle,
501 GROUPINFOATTRIBUTES,
502 &info);
503 break;
504 case 3:
505 g3 = (struct GROUP_INFO_3 *)r->in.buffer;
506 init_lsa_String(&info.description, g3->grpi3_comment);
507 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
508 &group_handle,
509 GROUPINFODESCRIPTION,
510 &info);
511 if (!NT_STATUS_IS_OK(status)) {
512 werr = ntstatus_to_werror(status);
513 goto done;
515 info.attributes.attributes = g3->grpi3_attributes;
516 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
517 &group_handle,
518 GROUPINFOATTRIBUTES,
519 &info);
520 break;
521 case 1002:
522 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
523 init_lsa_String(&info.description, g1002->grpi1002_comment);
524 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
525 &group_handle,
526 GROUPINFODESCRIPTION,
527 &info);
528 break;
529 case 1005:
530 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
531 info.attributes.attributes = g1005->grpi1005_attributes;
532 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
533 &group_handle,
534 GROUPINFOATTRIBUTES,
535 &info);
536 break;
537 default:
538 status = NT_STATUS_INVALID_LEVEL;
539 break;
542 if (!NT_STATUS_IS_OK(status)) {
543 werr = ntstatus_to_werror(status);
544 goto done;
547 werr = WERR_OK;
549 done:
550 if (!cli) {
551 return werr;
554 if (is_valid_policy_hnd(&group_handle)) {
555 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
558 if (ctx->disable_policy_handle_cache) {
559 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
560 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
563 return werr;
566 /****************************************************************
567 ****************************************************************/
569 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
570 struct NetGroupSetInfo *r)
572 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
575 /****************************************************************
576 ****************************************************************/
578 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
579 uint32_t level,
580 struct samr_GroupInfoAll *info,
581 struct dom_sid2 *domain_sid,
582 uint32_t rid,
583 uint8_t **buffer)
585 struct GROUP_INFO_0 info0;
586 struct GROUP_INFO_1 info1;
587 struct GROUP_INFO_2 info2;
588 struct GROUP_INFO_3 info3;
589 struct dom_sid sid;
591 switch (level) {
592 case 0:
593 info0.grpi0_name = info->name.string;
595 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
597 break;
598 case 1:
599 info1.grpi1_name = info->name.string;
600 info1.grpi1_comment = info->description.string;
602 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
604 break;
605 case 2:
606 info2.grpi2_name = info->name.string;
607 info2.grpi2_comment = info->description.string;
608 info2.grpi2_group_id = rid;
609 info2.grpi2_attributes = info->attributes;
611 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
613 break;
614 case 3:
615 if (!sid_compose(&sid, domain_sid, rid)) {
616 return WERR_NOMEM;
619 info3.grpi3_name = info->name.string;
620 info3.grpi3_comment = info->description.string;
621 info3.grpi3_attributes = info->attributes;
622 info3.grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
624 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
626 break;
627 default:
628 return WERR_UNKNOWN_LEVEL;
631 W_ERROR_HAVE_NO_MEMORY(*buffer);
633 return WERR_OK;
636 /****************************************************************
637 ****************************************************************/
639 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
640 struct NetGroupGetInfo *r)
642 struct cli_state *cli = NULL;
643 struct rpc_pipe_client *pipe_cli = NULL;
644 NTSTATUS status;
645 WERROR werr;
646 POLICY_HND connect_handle, domain_handle, group_handle;
647 struct lsa_String lsa_group_name;
648 struct dom_sid2 *domain_sid = NULL;
650 struct samr_Ids rids;
651 struct samr_Ids types;
652 union samr_GroupInfo *info = NULL;
653 bool group_info_all = false;
655 ZERO_STRUCT(connect_handle);
656 ZERO_STRUCT(domain_handle);
657 ZERO_STRUCT(group_handle);
659 if (!r->in.group_name) {
660 return WERR_INVALID_PARAM;
663 werr = libnetapi_open_pipe(ctx, r->in.server_name,
664 &ndr_table_samr.syntax_id,
665 &cli,
666 &pipe_cli);
667 if (!W_ERROR_IS_OK(werr)) {
668 goto done;
671 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
672 SAMR_ACCESS_ENUM_DOMAINS |
673 SAMR_ACCESS_LOOKUP_DOMAIN,
674 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
675 &connect_handle,
676 &domain_handle,
677 &domain_sid);
678 if (!W_ERROR_IS_OK(werr)) {
679 goto done;
682 init_lsa_String(&lsa_group_name, r->in.group_name);
684 status = rpccli_samr_LookupNames(pipe_cli, ctx,
685 &domain_handle,
687 &lsa_group_name,
688 &rids,
689 &types);
690 if (!NT_STATUS_IS_OK(status)) {
691 werr = ntstatus_to_werror(status);
692 goto done;
695 if (types.ids[0] != SID_NAME_DOM_GRP) {
696 werr = WERR_INVALID_DATATYPE;
697 goto done;
700 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
701 &domain_handle,
702 SAMR_GROUP_ACCESS_LOOKUP_INFO,
703 rids.ids[0],
704 &group_handle);
705 if (!NT_STATUS_IS_OK(status)) {
706 werr = ntstatus_to_werror(status);
707 goto done;
710 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
711 &group_handle,
712 GROUPINFOALL2,
713 &info);
714 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
715 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
716 &group_handle,
717 GROUPINFOALL,
718 &info);
719 group_info_all = true;
722 if (!NT_STATUS_IS_OK(status)) {
723 werr = ntstatus_to_werror(status);
724 goto done;
727 werr = map_group_info_to_buffer(ctx, r->in.level,
728 group_info_all ? &info->all : &info->all2,
729 domain_sid, rids.ids[0],
730 r->out.buffer);
731 if (!W_ERROR_IS_OK(werr)) {
732 goto done;
734 done:
735 if (!cli) {
736 return werr;
739 if (is_valid_policy_hnd(&group_handle)) {
740 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
743 if (ctx->disable_policy_handle_cache) {
744 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
745 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
748 return werr;
751 /****************************************************************
752 ****************************************************************/
754 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
755 struct NetGroupGetInfo *r)
757 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
760 /****************************************************************
761 ****************************************************************/
763 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
764 struct NetGroupAddUser *r)
766 struct cli_state *cli = NULL;
767 struct rpc_pipe_client *pipe_cli = NULL;
768 NTSTATUS status;
769 WERROR werr;
770 POLICY_HND connect_handle, domain_handle, group_handle;
771 struct lsa_String lsa_group_name, lsa_user_name;
772 struct dom_sid2 *domain_sid = NULL;
774 struct samr_Ids rids;
775 struct samr_Ids types;
777 ZERO_STRUCT(connect_handle);
778 ZERO_STRUCT(domain_handle);
779 ZERO_STRUCT(group_handle);
781 if (!r->in.group_name) {
782 return WERR_INVALID_PARAM;
785 werr = libnetapi_open_pipe(ctx, r->in.server_name,
786 &ndr_table_samr.syntax_id,
787 &cli,
788 &pipe_cli);
789 if (!W_ERROR_IS_OK(werr)) {
790 goto done;
793 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
794 SAMR_ACCESS_ENUM_DOMAINS |
795 SAMR_ACCESS_LOOKUP_DOMAIN,
796 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
797 &connect_handle,
798 &domain_handle,
799 &domain_sid);
800 if (!W_ERROR_IS_OK(werr)) {
801 goto done;
804 init_lsa_String(&lsa_group_name, r->in.group_name);
806 status = rpccli_samr_LookupNames(pipe_cli, ctx,
807 &domain_handle,
809 &lsa_group_name,
810 &rids,
811 &types);
812 if (!NT_STATUS_IS_OK(status)) {
813 werr = WERR_GROUP_NOT_FOUND;
814 goto done;
817 if (types.ids[0] != SID_NAME_DOM_GRP) {
818 werr = WERR_GROUP_NOT_FOUND;
819 goto done;
822 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
823 &domain_handle,
824 SAMR_GROUP_ACCESS_ADD_MEMBER,
825 rids.ids[0],
826 &group_handle);
827 if (!NT_STATUS_IS_OK(status)) {
828 werr = ntstatus_to_werror(status);
829 goto done;
832 init_lsa_String(&lsa_user_name, r->in.user_name);
834 status = rpccli_samr_LookupNames(pipe_cli, ctx,
835 &domain_handle,
837 &lsa_user_name,
838 &rids,
839 &types);
840 if (!NT_STATUS_IS_OK(status)) {
841 werr = WERR_USER_NOT_FOUND;
842 goto done;
845 if (types.ids[0] != SID_NAME_USER) {
846 werr = WERR_USER_NOT_FOUND;
847 goto done;
850 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
851 &group_handle,
852 rids.ids[0],
853 7); /* why ? */
854 if (!NT_STATUS_IS_OK(status)) {
855 werr = ntstatus_to_werror(status);
856 goto done;
859 werr = WERR_OK;
861 done:
862 if (!cli) {
863 return werr;
866 if (is_valid_policy_hnd(&group_handle)) {
867 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
870 if (ctx->disable_policy_handle_cache) {
871 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
872 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
875 return werr;
878 /****************************************************************
879 ****************************************************************/
881 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
882 struct NetGroupAddUser *r)
884 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
887 /****************************************************************
888 ****************************************************************/
890 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
891 struct NetGroupDelUser *r)
893 struct cli_state *cli = NULL;
894 struct rpc_pipe_client *pipe_cli = NULL;
895 NTSTATUS status;
896 WERROR werr;
897 POLICY_HND connect_handle, domain_handle, group_handle;
898 struct lsa_String lsa_group_name, lsa_user_name;
899 struct dom_sid2 *domain_sid = NULL;
901 struct samr_Ids rids;
902 struct samr_Ids types;
904 ZERO_STRUCT(connect_handle);
905 ZERO_STRUCT(domain_handle);
906 ZERO_STRUCT(group_handle);
908 if (!r->in.group_name) {
909 return WERR_INVALID_PARAM;
912 werr = libnetapi_open_pipe(ctx, r->in.server_name,
913 &ndr_table_samr.syntax_id,
914 &cli,
915 &pipe_cli);
916 if (!W_ERROR_IS_OK(werr)) {
917 goto done;
920 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
921 SAMR_ACCESS_ENUM_DOMAINS |
922 SAMR_ACCESS_LOOKUP_DOMAIN,
923 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
924 &connect_handle,
925 &domain_handle,
926 &domain_sid);
927 if (!W_ERROR_IS_OK(werr)) {
928 goto done;
931 init_lsa_String(&lsa_group_name, r->in.group_name);
933 status = rpccli_samr_LookupNames(pipe_cli, ctx,
934 &domain_handle,
936 &lsa_group_name,
937 &rids,
938 &types);
939 if (!NT_STATUS_IS_OK(status)) {
940 werr = WERR_GROUP_NOT_FOUND;
941 goto done;
944 if (types.ids[0] != SID_NAME_DOM_GRP) {
945 werr = WERR_GROUP_NOT_FOUND;
946 goto done;
949 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
950 &domain_handle,
951 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
952 rids.ids[0],
953 &group_handle);
954 if (!NT_STATUS_IS_OK(status)) {
955 werr = ntstatus_to_werror(status);
956 goto done;
959 init_lsa_String(&lsa_user_name, r->in.user_name);
961 status = rpccli_samr_LookupNames(pipe_cli, ctx,
962 &domain_handle,
964 &lsa_user_name,
965 &rids,
966 &types);
967 if (!NT_STATUS_IS_OK(status)) {
968 werr = WERR_USER_NOT_FOUND;
969 goto done;
972 if (types.ids[0] != SID_NAME_USER) {
973 werr = WERR_USER_NOT_FOUND;
974 goto done;
977 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
978 &group_handle,
979 rids.ids[0]);
980 if (!NT_STATUS_IS_OK(status)) {
981 werr = ntstatus_to_werror(status);
982 goto done;
985 werr = WERR_OK;
987 done:
988 if (!cli) {
989 return werr;
992 if (is_valid_policy_hnd(&group_handle)) {
993 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
996 if (ctx->disable_policy_handle_cache) {
997 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
998 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1001 return werr;
1004 /****************************************************************
1005 ****************************************************************/
1007 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1008 struct NetGroupDelUser *r)
1010 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
1013 /****************************************************************
1014 ****************************************************************/
1016 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
1017 struct samr_DispInfoFullGroups *groups,
1018 uint8_t **buffer)
1020 struct GROUP_INFO_0 *g0;
1021 int i;
1023 g0 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_0, groups->count);
1024 W_ERROR_HAVE_NO_MEMORY(g0);
1026 for (i=0; i<groups->count; i++) {
1027 g0[i].grpi0_name = talloc_strdup(mem_ctx,
1028 groups->entries[i].account_name.string);
1029 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
1032 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
1033 sizeof(struct GROUP_INFO_0) * groups->count);
1034 W_ERROR_HAVE_NO_MEMORY(*buffer);
1036 return WERR_OK;
1039 /****************************************************************
1040 ****************************************************************/
1042 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1043 struct samr_DispInfoFullGroups *groups,
1044 uint8_t **buffer)
1046 struct GROUP_INFO_1 *g1;
1047 int i;
1049 g1 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_1, groups->count);
1050 W_ERROR_HAVE_NO_MEMORY(g1);
1052 for (i=0; i<groups->count; i++) {
1053 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1054 groups->entries[i].account_name.string);
1055 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1056 groups->entries[i].description.string);
1057 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1060 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1061 sizeof(struct GROUP_INFO_1) * groups->count);
1062 W_ERROR_HAVE_NO_MEMORY(*buffer);
1064 return WERR_OK;
1067 /****************************************************************
1068 ****************************************************************/
1070 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1071 struct samr_DispInfoFullGroups *groups,
1072 uint8_t **buffer)
1074 struct GROUP_INFO_2 *g2;
1075 int i;
1077 g2 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_2, groups->count);
1078 W_ERROR_HAVE_NO_MEMORY(g2);
1080 for (i=0; i<groups->count; i++) {
1081 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1082 groups->entries[i].account_name.string);
1083 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1084 groups->entries[i].description.string);
1085 g2[i].grpi2_group_id = groups->entries[i].rid;
1086 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1087 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1090 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1091 sizeof(struct GROUP_INFO_2) * groups->count);
1092 W_ERROR_HAVE_NO_MEMORY(*buffer);
1094 return WERR_OK;
1097 /****************************************************************
1098 ****************************************************************/
1100 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1101 struct samr_DispInfoFullGroups *groups,
1102 const struct dom_sid *domain_sid,
1103 uint8_t **buffer)
1105 struct GROUP_INFO_3 *g3;
1106 int i;
1108 g3 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_3, groups->count);
1109 W_ERROR_HAVE_NO_MEMORY(g3);
1111 for (i=0; i<groups->count; i++) {
1113 struct dom_sid sid;
1115 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1116 return WERR_NOMEM;
1119 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1120 groups->entries[i].account_name.string);
1121 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1122 groups->entries[i].description.string);
1123 g3[i].grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
1124 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1125 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1128 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1129 sizeof(struct GROUP_INFO_3) * groups->count);
1130 W_ERROR_HAVE_NO_MEMORY(*buffer);
1132 return WERR_OK;
1135 /****************************************************************
1136 ****************************************************************/
1138 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1139 uint32_t level,
1140 struct samr_DispInfoFullGroups *groups,
1141 const struct dom_sid *domain_sid,
1142 uint32_t *entries_read,
1143 uint8_t **buffer)
1145 if (entries_read) {
1146 *entries_read = groups->count;
1149 switch (level) {
1150 case 0:
1151 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1152 case 1:
1153 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1154 case 2:
1155 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1156 case 3:
1157 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1158 default:
1159 return WERR_UNKNOWN_LEVEL;
1163 /****************************************************************
1164 ****************************************************************/
1166 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1167 struct NetGroupEnum *r)
1169 struct cli_state *cli = NULL;
1170 struct rpc_pipe_client *pipe_cli = NULL;
1171 struct policy_handle connect_handle;
1172 struct dom_sid2 *domain_sid = NULL;
1173 struct policy_handle domain_handle;
1174 union samr_DispInfo info;
1175 union samr_DomainInfo *domain_info = NULL;
1177 uint32_t total_size = 0;
1178 uint32_t returned_size = 0;
1180 NTSTATUS status = NT_STATUS_OK;
1181 WERROR werr, tmp_werr;
1183 ZERO_STRUCT(connect_handle);
1184 ZERO_STRUCT(domain_handle);
1186 switch (r->in.level) {
1187 case 0:
1188 case 1:
1189 case 2:
1190 case 3:
1191 break;
1192 default:
1193 return WERR_UNKNOWN_LEVEL;
1196 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1197 &ndr_table_samr.syntax_id,
1198 &cli,
1199 &pipe_cli);
1200 if (!W_ERROR_IS_OK(werr)) {
1201 goto done;
1204 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1205 SAMR_ACCESS_ENUM_DOMAINS |
1206 SAMR_ACCESS_LOOKUP_DOMAIN,
1207 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1208 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1209 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1210 &connect_handle,
1211 &domain_handle,
1212 &domain_sid);
1213 if (!W_ERROR_IS_OK(werr)) {
1214 goto done;
1217 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
1218 &domain_handle,
1220 &domain_info);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 werr = ntstatus_to_werror(status);
1223 goto done;
1226 if (r->out.total_entries) {
1227 *r->out.total_entries = domain_info->info2.num_groups;
1230 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1231 ctx,
1232 &domain_handle,
1234 r->in.resume_handle ?
1235 *r->in.resume_handle : 0,
1236 (uint32_t)-1,
1237 r->in.prefmaxlen,
1238 &total_size,
1239 &returned_size,
1240 &info);
1241 werr = ntstatus_to_werror(status);
1242 if (NT_STATUS_IS_ERR(status)) {
1243 goto done;
1246 if (r->out.resume_handle && info.info3.count > 0) {
1247 *r->out.resume_handle =
1248 info.info3.entries[info.info3.count-1].idx;
1251 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1252 r->in.level,
1253 &info.info3,
1254 domain_sid,
1255 r->out.entries_read,
1256 r->out.buffer);
1257 if (!W_ERROR_IS_OK(tmp_werr)) {
1258 werr = tmp_werr;
1259 goto done;
1262 done:
1263 if (!cli) {
1264 return werr;
1267 /* if last query */
1268 if (NT_STATUS_IS_OK(status) ||
1269 NT_STATUS_IS_ERR(status)) {
1271 if (ctx->disable_policy_handle_cache) {
1272 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1273 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1277 return werr;
1280 /****************************************************************
1281 ****************************************************************/
1283 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1284 struct NetGroupEnum *r)
1286 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1289 /****************************************************************
1290 ****************************************************************/
1292 WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1293 struct NetGroupGetUsers *r)
1295 /* FIXME: this call needs to cope with large replies */
1297 struct cli_state *cli = NULL;
1298 struct rpc_pipe_client *pipe_cli = NULL;
1299 struct policy_handle connect_handle, domain_handle, group_handle;
1300 struct lsa_String lsa_account_name;
1301 struct dom_sid2 *domain_sid = NULL;
1302 struct samr_Ids group_rids, name_types;
1303 struct samr_RidTypeArray *rid_array = NULL;
1304 struct lsa_Strings names;
1305 struct samr_Ids member_types;
1307 int i;
1308 uint32_t entries_read = 0;
1310 NTSTATUS status = NT_STATUS_OK;
1311 WERROR werr;
1313 ZERO_STRUCT(connect_handle);
1314 ZERO_STRUCT(domain_handle);
1316 if (!r->out.buffer) {
1317 return WERR_INVALID_PARAM;
1320 *r->out.buffer = NULL;
1321 *r->out.entries_read = 0;
1322 *r->out.total_entries = 0;
1324 switch (r->in.level) {
1325 case 0:
1326 case 1:
1327 break;
1328 default:
1329 return WERR_UNKNOWN_LEVEL;
1333 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1334 &ndr_table_samr.syntax_id,
1335 &cli,
1336 &pipe_cli);
1337 if (!W_ERROR_IS_OK(werr)) {
1338 goto done;
1341 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1342 SAMR_ACCESS_ENUM_DOMAINS |
1343 SAMR_ACCESS_LOOKUP_DOMAIN,
1344 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1345 &connect_handle,
1346 &domain_handle,
1347 &domain_sid);
1348 if (!W_ERROR_IS_OK(werr)) {
1349 goto done;
1352 init_lsa_String(&lsa_account_name, r->in.group_name);
1354 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1355 &domain_handle,
1357 &lsa_account_name,
1358 &group_rids,
1359 &name_types);
1360 if (!NT_STATUS_IS_OK(status)) {
1361 werr = ntstatus_to_werror(status);
1362 goto done;
1365 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1366 &domain_handle,
1367 SAMR_GROUP_ACCESS_GET_MEMBERS,
1368 group_rids.ids[0],
1369 &group_handle);
1370 if (!NT_STATUS_IS_OK(status)) {
1371 werr = ntstatus_to_werror(status);
1372 goto done;
1375 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1376 &group_handle,
1377 &rid_array);
1378 if (!NT_STATUS_IS_OK(status)) {
1379 werr = ntstatus_to_werror(status);
1380 goto done;
1383 status = rpccli_samr_LookupRids(pipe_cli, ctx,
1384 &domain_handle,
1385 rid_array->count,
1386 rid_array->rids,
1387 &names,
1388 &member_types);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 werr = ntstatus_to_werror(status);
1391 goto done;
1394 for (i=0; i < names.count; i++) {
1396 if (member_types.ids[i] != SID_NAME_USER) {
1397 continue;
1400 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1401 r->in.level,
1402 names.names[i].string,
1404 r->out.buffer,
1405 &entries_read);
1406 if (!NT_STATUS_IS_OK(status)) {
1407 werr = ntstatus_to_werror(status);
1408 goto done;
1412 *r->out.entries_read = entries_read;
1413 *r->out.total_entries = entries_read;
1415 werr = WERR_OK;
1417 done:
1418 if (!cli) {
1419 return werr;
1422 if (is_valid_policy_hnd(&group_handle)) {
1423 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1426 if (ctx->disable_policy_handle_cache) {
1427 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1428 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1431 return werr;
1434 /****************************************************************
1435 ****************************************************************/
1437 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1438 struct NetGroupGetUsers *r)
1440 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1443 /****************************************************************
1444 ****************************************************************/
1446 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1447 struct NetGroupSetUsers *r)
1449 struct cli_state *cli = NULL;
1450 struct rpc_pipe_client *pipe_cli = NULL;
1451 struct policy_handle connect_handle, domain_handle, group_handle;
1452 struct lsa_String lsa_account_name;
1453 struct dom_sid2 *domain_sid = NULL;
1454 union samr_GroupInfo *group_info = NULL;
1455 struct samr_Ids user_rids, name_types;
1456 struct samr_Ids group_rids, group_types;
1457 struct samr_RidTypeArray *rid_array = NULL;
1458 struct lsa_String *lsa_names = NULL;
1460 uint32_t *add_rids = NULL;
1461 uint32_t *del_rids = NULL;
1462 size_t num_add_rids = 0;
1463 size_t num_del_rids = 0;
1465 uint32_t *member_rids = NULL;
1466 size_t num_member_rids = 0;
1468 struct GROUP_USERS_INFO_0 *i0 = NULL;
1469 struct GROUP_USERS_INFO_1 *i1 = NULL;
1471 int i, k;
1473 NTSTATUS status = NT_STATUS_OK;
1474 WERROR werr;
1476 ZERO_STRUCT(connect_handle);
1477 ZERO_STRUCT(domain_handle);
1479 if (!r->in.buffer) {
1480 return WERR_INVALID_PARAM;
1483 switch (r->in.level) {
1484 case 0:
1485 case 1:
1486 break;
1487 default:
1488 return WERR_UNKNOWN_LEVEL;
1491 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1492 &ndr_table_samr.syntax_id,
1493 &cli,
1494 &pipe_cli);
1495 if (!W_ERROR_IS_OK(werr)) {
1496 goto done;
1499 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1500 SAMR_ACCESS_ENUM_DOMAINS |
1501 SAMR_ACCESS_LOOKUP_DOMAIN,
1502 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1503 &connect_handle,
1504 &domain_handle,
1505 &domain_sid);
1506 if (!W_ERROR_IS_OK(werr)) {
1507 goto done;
1510 init_lsa_String(&lsa_account_name, r->in.group_name);
1512 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1513 &domain_handle,
1515 &lsa_account_name,
1516 &group_rids,
1517 &group_types);
1518 if (!NT_STATUS_IS_OK(status)) {
1519 werr = ntstatus_to_werror(status);
1520 goto done;
1523 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1524 &domain_handle,
1525 SAMR_GROUP_ACCESS_GET_MEMBERS |
1526 SAMR_GROUP_ACCESS_ADD_MEMBER |
1527 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1528 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1529 group_rids.ids[0],
1530 &group_handle);
1531 if (!NT_STATUS_IS_OK(status)) {
1532 werr = ntstatus_to_werror(status);
1533 goto done;
1536 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
1537 &group_handle,
1538 GROUPINFOATTRIBUTES,
1539 &group_info);
1540 if (!NT_STATUS_IS_OK(status)) {
1541 werr = ntstatus_to_werror(status);
1542 goto done;
1545 switch (r->in.level) {
1546 case 0:
1547 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1548 break;
1549 case 1:
1550 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1551 break;
1554 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1555 if (!lsa_names) {
1556 werr = WERR_NOMEM;
1557 goto done;
1560 for (i=0; i < r->in.num_entries; i++) {
1562 switch (r->in.level) {
1563 case 0:
1564 init_lsa_String(&lsa_names[i], i0->grui0_name);
1565 i0++;
1566 break;
1567 case 1:
1568 init_lsa_String(&lsa_names[i], i1->grui1_name);
1569 i1++;
1570 break;
1574 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1575 &domain_handle,
1576 r->in.num_entries,
1577 lsa_names,
1578 &user_rids,
1579 &name_types);
1580 if (!NT_STATUS_IS_OK(status)) {
1581 werr = ntstatus_to_werror(status);
1582 goto done;
1585 member_rids = user_rids.ids;
1586 num_member_rids = user_rids.count;
1588 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1589 &group_handle,
1590 &rid_array);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 werr = ntstatus_to_werror(status);
1593 goto done;
1596 /* add list */
1598 for (i=0; i < r->in.num_entries; i++) {
1599 bool already_member = false;
1600 for (k=0; k < rid_array->count; k++) {
1601 if (member_rids[i] == rid_array->rids[k]) {
1602 already_member = true;
1603 break;
1606 if (!already_member) {
1607 if (!add_rid_to_array_unique(ctx,
1608 member_rids[i],
1609 &add_rids, &num_add_rids)) {
1610 werr = WERR_GENERAL_FAILURE;
1611 goto done;
1616 /* del list */
1618 for (k=0; k < rid_array->count; k++) {
1619 bool keep_member = false;
1620 for (i=0; i < r->in.num_entries; i++) {
1621 if (member_rids[i] == rid_array->rids[k]) {
1622 keep_member = true;
1623 break;
1626 if (!keep_member) {
1627 if (!add_rid_to_array_unique(ctx,
1628 rid_array->rids[k],
1629 &del_rids, &num_del_rids)) {
1630 werr = WERR_GENERAL_FAILURE;
1631 goto done;
1636 /* add list */
1638 for (i=0; i < num_add_rids; i++) {
1639 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
1640 &group_handle,
1641 add_rids[i],
1642 7 /* ? */);
1643 if (!NT_STATUS_IS_OK(status)) {
1644 werr = ntstatus_to_werror(status);
1645 goto done;
1649 /* del list */
1651 for (i=0; i < num_del_rids; i++) {
1652 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
1653 &group_handle,
1654 del_rids[i]);
1655 if (!NT_STATUS_IS_OK(status)) {
1656 werr = ntstatus_to_werror(status);
1657 goto done;
1661 werr = WERR_OK;
1663 done:
1664 if (!cli) {
1665 return werr;
1668 if (is_valid_policy_hnd(&group_handle)) {
1669 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1672 if (ctx->disable_policy_handle_cache) {
1673 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1674 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1677 return werr;
1680 /****************************************************************
1681 ****************************************************************/
1683 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1684 struct NetGroupSetUsers *r)
1686 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);