Fix bug #9147 - winbind can't fetch user or group info from AD via LDAP
[Samba.git] / source3 / lib / netapi / group.c
blobf5a7e77bb23d0175153a85bf9b0bf846074a0a45
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 "../librpc/gen_ndr/cli_samr.h"
28 /****************************************************************
29 ****************************************************************/
31 WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
32 struct NetGroupAdd *r)
34 struct rpc_pipe_client *pipe_cli = NULL;
35 NTSTATUS status;
36 WERROR werr;
37 struct policy_handle 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 &pipe_cli);
77 if (!W_ERROR_IS_OK(werr)) {
78 goto done;
81 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
82 SAMR_ACCESS_ENUM_DOMAINS |
83 SAMR_ACCESS_LOOKUP_DOMAIN,
84 SAMR_DOMAIN_ACCESS_CREATE_GROUP |
85 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
86 &connect_handle,
87 &domain_handle,
88 &domain_sid);
89 if (!W_ERROR_IS_OK(werr)) {
90 goto done;
93 switch (r->in.level) {
94 case 0:
95 init_lsa_String(&lsa_group_name, info0->grpi0_name);
96 break;
97 case 1:
98 init_lsa_String(&lsa_group_name, info1->grpi1_name);
99 break;
100 case 2:
101 init_lsa_String(&lsa_group_name, info2->grpi2_name);
102 break;
103 case 3:
104 init_lsa_String(&lsa_group_name, info3->grpi3_name);
105 break;
108 status = rpccli_samr_CreateDomainGroup(pipe_cli, talloc_tos(),
109 &domain_handle,
110 &lsa_group_name,
111 SEC_STD_DELETE |
112 SAMR_GROUP_ACCESS_SET_INFO,
113 &group_handle,
114 &rid);
116 if (!NT_STATUS_IS_OK(status)) {
117 werr = ntstatus_to_werror(status);
118 goto done;
121 switch (r->in.level) {
122 case 1:
123 if (info1->grpi1_comment) {
124 init_lsa_String(&info.description,
125 info1->grpi1_comment);
127 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
128 &group_handle,
129 GROUPINFODESCRIPTION,
130 &info);
132 break;
133 case 2:
134 if (info2->grpi2_comment) {
135 init_lsa_String(&info.description,
136 info2->grpi2_comment);
138 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
139 &group_handle,
140 GROUPINFODESCRIPTION,
141 &info);
142 if (!NT_STATUS_IS_OK(status)) {
143 werr = ntstatus_to_werror(status);
144 goto failed;
148 if (info2->grpi2_attributes != 0) {
149 info.attributes.attributes = info2->grpi2_attributes;
150 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
151 &group_handle,
152 GROUPINFOATTRIBUTES,
153 &info);
156 break;
157 case 3:
158 if (info3->grpi3_comment) {
159 init_lsa_String(&info.description,
160 info3->grpi3_comment);
162 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
163 &group_handle,
164 GROUPINFODESCRIPTION,
165 &info);
166 if (!NT_STATUS_IS_OK(status)) {
167 werr = ntstatus_to_werror(status);
168 goto failed;
172 if (info3->grpi3_attributes != 0) {
173 info.attributes.attributes = info3->grpi3_attributes;
174 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
175 &group_handle,
176 GROUPINFOATTRIBUTES,
177 &info);
179 break;
180 default:
181 break;
184 if (!NT_STATUS_IS_OK(status)) {
185 werr = ntstatus_to_werror(status);
186 goto failed;
189 werr = WERR_OK;
190 goto done;
192 failed:
193 rpccli_samr_DeleteDomainGroup(pipe_cli, talloc_tos(),
194 &group_handle);
196 done:
197 if (is_valid_policy_hnd(&group_handle)) {
198 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
201 if (ctx->disable_policy_handle_cache) {
202 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
203 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
206 return werr;
209 /****************************************************************
210 ****************************************************************/
212 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
213 struct NetGroupAdd *r)
215 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
218 /****************************************************************
219 ****************************************************************/
221 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
222 struct NetGroupDel *r)
224 struct rpc_pipe_client *pipe_cli = NULL;
225 NTSTATUS status;
226 WERROR werr;
227 struct policy_handle connect_handle, domain_handle, group_handle;
228 struct lsa_String lsa_group_name;
229 struct dom_sid2 *domain_sid = NULL;
230 int i = 0;
232 struct samr_Ids rids;
233 struct samr_Ids types;
234 union samr_GroupInfo *info = NULL;
235 struct samr_RidTypeArray *rid_array = NULL;
237 ZERO_STRUCT(connect_handle);
238 ZERO_STRUCT(domain_handle);
239 ZERO_STRUCT(group_handle);
241 if (!r->in.group_name) {
242 return WERR_INVALID_PARAM;
245 werr = libnetapi_open_pipe(ctx, r->in.server_name,
246 &ndr_table_samr.syntax_id,
247 &pipe_cli);
248 if (!W_ERROR_IS_OK(werr)) {
249 goto done;
252 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
253 SAMR_ACCESS_ENUM_DOMAINS |
254 SAMR_ACCESS_LOOKUP_DOMAIN,
255 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
256 &connect_handle,
257 &domain_handle,
258 &domain_sid);
259 if (!W_ERROR_IS_OK(werr)) {
260 goto done;
263 init_lsa_String(&lsa_group_name, r->in.group_name);
265 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
266 &domain_handle,
268 &lsa_group_name,
269 &rids,
270 &types);
271 if (!NT_STATUS_IS_OK(status)) {
272 werr = ntstatus_to_werror(status);
273 goto done;
276 if (types.ids[0] != SID_NAME_DOM_GRP) {
277 werr = WERR_INVALID_DATATYPE;
278 goto done;
281 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(),
282 &domain_handle,
283 SEC_STD_DELETE |
284 SAMR_GROUP_ACCESS_GET_MEMBERS |
285 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
286 SAMR_GROUP_ACCESS_ADD_MEMBER |
287 SAMR_GROUP_ACCESS_LOOKUP_INFO,
288 rids.ids[0],
289 &group_handle);
290 if (!NT_STATUS_IS_OK(status)) {
291 werr = ntstatus_to_werror(status);
292 goto done;
295 status = rpccli_samr_QueryGroupInfo(pipe_cli, talloc_tos(),
296 &group_handle,
297 GROUPINFOATTRIBUTES,
298 &info);
299 if (!NT_STATUS_IS_OK(status)) {
300 werr = ntstatus_to_werror(status);
301 goto done;
304 #if 0
305 /* breaks against NT4 */
306 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
307 werr = WERR_ACCESS_DENIED;
308 goto done;
310 #endif
311 status = rpccli_samr_QueryGroupMember(pipe_cli, talloc_tos(),
312 &group_handle,
313 &rid_array);
314 if (!NT_STATUS_IS_OK(status)) {
315 werr = ntstatus_to_werror(status);
316 goto done;
320 struct lsa_Strings names;
321 struct samr_Ids member_types;
323 status = rpccli_samr_LookupRids(pipe_cli, talloc_tos(),
324 &domain_handle,
325 rid_array->count,
326 rid_array->rids,
327 &names,
328 &member_types);
329 if (!NT_STATUS_IS_OK(status)) {
330 werr = ntstatus_to_werror(status);
331 goto done;
335 for (i=0; i < rid_array->count; i++) {
337 status = rpccli_samr_DeleteGroupMember(pipe_cli, talloc_tos(),
338 &group_handle,
339 rid_array->rids[i]);
340 if (!NT_STATUS_IS_OK(status)) {
341 werr = ntstatus_to_werror(status);
342 goto done;
346 status = rpccli_samr_DeleteDomainGroup(pipe_cli, talloc_tos(),
347 &group_handle);
348 if (!NT_STATUS_IS_OK(status)) {
349 werr = ntstatus_to_werror(status);
350 goto done;
353 ZERO_STRUCT(group_handle);
355 werr = WERR_OK;
357 done:
358 if (is_valid_policy_hnd(&group_handle)) {
359 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
362 if (ctx->disable_policy_handle_cache) {
363 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
364 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
367 return werr;
370 /****************************************************************
371 ****************************************************************/
373 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
374 struct NetGroupDel *r)
376 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
379 /****************************************************************
380 ****************************************************************/
382 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
383 struct NetGroupSetInfo *r)
385 struct rpc_pipe_client *pipe_cli = NULL;
386 NTSTATUS status;
387 WERROR werr;
388 struct policy_handle connect_handle, domain_handle, group_handle;
389 struct lsa_String lsa_group_name;
390 struct dom_sid2 *domain_sid = NULL;
392 struct samr_Ids rids;
393 struct samr_Ids types;
394 union samr_GroupInfo info;
395 struct GROUP_INFO_0 *g0;
396 struct GROUP_INFO_1 *g1;
397 struct GROUP_INFO_2 *g2;
398 struct GROUP_INFO_3 *g3;
399 struct GROUP_INFO_1002 *g1002;
400 struct GROUP_INFO_1005 *g1005;
402 ZERO_STRUCT(connect_handle);
403 ZERO_STRUCT(domain_handle);
404 ZERO_STRUCT(group_handle);
406 if (!r->in.group_name) {
407 return WERR_INVALID_PARAM;
410 werr = libnetapi_open_pipe(ctx, r->in.server_name,
411 &ndr_table_samr.syntax_id,
412 &pipe_cli);
413 if (!W_ERROR_IS_OK(werr)) {
414 goto done;
417 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
418 SAMR_ACCESS_ENUM_DOMAINS |
419 SAMR_ACCESS_LOOKUP_DOMAIN,
420 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
421 &connect_handle,
422 &domain_handle,
423 &domain_sid);
424 if (!W_ERROR_IS_OK(werr)) {
425 goto done;
428 init_lsa_String(&lsa_group_name, r->in.group_name);
430 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
431 &domain_handle,
433 &lsa_group_name,
434 &rids,
435 &types);
436 if (!NT_STATUS_IS_OK(status)) {
437 werr = ntstatus_to_werror(status);
438 goto done;
441 if (types.ids[0] != SID_NAME_DOM_GRP) {
442 werr = WERR_INVALID_DATATYPE;
443 goto done;
446 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(),
447 &domain_handle,
448 SAMR_GROUP_ACCESS_SET_INFO |
449 SAMR_GROUP_ACCESS_LOOKUP_INFO,
450 rids.ids[0],
451 &group_handle);
452 if (!NT_STATUS_IS_OK(status)) {
453 werr = ntstatus_to_werror(status);
454 goto done;
457 switch (r->in.level) {
458 case 0:
459 g0 = (struct GROUP_INFO_0 *)r->in.buffer;
460 init_lsa_String(&info.name, g0->grpi0_name);
461 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
462 &group_handle,
463 GROUPINFONAME,
464 &info);
465 break;
466 case 1:
467 g1 = (struct GROUP_INFO_1 *)r->in.buffer;
468 init_lsa_String(&info.description, g1->grpi1_comment);
469 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
470 &group_handle,
471 GROUPINFODESCRIPTION,
472 &info);
473 break;
474 case 2:
475 g2 = (struct GROUP_INFO_2 *)r->in.buffer;
476 init_lsa_String(&info.description, g2->grpi2_comment);
477 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
478 &group_handle,
479 GROUPINFODESCRIPTION,
480 &info);
481 if (!NT_STATUS_IS_OK(status)) {
482 werr = ntstatus_to_werror(status);
483 goto done;
485 info.attributes.attributes = g2->grpi2_attributes;
486 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
487 &group_handle,
488 GROUPINFOATTRIBUTES,
489 &info);
490 break;
491 case 3:
492 g3 = (struct GROUP_INFO_3 *)r->in.buffer;
493 init_lsa_String(&info.description, g3->grpi3_comment);
494 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
495 &group_handle,
496 GROUPINFODESCRIPTION,
497 &info);
498 if (!NT_STATUS_IS_OK(status)) {
499 werr = ntstatus_to_werror(status);
500 goto done;
502 info.attributes.attributes = g3->grpi3_attributes;
503 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
504 &group_handle,
505 GROUPINFOATTRIBUTES,
506 &info);
507 break;
508 case 1002:
509 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
510 init_lsa_String(&info.description, g1002->grpi1002_comment);
511 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
512 &group_handle,
513 GROUPINFODESCRIPTION,
514 &info);
515 break;
516 case 1005:
517 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
518 info.attributes.attributes = g1005->grpi1005_attributes;
519 status = rpccli_samr_SetGroupInfo(pipe_cli, talloc_tos(),
520 &group_handle,
521 GROUPINFOATTRIBUTES,
522 &info);
523 break;
524 default:
525 status = NT_STATUS_INVALID_LEVEL;
526 break;
529 if (!NT_STATUS_IS_OK(status)) {
530 werr = ntstatus_to_werror(status);
531 goto done;
534 werr = WERR_OK;
536 done:
537 if (is_valid_policy_hnd(&group_handle)) {
538 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
541 if (ctx->disable_policy_handle_cache) {
542 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
543 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
546 return werr;
549 /****************************************************************
550 ****************************************************************/
552 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
553 struct NetGroupSetInfo *r)
555 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
558 /****************************************************************
559 ****************************************************************/
561 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
562 uint32_t level,
563 struct samr_GroupInfoAll *info,
564 struct dom_sid2 *domain_sid,
565 uint32_t rid,
566 uint8_t **buffer)
568 struct GROUP_INFO_0 info0;
569 struct GROUP_INFO_1 info1;
570 struct GROUP_INFO_2 info2;
571 struct GROUP_INFO_3 info3;
572 struct dom_sid sid;
574 switch (level) {
575 case 0:
576 info0.grpi0_name = info->name.string;
578 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
580 break;
581 case 1:
582 info1.grpi1_name = info->name.string;
583 info1.grpi1_comment = info->description.string;
585 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
587 break;
588 case 2:
589 info2.grpi2_name = info->name.string;
590 info2.grpi2_comment = info->description.string;
591 info2.grpi2_group_id = rid;
592 info2.grpi2_attributes = info->attributes;
594 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
596 break;
597 case 3:
598 if (!sid_compose(&sid, domain_sid, rid)) {
599 return WERR_NOMEM;
602 info3.grpi3_name = info->name.string;
603 info3.grpi3_comment = info->description.string;
604 info3.grpi3_attributes = info->attributes;
605 info3.grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
607 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
609 break;
610 default:
611 return WERR_UNKNOWN_LEVEL;
614 W_ERROR_HAVE_NO_MEMORY(*buffer);
616 return WERR_OK;
619 /****************************************************************
620 ****************************************************************/
622 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
623 struct NetGroupGetInfo *r)
625 struct rpc_pipe_client *pipe_cli = NULL;
626 NTSTATUS status;
627 WERROR werr;
628 struct policy_handle connect_handle, domain_handle, group_handle;
629 struct lsa_String lsa_group_name;
630 struct dom_sid2 *domain_sid = NULL;
632 struct samr_Ids rids;
633 struct samr_Ids types;
634 union samr_GroupInfo *info = NULL;
635 bool group_info_all = false;
637 ZERO_STRUCT(connect_handle);
638 ZERO_STRUCT(domain_handle);
639 ZERO_STRUCT(group_handle);
641 if (!r->in.group_name) {
642 return WERR_INVALID_PARAM;
645 werr = libnetapi_open_pipe(ctx, r->in.server_name,
646 &ndr_table_samr.syntax_id,
647 &pipe_cli);
648 if (!W_ERROR_IS_OK(werr)) {
649 goto done;
652 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
653 SAMR_ACCESS_ENUM_DOMAINS |
654 SAMR_ACCESS_LOOKUP_DOMAIN,
655 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
656 &connect_handle,
657 &domain_handle,
658 &domain_sid);
659 if (!W_ERROR_IS_OK(werr)) {
660 goto done;
663 init_lsa_String(&lsa_group_name, r->in.group_name);
665 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
666 &domain_handle,
668 &lsa_group_name,
669 &rids,
670 &types);
671 if (!NT_STATUS_IS_OK(status)) {
672 werr = ntstatus_to_werror(status);
673 goto done;
676 if (types.ids[0] != SID_NAME_DOM_GRP) {
677 werr = WERR_INVALID_DATATYPE;
678 goto done;
681 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(),
682 &domain_handle,
683 SAMR_GROUP_ACCESS_LOOKUP_INFO,
684 rids.ids[0],
685 &group_handle);
686 if (!NT_STATUS_IS_OK(status)) {
687 werr = ntstatus_to_werror(status);
688 goto done;
691 status = rpccli_samr_QueryGroupInfo(pipe_cli, talloc_tos(),
692 &group_handle,
693 GROUPINFOALL2,
694 &info);
695 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
696 status = rpccli_samr_QueryGroupInfo(pipe_cli, talloc_tos(),
697 &group_handle,
698 GROUPINFOALL,
699 &info);
700 group_info_all = true;
703 if (!NT_STATUS_IS_OK(status)) {
704 werr = ntstatus_to_werror(status);
705 goto done;
708 werr = map_group_info_to_buffer(ctx, r->in.level,
709 group_info_all ? &info->all : &info->all2,
710 domain_sid, rids.ids[0],
711 r->out.buffer);
712 if (!W_ERROR_IS_OK(werr)) {
713 goto done;
715 done:
716 if (is_valid_policy_hnd(&group_handle)) {
717 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
720 if (ctx->disable_policy_handle_cache) {
721 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
722 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
725 return werr;
728 /****************************************************************
729 ****************************************************************/
731 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
732 struct NetGroupGetInfo *r)
734 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
737 /****************************************************************
738 ****************************************************************/
740 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
741 struct NetGroupAddUser *r)
743 struct rpc_pipe_client *pipe_cli = NULL;
744 NTSTATUS status;
745 WERROR werr;
746 struct policy_handle connect_handle, domain_handle, group_handle;
747 struct lsa_String lsa_group_name, lsa_user_name;
748 struct dom_sid2 *domain_sid = NULL;
750 struct samr_Ids rids;
751 struct samr_Ids types;
753 ZERO_STRUCT(connect_handle);
754 ZERO_STRUCT(domain_handle);
755 ZERO_STRUCT(group_handle);
757 if (!r->in.group_name) {
758 return WERR_INVALID_PARAM;
761 werr = libnetapi_open_pipe(ctx, r->in.server_name,
762 &ndr_table_samr.syntax_id,
763 &pipe_cli);
764 if (!W_ERROR_IS_OK(werr)) {
765 goto done;
768 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
769 SAMR_ACCESS_ENUM_DOMAINS |
770 SAMR_ACCESS_LOOKUP_DOMAIN,
771 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
772 &connect_handle,
773 &domain_handle,
774 &domain_sid);
775 if (!W_ERROR_IS_OK(werr)) {
776 goto done;
779 init_lsa_String(&lsa_group_name, r->in.group_name);
781 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
782 &domain_handle,
784 &lsa_group_name,
785 &rids,
786 &types);
787 if (!NT_STATUS_IS_OK(status)) {
788 werr = WERR_GROUPNOTFOUND;
789 goto done;
792 if (types.ids[0] != SID_NAME_DOM_GRP) {
793 werr = WERR_GROUPNOTFOUND;
794 goto done;
797 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(),
798 &domain_handle,
799 SAMR_GROUP_ACCESS_ADD_MEMBER,
800 rids.ids[0],
801 &group_handle);
802 if (!NT_STATUS_IS_OK(status)) {
803 werr = ntstatus_to_werror(status);
804 goto done;
807 init_lsa_String(&lsa_user_name, r->in.user_name);
809 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
810 &domain_handle,
812 &lsa_user_name,
813 &rids,
814 &types);
815 if (!NT_STATUS_IS_OK(status)) {
816 werr = WERR_USER_NOT_FOUND;
817 goto done;
820 if (types.ids[0] != SID_NAME_USER) {
821 werr = WERR_USER_NOT_FOUND;
822 goto done;
825 status = rpccli_samr_AddGroupMember(pipe_cli, talloc_tos(),
826 &group_handle,
827 rids.ids[0],
828 7); /* why ? */
829 if (!NT_STATUS_IS_OK(status)) {
830 werr = ntstatus_to_werror(status);
831 goto done;
834 werr = WERR_OK;
836 done:
837 if (is_valid_policy_hnd(&group_handle)) {
838 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
841 if (ctx->disable_policy_handle_cache) {
842 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
843 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
846 return werr;
849 /****************************************************************
850 ****************************************************************/
852 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
853 struct NetGroupAddUser *r)
855 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
858 /****************************************************************
859 ****************************************************************/
861 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
862 struct NetGroupDelUser *r)
864 struct rpc_pipe_client *pipe_cli = NULL;
865 NTSTATUS status;
866 WERROR werr;
867 struct policy_handle connect_handle, domain_handle, group_handle;
868 struct lsa_String lsa_group_name, lsa_user_name;
869 struct dom_sid2 *domain_sid = NULL;
871 struct samr_Ids rids;
872 struct samr_Ids types;
874 ZERO_STRUCT(connect_handle);
875 ZERO_STRUCT(domain_handle);
876 ZERO_STRUCT(group_handle);
878 if (!r->in.group_name) {
879 return WERR_INVALID_PARAM;
882 werr = libnetapi_open_pipe(ctx, r->in.server_name,
883 &ndr_table_samr.syntax_id,
884 &pipe_cli);
885 if (!W_ERROR_IS_OK(werr)) {
886 goto done;
889 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
890 SAMR_ACCESS_ENUM_DOMAINS |
891 SAMR_ACCESS_LOOKUP_DOMAIN,
892 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
893 &connect_handle,
894 &domain_handle,
895 &domain_sid);
896 if (!W_ERROR_IS_OK(werr)) {
897 goto done;
900 init_lsa_String(&lsa_group_name, r->in.group_name);
902 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
903 &domain_handle,
905 &lsa_group_name,
906 &rids,
907 &types);
908 if (!NT_STATUS_IS_OK(status)) {
909 werr = WERR_GROUPNOTFOUND;
910 goto done;
913 if (types.ids[0] != SID_NAME_DOM_GRP) {
914 werr = WERR_GROUPNOTFOUND;
915 goto done;
918 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(),
919 &domain_handle,
920 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
921 rids.ids[0],
922 &group_handle);
923 if (!NT_STATUS_IS_OK(status)) {
924 werr = ntstatus_to_werror(status);
925 goto done;
928 init_lsa_String(&lsa_user_name, r->in.user_name);
930 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
931 &domain_handle,
933 &lsa_user_name,
934 &rids,
935 &types);
936 if (!NT_STATUS_IS_OK(status)) {
937 werr = WERR_USER_NOT_FOUND;
938 goto done;
941 if (types.ids[0] != SID_NAME_USER) {
942 werr = WERR_USER_NOT_FOUND;
943 goto done;
946 status = rpccli_samr_DeleteGroupMember(pipe_cli, talloc_tos(),
947 &group_handle,
948 rids.ids[0]);
949 if (!NT_STATUS_IS_OK(status)) {
950 werr = ntstatus_to_werror(status);
951 goto done;
954 werr = WERR_OK;
956 done:
957 if (is_valid_policy_hnd(&group_handle)) {
958 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
961 if (ctx->disable_policy_handle_cache) {
962 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
963 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
966 return werr;
969 /****************************************************************
970 ****************************************************************/
972 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
973 struct NetGroupDelUser *r)
975 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
978 /****************************************************************
979 ****************************************************************/
981 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
982 struct samr_DispInfoFullGroups *groups,
983 uint8_t **buffer)
985 struct GROUP_INFO_0 *g0;
986 int i;
988 g0 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_0, groups->count);
989 W_ERROR_HAVE_NO_MEMORY(g0);
991 for (i=0; i<groups->count; i++) {
992 g0[i].grpi0_name = talloc_strdup(mem_ctx,
993 groups->entries[i].account_name.string);
994 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
997 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
998 sizeof(struct GROUP_INFO_0) * groups->count);
999 W_ERROR_HAVE_NO_MEMORY(*buffer);
1001 return WERR_OK;
1004 /****************************************************************
1005 ****************************************************************/
1007 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1008 struct samr_DispInfoFullGroups *groups,
1009 uint8_t **buffer)
1011 struct GROUP_INFO_1 *g1;
1012 int i;
1014 g1 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_1, groups->count);
1015 W_ERROR_HAVE_NO_MEMORY(g1);
1017 for (i=0; i<groups->count; i++) {
1018 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1019 groups->entries[i].account_name.string);
1020 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1021 groups->entries[i].description.string);
1022 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1025 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1026 sizeof(struct GROUP_INFO_1) * groups->count);
1027 W_ERROR_HAVE_NO_MEMORY(*buffer);
1029 return WERR_OK;
1032 /****************************************************************
1033 ****************************************************************/
1035 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1036 struct samr_DispInfoFullGroups *groups,
1037 uint8_t **buffer)
1039 struct GROUP_INFO_2 *g2;
1040 int i;
1042 g2 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_2, groups->count);
1043 W_ERROR_HAVE_NO_MEMORY(g2);
1045 for (i=0; i<groups->count; i++) {
1046 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1047 groups->entries[i].account_name.string);
1048 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1049 groups->entries[i].description.string);
1050 g2[i].grpi2_group_id = groups->entries[i].rid;
1051 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1052 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1055 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1056 sizeof(struct GROUP_INFO_2) * groups->count);
1057 W_ERROR_HAVE_NO_MEMORY(*buffer);
1059 return WERR_OK;
1062 /****************************************************************
1063 ****************************************************************/
1065 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1066 struct samr_DispInfoFullGroups *groups,
1067 const struct dom_sid *domain_sid,
1068 uint8_t **buffer)
1070 struct GROUP_INFO_3 *g3;
1071 int i;
1073 g3 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_3, groups->count);
1074 W_ERROR_HAVE_NO_MEMORY(g3);
1076 for (i=0; i<groups->count; i++) {
1078 struct dom_sid sid;
1080 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1081 return WERR_NOMEM;
1084 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1085 groups->entries[i].account_name.string);
1086 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1087 groups->entries[i].description.string);
1088 g3[i].grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
1089 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1090 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1093 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1094 sizeof(struct GROUP_INFO_3) * groups->count);
1095 W_ERROR_HAVE_NO_MEMORY(*buffer);
1097 return WERR_OK;
1100 /****************************************************************
1101 ****************************************************************/
1103 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1104 uint32_t level,
1105 struct samr_DispInfoFullGroups *groups,
1106 const struct dom_sid *domain_sid,
1107 uint32_t *entries_read,
1108 uint8_t **buffer)
1110 if (entries_read) {
1111 *entries_read = groups->count;
1114 switch (level) {
1115 case 0:
1116 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1117 case 1:
1118 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1119 case 2:
1120 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1121 case 3:
1122 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1123 default:
1124 return WERR_UNKNOWN_LEVEL;
1128 /****************************************************************
1129 ****************************************************************/
1131 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1132 struct NetGroupEnum *r)
1134 struct rpc_pipe_client *pipe_cli = NULL;
1135 struct policy_handle connect_handle;
1136 struct dom_sid2 *domain_sid = NULL;
1137 struct policy_handle domain_handle;
1138 union samr_DispInfo info;
1139 union samr_DomainInfo *domain_info = NULL;
1141 uint32_t total_size = 0;
1142 uint32_t returned_size = 0;
1144 NTSTATUS status = NT_STATUS_OK;
1145 WERROR werr, tmp_werr;
1147 ZERO_STRUCT(connect_handle);
1148 ZERO_STRUCT(domain_handle);
1150 switch (r->in.level) {
1151 case 0:
1152 case 1:
1153 case 2:
1154 case 3:
1155 break;
1156 default:
1157 return WERR_UNKNOWN_LEVEL;
1160 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1161 &ndr_table_samr.syntax_id,
1162 &pipe_cli);
1163 if (!W_ERROR_IS_OK(werr)) {
1164 goto done;
1167 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1168 SAMR_ACCESS_ENUM_DOMAINS |
1169 SAMR_ACCESS_LOOKUP_DOMAIN,
1170 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1171 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1172 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1173 &connect_handle,
1174 &domain_handle,
1175 &domain_sid);
1176 if (!W_ERROR_IS_OK(werr)) {
1177 goto done;
1180 status = rpccli_samr_QueryDomainInfo(pipe_cli, talloc_tos(),
1181 &domain_handle,
1183 &domain_info);
1184 if (!NT_STATUS_IS_OK(status)) {
1185 werr = ntstatus_to_werror(status);
1186 goto done;
1189 if (r->out.total_entries) {
1190 *r->out.total_entries = domain_info->general.num_groups;
1193 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1194 ctx,
1195 &domain_handle,
1197 r->in.resume_handle ?
1198 *r->in.resume_handle : 0,
1199 (uint32_t)-1,
1200 r->in.prefmaxlen,
1201 &total_size,
1202 &returned_size,
1203 &info);
1204 werr = ntstatus_to_werror(status);
1205 if (NT_STATUS_IS_ERR(status)) {
1206 goto done;
1209 if (r->out.resume_handle && info.info3.count > 0) {
1210 *r->out.resume_handle =
1211 info.info3.entries[info.info3.count-1].idx;
1214 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1215 r->in.level,
1216 &info.info3,
1217 domain_sid,
1218 r->out.entries_read,
1219 r->out.buffer);
1220 if (!W_ERROR_IS_OK(tmp_werr)) {
1221 werr = tmp_werr;
1222 goto done;
1225 done:
1226 /* if last query */
1227 if (NT_STATUS_IS_OK(status) ||
1228 NT_STATUS_IS_ERR(status)) {
1230 if (ctx->disable_policy_handle_cache) {
1231 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1232 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1236 return werr;
1239 /****************************************************************
1240 ****************************************************************/
1242 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1243 struct NetGroupEnum *r)
1245 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1248 /****************************************************************
1249 ****************************************************************/
1251 WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1252 struct NetGroupGetUsers *r)
1254 /* FIXME: this call needs to cope with large replies */
1256 struct rpc_pipe_client *pipe_cli = NULL;
1257 struct policy_handle connect_handle, domain_handle, group_handle;
1258 struct lsa_String lsa_account_name;
1259 struct dom_sid2 *domain_sid = NULL;
1260 struct samr_Ids group_rids, name_types;
1261 struct samr_RidTypeArray *rid_array = NULL;
1262 struct lsa_Strings names;
1263 struct samr_Ids member_types;
1265 int i;
1266 uint32_t entries_read = 0;
1268 NTSTATUS status = NT_STATUS_OK;
1269 WERROR werr;
1271 ZERO_STRUCT(connect_handle);
1272 ZERO_STRUCT(domain_handle);
1274 if (!r->out.buffer) {
1275 return WERR_INVALID_PARAM;
1278 *r->out.buffer = NULL;
1279 *r->out.entries_read = 0;
1280 *r->out.total_entries = 0;
1282 switch (r->in.level) {
1283 case 0:
1284 case 1:
1285 break;
1286 default:
1287 return WERR_UNKNOWN_LEVEL;
1291 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1292 &ndr_table_samr.syntax_id,
1293 &pipe_cli);
1294 if (!W_ERROR_IS_OK(werr)) {
1295 goto done;
1298 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1299 SAMR_ACCESS_ENUM_DOMAINS |
1300 SAMR_ACCESS_LOOKUP_DOMAIN,
1301 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1302 &connect_handle,
1303 &domain_handle,
1304 &domain_sid);
1305 if (!W_ERROR_IS_OK(werr)) {
1306 goto done;
1309 init_lsa_String(&lsa_account_name, r->in.group_name);
1311 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
1312 &domain_handle,
1314 &lsa_account_name,
1315 &group_rids,
1316 &name_types);
1317 if (!NT_STATUS_IS_OK(status)) {
1318 werr = ntstatus_to_werror(status);
1319 goto done;
1322 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(),
1323 &domain_handle,
1324 SAMR_GROUP_ACCESS_GET_MEMBERS,
1325 group_rids.ids[0],
1326 &group_handle);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 werr = ntstatus_to_werror(status);
1329 goto done;
1332 status = rpccli_samr_QueryGroupMember(pipe_cli, talloc_tos(),
1333 &group_handle,
1334 &rid_array);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 werr = ntstatus_to_werror(status);
1337 goto done;
1340 status = rpccli_samr_LookupRids(pipe_cli, talloc_tos(),
1341 &domain_handle,
1342 rid_array->count,
1343 rid_array->rids,
1344 &names,
1345 &member_types);
1346 if (!NT_STATUS_IS_OK(status)) {
1347 werr = ntstatus_to_werror(status);
1348 goto done;
1351 for (i=0; i < names.count; i++) {
1353 if (member_types.ids[i] != SID_NAME_USER) {
1354 continue;
1357 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1358 r->in.level,
1359 names.names[i].string,
1361 r->out.buffer,
1362 &entries_read);
1363 if (!NT_STATUS_IS_OK(status)) {
1364 werr = ntstatus_to_werror(status);
1365 goto done;
1369 *r->out.entries_read = entries_read;
1370 *r->out.total_entries = entries_read;
1372 werr = WERR_OK;
1374 done:
1375 if (is_valid_policy_hnd(&group_handle)) {
1376 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
1379 if (ctx->disable_policy_handle_cache) {
1380 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1381 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1384 return werr;
1387 /****************************************************************
1388 ****************************************************************/
1390 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1391 struct NetGroupGetUsers *r)
1393 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1396 /****************************************************************
1397 ****************************************************************/
1399 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1400 struct NetGroupSetUsers *r)
1402 struct rpc_pipe_client *pipe_cli = NULL;
1403 struct policy_handle connect_handle, domain_handle, group_handle;
1404 struct lsa_String lsa_account_name;
1405 struct dom_sid2 *domain_sid = NULL;
1406 union samr_GroupInfo *group_info = NULL;
1407 struct samr_Ids user_rids, name_types;
1408 struct samr_Ids group_rids, group_types;
1409 struct samr_RidTypeArray *rid_array = NULL;
1410 struct lsa_String *lsa_names = NULL;
1412 uint32_t *add_rids = NULL;
1413 uint32_t *del_rids = NULL;
1414 size_t num_add_rids = 0;
1415 size_t num_del_rids = 0;
1417 uint32_t *member_rids = NULL;
1418 size_t num_member_rids = 0;
1420 struct GROUP_USERS_INFO_0 *i0 = NULL;
1421 struct GROUP_USERS_INFO_1 *i1 = NULL;
1423 int i, k;
1425 NTSTATUS status = NT_STATUS_OK;
1426 WERROR werr;
1428 ZERO_STRUCT(connect_handle);
1429 ZERO_STRUCT(domain_handle);
1431 if (!r->in.buffer) {
1432 return WERR_INVALID_PARAM;
1435 switch (r->in.level) {
1436 case 0:
1437 case 1:
1438 break;
1439 default:
1440 return WERR_UNKNOWN_LEVEL;
1443 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1444 &ndr_table_samr.syntax_id,
1445 &pipe_cli);
1446 if (!W_ERROR_IS_OK(werr)) {
1447 goto done;
1450 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1451 SAMR_ACCESS_ENUM_DOMAINS |
1452 SAMR_ACCESS_LOOKUP_DOMAIN,
1453 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1454 &connect_handle,
1455 &domain_handle,
1456 &domain_sid);
1457 if (!W_ERROR_IS_OK(werr)) {
1458 goto done;
1461 init_lsa_String(&lsa_account_name, r->in.group_name);
1463 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
1464 &domain_handle,
1466 &lsa_account_name,
1467 &group_rids,
1468 &group_types);
1469 if (!NT_STATUS_IS_OK(status)) {
1470 werr = ntstatus_to_werror(status);
1471 goto done;
1474 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(),
1475 &domain_handle,
1476 SAMR_GROUP_ACCESS_GET_MEMBERS |
1477 SAMR_GROUP_ACCESS_ADD_MEMBER |
1478 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1479 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1480 group_rids.ids[0],
1481 &group_handle);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 werr = ntstatus_to_werror(status);
1484 goto done;
1487 status = rpccli_samr_QueryGroupInfo(pipe_cli, talloc_tos(),
1488 &group_handle,
1489 GROUPINFOATTRIBUTES,
1490 &group_info);
1491 if (!NT_STATUS_IS_OK(status)) {
1492 werr = ntstatus_to_werror(status);
1493 goto done;
1496 switch (r->in.level) {
1497 case 0:
1498 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1499 break;
1500 case 1:
1501 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1502 break;
1505 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1506 if (!lsa_names) {
1507 werr = WERR_NOMEM;
1508 goto done;
1511 for (i=0; i < r->in.num_entries; i++) {
1513 switch (r->in.level) {
1514 case 0:
1515 init_lsa_String(&lsa_names[i], i0->grui0_name);
1516 i0++;
1517 break;
1518 case 1:
1519 init_lsa_String(&lsa_names[i], i1->grui1_name);
1520 i1++;
1521 break;
1525 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
1526 &domain_handle,
1527 r->in.num_entries,
1528 lsa_names,
1529 &user_rids,
1530 &name_types);
1531 if (!NT_STATUS_IS_OK(status)) {
1532 werr = ntstatus_to_werror(status);
1533 goto done;
1536 member_rids = user_rids.ids;
1537 num_member_rids = user_rids.count;
1539 status = rpccli_samr_QueryGroupMember(pipe_cli, talloc_tos(),
1540 &group_handle,
1541 &rid_array);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 werr = ntstatus_to_werror(status);
1544 goto done;
1547 /* add list */
1549 for (i=0; i < r->in.num_entries; i++) {
1550 bool already_member = false;
1551 for (k=0; k < rid_array->count; k++) {
1552 if (member_rids[i] == rid_array->rids[k]) {
1553 already_member = true;
1554 break;
1557 if (!already_member) {
1558 if (!add_rid_to_array_unique(ctx,
1559 member_rids[i],
1560 &add_rids, &num_add_rids)) {
1561 werr = WERR_GENERAL_FAILURE;
1562 goto done;
1567 /* del list */
1569 for (k=0; k < rid_array->count; k++) {
1570 bool keep_member = false;
1571 for (i=0; i < r->in.num_entries; i++) {
1572 if (member_rids[i] == rid_array->rids[k]) {
1573 keep_member = true;
1574 break;
1577 if (!keep_member) {
1578 if (!add_rid_to_array_unique(ctx,
1579 rid_array->rids[k],
1580 &del_rids, &num_del_rids)) {
1581 werr = WERR_GENERAL_FAILURE;
1582 goto done;
1587 /* add list */
1589 for (i=0; i < num_add_rids; i++) {
1590 status = rpccli_samr_AddGroupMember(pipe_cli, talloc_tos(),
1591 &group_handle,
1592 add_rids[i],
1593 7 /* ? */);
1594 if (!NT_STATUS_IS_OK(status)) {
1595 werr = ntstatus_to_werror(status);
1596 goto done;
1600 /* del list */
1602 for (i=0; i < num_del_rids; i++) {
1603 status = rpccli_samr_DeleteGroupMember(pipe_cli, talloc_tos(),
1604 &group_handle,
1605 del_rids[i]);
1606 if (!NT_STATUS_IS_OK(status)) {
1607 werr = ntstatus_to_werror(status);
1608 goto done;
1612 werr = WERR_OK;
1614 done:
1615 if (is_valid_policy_hnd(&group_handle)) {
1616 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
1619 if (ctx->disable_policy_handle_cache) {
1620 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1621 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1624 return werr;
1627 /****************************************************************
1628 ****************************************************************/
1630 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1631 struct NetGroupSetUsers *r)
1633 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);