s3-rpc_client: add and use rpc_client/rpc_client.h.
[Samba.git] / source3 / lib / netapi / group.c
blob4295d9f7bbf7ba52f8b9b9f3fd2df2c021601eef
1 /*
2 * Unix SMB/CIFS implementation.
3 * NetApi Group Support
4 * Copyright (C) Guenther Deschner 2008
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
26 #include "rpc_client/rpc_client.h"
27 #include "../librpc/gen_ndr/ndr_samr_c.h"
28 #include "rpc_client/init_lsa.h"
29 #include "../libcli/security/security.h"
31 /****************************************************************
32 ****************************************************************/
34 WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
35 struct NetGroupAdd *r)
37 struct rpc_pipe_client *pipe_cli = NULL;
38 NTSTATUS status, result;
39 WERROR werr;
40 struct policy_handle connect_handle, domain_handle, group_handle;
41 struct lsa_String lsa_group_name;
42 struct dom_sid2 *domain_sid = NULL;
43 uint32_t rid = 0;
44 struct dcerpc_binding_handle *b = NULL;
46 struct GROUP_INFO_0 *info0 = NULL;
47 struct GROUP_INFO_1 *info1 = NULL;
48 struct GROUP_INFO_2 *info2 = NULL;
49 struct GROUP_INFO_3 *info3 = NULL;
50 union samr_GroupInfo info;
52 ZERO_STRUCT(connect_handle);
53 ZERO_STRUCT(domain_handle);
54 ZERO_STRUCT(group_handle);
56 if (!r->in.buffer) {
57 return WERR_INVALID_PARAM;
60 switch (r->in.level) {
61 case 0:
62 info0 = (struct GROUP_INFO_0 *)r->in.buffer;
63 break;
64 case 1:
65 info1 = (struct GROUP_INFO_1 *)r->in.buffer;
66 break;
67 case 2:
68 info2 = (struct GROUP_INFO_2 *)r->in.buffer;
69 break;
70 case 3:
71 info3 = (struct GROUP_INFO_3 *)r->in.buffer;
72 break;
73 default:
74 werr = WERR_UNKNOWN_LEVEL;
75 goto done;
78 werr = libnetapi_open_pipe(ctx, r->in.server_name,
79 &ndr_table_samr.syntax_id,
80 &pipe_cli);
81 if (!W_ERROR_IS_OK(werr)) {
82 goto done;
85 b = pipe_cli->binding_handle;
87 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
88 SAMR_ACCESS_ENUM_DOMAINS |
89 SAMR_ACCESS_LOOKUP_DOMAIN,
90 SAMR_DOMAIN_ACCESS_CREATE_GROUP |
91 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
92 &connect_handle,
93 &domain_handle,
94 &domain_sid);
95 if (!W_ERROR_IS_OK(werr)) {
96 goto done;
99 switch (r->in.level) {
100 case 0:
101 init_lsa_String(&lsa_group_name, info0->grpi0_name);
102 break;
103 case 1:
104 init_lsa_String(&lsa_group_name, info1->grpi1_name);
105 break;
106 case 2:
107 init_lsa_String(&lsa_group_name, info2->grpi2_name);
108 break;
109 case 3:
110 init_lsa_String(&lsa_group_name, info3->grpi3_name);
111 break;
114 status = dcerpc_samr_CreateDomainGroup(b, talloc_tos(),
115 &domain_handle,
116 &lsa_group_name,
117 SEC_STD_DELETE |
118 SAMR_GROUP_ACCESS_SET_INFO,
119 &group_handle,
120 &rid,
121 &result);
123 if (!NT_STATUS_IS_OK(status)) {
124 werr = ntstatus_to_werror(status);
125 goto done;
127 if (!NT_STATUS_IS_OK(result)) {
128 werr = ntstatus_to_werror(result);
129 goto done;
132 switch (r->in.level) {
133 case 1:
134 if (info1->grpi1_comment) {
135 init_lsa_String(&info.description,
136 info1->grpi1_comment);
138 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
139 &group_handle,
140 GROUPINFODESCRIPTION,
141 &info,
142 &result);
144 break;
145 case 2:
146 if (info2->grpi2_comment) {
147 init_lsa_String(&info.description,
148 info2->grpi2_comment);
150 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
151 &group_handle,
152 GROUPINFODESCRIPTION,
153 &info,
154 &result);
155 if (!NT_STATUS_IS_OK(status)) {
156 werr = ntstatus_to_werror(status);
157 goto failed;
159 if (!NT_STATUS_IS_OK(result)) {
160 werr = ntstatus_to_werror(result);
161 goto failed;
165 if (info2->grpi2_attributes != 0) {
166 info.attributes.attributes = info2->grpi2_attributes;
167 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
168 &group_handle,
169 GROUPINFOATTRIBUTES,
170 &info,
171 &result);
174 break;
175 case 3:
176 if (info3->grpi3_comment) {
177 init_lsa_String(&info.description,
178 info3->grpi3_comment);
180 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
181 &group_handle,
182 GROUPINFODESCRIPTION,
183 &info,
184 &result);
185 if (!NT_STATUS_IS_OK(status)) {
186 werr = ntstatus_to_werror(status);
187 goto failed;
189 if (!NT_STATUS_IS_OK(result)) {
190 werr = ntstatus_to_werror(result);
191 goto failed;
195 if (info3->grpi3_attributes != 0) {
196 info.attributes.attributes = info3->grpi3_attributes;
197 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
198 &group_handle,
199 GROUPINFOATTRIBUTES,
200 &info,
201 &result);
203 break;
204 default:
205 break;
208 if (!NT_STATUS_IS_OK(status)) {
209 werr = ntstatus_to_werror(status);
210 goto failed;
212 if (!NT_STATUS_IS_OK(result)) {
213 werr = ntstatus_to_werror(result);
214 goto failed;
217 werr = WERR_OK;
218 goto done;
220 failed:
221 dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
222 &group_handle, &result);
224 done:
225 if (is_valid_policy_hnd(&group_handle)) {
226 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
229 if (ctx->disable_policy_handle_cache) {
230 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
231 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
234 return werr;
237 /****************************************************************
238 ****************************************************************/
240 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
241 struct NetGroupAdd *r)
243 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
246 /****************************************************************
247 ****************************************************************/
249 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
250 struct NetGroupDel *r)
252 struct rpc_pipe_client *pipe_cli = NULL;
253 NTSTATUS status, result;
254 WERROR werr;
255 struct policy_handle connect_handle, domain_handle, group_handle;
256 struct lsa_String lsa_group_name;
257 struct dom_sid2 *domain_sid = NULL;
258 int i = 0;
259 struct dcerpc_binding_handle *b = NULL;
261 struct samr_Ids rids;
262 struct samr_Ids types;
263 union samr_GroupInfo *info = NULL;
264 struct samr_RidAttrArray *rid_array = NULL;
266 ZERO_STRUCT(connect_handle);
267 ZERO_STRUCT(domain_handle);
268 ZERO_STRUCT(group_handle);
270 if (!r->in.group_name) {
271 return WERR_INVALID_PARAM;
274 werr = libnetapi_open_pipe(ctx, r->in.server_name,
275 &ndr_table_samr.syntax_id,
276 &pipe_cli);
277 if (!W_ERROR_IS_OK(werr)) {
278 goto done;
281 b = pipe_cli->binding_handle;
283 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
284 SAMR_ACCESS_ENUM_DOMAINS |
285 SAMR_ACCESS_LOOKUP_DOMAIN,
286 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
287 &connect_handle,
288 &domain_handle,
289 &domain_sid);
290 if (!W_ERROR_IS_OK(werr)) {
291 goto done;
294 init_lsa_String(&lsa_group_name, r->in.group_name);
296 status = dcerpc_samr_LookupNames(b, talloc_tos(),
297 &domain_handle,
299 &lsa_group_name,
300 &rids,
301 &types,
302 &result);
303 if (!NT_STATUS_IS_OK(status)) {
304 werr = ntstatus_to_werror(status);
305 goto done;
307 if (!NT_STATUS_IS_OK(result)) {
308 werr = ntstatus_to_werror(result);
309 goto done;
312 if (types.ids[0] != SID_NAME_DOM_GRP) {
313 werr = WERR_INVALID_DATATYPE;
314 goto done;
317 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
318 &domain_handle,
319 SEC_STD_DELETE |
320 SAMR_GROUP_ACCESS_GET_MEMBERS |
321 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
322 SAMR_GROUP_ACCESS_ADD_MEMBER |
323 SAMR_GROUP_ACCESS_LOOKUP_INFO,
324 rids.ids[0],
325 &group_handle,
326 &result);
327 if (!NT_STATUS_IS_OK(status)) {
328 werr = ntstatus_to_werror(status);
329 goto done;
331 if (!NT_STATUS_IS_OK(result)) {
332 werr = ntstatus_to_werror(result);
333 goto done;
336 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
337 &group_handle,
338 GROUPINFOATTRIBUTES,
339 &info,
340 &result);
341 if (!NT_STATUS_IS_OK(status)) {
342 werr = ntstatus_to_werror(status);
343 goto done;
345 if (!NT_STATUS_IS_OK(result)) {
346 werr = ntstatus_to_werror(result);
347 goto done;
350 #if 0
351 /* breaks against NT4 */
352 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
353 werr = WERR_ACCESS_DENIED;
354 goto done;
356 #endif
357 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
358 &group_handle,
359 &rid_array,
360 &result);
361 if (!NT_STATUS_IS_OK(status)) {
362 werr = ntstatus_to_werror(status);
363 goto done;
365 if (!NT_STATUS_IS_OK(result)) {
366 werr = ntstatus_to_werror(result);
367 goto done;
371 struct lsa_Strings names;
372 struct samr_Ids member_types;
374 status = dcerpc_samr_LookupRids(b, talloc_tos(),
375 &domain_handle,
376 rid_array->count,
377 rid_array->rids,
378 &names,
379 &member_types,
380 &result);
381 if (!NT_STATUS_IS_OK(status)) {
382 werr = ntstatus_to_werror(status);
383 goto done;
385 if (!NT_STATUS_IS_OK(result)) {
386 werr = ntstatus_to_werror(result);
387 goto done;
391 for (i=0; i < rid_array->count; i++) {
393 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
394 &group_handle,
395 rid_array->rids[i],
396 &result);
397 if (!NT_STATUS_IS_OK(status)) {
398 werr = ntstatus_to_werror(status);
399 goto done;
401 if (!NT_STATUS_IS_OK(result)) {
402 werr = ntstatus_to_werror(result);
403 goto done;
407 status = dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
408 &group_handle,
409 &result);
410 if (!NT_STATUS_IS_OK(status)) {
411 werr = ntstatus_to_werror(status);
412 goto done;
414 if (!NT_STATUS_IS_OK(result)) {
415 werr = ntstatus_to_werror(result);
416 goto done;
419 ZERO_STRUCT(group_handle);
421 werr = WERR_OK;
423 done:
424 if (is_valid_policy_hnd(&group_handle)) {
425 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
428 if (ctx->disable_policy_handle_cache) {
429 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
430 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
433 return werr;
436 /****************************************************************
437 ****************************************************************/
439 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
440 struct NetGroupDel *r)
442 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
445 /****************************************************************
446 ****************************************************************/
448 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
449 struct NetGroupSetInfo *r)
451 struct rpc_pipe_client *pipe_cli = NULL;
452 NTSTATUS status, result;
453 WERROR werr;
454 struct policy_handle connect_handle, domain_handle, group_handle;
455 struct lsa_String lsa_group_name;
456 struct dom_sid2 *domain_sid = NULL;
457 struct dcerpc_binding_handle *b = NULL;
459 struct samr_Ids rids;
460 struct samr_Ids types;
461 union samr_GroupInfo info;
462 struct GROUP_INFO_0 *g0;
463 struct GROUP_INFO_1 *g1;
464 struct GROUP_INFO_2 *g2;
465 struct GROUP_INFO_3 *g3;
466 struct GROUP_INFO_1002 *g1002;
467 struct GROUP_INFO_1005 *g1005;
469 ZERO_STRUCT(connect_handle);
470 ZERO_STRUCT(domain_handle);
471 ZERO_STRUCT(group_handle);
473 if (!r->in.group_name) {
474 return WERR_INVALID_PARAM;
477 werr = libnetapi_open_pipe(ctx, r->in.server_name,
478 &ndr_table_samr.syntax_id,
479 &pipe_cli);
480 if (!W_ERROR_IS_OK(werr)) {
481 goto done;
484 b = pipe_cli->binding_handle;
486 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
487 SAMR_ACCESS_ENUM_DOMAINS |
488 SAMR_ACCESS_LOOKUP_DOMAIN,
489 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
490 &connect_handle,
491 &domain_handle,
492 &domain_sid);
493 if (!W_ERROR_IS_OK(werr)) {
494 goto done;
497 init_lsa_String(&lsa_group_name, r->in.group_name);
499 status = dcerpc_samr_LookupNames(b, talloc_tos(),
500 &domain_handle,
502 &lsa_group_name,
503 &rids,
504 &types,
505 &result);
506 if (!NT_STATUS_IS_OK(status)) {
507 werr = ntstatus_to_werror(status);
508 goto done;
510 if (!NT_STATUS_IS_OK(result)) {
511 werr = ntstatus_to_werror(result);
512 goto done;
515 if (types.ids[0] != SID_NAME_DOM_GRP) {
516 werr = WERR_INVALID_DATATYPE;
517 goto done;
520 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
521 &domain_handle,
522 SAMR_GROUP_ACCESS_SET_INFO |
523 SAMR_GROUP_ACCESS_LOOKUP_INFO,
524 rids.ids[0],
525 &group_handle,
526 &result);
527 if (!NT_STATUS_IS_OK(status)) {
528 werr = ntstatus_to_werror(status);
529 goto done;
531 if (!NT_STATUS_IS_OK(result)) {
532 werr = ntstatus_to_werror(result);
533 goto done;
536 switch (r->in.level) {
537 case 0:
538 g0 = (struct GROUP_INFO_0 *)r->in.buffer;
539 init_lsa_String(&info.name, g0->grpi0_name);
540 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
541 &group_handle,
542 GROUPINFONAME,
543 &info,
544 &result);
545 break;
546 case 1:
547 g1 = (struct GROUP_INFO_1 *)r->in.buffer;
548 init_lsa_String(&info.description, g1->grpi1_comment);
549 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
550 &group_handle,
551 GROUPINFODESCRIPTION,
552 &info,
553 &result);
554 break;
555 case 2:
556 g2 = (struct GROUP_INFO_2 *)r->in.buffer;
557 init_lsa_String(&info.description, g2->grpi2_comment);
558 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
559 &group_handle,
560 GROUPINFODESCRIPTION,
561 &info,
562 &result);
563 if (!NT_STATUS_IS_OK(status)) {
564 werr = ntstatus_to_werror(status);
565 goto done;
567 if (!NT_STATUS_IS_OK(result)) {
568 werr = ntstatus_to_werror(result);
569 goto done;
572 info.attributes.attributes = g2->grpi2_attributes;
573 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
574 &group_handle,
575 GROUPINFOATTRIBUTES,
576 &info,
577 &result);
578 break;
579 case 3:
580 g3 = (struct GROUP_INFO_3 *)r->in.buffer;
581 init_lsa_String(&info.description, g3->grpi3_comment);
582 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
583 &group_handle,
584 GROUPINFODESCRIPTION,
585 &info,
586 &result);
587 if (!NT_STATUS_IS_OK(status)) {
588 werr = ntstatus_to_werror(status);
589 goto done;
591 if (!NT_STATUS_IS_OK(result)) {
592 werr = ntstatus_to_werror(result);
593 goto done;
596 info.attributes.attributes = g3->grpi3_attributes;
597 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
598 &group_handle,
599 GROUPINFOATTRIBUTES,
600 &info,
601 &result);
602 break;
603 case 1002:
604 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
605 init_lsa_String(&info.description, g1002->grpi1002_comment);
606 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
607 &group_handle,
608 GROUPINFODESCRIPTION,
609 &info,
610 &result);
611 break;
612 case 1005:
613 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
614 info.attributes.attributes = g1005->grpi1005_attributes;
615 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
616 &group_handle,
617 GROUPINFOATTRIBUTES,
618 &info,
619 &result);
620 break;
621 default:
622 status = NT_STATUS_INVALID_LEVEL;
623 break;
626 if (!NT_STATUS_IS_OK(status)) {
627 werr = ntstatus_to_werror(status);
628 goto done;
630 if (!NT_STATUS_IS_OK(result)) {
631 werr = ntstatus_to_werror(result);
632 goto done;
635 werr = WERR_OK;
637 done:
638 if (is_valid_policy_hnd(&group_handle)) {
639 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
642 if (ctx->disable_policy_handle_cache) {
643 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
644 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
647 return werr;
650 /****************************************************************
651 ****************************************************************/
653 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
654 struct NetGroupSetInfo *r)
656 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
659 /****************************************************************
660 ****************************************************************/
662 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
663 uint32_t level,
664 struct samr_GroupInfoAll *info,
665 struct dom_sid2 *domain_sid,
666 uint32_t rid,
667 uint8_t **buffer)
669 struct GROUP_INFO_0 info0;
670 struct GROUP_INFO_1 info1;
671 struct GROUP_INFO_2 info2;
672 struct GROUP_INFO_3 info3;
673 struct dom_sid sid;
675 switch (level) {
676 case 0:
677 info0.grpi0_name = info->name.string;
679 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
681 break;
682 case 1:
683 info1.grpi1_name = info->name.string;
684 info1.grpi1_comment = info->description.string;
686 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
688 break;
689 case 2:
690 info2.grpi2_name = info->name.string;
691 info2.grpi2_comment = info->description.string;
692 info2.grpi2_group_id = rid;
693 info2.grpi2_attributes = info->attributes;
695 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
697 break;
698 case 3:
699 if (!sid_compose(&sid, domain_sid, rid)) {
700 return WERR_NOMEM;
703 info3.grpi3_name = info->name.string;
704 info3.grpi3_comment = info->description.string;
705 info3.grpi3_attributes = info->attributes;
706 info3.grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
708 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
710 break;
711 default:
712 return WERR_UNKNOWN_LEVEL;
715 W_ERROR_HAVE_NO_MEMORY(*buffer);
717 return WERR_OK;
720 /****************************************************************
721 ****************************************************************/
723 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
724 struct NetGroupGetInfo *r)
726 struct rpc_pipe_client *pipe_cli = NULL;
727 NTSTATUS status, result;
728 WERROR werr;
729 struct policy_handle connect_handle, domain_handle, group_handle;
730 struct lsa_String lsa_group_name;
731 struct dom_sid2 *domain_sid = NULL;
732 struct dcerpc_binding_handle *b = NULL;
734 struct samr_Ids rids;
735 struct samr_Ids types;
736 union samr_GroupInfo *info = NULL;
737 bool group_info_all = false;
739 ZERO_STRUCT(connect_handle);
740 ZERO_STRUCT(domain_handle);
741 ZERO_STRUCT(group_handle);
743 if (!r->in.group_name) {
744 return WERR_INVALID_PARAM;
747 werr = libnetapi_open_pipe(ctx, r->in.server_name,
748 &ndr_table_samr.syntax_id,
749 &pipe_cli);
750 if (!W_ERROR_IS_OK(werr)) {
751 goto done;
754 b = pipe_cli->binding_handle;
756 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
757 SAMR_ACCESS_ENUM_DOMAINS |
758 SAMR_ACCESS_LOOKUP_DOMAIN,
759 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
760 &connect_handle,
761 &domain_handle,
762 &domain_sid);
763 if (!W_ERROR_IS_OK(werr)) {
764 goto done;
767 init_lsa_String(&lsa_group_name, r->in.group_name);
769 status = dcerpc_samr_LookupNames(b, talloc_tos(),
770 &domain_handle,
772 &lsa_group_name,
773 &rids,
774 &types,
775 &result);
776 if (!NT_STATUS_IS_OK(status)) {
777 werr = ntstatus_to_werror(status);
778 goto done;
780 if (!NT_STATUS_IS_OK(result)) {
781 werr = ntstatus_to_werror(result);
782 goto done;
785 if (types.ids[0] != SID_NAME_DOM_GRP) {
786 werr = WERR_INVALID_DATATYPE;
787 goto done;
790 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
791 &domain_handle,
792 SAMR_GROUP_ACCESS_LOOKUP_INFO,
793 rids.ids[0],
794 &group_handle,
795 &result);
796 if (!NT_STATUS_IS_OK(status)) {
797 werr = ntstatus_to_werror(status);
798 goto done;
800 if (!NT_STATUS_IS_OK(result)) {
801 werr = ntstatus_to_werror(result);
802 goto done;
805 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
806 &group_handle,
807 GROUPINFOALL2,
808 &info,
809 &result);
810 if (!NT_STATUS_IS_OK(status)) {
811 werr = ntstatus_to_werror(status);
812 goto done;
815 if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS)) {
816 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
817 &group_handle,
818 GROUPINFOALL,
819 &info,
820 &result);
821 group_info_all = true;
822 if (!NT_STATUS_IS_OK(status)) {
823 werr = ntstatus_to_werror(status);
824 goto done;
828 if (!NT_STATUS_IS_OK(result)) {
829 werr = ntstatus_to_werror(result);
830 goto done;
833 werr = map_group_info_to_buffer(ctx, r->in.level,
834 group_info_all ? &info->all : &info->all2,
835 domain_sid, rids.ids[0],
836 r->out.buffer);
837 if (!W_ERROR_IS_OK(werr)) {
838 goto done;
840 done:
841 if (is_valid_policy_hnd(&group_handle)) {
842 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
845 if (ctx->disable_policy_handle_cache) {
846 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
847 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
850 return werr;
853 /****************************************************************
854 ****************************************************************/
856 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
857 struct NetGroupGetInfo *r)
859 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
862 /****************************************************************
863 ****************************************************************/
865 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
866 struct NetGroupAddUser *r)
868 struct rpc_pipe_client *pipe_cli = NULL;
869 NTSTATUS status, result;
870 WERROR werr;
871 struct policy_handle connect_handle, domain_handle, group_handle;
872 struct lsa_String lsa_group_name, lsa_user_name;
873 struct dom_sid2 *domain_sid = NULL;
874 struct dcerpc_binding_handle *b = NULL;
876 struct samr_Ids rids;
877 struct samr_Ids types;
879 ZERO_STRUCT(connect_handle);
880 ZERO_STRUCT(domain_handle);
881 ZERO_STRUCT(group_handle);
883 if (!r->in.group_name) {
884 return WERR_INVALID_PARAM;
887 werr = libnetapi_open_pipe(ctx, r->in.server_name,
888 &ndr_table_samr.syntax_id,
889 &pipe_cli);
890 if (!W_ERROR_IS_OK(werr)) {
891 goto done;
894 b = pipe_cli->binding_handle;
896 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
897 SAMR_ACCESS_ENUM_DOMAINS |
898 SAMR_ACCESS_LOOKUP_DOMAIN,
899 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
900 &connect_handle,
901 &domain_handle,
902 &domain_sid);
903 if (!W_ERROR_IS_OK(werr)) {
904 goto done;
907 init_lsa_String(&lsa_group_name, r->in.group_name);
909 status = dcerpc_samr_LookupNames(b, talloc_tos(),
910 &domain_handle,
912 &lsa_group_name,
913 &rids,
914 &types,
915 &result);
916 if (!NT_STATUS_IS_OK(status)) {
917 werr = ntstatus_to_werror(status);
918 goto done;
920 if (!NT_STATUS_IS_OK(result)) {
921 werr = WERR_GROUPNOTFOUND;
922 goto done;
925 if (types.ids[0] != SID_NAME_DOM_GRP) {
926 werr = WERR_GROUPNOTFOUND;
927 goto done;
930 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
931 &domain_handle,
932 SAMR_GROUP_ACCESS_ADD_MEMBER,
933 rids.ids[0],
934 &group_handle,
935 &result);
936 if (!NT_STATUS_IS_OK(status)) {
937 werr = ntstatus_to_werror(status);
938 goto done;
940 if (!NT_STATUS_IS_OK(result)) {
941 werr = ntstatus_to_werror(result);
942 goto done;
945 init_lsa_String(&lsa_user_name, r->in.user_name);
947 status = dcerpc_samr_LookupNames(b, talloc_tos(),
948 &domain_handle,
950 &lsa_user_name,
951 &rids,
952 &types,
953 &result);
954 if (!NT_STATUS_IS_OK(status)) {
955 werr = ntstatus_to_werror(status);
956 goto done;
958 if (!NT_STATUS_IS_OK(result)) {
959 werr = WERR_USER_NOT_FOUND;
960 goto done;
963 if (types.ids[0] != SID_NAME_USER) {
964 werr = WERR_USER_NOT_FOUND;
965 goto done;
968 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
969 &group_handle,
970 rids.ids[0],
971 7, /* why ? */
972 &result);
973 if (!NT_STATUS_IS_OK(status)) {
974 werr = ntstatus_to_werror(status);
975 goto done;
977 if (!NT_STATUS_IS_OK(result)) {
978 werr = ntstatus_to_werror(result);
979 goto done;
982 werr = WERR_OK;
984 done:
985 if (is_valid_policy_hnd(&group_handle)) {
986 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
989 if (ctx->disable_policy_handle_cache) {
990 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
991 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
994 return werr;
997 /****************************************************************
998 ****************************************************************/
1000 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
1001 struct NetGroupAddUser *r)
1003 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
1006 /****************************************************************
1007 ****************************************************************/
1009 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
1010 struct NetGroupDelUser *r)
1012 struct rpc_pipe_client *pipe_cli = NULL;
1013 NTSTATUS status, result;
1014 WERROR werr;
1015 struct policy_handle connect_handle, domain_handle, group_handle;
1016 struct lsa_String lsa_group_name, lsa_user_name;
1017 struct dom_sid2 *domain_sid = NULL;
1018 struct dcerpc_binding_handle *b = NULL;
1020 struct samr_Ids rids;
1021 struct samr_Ids types;
1023 ZERO_STRUCT(connect_handle);
1024 ZERO_STRUCT(domain_handle);
1025 ZERO_STRUCT(group_handle);
1027 if (!r->in.group_name) {
1028 return WERR_INVALID_PARAM;
1031 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1032 &ndr_table_samr.syntax_id,
1033 &pipe_cli);
1034 if (!W_ERROR_IS_OK(werr)) {
1035 goto done;
1038 b = pipe_cli->binding_handle;
1040 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1041 SAMR_ACCESS_ENUM_DOMAINS |
1042 SAMR_ACCESS_LOOKUP_DOMAIN,
1043 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1044 &connect_handle,
1045 &domain_handle,
1046 &domain_sid);
1047 if (!W_ERROR_IS_OK(werr)) {
1048 goto done;
1051 init_lsa_String(&lsa_group_name, r->in.group_name);
1053 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1054 &domain_handle,
1056 &lsa_group_name,
1057 &rids,
1058 &types,
1059 &result);
1060 if (!NT_STATUS_IS_OK(status)) {
1061 werr = ntstatus_to_werror(status);
1062 goto done;
1064 if (!NT_STATUS_IS_OK(result)) {
1065 werr = WERR_GROUPNOTFOUND;
1066 goto done;
1069 if (types.ids[0] != SID_NAME_DOM_GRP) {
1070 werr = WERR_GROUPNOTFOUND;
1071 goto done;
1074 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1075 &domain_handle,
1076 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
1077 rids.ids[0],
1078 &group_handle,
1079 &result);
1080 if (!NT_STATUS_IS_OK(status)) {
1081 werr = ntstatus_to_werror(status);
1082 goto done;
1084 if (!NT_STATUS_IS_OK(result)) {
1085 werr = ntstatus_to_werror(result);
1086 goto done;
1089 init_lsa_String(&lsa_user_name, r->in.user_name);
1091 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1092 &domain_handle,
1094 &lsa_user_name,
1095 &rids,
1096 &types,
1097 &result);
1098 if (!NT_STATUS_IS_OK(status)) {
1099 werr = ntstatus_to_werror(status);
1100 goto done;
1103 if (!NT_STATUS_IS_OK(result)) {
1104 werr = WERR_USER_NOT_FOUND;
1105 goto done;
1108 if (types.ids[0] != SID_NAME_USER) {
1109 werr = WERR_USER_NOT_FOUND;
1110 goto done;
1113 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1114 &group_handle,
1115 rids.ids[0],
1116 &result);
1117 if (!NT_STATUS_IS_OK(status)) {
1118 werr = ntstatus_to_werror(status);
1119 goto done;
1121 if (!NT_STATUS_IS_OK(result)) {
1122 werr = ntstatus_to_werror(result);
1123 goto done;
1126 werr = WERR_OK;
1128 done:
1129 if (is_valid_policy_hnd(&group_handle)) {
1130 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1133 if (ctx->disable_policy_handle_cache) {
1134 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1135 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1138 return werr;
1141 /****************************************************************
1142 ****************************************************************/
1144 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1145 struct NetGroupDelUser *r)
1147 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
1150 /****************************************************************
1151 ****************************************************************/
1153 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
1154 struct samr_DispInfoFullGroups *groups,
1155 uint8_t **buffer)
1157 struct GROUP_INFO_0 *g0;
1158 int i;
1160 g0 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_0, groups->count);
1161 W_ERROR_HAVE_NO_MEMORY(g0);
1163 for (i=0; i<groups->count; i++) {
1164 g0[i].grpi0_name = talloc_strdup(mem_ctx,
1165 groups->entries[i].account_name.string);
1166 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
1169 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
1170 sizeof(struct GROUP_INFO_0) * groups->count);
1171 W_ERROR_HAVE_NO_MEMORY(*buffer);
1173 return WERR_OK;
1176 /****************************************************************
1177 ****************************************************************/
1179 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1180 struct samr_DispInfoFullGroups *groups,
1181 uint8_t **buffer)
1183 struct GROUP_INFO_1 *g1;
1184 int i;
1186 g1 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_1, groups->count);
1187 W_ERROR_HAVE_NO_MEMORY(g1);
1189 for (i=0; i<groups->count; i++) {
1190 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1191 groups->entries[i].account_name.string);
1192 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1193 groups->entries[i].description.string);
1194 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1197 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1198 sizeof(struct GROUP_INFO_1) * groups->count);
1199 W_ERROR_HAVE_NO_MEMORY(*buffer);
1201 return WERR_OK;
1204 /****************************************************************
1205 ****************************************************************/
1207 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1208 struct samr_DispInfoFullGroups *groups,
1209 uint8_t **buffer)
1211 struct GROUP_INFO_2 *g2;
1212 int i;
1214 g2 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_2, groups->count);
1215 W_ERROR_HAVE_NO_MEMORY(g2);
1217 for (i=0; i<groups->count; i++) {
1218 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1219 groups->entries[i].account_name.string);
1220 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1221 groups->entries[i].description.string);
1222 g2[i].grpi2_group_id = groups->entries[i].rid;
1223 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1224 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1227 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1228 sizeof(struct GROUP_INFO_2) * groups->count);
1229 W_ERROR_HAVE_NO_MEMORY(*buffer);
1231 return WERR_OK;
1234 /****************************************************************
1235 ****************************************************************/
1237 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1238 struct samr_DispInfoFullGroups *groups,
1239 const struct dom_sid *domain_sid,
1240 uint8_t **buffer)
1242 struct GROUP_INFO_3 *g3;
1243 int i;
1245 g3 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_3, groups->count);
1246 W_ERROR_HAVE_NO_MEMORY(g3);
1248 for (i=0; i<groups->count; i++) {
1250 struct dom_sid sid;
1252 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1253 return WERR_NOMEM;
1256 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1257 groups->entries[i].account_name.string);
1258 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1259 groups->entries[i].description.string);
1260 g3[i].grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
1261 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1262 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1265 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1266 sizeof(struct GROUP_INFO_3) * groups->count);
1267 W_ERROR_HAVE_NO_MEMORY(*buffer);
1269 return WERR_OK;
1272 /****************************************************************
1273 ****************************************************************/
1275 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1276 uint32_t level,
1277 struct samr_DispInfoFullGroups *groups,
1278 const struct dom_sid *domain_sid,
1279 uint32_t *entries_read,
1280 uint8_t **buffer)
1282 if (entries_read) {
1283 *entries_read = groups->count;
1286 switch (level) {
1287 case 0:
1288 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1289 case 1:
1290 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1291 case 2:
1292 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1293 case 3:
1294 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1295 default:
1296 return WERR_UNKNOWN_LEVEL;
1300 /****************************************************************
1301 ****************************************************************/
1303 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1304 struct NetGroupEnum *r)
1306 struct rpc_pipe_client *pipe_cli = NULL;
1307 struct policy_handle connect_handle;
1308 struct dom_sid2 *domain_sid = NULL;
1309 struct policy_handle domain_handle;
1310 union samr_DispInfo info;
1311 union samr_DomainInfo *domain_info = NULL;
1312 struct dcerpc_binding_handle *b = NULL;
1314 uint32_t total_size = 0;
1315 uint32_t returned_size = 0;
1317 NTSTATUS result = NT_STATUS_OK;
1318 NTSTATUS status = NT_STATUS_OK;
1319 WERROR werr, tmp_werr;
1321 ZERO_STRUCT(connect_handle);
1322 ZERO_STRUCT(domain_handle);
1324 switch (r->in.level) {
1325 case 0:
1326 case 1:
1327 case 2:
1328 case 3:
1329 break;
1330 default:
1331 return WERR_UNKNOWN_LEVEL;
1334 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1335 &ndr_table_samr.syntax_id,
1336 &pipe_cli);
1337 if (!W_ERROR_IS_OK(werr)) {
1338 goto done;
1341 b = pipe_cli->binding_handle;
1343 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1344 SAMR_ACCESS_ENUM_DOMAINS |
1345 SAMR_ACCESS_LOOKUP_DOMAIN,
1346 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1347 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1348 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1349 &connect_handle,
1350 &domain_handle,
1351 &domain_sid);
1352 if (!W_ERROR_IS_OK(werr)) {
1353 goto done;
1356 status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
1357 &domain_handle,
1359 &domain_info,
1360 &result);
1361 if (!NT_STATUS_IS_OK(status)) {
1362 werr = ntstatus_to_werror(status);
1363 goto done;
1365 if (!NT_STATUS_IS_OK(result)) {
1366 werr = ntstatus_to_werror(result);
1367 goto done;
1370 if (r->out.total_entries) {
1371 *r->out.total_entries = domain_info->general.num_groups;
1374 status = dcerpc_samr_QueryDisplayInfo2(b,
1375 ctx,
1376 &domain_handle,
1378 r->in.resume_handle ?
1379 *r->in.resume_handle : 0,
1380 (uint32_t)-1,
1381 r->in.prefmaxlen,
1382 &total_size,
1383 &returned_size,
1384 &info,
1385 &result);
1386 if (!NT_STATUS_IS_OK(status)) {
1387 werr = ntstatus_to_werror(status);
1388 goto done;
1391 werr = ntstatus_to_werror(result);
1392 if (NT_STATUS_IS_ERR(result)) {
1393 goto done;
1396 if (r->out.resume_handle && info.info3.count > 0) {
1397 *r->out.resume_handle =
1398 info.info3.entries[info.info3.count-1].idx;
1401 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1402 r->in.level,
1403 &info.info3,
1404 domain_sid,
1405 r->out.entries_read,
1406 r->out.buffer);
1407 if (!W_ERROR_IS_OK(tmp_werr)) {
1408 werr = tmp_werr;
1409 goto done;
1412 done:
1413 /* if last query */
1414 if (NT_STATUS_IS_OK(result) ||
1415 NT_STATUS_IS_ERR(result)) {
1417 if (ctx->disable_policy_handle_cache) {
1418 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1419 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1423 return werr;
1426 /****************************************************************
1427 ****************************************************************/
1429 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1430 struct NetGroupEnum *r)
1432 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1435 /****************************************************************
1436 ****************************************************************/
1438 WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1439 struct NetGroupGetUsers *r)
1441 /* FIXME: this call needs to cope with large replies */
1443 struct rpc_pipe_client *pipe_cli = NULL;
1444 struct policy_handle connect_handle, domain_handle, group_handle;
1445 struct lsa_String lsa_account_name;
1446 struct dom_sid2 *domain_sid = NULL;
1447 struct samr_Ids group_rids, name_types;
1448 struct samr_RidAttrArray *rid_array = NULL;
1449 struct lsa_Strings names;
1450 struct samr_Ids member_types;
1451 struct dcerpc_binding_handle *b = NULL;
1453 int i;
1454 uint32_t entries_read = 0;
1456 NTSTATUS status = NT_STATUS_OK;
1457 NTSTATUS result = NT_STATUS_OK;
1458 WERROR werr;
1460 ZERO_STRUCT(connect_handle);
1461 ZERO_STRUCT(domain_handle);
1463 if (!r->out.buffer) {
1464 return WERR_INVALID_PARAM;
1467 *r->out.buffer = NULL;
1468 *r->out.entries_read = 0;
1469 *r->out.total_entries = 0;
1471 switch (r->in.level) {
1472 case 0:
1473 case 1:
1474 break;
1475 default:
1476 return WERR_UNKNOWN_LEVEL;
1480 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1481 &ndr_table_samr.syntax_id,
1482 &pipe_cli);
1483 if (!W_ERROR_IS_OK(werr)) {
1484 goto done;
1487 b = pipe_cli->binding_handle;
1489 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1490 SAMR_ACCESS_ENUM_DOMAINS |
1491 SAMR_ACCESS_LOOKUP_DOMAIN,
1492 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1493 &connect_handle,
1494 &domain_handle,
1495 &domain_sid);
1496 if (!W_ERROR_IS_OK(werr)) {
1497 goto done;
1500 init_lsa_String(&lsa_account_name, r->in.group_name);
1502 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1503 &domain_handle,
1505 &lsa_account_name,
1506 &group_rids,
1507 &name_types,
1508 &result);
1509 if (!NT_STATUS_IS_OK(status)) {
1510 werr = ntstatus_to_werror(status);
1511 goto done;
1513 if (!NT_STATUS_IS_OK(result)) {
1514 werr = ntstatus_to_werror(result);
1515 goto done;
1518 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1519 &domain_handle,
1520 SAMR_GROUP_ACCESS_GET_MEMBERS,
1521 group_rids.ids[0],
1522 &group_handle,
1523 &result);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 werr = ntstatus_to_werror(status);
1526 goto done;
1528 if (!NT_STATUS_IS_OK(result)) {
1529 werr = ntstatus_to_werror(result);
1530 goto done;
1533 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1534 &group_handle,
1535 &rid_array,
1536 &result);
1537 if (!NT_STATUS_IS_OK(status)) {
1538 werr = ntstatus_to_werror(status);
1539 goto done;
1541 if (!NT_STATUS_IS_OK(result)) {
1542 werr = ntstatus_to_werror(result);
1543 goto done;
1546 status = dcerpc_samr_LookupRids(b, talloc_tos(),
1547 &domain_handle,
1548 rid_array->count,
1549 rid_array->rids,
1550 &names,
1551 &member_types,
1552 &result);
1553 if (!NT_STATUS_IS_OK(status)) {
1554 werr = ntstatus_to_werror(status);
1555 goto done;
1557 if (!NT_STATUS_IS_OK(result)) {
1558 werr = ntstatus_to_werror(result);
1559 goto done;
1562 for (i=0; i < names.count; i++) {
1564 if (member_types.ids[i] != SID_NAME_USER) {
1565 continue;
1568 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1569 r->in.level,
1570 names.names[i].string,
1572 r->out.buffer,
1573 &entries_read);
1574 if (!NT_STATUS_IS_OK(status)) {
1575 werr = ntstatus_to_werror(status);
1576 goto done;
1580 *r->out.entries_read = entries_read;
1581 *r->out.total_entries = entries_read;
1583 werr = WERR_OK;
1585 done:
1586 if (is_valid_policy_hnd(&group_handle)) {
1587 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1590 if (ctx->disable_policy_handle_cache) {
1591 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1592 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1595 return werr;
1598 /****************************************************************
1599 ****************************************************************/
1601 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1602 struct NetGroupGetUsers *r)
1604 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1607 /****************************************************************
1608 ****************************************************************/
1610 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1611 struct NetGroupSetUsers *r)
1613 struct rpc_pipe_client *pipe_cli = NULL;
1614 struct policy_handle connect_handle, domain_handle, group_handle;
1615 struct lsa_String lsa_account_name;
1616 struct dom_sid2 *domain_sid = NULL;
1617 union samr_GroupInfo *group_info = NULL;
1618 struct samr_Ids user_rids, name_types;
1619 struct samr_Ids group_rids, group_types;
1620 struct samr_RidAttrArray *rid_array = NULL;
1621 struct lsa_String *lsa_names = NULL;
1622 struct dcerpc_binding_handle *b = NULL;
1624 uint32_t *add_rids = NULL;
1625 uint32_t *del_rids = NULL;
1626 size_t num_add_rids = 0;
1627 size_t num_del_rids = 0;
1629 uint32_t *member_rids = NULL;
1631 struct GROUP_USERS_INFO_0 *i0 = NULL;
1632 struct GROUP_USERS_INFO_1 *i1 = NULL;
1634 int i, k;
1636 NTSTATUS status = NT_STATUS_OK;
1637 NTSTATUS result = NT_STATUS_OK;
1638 WERROR werr;
1640 ZERO_STRUCT(connect_handle);
1641 ZERO_STRUCT(domain_handle);
1643 if (!r->in.buffer) {
1644 return WERR_INVALID_PARAM;
1647 switch (r->in.level) {
1648 case 0:
1649 case 1:
1650 break;
1651 default:
1652 return WERR_UNKNOWN_LEVEL;
1655 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1656 &ndr_table_samr.syntax_id,
1657 &pipe_cli);
1658 if (!W_ERROR_IS_OK(werr)) {
1659 goto done;
1662 b = pipe_cli->binding_handle;
1664 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1665 SAMR_ACCESS_ENUM_DOMAINS |
1666 SAMR_ACCESS_LOOKUP_DOMAIN,
1667 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1668 &connect_handle,
1669 &domain_handle,
1670 &domain_sid);
1671 if (!W_ERROR_IS_OK(werr)) {
1672 goto done;
1675 init_lsa_String(&lsa_account_name, r->in.group_name);
1677 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1678 &domain_handle,
1680 &lsa_account_name,
1681 &group_rids,
1682 &group_types,
1683 &result);
1684 if (!NT_STATUS_IS_OK(status)) {
1685 werr = ntstatus_to_werror(status);
1686 goto done;
1688 if (!NT_STATUS_IS_OK(result)) {
1689 werr = ntstatus_to_werror(result);
1690 goto done;
1693 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1694 &domain_handle,
1695 SAMR_GROUP_ACCESS_GET_MEMBERS |
1696 SAMR_GROUP_ACCESS_ADD_MEMBER |
1697 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1698 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1699 group_rids.ids[0],
1700 &group_handle,
1701 &result);
1702 if (!NT_STATUS_IS_OK(status)) {
1703 werr = ntstatus_to_werror(status);
1704 goto done;
1706 if (!NT_STATUS_IS_OK(result)) {
1707 werr = ntstatus_to_werror(result);
1708 goto done;
1711 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
1712 &group_handle,
1713 GROUPINFOATTRIBUTES,
1714 &group_info,
1715 &result);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 werr = ntstatus_to_werror(status);
1718 goto done;
1720 if (!NT_STATUS_IS_OK(result)) {
1721 werr = ntstatus_to_werror(result);
1722 goto done;
1725 switch (r->in.level) {
1726 case 0:
1727 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1728 break;
1729 case 1:
1730 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1731 break;
1734 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1735 if (!lsa_names) {
1736 werr = WERR_NOMEM;
1737 goto done;
1740 for (i=0; i < r->in.num_entries; i++) {
1742 switch (r->in.level) {
1743 case 0:
1744 init_lsa_String(&lsa_names[i], i0->grui0_name);
1745 i0++;
1746 break;
1747 case 1:
1748 init_lsa_String(&lsa_names[i], i1->grui1_name);
1749 i1++;
1750 break;
1754 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1755 &domain_handle,
1756 r->in.num_entries,
1757 lsa_names,
1758 &user_rids,
1759 &name_types,
1760 &result);
1761 if (!NT_STATUS_IS_OK(status)) {
1762 werr = ntstatus_to_werror(status);
1763 goto done;
1765 if (!NT_STATUS_IS_OK(result)) {
1766 werr = ntstatus_to_werror(result);
1767 goto done;
1770 member_rids = user_rids.ids;
1772 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1773 &group_handle,
1774 &rid_array,
1775 &result);
1776 if (!NT_STATUS_IS_OK(status)) {
1777 werr = ntstatus_to_werror(status);
1778 goto done;
1780 if (!NT_STATUS_IS_OK(result)) {
1781 werr = ntstatus_to_werror(result);
1782 goto done;
1785 /* add list */
1787 for (i=0; i < r->in.num_entries; i++) {
1788 bool already_member = false;
1789 for (k=0; k < rid_array->count; k++) {
1790 if (member_rids[i] == rid_array->rids[k]) {
1791 already_member = true;
1792 break;
1795 if (!already_member) {
1796 if (!add_rid_to_array_unique(ctx,
1797 member_rids[i],
1798 &add_rids, &num_add_rids)) {
1799 werr = WERR_GENERAL_FAILURE;
1800 goto done;
1805 /* del list */
1807 for (k=0; k < rid_array->count; k++) {
1808 bool keep_member = false;
1809 for (i=0; i < r->in.num_entries; i++) {
1810 if (member_rids[i] == rid_array->rids[k]) {
1811 keep_member = true;
1812 break;
1815 if (!keep_member) {
1816 if (!add_rid_to_array_unique(ctx,
1817 rid_array->rids[k],
1818 &del_rids, &num_del_rids)) {
1819 werr = WERR_GENERAL_FAILURE;
1820 goto done;
1825 /* add list */
1827 for (i=0; i < num_add_rids; i++) {
1828 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
1829 &group_handle,
1830 add_rids[i],
1831 7 /* ? */,
1832 &result);
1833 if (!NT_STATUS_IS_OK(status)) {
1834 werr = ntstatus_to_werror(status);
1835 goto done;
1837 if (!NT_STATUS_IS_OK(result)) {
1838 werr = ntstatus_to_werror(result);
1839 goto done;
1843 /* del list */
1845 for (i=0; i < num_del_rids; i++) {
1846 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1847 &group_handle,
1848 del_rids[i],
1849 &result);
1850 if (!NT_STATUS_IS_OK(status)) {
1851 werr = ntstatus_to_werror(status);
1852 goto done;
1854 if (!NT_STATUS_IS_OK(result)) {
1855 werr = ntstatus_to_werror(result);
1856 goto done;
1860 werr = WERR_OK;
1862 done:
1863 if (is_valid_policy_hnd(&group_handle)) {
1864 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1867 if (ctx->disable_policy_handle_cache) {
1868 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1869 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1872 return werr;
1875 /****************************************************************
1876 ****************************************************************/
1878 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1879 struct NetGroupSetUsers *r)
1881 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);