s3/docs: Fix typo.
[Samba/gebeck_regimport.git] / source3 / lib / netapi / group.c
blob004fd3aff6f08feddf25208a33d472e4bed808f1
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 rpc_pipe_client *pipe_cli = NULL;
34 NTSTATUS status;
35 WERROR werr;
36 struct policy_handle connect_handle, domain_handle, group_handle;
37 struct lsa_String lsa_group_name;
38 struct dom_sid2 *domain_sid = NULL;
39 uint32_t rid = 0;
41 struct GROUP_INFO_0 *info0 = NULL;
42 struct GROUP_INFO_1 *info1 = NULL;
43 struct GROUP_INFO_2 *info2 = NULL;
44 struct GROUP_INFO_3 *info3 = NULL;
45 union samr_GroupInfo info;
47 ZERO_STRUCT(connect_handle);
48 ZERO_STRUCT(domain_handle);
49 ZERO_STRUCT(group_handle);
51 if (!r->in.buffer) {
52 return WERR_INVALID_PARAM;
55 switch (r->in.level) {
56 case 0:
57 info0 = (struct GROUP_INFO_0 *)r->in.buffer;
58 break;
59 case 1:
60 info1 = (struct GROUP_INFO_1 *)r->in.buffer;
61 break;
62 case 2:
63 info2 = (struct GROUP_INFO_2 *)r->in.buffer;
64 break;
65 case 3:
66 info3 = (struct GROUP_INFO_3 *)r->in.buffer;
67 break;
68 default:
69 werr = WERR_UNKNOWN_LEVEL;
70 goto done;
73 werr = libnetapi_open_pipe(ctx, r->in.server_name,
74 &ndr_table_samr.syntax_id,
75 &pipe_cli);
76 if (!W_ERROR_IS_OK(werr)) {
77 goto done;
80 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
81 SAMR_ACCESS_ENUM_DOMAINS |
82 SAMR_ACCESS_LOOKUP_DOMAIN,
83 SAMR_DOMAIN_ACCESS_CREATE_GROUP |
84 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
85 &connect_handle,
86 &domain_handle,
87 &domain_sid);
88 if (!W_ERROR_IS_OK(werr)) {
89 goto done;
92 switch (r->in.level) {
93 case 0:
94 init_lsa_String(&lsa_group_name, info0->grpi0_name);
95 break;
96 case 1:
97 init_lsa_String(&lsa_group_name, info1->grpi1_name);
98 break;
99 case 2:
100 init_lsa_String(&lsa_group_name, info2->grpi2_name);
101 break;
102 case 3:
103 init_lsa_String(&lsa_group_name, info3->grpi3_name);
104 break;
107 status = rpccli_samr_CreateDomainGroup(pipe_cli, ctx,
108 &domain_handle,
109 &lsa_group_name,
110 SEC_STD_DELETE |
111 SAMR_GROUP_ACCESS_SET_INFO,
112 &group_handle,
113 &rid);
115 if (!NT_STATUS_IS_OK(status)) {
116 werr = ntstatus_to_werror(status);
117 goto done;
120 switch (r->in.level) {
121 case 1:
122 if (info1->grpi1_comment) {
123 init_lsa_String(&info.description,
124 info1->grpi1_comment);
126 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
127 &group_handle,
128 GROUPINFODESCRIPTION,
129 &info);
131 break;
132 case 2:
133 if (info2->grpi2_comment) {
134 init_lsa_String(&info.description,
135 info2->grpi2_comment);
137 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
138 &group_handle,
139 GROUPINFODESCRIPTION,
140 &info);
141 if (!NT_STATUS_IS_OK(status)) {
142 werr = ntstatus_to_werror(status);
143 goto failed;
147 if (info2->grpi2_attributes != 0) {
148 info.attributes.attributes = info2->grpi2_attributes;
149 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
150 &group_handle,
151 GROUPINFOATTRIBUTES,
152 &info);
155 break;
156 case 3:
157 if (info3->grpi3_comment) {
158 init_lsa_String(&info.description,
159 info3->grpi3_comment);
161 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
162 &group_handle,
163 GROUPINFODESCRIPTION,
164 &info);
165 if (!NT_STATUS_IS_OK(status)) {
166 werr = ntstatus_to_werror(status);
167 goto failed;
171 if (info3->grpi3_attributes != 0) {
172 info.attributes.attributes = info3->grpi3_attributes;
173 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
174 &group_handle,
175 GROUPINFOATTRIBUTES,
176 &info);
178 break;
179 default:
180 break;
183 if (!NT_STATUS_IS_OK(status)) {
184 werr = ntstatus_to_werror(status);
185 goto failed;
188 werr = WERR_OK;
189 goto done;
191 failed:
192 rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
193 &group_handle);
195 done:
196 if (is_valid_policy_hnd(&group_handle)) {
197 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
200 if (ctx->disable_policy_handle_cache) {
201 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
202 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
205 return werr;
208 /****************************************************************
209 ****************************************************************/
211 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
212 struct NetGroupAdd *r)
214 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
217 /****************************************************************
218 ****************************************************************/
220 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
221 struct NetGroupDel *r)
223 struct rpc_pipe_client *pipe_cli = NULL;
224 NTSTATUS status;
225 WERROR werr;
226 struct policy_handle connect_handle, domain_handle, group_handle;
227 struct lsa_String lsa_group_name;
228 struct dom_sid2 *domain_sid = NULL;
229 int i = 0;
231 struct samr_Ids rids;
232 struct samr_Ids types;
233 union samr_GroupInfo *info = NULL;
234 struct samr_RidTypeArray *rid_array = NULL;
236 ZERO_STRUCT(connect_handle);
237 ZERO_STRUCT(domain_handle);
238 ZERO_STRUCT(group_handle);
240 if (!r->in.group_name) {
241 return WERR_INVALID_PARAM;
244 werr = libnetapi_open_pipe(ctx, r->in.server_name,
245 &ndr_table_samr.syntax_id,
246 &pipe_cli);
247 if (!W_ERROR_IS_OK(werr)) {
248 goto done;
251 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
252 SAMR_ACCESS_ENUM_DOMAINS |
253 SAMR_ACCESS_LOOKUP_DOMAIN,
254 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
255 &connect_handle,
256 &domain_handle,
257 &domain_sid);
258 if (!W_ERROR_IS_OK(werr)) {
259 goto done;
262 init_lsa_String(&lsa_group_name, r->in.group_name);
264 status = rpccli_samr_LookupNames(pipe_cli, ctx,
265 &domain_handle,
267 &lsa_group_name,
268 &rids,
269 &types);
270 if (!NT_STATUS_IS_OK(status)) {
271 werr = ntstatus_to_werror(status);
272 goto done;
275 if (types.ids[0] != SID_NAME_DOM_GRP) {
276 werr = WERR_INVALID_DATATYPE;
277 goto done;
280 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
281 &domain_handle,
282 SEC_STD_DELETE |
283 SAMR_GROUP_ACCESS_GET_MEMBERS |
284 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
285 SAMR_GROUP_ACCESS_ADD_MEMBER |
286 SAMR_GROUP_ACCESS_LOOKUP_INFO,
287 rids.ids[0],
288 &group_handle);
289 if (!NT_STATUS_IS_OK(status)) {
290 werr = ntstatus_to_werror(status);
291 goto done;
294 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
295 &group_handle,
296 GROUPINFOATTRIBUTES,
297 &info);
298 if (!NT_STATUS_IS_OK(status)) {
299 werr = ntstatus_to_werror(status);
300 goto done;
303 #if 0
304 /* breaks against NT4 */
305 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
306 werr = WERR_ACCESS_DENIED;
307 goto done;
309 #endif
310 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
311 &group_handle,
312 &rid_array);
313 if (!NT_STATUS_IS_OK(status)) {
314 werr = ntstatus_to_werror(status);
315 goto done;
319 struct lsa_Strings names;
320 struct samr_Ids member_types;
322 status = rpccli_samr_LookupRids(pipe_cli, ctx,
323 &domain_handle,
324 rid_array->count,
325 rid_array->rids,
326 &names,
327 &member_types);
328 if (!NT_STATUS_IS_OK(status)) {
329 werr = ntstatus_to_werror(status);
330 goto done;
334 for (i=0; i < rid_array->count; i++) {
336 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
337 &group_handle,
338 rid_array->rids[i]);
339 if (!NT_STATUS_IS_OK(status)) {
340 werr = ntstatus_to_werror(status);
341 goto done;
345 status = rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
346 &group_handle);
347 if (!NT_STATUS_IS_OK(status)) {
348 werr = ntstatus_to_werror(status);
349 goto done;
352 ZERO_STRUCT(group_handle);
354 werr = WERR_OK;
356 done:
357 if (is_valid_policy_hnd(&group_handle)) {
358 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
361 if (ctx->disable_policy_handle_cache) {
362 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
363 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
366 return werr;
369 /****************************************************************
370 ****************************************************************/
372 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
373 struct NetGroupDel *r)
375 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
378 /****************************************************************
379 ****************************************************************/
381 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
382 struct NetGroupSetInfo *r)
384 struct rpc_pipe_client *pipe_cli = NULL;
385 NTSTATUS status;
386 WERROR werr;
387 struct policy_handle connect_handle, domain_handle, group_handle;
388 struct lsa_String lsa_group_name;
389 struct dom_sid2 *domain_sid = NULL;
391 struct samr_Ids rids;
392 struct samr_Ids types;
393 union samr_GroupInfo info;
394 struct GROUP_INFO_0 *g0;
395 struct GROUP_INFO_1 *g1;
396 struct GROUP_INFO_2 *g2;
397 struct GROUP_INFO_3 *g3;
398 struct GROUP_INFO_1002 *g1002;
399 struct GROUP_INFO_1005 *g1005;
401 ZERO_STRUCT(connect_handle);
402 ZERO_STRUCT(domain_handle);
403 ZERO_STRUCT(group_handle);
405 if (!r->in.group_name) {
406 return WERR_INVALID_PARAM;
409 werr = libnetapi_open_pipe(ctx, r->in.server_name,
410 &ndr_table_samr.syntax_id,
411 &pipe_cli);
412 if (!W_ERROR_IS_OK(werr)) {
413 goto done;
416 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
417 SAMR_ACCESS_ENUM_DOMAINS |
418 SAMR_ACCESS_LOOKUP_DOMAIN,
419 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
420 &connect_handle,
421 &domain_handle,
422 &domain_sid);
423 if (!W_ERROR_IS_OK(werr)) {
424 goto done;
427 init_lsa_String(&lsa_group_name, r->in.group_name);
429 status = rpccli_samr_LookupNames(pipe_cli, ctx,
430 &domain_handle,
432 &lsa_group_name,
433 &rids,
434 &types);
435 if (!NT_STATUS_IS_OK(status)) {
436 werr = ntstatus_to_werror(status);
437 goto done;
440 if (types.ids[0] != SID_NAME_DOM_GRP) {
441 werr = WERR_INVALID_DATATYPE;
442 goto done;
445 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
446 &domain_handle,
447 SAMR_GROUP_ACCESS_SET_INFO |
448 SAMR_GROUP_ACCESS_LOOKUP_INFO,
449 rids.ids[0],
450 &group_handle);
451 if (!NT_STATUS_IS_OK(status)) {
452 werr = ntstatus_to_werror(status);
453 goto done;
456 switch (r->in.level) {
457 case 0:
458 g0 = (struct GROUP_INFO_0 *)r->in.buffer;
459 init_lsa_String(&info.name, g0->grpi0_name);
460 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
461 &group_handle,
462 GROUPINFONAME,
463 &info);
464 break;
465 case 1:
466 g1 = (struct GROUP_INFO_1 *)r->in.buffer;
467 init_lsa_String(&info.description, g1->grpi1_comment);
468 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
469 &group_handle,
470 GROUPINFODESCRIPTION,
471 &info);
472 break;
473 case 2:
474 g2 = (struct GROUP_INFO_2 *)r->in.buffer;
475 init_lsa_String(&info.description, g2->grpi2_comment);
476 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
477 &group_handle,
478 GROUPINFODESCRIPTION,
479 &info);
480 if (!NT_STATUS_IS_OK(status)) {
481 werr = ntstatus_to_werror(status);
482 goto done;
484 info.attributes.attributes = g2->grpi2_attributes;
485 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
486 &group_handle,
487 GROUPINFOATTRIBUTES,
488 &info);
489 break;
490 case 3:
491 g3 = (struct GROUP_INFO_3 *)r->in.buffer;
492 init_lsa_String(&info.description, g3->grpi3_comment);
493 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
494 &group_handle,
495 GROUPINFODESCRIPTION,
496 &info);
497 if (!NT_STATUS_IS_OK(status)) {
498 werr = ntstatus_to_werror(status);
499 goto done;
501 info.attributes.attributes = g3->grpi3_attributes;
502 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
503 &group_handle,
504 GROUPINFOATTRIBUTES,
505 &info);
506 break;
507 case 1002:
508 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
509 init_lsa_String(&info.description, g1002->grpi1002_comment);
510 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
511 &group_handle,
512 GROUPINFODESCRIPTION,
513 &info);
514 break;
515 case 1005:
516 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
517 info.attributes.attributes = g1005->grpi1005_attributes;
518 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
519 &group_handle,
520 GROUPINFOATTRIBUTES,
521 &info);
522 break;
523 default:
524 status = NT_STATUS_INVALID_LEVEL;
525 break;
528 if (!NT_STATUS_IS_OK(status)) {
529 werr = ntstatus_to_werror(status);
530 goto done;
533 werr = WERR_OK;
535 done:
536 if (is_valid_policy_hnd(&group_handle)) {
537 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
540 if (ctx->disable_policy_handle_cache) {
541 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
542 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
545 return werr;
548 /****************************************************************
549 ****************************************************************/
551 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
552 struct NetGroupSetInfo *r)
554 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
557 /****************************************************************
558 ****************************************************************/
560 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
561 uint32_t level,
562 struct samr_GroupInfoAll *info,
563 struct dom_sid2 *domain_sid,
564 uint32_t rid,
565 uint8_t **buffer)
567 struct GROUP_INFO_0 info0;
568 struct GROUP_INFO_1 info1;
569 struct GROUP_INFO_2 info2;
570 struct GROUP_INFO_3 info3;
571 struct dom_sid sid;
573 switch (level) {
574 case 0:
575 info0.grpi0_name = info->name.string;
577 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
579 break;
580 case 1:
581 info1.grpi1_name = info->name.string;
582 info1.grpi1_comment = info->description.string;
584 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
586 break;
587 case 2:
588 info2.grpi2_name = info->name.string;
589 info2.grpi2_comment = info->description.string;
590 info2.grpi2_group_id = rid;
591 info2.grpi2_attributes = info->attributes;
593 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
595 break;
596 case 3:
597 if (!sid_compose(&sid, domain_sid, rid)) {
598 return WERR_NOMEM;
601 info3.grpi3_name = info->name.string;
602 info3.grpi3_comment = info->description.string;
603 info3.grpi3_attributes = info->attributes;
604 info3.grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
606 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
608 break;
609 default:
610 return WERR_UNKNOWN_LEVEL;
613 W_ERROR_HAVE_NO_MEMORY(*buffer);
615 return WERR_OK;
618 /****************************************************************
619 ****************************************************************/
621 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
622 struct NetGroupGetInfo *r)
624 struct rpc_pipe_client *pipe_cli = NULL;
625 NTSTATUS status;
626 WERROR werr;
627 struct policy_handle connect_handle, domain_handle, group_handle;
628 struct lsa_String lsa_group_name;
629 struct dom_sid2 *domain_sid = NULL;
631 struct samr_Ids rids;
632 struct samr_Ids types;
633 union samr_GroupInfo *info = NULL;
634 bool group_info_all = false;
636 ZERO_STRUCT(connect_handle);
637 ZERO_STRUCT(domain_handle);
638 ZERO_STRUCT(group_handle);
640 if (!r->in.group_name) {
641 return WERR_INVALID_PARAM;
644 werr = libnetapi_open_pipe(ctx, r->in.server_name,
645 &ndr_table_samr.syntax_id,
646 &pipe_cli);
647 if (!W_ERROR_IS_OK(werr)) {
648 goto done;
651 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
652 SAMR_ACCESS_ENUM_DOMAINS |
653 SAMR_ACCESS_LOOKUP_DOMAIN,
654 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
655 &connect_handle,
656 &domain_handle,
657 &domain_sid);
658 if (!W_ERROR_IS_OK(werr)) {
659 goto done;
662 init_lsa_String(&lsa_group_name, r->in.group_name);
664 status = rpccli_samr_LookupNames(pipe_cli, ctx,
665 &domain_handle,
667 &lsa_group_name,
668 &rids,
669 &types);
670 if (!NT_STATUS_IS_OK(status)) {
671 werr = ntstatus_to_werror(status);
672 goto done;
675 if (types.ids[0] != SID_NAME_DOM_GRP) {
676 werr = WERR_INVALID_DATATYPE;
677 goto done;
680 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
681 &domain_handle,
682 SAMR_GROUP_ACCESS_LOOKUP_INFO,
683 rids.ids[0],
684 &group_handle);
685 if (!NT_STATUS_IS_OK(status)) {
686 werr = ntstatus_to_werror(status);
687 goto done;
690 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
691 &group_handle,
692 GROUPINFOALL2,
693 &info);
694 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
695 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
696 &group_handle,
697 GROUPINFOALL,
698 &info);
699 group_info_all = true;
702 if (!NT_STATUS_IS_OK(status)) {
703 werr = ntstatus_to_werror(status);
704 goto done;
707 werr = map_group_info_to_buffer(ctx, r->in.level,
708 group_info_all ? &info->all : &info->all2,
709 domain_sid, rids.ids[0],
710 r->out.buffer);
711 if (!W_ERROR_IS_OK(werr)) {
712 goto done;
714 done:
715 if (is_valid_policy_hnd(&group_handle)) {
716 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
719 if (ctx->disable_policy_handle_cache) {
720 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
721 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
724 return werr;
727 /****************************************************************
728 ****************************************************************/
730 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
731 struct NetGroupGetInfo *r)
733 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
736 /****************************************************************
737 ****************************************************************/
739 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
740 struct NetGroupAddUser *r)
742 struct rpc_pipe_client *pipe_cli = NULL;
743 NTSTATUS status;
744 WERROR werr;
745 struct policy_handle connect_handle, domain_handle, group_handle;
746 struct lsa_String lsa_group_name, lsa_user_name;
747 struct dom_sid2 *domain_sid = NULL;
749 struct samr_Ids rids;
750 struct samr_Ids types;
752 ZERO_STRUCT(connect_handle);
753 ZERO_STRUCT(domain_handle);
754 ZERO_STRUCT(group_handle);
756 if (!r->in.group_name) {
757 return WERR_INVALID_PARAM;
760 werr = libnetapi_open_pipe(ctx, r->in.server_name,
761 &ndr_table_samr.syntax_id,
762 &pipe_cli);
763 if (!W_ERROR_IS_OK(werr)) {
764 goto done;
767 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
768 SAMR_ACCESS_ENUM_DOMAINS |
769 SAMR_ACCESS_LOOKUP_DOMAIN,
770 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
771 &connect_handle,
772 &domain_handle,
773 &domain_sid);
774 if (!W_ERROR_IS_OK(werr)) {
775 goto done;
778 init_lsa_String(&lsa_group_name, r->in.group_name);
780 status = rpccli_samr_LookupNames(pipe_cli, ctx,
781 &domain_handle,
783 &lsa_group_name,
784 &rids,
785 &types);
786 if (!NT_STATUS_IS_OK(status)) {
787 werr = WERR_GROUP_NOT_FOUND;
788 goto done;
791 if (types.ids[0] != SID_NAME_DOM_GRP) {
792 werr = WERR_GROUP_NOT_FOUND;
793 goto done;
796 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
797 &domain_handle,
798 SAMR_GROUP_ACCESS_ADD_MEMBER,
799 rids.ids[0],
800 &group_handle);
801 if (!NT_STATUS_IS_OK(status)) {
802 werr = ntstatus_to_werror(status);
803 goto done;
806 init_lsa_String(&lsa_user_name, r->in.user_name);
808 status = rpccli_samr_LookupNames(pipe_cli, ctx,
809 &domain_handle,
811 &lsa_user_name,
812 &rids,
813 &types);
814 if (!NT_STATUS_IS_OK(status)) {
815 werr = WERR_USER_NOT_FOUND;
816 goto done;
819 if (types.ids[0] != SID_NAME_USER) {
820 werr = WERR_USER_NOT_FOUND;
821 goto done;
824 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
825 &group_handle,
826 rids.ids[0],
827 7); /* why ? */
828 if (!NT_STATUS_IS_OK(status)) {
829 werr = ntstatus_to_werror(status);
830 goto done;
833 werr = WERR_OK;
835 done:
836 if (is_valid_policy_hnd(&group_handle)) {
837 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
840 if (ctx->disable_policy_handle_cache) {
841 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
842 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
845 return werr;
848 /****************************************************************
849 ****************************************************************/
851 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
852 struct NetGroupAddUser *r)
854 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
857 /****************************************************************
858 ****************************************************************/
860 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
861 struct NetGroupDelUser *r)
863 struct rpc_pipe_client *pipe_cli = NULL;
864 NTSTATUS status;
865 WERROR werr;
866 struct policy_handle connect_handle, domain_handle, group_handle;
867 struct lsa_String lsa_group_name, lsa_user_name;
868 struct dom_sid2 *domain_sid = NULL;
870 struct samr_Ids rids;
871 struct samr_Ids types;
873 ZERO_STRUCT(connect_handle);
874 ZERO_STRUCT(domain_handle);
875 ZERO_STRUCT(group_handle);
877 if (!r->in.group_name) {
878 return WERR_INVALID_PARAM;
881 werr = libnetapi_open_pipe(ctx, r->in.server_name,
882 &ndr_table_samr.syntax_id,
883 &pipe_cli);
884 if (!W_ERROR_IS_OK(werr)) {
885 goto done;
888 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
889 SAMR_ACCESS_ENUM_DOMAINS |
890 SAMR_ACCESS_LOOKUP_DOMAIN,
891 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
892 &connect_handle,
893 &domain_handle,
894 &domain_sid);
895 if (!W_ERROR_IS_OK(werr)) {
896 goto done;
899 init_lsa_String(&lsa_group_name, r->in.group_name);
901 status = rpccli_samr_LookupNames(pipe_cli, ctx,
902 &domain_handle,
904 &lsa_group_name,
905 &rids,
906 &types);
907 if (!NT_STATUS_IS_OK(status)) {
908 werr = WERR_GROUP_NOT_FOUND;
909 goto done;
912 if (types.ids[0] != SID_NAME_DOM_GRP) {
913 werr = WERR_GROUP_NOT_FOUND;
914 goto done;
917 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
918 &domain_handle,
919 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
920 rids.ids[0],
921 &group_handle);
922 if (!NT_STATUS_IS_OK(status)) {
923 werr = ntstatus_to_werror(status);
924 goto done;
927 init_lsa_String(&lsa_user_name, r->in.user_name);
929 status = rpccli_samr_LookupNames(pipe_cli, ctx,
930 &domain_handle,
932 &lsa_user_name,
933 &rids,
934 &types);
935 if (!NT_STATUS_IS_OK(status)) {
936 werr = WERR_USER_NOT_FOUND;
937 goto done;
940 if (types.ids[0] != SID_NAME_USER) {
941 werr = WERR_USER_NOT_FOUND;
942 goto done;
945 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
946 &group_handle,
947 rids.ids[0]);
948 if (!NT_STATUS_IS_OK(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 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
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 NetGroupDelUser_l(struct libnetapi_ctx *ctx,
972 struct NetGroupDelUser *r)
974 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
977 /****************************************************************
978 ****************************************************************/
980 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
981 struct samr_DispInfoFullGroups *groups,
982 uint8_t **buffer)
984 struct GROUP_INFO_0 *g0;
985 int i;
987 g0 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_0, groups->count);
988 W_ERROR_HAVE_NO_MEMORY(g0);
990 for (i=0; i<groups->count; i++) {
991 g0[i].grpi0_name = talloc_strdup(mem_ctx,
992 groups->entries[i].account_name.string);
993 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
996 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
997 sizeof(struct GROUP_INFO_0) * groups->count);
998 W_ERROR_HAVE_NO_MEMORY(*buffer);
1000 return WERR_OK;
1003 /****************************************************************
1004 ****************************************************************/
1006 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1007 struct samr_DispInfoFullGroups *groups,
1008 uint8_t **buffer)
1010 struct GROUP_INFO_1 *g1;
1011 int i;
1013 g1 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_1, groups->count);
1014 W_ERROR_HAVE_NO_MEMORY(g1);
1016 for (i=0; i<groups->count; i++) {
1017 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1018 groups->entries[i].account_name.string);
1019 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1020 groups->entries[i].description.string);
1021 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1024 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1025 sizeof(struct GROUP_INFO_1) * groups->count);
1026 W_ERROR_HAVE_NO_MEMORY(*buffer);
1028 return WERR_OK;
1031 /****************************************************************
1032 ****************************************************************/
1034 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1035 struct samr_DispInfoFullGroups *groups,
1036 uint8_t **buffer)
1038 struct GROUP_INFO_2 *g2;
1039 int i;
1041 g2 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_2, groups->count);
1042 W_ERROR_HAVE_NO_MEMORY(g2);
1044 for (i=0; i<groups->count; i++) {
1045 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1046 groups->entries[i].account_name.string);
1047 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1048 groups->entries[i].description.string);
1049 g2[i].grpi2_group_id = groups->entries[i].rid;
1050 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1051 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1054 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1055 sizeof(struct GROUP_INFO_2) * groups->count);
1056 W_ERROR_HAVE_NO_MEMORY(*buffer);
1058 return WERR_OK;
1061 /****************************************************************
1062 ****************************************************************/
1064 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1065 struct samr_DispInfoFullGroups *groups,
1066 const struct dom_sid *domain_sid,
1067 uint8_t **buffer)
1069 struct GROUP_INFO_3 *g3;
1070 int i;
1072 g3 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_3, groups->count);
1073 W_ERROR_HAVE_NO_MEMORY(g3);
1075 for (i=0; i<groups->count; i++) {
1077 struct dom_sid sid;
1079 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1080 return WERR_NOMEM;
1083 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1084 groups->entries[i].account_name.string);
1085 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1086 groups->entries[i].description.string);
1087 g3[i].grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
1088 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1089 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1092 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1093 sizeof(struct GROUP_INFO_3) * groups->count);
1094 W_ERROR_HAVE_NO_MEMORY(*buffer);
1096 return WERR_OK;
1099 /****************************************************************
1100 ****************************************************************/
1102 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1103 uint32_t level,
1104 struct samr_DispInfoFullGroups *groups,
1105 const struct dom_sid *domain_sid,
1106 uint32_t *entries_read,
1107 uint8_t **buffer)
1109 if (entries_read) {
1110 *entries_read = groups->count;
1113 switch (level) {
1114 case 0:
1115 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1116 case 1:
1117 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1118 case 2:
1119 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1120 case 3:
1121 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1122 default:
1123 return WERR_UNKNOWN_LEVEL;
1127 /****************************************************************
1128 ****************************************************************/
1130 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1131 struct NetGroupEnum *r)
1133 struct rpc_pipe_client *pipe_cli = NULL;
1134 struct policy_handle connect_handle;
1135 struct dom_sid2 *domain_sid = NULL;
1136 struct policy_handle domain_handle;
1137 union samr_DispInfo info;
1138 union samr_DomainInfo *domain_info = NULL;
1140 uint32_t total_size = 0;
1141 uint32_t returned_size = 0;
1143 NTSTATUS status = NT_STATUS_OK;
1144 WERROR werr, tmp_werr;
1146 ZERO_STRUCT(connect_handle);
1147 ZERO_STRUCT(domain_handle);
1149 switch (r->in.level) {
1150 case 0:
1151 case 1:
1152 case 2:
1153 case 3:
1154 break;
1155 default:
1156 return WERR_UNKNOWN_LEVEL;
1159 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1160 &ndr_table_samr.syntax_id,
1161 &pipe_cli);
1162 if (!W_ERROR_IS_OK(werr)) {
1163 goto done;
1166 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1167 SAMR_ACCESS_ENUM_DOMAINS |
1168 SAMR_ACCESS_LOOKUP_DOMAIN,
1169 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1170 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1171 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1172 &connect_handle,
1173 &domain_handle,
1174 &domain_sid);
1175 if (!W_ERROR_IS_OK(werr)) {
1176 goto done;
1179 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
1180 &domain_handle,
1182 &domain_info);
1183 if (!NT_STATUS_IS_OK(status)) {
1184 werr = ntstatus_to_werror(status);
1185 goto done;
1188 if (r->out.total_entries) {
1189 *r->out.total_entries = domain_info->general.num_groups;
1192 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1193 ctx,
1194 &domain_handle,
1196 r->in.resume_handle ?
1197 *r->in.resume_handle : 0,
1198 (uint32_t)-1,
1199 r->in.prefmaxlen,
1200 &total_size,
1201 &returned_size,
1202 &info);
1203 werr = ntstatus_to_werror(status);
1204 if (NT_STATUS_IS_ERR(status)) {
1205 goto done;
1208 if (r->out.resume_handle && info.info3.count > 0) {
1209 *r->out.resume_handle =
1210 info.info3.entries[info.info3.count-1].idx;
1213 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1214 r->in.level,
1215 &info.info3,
1216 domain_sid,
1217 r->out.entries_read,
1218 r->out.buffer);
1219 if (!W_ERROR_IS_OK(tmp_werr)) {
1220 werr = tmp_werr;
1221 goto done;
1224 done:
1225 /* if last query */
1226 if (NT_STATUS_IS_OK(status) ||
1227 NT_STATUS_IS_ERR(status)) {
1229 if (ctx->disable_policy_handle_cache) {
1230 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1231 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1235 return werr;
1238 /****************************************************************
1239 ****************************************************************/
1241 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1242 struct NetGroupEnum *r)
1244 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1247 /****************************************************************
1248 ****************************************************************/
1250 WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1251 struct NetGroupGetUsers *r)
1253 /* FIXME: this call needs to cope with large replies */
1255 struct rpc_pipe_client *pipe_cli = NULL;
1256 struct policy_handle connect_handle, domain_handle, group_handle;
1257 struct lsa_String lsa_account_name;
1258 struct dom_sid2 *domain_sid = NULL;
1259 struct samr_Ids group_rids, name_types;
1260 struct samr_RidTypeArray *rid_array = NULL;
1261 struct lsa_Strings names;
1262 struct samr_Ids member_types;
1264 int i;
1265 uint32_t entries_read = 0;
1267 NTSTATUS status = NT_STATUS_OK;
1268 WERROR werr;
1270 ZERO_STRUCT(connect_handle);
1271 ZERO_STRUCT(domain_handle);
1273 if (!r->out.buffer) {
1274 return WERR_INVALID_PARAM;
1277 *r->out.buffer = NULL;
1278 *r->out.entries_read = 0;
1279 *r->out.total_entries = 0;
1281 switch (r->in.level) {
1282 case 0:
1283 case 1:
1284 break;
1285 default:
1286 return WERR_UNKNOWN_LEVEL;
1290 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1291 &ndr_table_samr.syntax_id,
1292 &pipe_cli);
1293 if (!W_ERROR_IS_OK(werr)) {
1294 goto done;
1297 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1298 SAMR_ACCESS_ENUM_DOMAINS |
1299 SAMR_ACCESS_LOOKUP_DOMAIN,
1300 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1301 &connect_handle,
1302 &domain_handle,
1303 &domain_sid);
1304 if (!W_ERROR_IS_OK(werr)) {
1305 goto done;
1308 init_lsa_String(&lsa_account_name, r->in.group_name);
1310 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1311 &domain_handle,
1313 &lsa_account_name,
1314 &group_rids,
1315 &name_types);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 werr = ntstatus_to_werror(status);
1318 goto done;
1321 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1322 &domain_handle,
1323 SAMR_GROUP_ACCESS_GET_MEMBERS,
1324 group_rids.ids[0],
1325 &group_handle);
1326 if (!NT_STATUS_IS_OK(status)) {
1327 werr = ntstatus_to_werror(status);
1328 goto done;
1331 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1332 &group_handle,
1333 &rid_array);
1334 if (!NT_STATUS_IS_OK(status)) {
1335 werr = ntstatus_to_werror(status);
1336 goto done;
1339 status = rpccli_samr_LookupRids(pipe_cli, ctx,
1340 &domain_handle,
1341 rid_array->count,
1342 rid_array->rids,
1343 &names,
1344 &member_types);
1345 if (!NT_STATUS_IS_OK(status)) {
1346 werr = ntstatus_to_werror(status);
1347 goto done;
1350 for (i=0; i < names.count; i++) {
1352 if (member_types.ids[i] != SID_NAME_USER) {
1353 continue;
1356 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1357 r->in.level,
1358 names.names[i].string,
1360 r->out.buffer,
1361 &entries_read);
1362 if (!NT_STATUS_IS_OK(status)) {
1363 werr = ntstatus_to_werror(status);
1364 goto done;
1368 *r->out.entries_read = entries_read;
1369 *r->out.total_entries = entries_read;
1371 werr = WERR_OK;
1373 done:
1374 if (is_valid_policy_hnd(&group_handle)) {
1375 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1378 if (ctx->disable_policy_handle_cache) {
1379 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1380 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1383 return werr;
1386 /****************************************************************
1387 ****************************************************************/
1389 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1390 struct NetGroupGetUsers *r)
1392 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1395 /****************************************************************
1396 ****************************************************************/
1398 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1399 struct NetGroupSetUsers *r)
1401 struct rpc_pipe_client *pipe_cli = NULL;
1402 struct policy_handle connect_handle, domain_handle, group_handle;
1403 struct lsa_String lsa_account_name;
1404 struct dom_sid2 *domain_sid = NULL;
1405 union samr_GroupInfo *group_info = NULL;
1406 struct samr_Ids user_rids, name_types;
1407 struct samr_Ids group_rids, group_types;
1408 struct samr_RidTypeArray *rid_array = NULL;
1409 struct lsa_String *lsa_names = NULL;
1411 uint32_t *add_rids = NULL;
1412 uint32_t *del_rids = NULL;
1413 size_t num_add_rids = 0;
1414 size_t num_del_rids = 0;
1416 uint32_t *member_rids = NULL;
1417 size_t num_member_rids = 0;
1419 struct GROUP_USERS_INFO_0 *i0 = NULL;
1420 struct GROUP_USERS_INFO_1 *i1 = NULL;
1422 int i, k;
1424 NTSTATUS status = NT_STATUS_OK;
1425 WERROR werr;
1427 ZERO_STRUCT(connect_handle);
1428 ZERO_STRUCT(domain_handle);
1430 if (!r->in.buffer) {
1431 return WERR_INVALID_PARAM;
1434 switch (r->in.level) {
1435 case 0:
1436 case 1:
1437 break;
1438 default:
1439 return WERR_UNKNOWN_LEVEL;
1442 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1443 &ndr_table_samr.syntax_id,
1444 &pipe_cli);
1445 if (!W_ERROR_IS_OK(werr)) {
1446 goto done;
1449 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1450 SAMR_ACCESS_ENUM_DOMAINS |
1451 SAMR_ACCESS_LOOKUP_DOMAIN,
1452 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1453 &connect_handle,
1454 &domain_handle,
1455 &domain_sid);
1456 if (!W_ERROR_IS_OK(werr)) {
1457 goto done;
1460 init_lsa_String(&lsa_account_name, r->in.group_name);
1462 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1463 &domain_handle,
1465 &lsa_account_name,
1466 &group_rids,
1467 &group_types);
1468 if (!NT_STATUS_IS_OK(status)) {
1469 werr = ntstatus_to_werror(status);
1470 goto done;
1473 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1474 &domain_handle,
1475 SAMR_GROUP_ACCESS_GET_MEMBERS |
1476 SAMR_GROUP_ACCESS_ADD_MEMBER |
1477 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1478 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1479 group_rids.ids[0],
1480 &group_handle);
1481 if (!NT_STATUS_IS_OK(status)) {
1482 werr = ntstatus_to_werror(status);
1483 goto done;
1486 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
1487 &group_handle,
1488 GROUPINFOATTRIBUTES,
1489 &group_info);
1490 if (!NT_STATUS_IS_OK(status)) {
1491 werr = ntstatus_to_werror(status);
1492 goto done;
1495 switch (r->in.level) {
1496 case 0:
1497 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1498 break;
1499 case 1:
1500 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1501 break;
1504 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1505 if (!lsa_names) {
1506 werr = WERR_NOMEM;
1507 goto done;
1510 for (i=0; i < r->in.num_entries; i++) {
1512 switch (r->in.level) {
1513 case 0:
1514 init_lsa_String(&lsa_names[i], i0->grui0_name);
1515 i0++;
1516 break;
1517 case 1:
1518 init_lsa_String(&lsa_names[i], i1->grui1_name);
1519 i1++;
1520 break;
1524 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1525 &domain_handle,
1526 r->in.num_entries,
1527 lsa_names,
1528 &user_rids,
1529 &name_types);
1530 if (!NT_STATUS_IS_OK(status)) {
1531 werr = ntstatus_to_werror(status);
1532 goto done;
1535 member_rids = user_rids.ids;
1536 num_member_rids = user_rids.count;
1538 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1539 &group_handle,
1540 &rid_array);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 werr = ntstatus_to_werror(status);
1543 goto done;
1546 /* add list */
1548 for (i=0; i < r->in.num_entries; i++) {
1549 bool already_member = false;
1550 for (k=0; k < rid_array->count; k++) {
1551 if (member_rids[i] == rid_array->rids[k]) {
1552 already_member = true;
1553 break;
1556 if (!already_member) {
1557 if (!add_rid_to_array_unique(ctx,
1558 member_rids[i],
1559 &add_rids, &num_add_rids)) {
1560 werr = WERR_GENERAL_FAILURE;
1561 goto done;
1566 /* del list */
1568 for (k=0; k < rid_array->count; k++) {
1569 bool keep_member = false;
1570 for (i=0; i < r->in.num_entries; i++) {
1571 if (member_rids[i] == rid_array->rids[k]) {
1572 keep_member = true;
1573 break;
1576 if (!keep_member) {
1577 if (!add_rid_to_array_unique(ctx,
1578 rid_array->rids[k],
1579 &del_rids, &num_del_rids)) {
1580 werr = WERR_GENERAL_FAILURE;
1581 goto done;
1586 /* add list */
1588 for (i=0; i < num_add_rids; i++) {
1589 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
1590 &group_handle,
1591 add_rids[i],
1592 7 /* ? */);
1593 if (!NT_STATUS_IS_OK(status)) {
1594 werr = ntstatus_to_werror(status);
1595 goto done;
1599 /* del list */
1601 for (i=0; i < num_del_rids; i++) {
1602 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
1603 &group_handle,
1604 del_rids[i]);
1605 if (!NT_STATUS_IS_OK(status)) {
1606 werr = ntstatus_to_werror(status);
1607 goto done;
1611 werr = WERR_OK;
1613 done:
1614 if (is_valid_policy_hnd(&group_handle)) {
1615 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1618 if (ctx->disable_policy_handle_cache) {
1619 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1620 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1623 return werr;
1626 /****************************************************************
1627 ****************************************************************/
1629 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1630 struct NetGroupSetUsers *r)
1632 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);