librpc: Shorten dcerpc_binding_handle_call a bit
[Samba/gebeck_regimport.git] / source3 / lib / netapi / group.c
blob9813f7eacb3639b975e0f710e07a48c9864c79e7
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);
1462 ZERO_STRUCT(group_handle);
1464 if (!r->out.buffer) {
1465 return WERR_INVALID_PARAM;
1468 *r->out.buffer = NULL;
1469 *r->out.entries_read = 0;
1470 *r->out.total_entries = 0;
1472 switch (r->in.level) {
1473 case 0:
1474 case 1:
1475 break;
1476 default:
1477 return WERR_UNKNOWN_LEVEL;
1481 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1482 &ndr_table_samr.syntax_id,
1483 &pipe_cli);
1484 if (!W_ERROR_IS_OK(werr)) {
1485 goto done;
1488 b = pipe_cli->binding_handle;
1490 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1491 SAMR_ACCESS_ENUM_DOMAINS |
1492 SAMR_ACCESS_LOOKUP_DOMAIN,
1493 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1494 &connect_handle,
1495 &domain_handle,
1496 &domain_sid);
1497 if (!W_ERROR_IS_OK(werr)) {
1498 goto done;
1501 init_lsa_String(&lsa_account_name, r->in.group_name);
1503 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1504 &domain_handle,
1506 &lsa_account_name,
1507 &group_rids,
1508 &name_types,
1509 &result);
1510 if (!NT_STATUS_IS_OK(status)) {
1511 werr = ntstatus_to_werror(status);
1512 goto done;
1514 if (!NT_STATUS_IS_OK(result)) {
1515 werr = ntstatus_to_werror(result);
1516 goto done;
1519 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1520 &domain_handle,
1521 SAMR_GROUP_ACCESS_GET_MEMBERS,
1522 group_rids.ids[0],
1523 &group_handle,
1524 &result);
1525 if (!NT_STATUS_IS_OK(status)) {
1526 werr = ntstatus_to_werror(status);
1527 goto done;
1529 if (!NT_STATUS_IS_OK(result)) {
1530 werr = ntstatus_to_werror(result);
1531 goto done;
1534 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1535 &group_handle,
1536 &rid_array,
1537 &result);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 werr = ntstatus_to_werror(status);
1540 goto done;
1542 if (!NT_STATUS_IS_OK(result)) {
1543 werr = ntstatus_to_werror(result);
1544 goto done;
1547 status = dcerpc_samr_LookupRids(b, talloc_tos(),
1548 &domain_handle,
1549 rid_array->count,
1550 rid_array->rids,
1551 &names,
1552 &member_types,
1553 &result);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 werr = ntstatus_to_werror(status);
1556 goto done;
1558 if (!NT_STATUS_IS_OK(result)) {
1559 werr = ntstatus_to_werror(result);
1560 goto done;
1563 for (i=0; i < names.count; i++) {
1565 if (member_types.ids[i] != SID_NAME_USER) {
1566 continue;
1569 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1570 r->in.level,
1571 names.names[i].string,
1573 r->out.buffer,
1574 &entries_read);
1575 if (!NT_STATUS_IS_OK(status)) {
1576 werr = ntstatus_to_werror(status);
1577 goto done;
1581 *r->out.entries_read = entries_read;
1582 *r->out.total_entries = entries_read;
1584 werr = WERR_OK;
1586 done:
1587 if (is_valid_policy_hnd(&group_handle)) {
1588 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1591 if (ctx->disable_policy_handle_cache) {
1592 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1593 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1596 return werr;
1599 /****************************************************************
1600 ****************************************************************/
1602 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1603 struct NetGroupGetUsers *r)
1605 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1608 /****************************************************************
1609 ****************************************************************/
1611 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1612 struct NetGroupSetUsers *r)
1614 struct rpc_pipe_client *pipe_cli = NULL;
1615 struct policy_handle connect_handle, domain_handle, group_handle;
1616 struct lsa_String lsa_account_name;
1617 struct dom_sid2 *domain_sid = NULL;
1618 union samr_GroupInfo *group_info = NULL;
1619 struct samr_Ids user_rids, name_types;
1620 struct samr_Ids group_rids, group_types;
1621 struct samr_RidAttrArray *rid_array = NULL;
1622 struct lsa_String *lsa_names = NULL;
1623 struct dcerpc_binding_handle *b = NULL;
1625 uint32_t *add_rids = NULL;
1626 uint32_t *del_rids = NULL;
1627 size_t num_add_rids = 0;
1628 size_t num_del_rids = 0;
1630 uint32_t *member_rids = NULL;
1632 struct GROUP_USERS_INFO_0 *i0 = NULL;
1633 struct GROUP_USERS_INFO_1 *i1 = NULL;
1635 int i, k;
1637 NTSTATUS status = NT_STATUS_OK;
1638 NTSTATUS result = NT_STATUS_OK;
1639 WERROR werr;
1641 ZERO_STRUCT(connect_handle);
1642 ZERO_STRUCT(domain_handle);
1643 ZERO_STRUCT(group_handle);
1645 if (!r->in.buffer) {
1646 return WERR_INVALID_PARAM;
1649 switch (r->in.level) {
1650 case 0:
1651 case 1:
1652 break;
1653 default:
1654 return WERR_UNKNOWN_LEVEL;
1657 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1658 &ndr_table_samr.syntax_id,
1659 &pipe_cli);
1660 if (!W_ERROR_IS_OK(werr)) {
1661 goto done;
1664 b = pipe_cli->binding_handle;
1666 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1667 SAMR_ACCESS_ENUM_DOMAINS |
1668 SAMR_ACCESS_LOOKUP_DOMAIN,
1669 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1670 &connect_handle,
1671 &domain_handle,
1672 &domain_sid);
1673 if (!W_ERROR_IS_OK(werr)) {
1674 goto done;
1677 init_lsa_String(&lsa_account_name, r->in.group_name);
1679 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1680 &domain_handle,
1682 &lsa_account_name,
1683 &group_rids,
1684 &group_types,
1685 &result);
1686 if (!NT_STATUS_IS_OK(status)) {
1687 werr = ntstatus_to_werror(status);
1688 goto done;
1690 if (!NT_STATUS_IS_OK(result)) {
1691 werr = ntstatus_to_werror(result);
1692 goto done;
1695 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1696 &domain_handle,
1697 SAMR_GROUP_ACCESS_GET_MEMBERS |
1698 SAMR_GROUP_ACCESS_ADD_MEMBER |
1699 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1700 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1701 group_rids.ids[0],
1702 &group_handle,
1703 &result);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 werr = ntstatus_to_werror(status);
1706 goto done;
1708 if (!NT_STATUS_IS_OK(result)) {
1709 werr = ntstatus_to_werror(result);
1710 goto done;
1713 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
1714 &group_handle,
1715 GROUPINFOATTRIBUTES,
1716 &group_info,
1717 &result);
1718 if (!NT_STATUS_IS_OK(status)) {
1719 werr = ntstatus_to_werror(status);
1720 goto done;
1722 if (!NT_STATUS_IS_OK(result)) {
1723 werr = ntstatus_to_werror(result);
1724 goto done;
1727 switch (r->in.level) {
1728 case 0:
1729 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1730 break;
1731 case 1:
1732 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1733 break;
1736 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1737 if (!lsa_names) {
1738 werr = WERR_NOMEM;
1739 goto done;
1742 for (i=0; i < r->in.num_entries; i++) {
1744 switch (r->in.level) {
1745 case 0:
1746 init_lsa_String(&lsa_names[i], i0->grui0_name);
1747 i0++;
1748 break;
1749 case 1:
1750 init_lsa_String(&lsa_names[i], i1->grui1_name);
1751 i1++;
1752 break;
1756 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1757 &domain_handle,
1758 r->in.num_entries,
1759 lsa_names,
1760 &user_rids,
1761 &name_types,
1762 &result);
1763 if (!NT_STATUS_IS_OK(status)) {
1764 werr = ntstatus_to_werror(status);
1765 goto done;
1767 if (!NT_STATUS_IS_OK(result)) {
1768 werr = ntstatus_to_werror(result);
1769 goto done;
1772 member_rids = user_rids.ids;
1774 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1775 &group_handle,
1776 &rid_array,
1777 &result);
1778 if (!NT_STATUS_IS_OK(status)) {
1779 werr = ntstatus_to_werror(status);
1780 goto done;
1782 if (!NT_STATUS_IS_OK(result)) {
1783 werr = ntstatus_to_werror(result);
1784 goto done;
1787 /* add list */
1789 for (i=0; i < r->in.num_entries; i++) {
1790 bool already_member = false;
1791 for (k=0; k < rid_array->count; k++) {
1792 if (member_rids[i] == rid_array->rids[k]) {
1793 already_member = true;
1794 break;
1797 if (!already_member) {
1798 if (!add_rid_to_array_unique(ctx,
1799 member_rids[i],
1800 &add_rids, &num_add_rids)) {
1801 werr = WERR_GENERAL_FAILURE;
1802 goto done;
1807 /* del list */
1809 for (k=0; k < rid_array->count; k++) {
1810 bool keep_member = false;
1811 for (i=0; i < r->in.num_entries; i++) {
1812 if (member_rids[i] == rid_array->rids[k]) {
1813 keep_member = true;
1814 break;
1817 if (!keep_member) {
1818 if (!add_rid_to_array_unique(ctx,
1819 rid_array->rids[k],
1820 &del_rids, &num_del_rids)) {
1821 werr = WERR_GENERAL_FAILURE;
1822 goto done;
1827 /* add list */
1829 for (i=0; i < num_add_rids; i++) {
1830 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
1831 &group_handle,
1832 add_rids[i],
1833 7 /* ? */,
1834 &result);
1835 if (!NT_STATUS_IS_OK(status)) {
1836 werr = ntstatus_to_werror(status);
1837 goto done;
1839 if (!NT_STATUS_IS_OK(result)) {
1840 werr = ntstatus_to_werror(result);
1841 goto done;
1845 /* del list */
1847 for (i=0; i < num_del_rids; i++) {
1848 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1849 &group_handle,
1850 del_rids[i],
1851 &result);
1852 if (!NT_STATUS_IS_OK(status)) {
1853 werr = ntstatus_to_werror(status);
1854 goto done;
1856 if (!NT_STATUS_IS_OK(result)) {
1857 werr = ntstatus_to_werror(result);
1858 goto done;
1862 werr = WERR_OK;
1864 done:
1865 if (is_valid_policy_hnd(&group_handle)) {
1866 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1869 if (ctx->disable_policy_handle_cache) {
1870 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1871 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1874 return werr;
1877 /****************************************************************
1878 ****************************************************************/
1880 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1881 struct NetGroupSetUsers *r)
1883 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);