idmap_tdb_common: fix a debug message in idmap_tdb_common_unixid_to_sid()
[Samba/wip.git] / source3 / lib / netapi / group.c
blob6d9b248968a539585de04d8d1d625bb084b9a477
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,
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,
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 (rids.count != 1) {
313 werr = WERR_BAD_NET_RESP;
314 goto done;
316 if (types.count != 1) {
317 werr = WERR_BAD_NET_RESP;
318 goto done;
321 if (types.ids[0] != SID_NAME_DOM_GRP) {
322 werr = WERR_INVALID_DATATYPE;
323 goto done;
326 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
327 &domain_handle,
328 SEC_STD_DELETE |
329 SAMR_GROUP_ACCESS_GET_MEMBERS |
330 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
331 SAMR_GROUP_ACCESS_ADD_MEMBER |
332 SAMR_GROUP_ACCESS_LOOKUP_INFO,
333 rids.ids[0],
334 &group_handle,
335 &result);
336 if (!NT_STATUS_IS_OK(status)) {
337 werr = ntstatus_to_werror(status);
338 goto done;
340 if (!NT_STATUS_IS_OK(result)) {
341 werr = ntstatus_to_werror(result);
342 goto done;
345 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
346 &group_handle,
347 GROUPINFOATTRIBUTES,
348 &info,
349 &result);
350 if (!NT_STATUS_IS_OK(status)) {
351 werr = ntstatus_to_werror(status);
352 goto done;
354 if (!NT_STATUS_IS_OK(result)) {
355 werr = ntstatus_to_werror(result);
356 goto done;
359 #if 0
360 /* breaks against NT4 */
361 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
362 werr = WERR_ACCESS_DENIED;
363 goto done;
365 #endif
366 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
367 &group_handle,
368 &rid_array,
369 &result);
370 if (!NT_STATUS_IS_OK(status)) {
371 werr = ntstatus_to_werror(status);
372 goto done;
374 if (!NT_STATUS_IS_OK(result)) {
375 werr = ntstatus_to_werror(result);
376 goto done;
380 struct lsa_Strings names;
381 struct samr_Ids member_types;
383 status = dcerpc_samr_LookupRids(b, talloc_tos(),
384 &domain_handle,
385 rid_array->count,
386 rid_array->rids,
387 &names,
388 &member_types,
389 &result);
390 if (!NT_STATUS_IS_OK(status)) {
391 werr = ntstatus_to_werror(status);
392 goto done;
394 if (!NT_STATUS_IS_OK(result)) {
395 werr = ntstatus_to_werror(result);
396 goto done;
398 if (names.count != rid_array->count) {
399 werr = WERR_BAD_NET_RESP;
400 goto done;
402 if (member_types.count != rid_array->count) {
403 werr = WERR_BAD_NET_RESP;
404 goto done;
408 for (i=0; i < rid_array->count; i++) {
410 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
411 &group_handle,
412 rid_array->rids[i],
413 &result);
414 if (!NT_STATUS_IS_OK(status)) {
415 werr = ntstatus_to_werror(status);
416 goto done;
418 if (!NT_STATUS_IS_OK(result)) {
419 werr = ntstatus_to_werror(result);
420 goto done;
424 status = dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
425 &group_handle,
426 &result);
427 if (!NT_STATUS_IS_OK(status)) {
428 werr = ntstatus_to_werror(status);
429 goto done;
431 if (!NT_STATUS_IS_OK(result)) {
432 werr = ntstatus_to_werror(result);
433 goto done;
436 ZERO_STRUCT(group_handle);
438 werr = WERR_OK;
440 done:
441 if (is_valid_policy_hnd(&group_handle)) {
442 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
445 if (ctx->disable_policy_handle_cache) {
446 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
447 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
450 return werr;
453 /****************************************************************
454 ****************************************************************/
456 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
457 struct NetGroupDel *r)
459 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
462 /****************************************************************
463 ****************************************************************/
465 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
466 struct NetGroupSetInfo *r)
468 struct rpc_pipe_client *pipe_cli = NULL;
469 NTSTATUS status, result;
470 WERROR werr;
471 struct policy_handle connect_handle, domain_handle, group_handle;
472 struct lsa_String lsa_group_name;
473 struct dom_sid2 *domain_sid = NULL;
474 struct dcerpc_binding_handle *b = NULL;
476 struct samr_Ids rids;
477 struct samr_Ids types;
478 union samr_GroupInfo info;
479 struct GROUP_INFO_0 *g0;
480 struct GROUP_INFO_1 *g1;
481 struct GROUP_INFO_2 *g2;
482 struct GROUP_INFO_3 *g3;
483 struct GROUP_INFO_1002 *g1002;
484 struct GROUP_INFO_1005 *g1005;
486 ZERO_STRUCT(connect_handle);
487 ZERO_STRUCT(domain_handle);
488 ZERO_STRUCT(group_handle);
490 if (!r->in.group_name) {
491 return WERR_INVALID_PARAM;
494 werr = libnetapi_open_pipe(ctx, r->in.server_name,
495 &ndr_table_samr,
496 &pipe_cli);
497 if (!W_ERROR_IS_OK(werr)) {
498 goto done;
501 b = pipe_cli->binding_handle;
503 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
504 SAMR_ACCESS_ENUM_DOMAINS |
505 SAMR_ACCESS_LOOKUP_DOMAIN,
506 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
507 &connect_handle,
508 &domain_handle,
509 &domain_sid);
510 if (!W_ERROR_IS_OK(werr)) {
511 goto done;
514 init_lsa_String(&lsa_group_name, r->in.group_name);
516 status = dcerpc_samr_LookupNames(b, talloc_tos(),
517 &domain_handle,
519 &lsa_group_name,
520 &rids,
521 &types,
522 &result);
523 if (!NT_STATUS_IS_OK(status)) {
524 werr = ntstatus_to_werror(status);
525 goto done;
527 if (!NT_STATUS_IS_OK(result)) {
528 werr = ntstatus_to_werror(result);
529 goto done;
531 if (rids.count != 1) {
532 werr = WERR_BAD_NET_RESP;
533 goto done;
535 if (types.count != 1) {
536 werr = WERR_BAD_NET_RESP;
537 goto done;
540 if (types.ids[0] != SID_NAME_DOM_GRP) {
541 werr = WERR_INVALID_DATATYPE;
542 goto done;
545 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
546 &domain_handle,
547 SAMR_GROUP_ACCESS_SET_INFO |
548 SAMR_GROUP_ACCESS_LOOKUP_INFO,
549 rids.ids[0],
550 &group_handle,
551 &result);
552 if (!NT_STATUS_IS_OK(status)) {
553 werr = ntstatus_to_werror(status);
554 goto done;
556 if (!NT_STATUS_IS_OK(result)) {
557 werr = ntstatus_to_werror(result);
558 goto done;
561 switch (r->in.level) {
562 case 0:
563 g0 = (struct GROUP_INFO_0 *)r->in.buffer;
564 init_lsa_String(&info.name, g0->grpi0_name);
565 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
566 &group_handle,
567 GROUPINFONAME,
568 &info,
569 &result);
570 break;
571 case 1:
572 g1 = (struct GROUP_INFO_1 *)r->in.buffer;
573 init_lsa_String(&info.description, g1->grpi1_comment);
574 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
575 &group_handle,
576 GROUPINFODESCRIPTION,
577 &info,
578 &result);
579 break;
580 case 2:
581 g2 = (struct GROUP_INFO_2 *)r->in.buffer;
582 init_lsa_String(&info.description, g2->grpi2_comment);
583 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
584 &group_handle,
585 GROUPINFODESCRIPTION,
586 &info,
587 &result);
588 if (!NT_STATUS_IS_OK(status)) {
589 werr = ntstatus_to_werror(status);
590 goto done;
592 if (!NT_STATUS_IS_OK(result)) {
593 werr = ntstatus_to_werror(result);
594 goto done;
597 info.attributes.attributes = g2->grpi2_attributes;
598 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
599 &group_handle,
600 GROUPINFOATTRIBUTES,
601 &info,
602 &result);
603 break;
604 case 3:
605 g3 = (struct GROUP_INFO_3 *)r->in.buffer;
606 init_lsa_String(&info.description, g3->grpi3_comment);
607 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
608 &group_handle,
609 GROUPINFODESCRIPTION,
610 &info,
611 &result);
612 if (!NT_STATUS_IS_OK(status)) {
613 werr = ntstatus_to_werror(status);
614 goto done;
616 if (!NT_STATUS_IS_OK(result)) {
617 werr = ntstatus_to_werror(result);
618 goto done;
621 info.attributes.attributes = g3->grpi3_attributes;
622 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
623 &group_handle,
624 GROUPINFOATTRIBUTES,
625 &info,
626 &result);
627 break;
628 case 1002:
629 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
630 init_lsa_String(&info.description, g1002->grpi1002_comment);
631 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
632 &group_handle,
633 GROUPINFODESCRIPTION,
634 &info,
635 &result);
636 break;
637 case 1005:
638 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
639 info.attributes.attributes = g1005->grpi1005_attributes;
640 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
641 &group_handle,
642 GROUPINFOATTRIBUTES,
643 &info,
644 &result);
645 break;
646 default:
647 status = NT_STATUS_INVALID_LEVEL;
648 break;
651 if (!NT_STATUS_IS_OK(status)) {
652 werr = ntstatus_to_werror(status);
653 goto done;
655 if (!NT_STATUS_IS_OK(result)) {
656 werr = ntstatus_to_werror(result);
657 goto done;
660 werr = WERR_OK;
662 done:
663 if (is_valid_policy_hnd(&group_handle)) {
664 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
667 if (ctx->disable_policy_handle_cache) {
668 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
669 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
672 return werr;
675 /****************************************************************
676 ****************************************************************/
678 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
679 struct NetGroupSetInfo *r)
681 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
684 /****************************************************************
685 ****************************************************************/
687 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
688 uint32_t level,
689 struct samr_GroupInfoAll *info,
690 struct dom_sid2 *domain_sid,
691 uint32_t rid,
692 uint8_t **buffer)
694 struct GROUP_INFO_0 info0;
695 struct GROUP_INFO_1 info1;
696 struct GROUP_INFO_2 info2;
697 struct GROUP_INFO_3 info3;
698 struct dom_sid sid;
700 switch (level) {
701 case 0:
702 info0.grpi0_name = info->name.string;
704 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
706 break;
707 case 1:
708 info1.grpi1_name = info->name.string;
709 info1.grpi1_comment = info->description.string;
711 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
713 break;
714 case 2:
715 info2.grpi2_name = info->name.string;
716 info2.grpi2_comment = info->description.string;
717 info2.grpi2_group_id = rid;
718 info2.grpi2_attributes = info->attributes;
720 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
722 break;
723 case 3:
724 if (!sid_compose(&sid, domain_sid, rid)) {
725 return WERR_NOMEM;
728 info3.grpi3_name = info->name.string;
729 info3.grpi3_comment = info->description.string;
730 info3.grpi3_attributes = info->attributes;
731 info3.grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
733 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
735 break;
736 default:
737 return WERR_UNKNOWN_LEVEL;
740 W_ERROR_HAVE_NO_MEMORY(*buffer);
742 return WERR_OK;
745 /****************************************************************
746 ****************************************************************/
748 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
749 struct NetGroupGetInfo *r)
751 struct rpc_pipe_client *pipe_cli = NULL;
752 NTSTATUS status, result;
753 WERROR werr;
754 struct policy_handle connect_handle, domain_handle, group_handle;
755 struct lsa_String lsa_group_name;
756 struct dom_sid2 *domain_sid = NULL;
757 struct dcerpc_binding_handle *b = NULL;
759 struct samr_Ids rids;
760 struct samr_Ids types;
761 union samr_GroupInfo *info = NULL;
762 bool group_info_all = false;
764 ZERO_STRUCT(connect_handle);
765 ZERO_STRUCT(domain_handle);
766 ZERO_STRUCT(group_handle);
768 if (!r->in.group_name) {
769 return WERR_INVALID_PARAM;
772 werr = libnetapi_open_pipe(ctx, r->in.server_name,
773 &ndr_table_samr,
774 &pipe_cli);
775 if (!W_ERROR_IS_OK(werr)) {
776 goto done;
779 b = pipe_cli->binding_handle;
781 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
782 SAMR_ACCESS_ENUM_DOMAINS |
783 SAMR_ACCESS_LOOKUP_DOMAIN,
784 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
785 &connect_handle,
786 &domain_handle,
787 &domain_sid);
788 if (!W_ERROR_IS_OK(werr)) {
789 goto done;
792 init_lsa_String(&lsa_group_name, r->in.group_name);
794 status = dcerpc_samr_LookupNames(b, talloc_tos(),
795 &domain_handle,
797 &lsa_group_name,
798 &rids,
799 &types,
800 &result);
801 if (!NT_STATUS_IS_OK(status)) {
802 werr = ntstatus_to_werror(status);
803 goto done;
805 if (!NT_STATUS_IS_OK(result)) {
806 werr = ntstatus_to_werror(result);
807 goto done;
809 if (rids.count != 1) {
810 werr = WERR_BAD_NET_RESP;
811 goto done;
813 if (types.count != 1) {
814 werr = WERR_BAD_NET_RESP;
815 goto done;
818 if (types.ids[0] != SID_NAME_DOM_GRP) {
819 werr = WERR_INVALID_DATATYPE;
820 goto done;
823 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
824 &domain_handle,
825 SAMR_GROUP_ACCESS_LOOKUP_INFO,
826 rids.ids[0],
827 &group_handle,
828 &result);
829 if (!NT_STATUS_IS_OK(status)) {
830 werr = ntstatus_to_werror(status);
831 goto done;
833 if (!NT_STATUS_IS_OK(result)) {
834 werr = ntstatus_to_werror(result);
835 goto done;
838 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
839 &group_handle,
840 GROUPINFOALL2,
841 &info,
842 &result);
843 if (!NT_STATUS_IS_OK(status)) {
844 werr = ntstatus_to_werror(status);
845 goto done;
848 if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS)) {
849 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
850 &group_handle,
851 GROUPINFOALL,
852 &info,
853 &result);
854 group_info_all = true;
855 if (!NT_STATUS_IS_OK(status)) {
856 werr = ntstatus_to_werror(status);
857 goto done;
861 if (!NT_STATUS_IS_OK(result)) {
862 werr = ntstatus_to_werror(result);
863 goto done;
866 werr = map_group_info_to_buffer(ctx, r->in.level,
867 group_info_all ? &info->all : &info->all2,
868 domain_sid, rids.ids[0],
869 r->out.buffer);
870 if (!W_ERROR_IS_OK(werr)) {
871 goto done;
873 done:
874 if (is_valid_policy_hnd(&group_handle)) {
875 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
878 if (ctx->disable_policy_handle_cache) {
879 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
880 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
883 return werr;
886 /****************************************************************
887 ****************************************************************/
889 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
890 struct NetGroupGetInfo *r)
892 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
895 /****************************************************************
896 ****************************************************************/
898 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
899 struct NetGroupAddUser *r)
901 struct rpc_pipe_client *pipe_cli = NULL;
902 NTSTATUS status, result;
903 WERROR werr;
904 struct policy_handle connect_handle, domain_handle, group_handle;
905 struct lsa_String lsa_group_name, lsa_user_name;
906 struct dom_sid2 *domain_sid = NULL;
907 struct dcerpc_binding_handle *b = NULL;
909 struct samr_Ids rids;
910 struct samr_Ids types;
912 ZERO_STRUCT(connect_handle);
913 ZERO_STRUCT(domain_handle);
914 ZERO_STRUCT(group_handle);
916 if (!r->in.group_name) {
917 return WERR_INVALID_PARAM;
920 werr = libnetapi_open_pipe(ctx, r->in.server_name,
921 &ndr_table_samr,
922 &pipe_cli);
923 if (!W_ERROR_IS_OK(werr)) {
924 goto done;
927 b = pipe_cli->binding_handle;
929 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
930 SAMR_ACCESS_ENUM_DOMAINS |
931 SAMR_ACCESS_LOOKUP_DOMAIN,
932 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
933 &connect_handle,
934 &domain_handle,
935 &domain_sid);
936 if (!W_ERROR_IS_OK(werr)) {
937 goto done;
940 init_lsa_String(&lsa_group_name, r->in.group_name);
942 status = dcerpc_samr_LookupNames(b, talloc_tos(),
943 &domain_handle,
945 &lsa_group_name,
946 &rids,
947 &types,
948 &result);
949 if (!NT_STATUS_IS_OK(status)) {
950 werr = ntstatus_to_werror(status);
951 goto done;
953 if (!NT_STATUS_IS_OK(result)) {
954 werr = WERR_GROUPNOTFOUND;
955 goto done;
957 if (rids.count != 1) {
958 werr = WERR_BAD_NET_RESP;
959 goto done;
961 if (types.count != 1) {
962 werr = WERR_BAD_NET_RESP;
963 goto done;
966 if (types.ids[0] != SID_NAME_DOM_GRP) {
967 werr = WERR_GROUPNOTFOUND;
968 goto done;
971 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
972 &domain_handle,
973 SAMR_GROUP_ACCESS_ADD_MEMBER,
974 rids.ids[0],
975 &group_handle,
976 &result);
977 if (!NT_STATUS_IS_OK(status)) {
978 werr = ntstatus_to_werror(status);
979 goto done;
981 if (!NT_STATUS_IS_OK(result)) {
982 werr = ntstatus_to_werror(result);
983 goto done;
986 init_lsa_String(&lsa_user_name, r->in.user_name);
988 status = dcerpc_samr_LookupNames(b, talloc_tos(),
989 &domain_handle,
991 &lsa_user_name,
992 &rids,
993 &types,
994 &result);
995 if (!NT_STATUS_IS_OK(status)) {
996 werr = ntstatus_to_werror(status);
997 goto done;
999 if (!NT_STATUS_IS_OK(result)) {
1000 werr = WERR_USER_NOT_FOUND;
1001 goto done;
1003 if (rids.count != 1) {
1004 werr = WERR_BAD_NET_RESP;
1005 goto done;
1007 if (types.count != 1) {
1008 werr = WERR_BAD_NET_RESP;
1009 goto done;
1012 if (types.ids[0] != SID_NAME_USER) {
1013 werr = WERR_USER_NOT_FOUND;
1014 goto done;
1017 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
1018 &group_handle,
1019 rids.ids[0],
1020 7, /* why ? */
1021 &result);
1022 if (!NT_STATUS_IS_OK(status)) {
1023 werr = ntstatus_to_werror(status);
1024 goto done;
1026 if (!NT_STATUS_IS_OK(result)) {
1027 werr = ntstatus_to_werror(result);
1028 goto done;
1031 werr = WERR_OK;
1033 done:
1034 if (is_valid_policy_hnd(&group_handle)) {
1035 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1038 if (ctx->disable_policy_handle_cache) {
1039 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1040 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1043 return werr;
1046 /****************************************************************
1047 ****************************************************************/
1049 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
1050 struct NetGroupAddUser *r)
1052 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
1055 /****************************************************************
1056 ****************************************************************/
1058 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
1059 struct NetGroupDelUser *r)
1061 struct rpc_pipe_client *pipe_cli = NULL;
1062 NTSTATUS status, result;
1063 WERROR werr;
1064 struct policy_handle connect_handle, domain_handle, group_handle;
1065 struct lsa_String lsa_group_name, lsa_user_name;
1066 struct dom_sid2 *domain_sid = NULL;
1067 struct dcerpc_binding_handle *b = NULL;
1069 struct samr_Ids rids;
1070 struct samr_Ids types;
1072 ZERO_STRUCT(connect_handle);
1073 ZERO_STRUCT(domain_handle);
1074 ZERO_STRUCT(group_handle);
1076 if (!r->in.group_name) {
1077 return WERR_INVALID_PARAM;
1080 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1081 &ndr_table_samr,
1082 &pipe_cli);
1083 if (!W_ERROR_IS_OK(werr)) {
1084 goto done;
1087 b = pipe_cli->binding_handle;
1089 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1090 SAMR_ACCESS_ENUM_DOMAINS |
1091 SAMR_ACCESS_LOOKUP_DOMAIN,
1092 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1093 &connect_handle,
1094 &domain_handle,
1095 &domain_sid);
1096 if (!W_ERROR_IS_OK(werr)) {
1097 goto done;
1100 init_lsa_String(&lsa_group_name, r->in.group_name);
1102 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1103 &domain_handle,
1105 &lsa_group_name,
1106 &rids,
1107 &types,
1108 &result);
1109 if (!NT_STATUS_IS_OK(status)) {
1110 werr = ntstatus_to_werror(status);
1111 goto done;
1113 if (!NT_STATUS_IS_OK(result)) {
1114 werr = WERR_GROUPNOTFOUND;
1115 goto done;
1117 if (rids.count != 1) {
1118 werr = WERR_BAD_NET_RESP;
1119 goto done;
1121 if (types.count != 1) {
1122 werr = WERR_BAD_NET_RESP;
1123 goto done;
1126 if (types.ids[0] != SID_NAME_DOM_GRP) {
1127 werr = WERR_GROUPNOTFOUND;
1128 goto done;
1131 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1132 &domain_handle,
1133 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
1134 rids.ids[0],
1135 &group_handle,
1136 &result);
1137 if (!NT_STATUS_IS_OK(status)) {
1138 werr = ntstatus_to_werror(status);
1139 goto done;
1141 if (!NT_STATUS_IS_OK(result)) {
1142 werr = ntstatus_to_werror(result);
1143 goto done;
1146 init_lsa_String(&lsa_user_name, r->in.user_name);
1148 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1149 &domain_handle,
1151 &lsa_user_name,
1152 &rids,
1153 &types,
1154 &result);
1155 if (!NT_STATUS_IS_OK(status)) {
1156 werr = ntstatus_to_werror(status);
1157 goto done;
1160 if (!NT_STATUS_IS_OK(result)) {
1161 werr = WERR_USER_NOT_FOUND;
1162 goto done;
1164 if (rids.count != 1) {
1165 werr = WERR_BAD_NET_RESP;
1166 goto done;
1168 if (types.count != 1) {
1169 werr = WERR_BAD_NET_RESP;
1170 goto done;
1173 if (types.ids[0] != SID_NAME_USER) {
1174 werr = WERR_USER_NOT_FOUND;
1175 goto done;
1178 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1179 &group_handle,
1180 rids.ids[0],
1181 &result);
1182 if (!NT_STATUS_IS_OK(status)) {
1183 werr = ntstatus_to_werror(status);
1184 goto done;
1186 if (!NT_STATUS_IS_OK(result)) {
1187 werr = ntstatus_to_werror(result);
1188 goto done;
1191 werr = WERR_OK;
1193 done:
1194 if (is_valid_policy_hnd(&group_handle)) {
1195 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1198 if (ctx->disable_policy_handle_cache) {
1199 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1200 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1203 return werr;
1206 /****************************************************************
1207 ****************************************************************/
1209 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1210 struct NetGroupDelUser *r)
1212 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
1215 /****************************************************************
1216 ****************************************************************/
1218 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
1219 struct samr_DispInfoFullGroups *groups,
1220 uint8_t **buffer)
1222 struct GROUP_INFO_0 *g0;
1223 int i;
1225 g0 = talloc_zero_array(mem_ctx, struct GROUP_INFO_0, groups->count);
1226 W_ERROR_HAVE_NO_MEMORY(g0);
1228 for (i=0; i<groups->count; i++) {
1229 g0[i].grpi0_name = talloc_strdup(mem_ctx,
1230 groups->entries[i].account_name.string);
1231 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
1234 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
1235 sizeof(struct GROUP_INFO_0) * groups->count);
1236 W_ERROR_HAVE_NO_MEMORY(*buffer);
1238 return WERR_OK;
1241 /****************************************************************
1242 ****************************************************************/
1244 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1245 struct samr_DispInfoFullGroups *groups,
1246 uint8_t **buffer)
1248 struct GROUP_INFO_1 *g1;
1249 int i;
1251 g1 = talloc_zero_array(mem_ctx, struct GROUP_INFO_1, groups->count);
1252 W_ERROR_HAVE_NO_MEMORY(g1);
1254 for (i=0; i<groups->count; i++) {
1255 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1256 groups->entries[i].account_name.string);
1257 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1258 groups->entries[i].description.string);
1259 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1262 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1263 sizeof(struct GROUP_INFO_1) * groups->count);
1264 W_ERROR_HAVE_NO_MEMORY(*buffer);
1266 return WERR_OK;
1269 /****************************************************************
1270 ****************************************************************/
1272 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1273 struct samr_DispInfoFullGroups *groups,
1274 uint8_t **buffer)
1276 struct GROUP_INFO_2 *g2;
1277 int i;
1279 g2 = talloc_zero_array(mem_ctx, struct GROUP_INFO_2, groups->count);
1280 W_ERROR_HAVE_NO_MEMORY(g2);
1282 for (i=0; i<groups->count; i++) {
1283 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1284 groups->entries[i].account_name.string);
1285 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1286 groups->entries[i].description.string);
1287 g2[i].grpi2_group_id = groups->entries[i].rid;
1288 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1289 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1292 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1293 sizeof(struct GROUP_INFO_2) * groups->count);
1294 W_ERROR_HAVE_NO_MEMORY(*buffer);
1296 return WERR_OK;
1299 /****************************************************************
1300 ****************************************************************/
1302 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1303 struct samr_DispInfoFullGroups *groups,
1304 const struct dom_sid *domain_sid,
1305 uint8_t **buffer)
1307 struct GROUP_INFO_3 *g3;
1308 int i;
1310 g3 = talloc_zero_array(mem_ctx, struct GROUP_INFO_3, groups->count);
1311 W_ERROR_HAVE_NO_MEMORY(g3);
1313 for (i=0; i<groups->count; i++) {
1315 struct dom_sid sid;
1317 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1318 return WERR_NOMEM;
1321 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1322 groups->entries[i].account_name.string);
1323 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1324 groups->entries[i].description.string);
1325 g3[i].grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
1326 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1327 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1330 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1331 sizeof(struct GROUP_INFO_3) * groups->count);
1332 W_ERROR_HAVE_NO_MEMORY(*buffer);
1334 return WERR_OK;
1337 /****************************************************************
1338 ****************************************************************/
1340 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1341 uint32_t level,
1342 struct samr_DispInfoFullGroups *groups,
1343 const struct dom_sid *domain_sid,
1344 uint32_t *entries_read,
1345 uint8_t **buffer)
1347 if (entries_read) {
1348 *entries_read = groups->count;
1351 switch (level) {
1352 case 0:
1353 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1354 case 1:
1355 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1356 case 2:
1357 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1358 case 3:
1359 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1360 default:
1361 return WERR_UNKNOWN_LEVEL;
1365 /****************************************************************
1366 ****************************************************************/
1368 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1369 struct NetGroupEnum *r)
1371 struct rpc_pipe_client *pipe_cli = NULL;
1372 struct policy_handle connect_handle;
1373 struct dom_sid2 *domain_sid = NULL;
1374 struct policy_handle domain_handle;
1375 union samr_DispInfo info;
1376 union samr_DomainInfo *domain_info = NULL;
1377 struct dcerpc_binding_handle *b = NULL;
1379 uint32_t total_size = 0;
1380 uint32_t returned_size = 0;
1382 NTSTATUS result = NT_STATUS_OK;
1383 NTSTATUS status = NT_STATUS_OK;
1384 WERROR werr, tmp_werr;
1386 ZERO_STRUCT(connect_handle);
1387 ZERO_STRUCT(domain_handle);
1389 switch (r->in.level) {
1390 case 0:
1391 case 1:
1392 case 2:
1393 case 3:
1394 break;
1395 default:
1396 return WERR_UNKNOWN_LEVEL;
1399 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1400 &ndr_table_samr,
1401 &pipe_cli);
1402 if (!W_ERROR_IS_OK(werr)) {
1403 goto done;
1406 b = pipe_cli->binding_handle;
1408 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1409 SAMR_ACCESS_ENUM_DOMAINS |
1410 SAMR_ACCESS_LOOKUP_DOMAIN,
1411 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1412 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1413 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1414 &connect_handle,
1415 &domain_handle,
1416 &domain_sid);
1417 if (!W_ERROR_IS_OK(werr)) {
1418 goto done;
1421 status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
1422 &domain_handle,
1424 &domain_info,
1425 &result);
1426 if (!NT_STATUS_IS_OK(status)) {
1427 werr = ntstatus_to_werror(status);
1428 goto done;
1430 if (!NT_STATUS_IS_OK(result)) {
1431 werr = ntstatus_to_werror(result);
1432 goto done;
1435 if (r->out.total_entries) {
1436 *r->out.total_entries = domain_info->general.num_groups;
1439 status = dcerpc_samr_QueryDisplayInfo2(b,
1440 ctx,
1441 &domain_handle,
1443 r->in.resume_handle ?
1444 *r->in.resume_handle : 0,
1445 (uint32_t)-1,
1446 r->in.prefmaxlen,
1447 &total_size,
1448 &returned_size,
1449 &info,
1450 &result);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 werr = ntstatus_to_werror(status);
1453 goto done;
1456 werr = ntstatus_to_werror(result);
1457 if (NT_STATUS_IS_ERR(result)) {
1458 goto done;
1461 if (r->out.resume_handle && info.info3.count > 0) {
1462 *r->out.resume_handle =
1463 info.info3.entries[info.info3.count-1].idx;
1466 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1467 r->in.level,
1468 &info.info3,
1469 domain_sid,
1470 r->out.entries_read,
1471 r->out.buffer);
1472 if (!W_ERROR_IS_OK(tmp_werr)) {
1473 werr = tmp_werr;
1474 goto done;
1477 done:
1478 /* if last query */
1479 if (NT_STATUS_IS_OK(result) ||
1480 NT_STATUS_IS_ERR(result)) {
1482 if (ctx->disable_policy_handle_cache) {
1483 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1484 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1488 return werr;
1491 /****************************************************************
1492 ****************************************************************/
1494 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1495 struct NetGroupEnum *r)
1497 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1500 /****************************************************************
1501 ****************************************************************/
1503 WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1504 struct NetGroupGetUsers *r)
1506 /* FIXME: this call needs to cope with large replies */
1508 struct rpc_pipe_client *pipe_cli = NULL;
1509 struct policy_handle connect_handle, domain_handle, group_handle;
1510 struct lsa_String lsa_account_name;
1511 struct dom_sid2 *domain_sid = NULL;
1512 struct samr_Ids group_rids, name_types;
1513 struct samr_RidAttrArray *rid_array = NULL;
1514 struct lsa_Strings names;
1515 struct samr_Ids member_types;
1516 struct dcerpc_binding_handle *b = NULL;
1518 int i;
1519 uint32_t entries_read = 0;
1521 NTSTATUS status = NT_STATUS_OK;
1522 NTSTATUS result = NT_STATUS_OK;
1523 WERROR werr;
1525 ZERO_STRUCT(connect_handle);
1526 ZERO_STRUCT(domain_handle);
1527 ZERO_STRUCT(group_handle);
1529 if (!r->out.buffer) {
1530 return WERR_INVALID_PARAM;
1533 *r->out.buffer = NULL;
1534 *r->out.entries_read = 0;
1535 *r->out.total_entries = 0;
1537 switch (r->in.level) {
1538 case 0:
1539 case 1:
1540 break;
1541 default:
1542 return WERR_UNKNOWN_LEVEL;
1546 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1547 &ndr_table_samr,
1548 &pipe_cli);
1549 if (!W_ERROR_IS_OK(werr)) {
1550 goto done;
1553 b = pipe_cli->binding_handle;
1555 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1556 SAMR_ACCESS_ENUM_DOMAINS |
1557 SAMR_ACCESS_LOOKUP_DOMAIN,
1558 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1559 &connect_handle,
1560 &domain_handle,
1561 &domain_sid);
1562 if (!W_ERROR_IS_OK(werr)) {
1563 goto done;
1566 init_lsa_String(&lsa_account_name, r->in.group_name);
1568 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1569 &domain_handle,
1571 &lsa_account_name,
1572 &group_rids,
1573 &name_types,
1574 &result);
1575 if (!NT_STATUS_IS_OK(status)) {
1576 werr = ntstatus_to_werror(status);
1577 goto done;
1579 if (!NT_STATUS_IS_OK(result)) {
1580 werr = ntstatus_to_werror(result);
1581 goto done;
1583 if (group_rids.count != 1) {
1584 werr = WERR_BAD_NET_RESP;
1585 goto done;
1587 if (name_types.count != 1) {
1588 werr = WERR_BAD_NET_RESP;
1589 goto done;
1592 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1593 &domain_handle,
1594 SAMR_GROUP_ACCESS_GET_MEMBERS,
1595 group_rids.ids[0],
1596 &group_handle,
1597 &result);
1598 if (!NT_STATUS_IS_OK(status)) {
1599 werr = ntstatus_to_werror(status);
1600 goto done;
1602 if (!NT_STATUS_IS_OK(result)) {
1603 werr = ntstatus_to_werror(result);
1604 goto done;
1607 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1608 &group_handle,
1609 &rid_array,
1610 &result);
1611 if (!NT_STATUS_IS_OK(status)) {
1612 werr = ntstatus_to_werror(status);
1613 goto done;
1615 if (!NT_STATUS_IS_OK(result)) {
1616 werr = ntstatus_to_werror(result);
1617 goto done;
1620 status = dcerpc_samr_LookupRids(b, talloc_tos(),
1621 &domain_handle,
1622 rid_array->count,
1623 rid_array->rids,
1624 &names,
1625 &member_types,
1626 &result);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 werr = ntstatus_to_werror(status);
1629 goto done;
1631 if (!NT_STATUS_IS_OK(result)) {
1632 werr = ntstatus_to_werror(result);
1633 goto done;
1635 if (names.count != rid_array->count) {
1636 werr = WERR_BAD_NET_RESP;
1637 goto done;
1639 if (member_types.count != rid_array->count) {
1640 werr = WERR_BAD_NET_RESP;
1641 goto done;
1644 for (i=0; i < names.count; i++) {
1646 if (member_types.ids[i] != SID_NAME_USER) {
1647 continue;
1650 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1651 r->in.level,
1652 names.names[i].string,
1654 r->out.buffer,
1655 &entries_read);
1656 if (!NT_STATUS_IS_OK(status)) {
1657 werr = ntstatus_to_werror(status);
1658 goto done;
1662 *r->out.entries_read = entries_read;
1663 *r->out.total_entries = entries_read;
1665 werr = WERR_OK;
1667 done:
1668 if (is_valid_policy_hnd(&group_handle)) {
1669 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1672 if (ctx->disable_policy_handle_cache) {
1673 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1674 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1677 return werr;
1680 /****************************************************************
1681 ****************************************************************/
1683 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1684 struct NetGroupGetUsers *r)
1686 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1689 /****************************************************************
1690 ****************************************************************/
1692 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1693 struct NetGroupSetUsers *r)
1695 struct rpc_pipe_client *pipe_cli = NULL;
1696 struct policy_handle connect_handle, domain_handle, group_handle;
1697 struct lsa_String lsa_account_name;
1698 struct dom_sid2 *domain_sid = NULL;
1699 union samr_GroupInfo *group_info = NULL;
1700 struct samr_Ids user_rids, name_types;
1701 struct samr_Ids group_rids, group_types;
1702 struct samr_RidAttrArray *rid_array = NULL;
1703 struct lsa_String *lsa_names = NULL;
1704 struct dcerpc_binding_handle *b = NULL;
1706 uint32_t *add_rids = NULL;
1707 uint32_t *del_rids = NULL;
1708 size_t num_add_rids = 0;
1709 size_t num_del_rids = 0;
1711 uint32_t *member_rids = NULL;
1713 struct GROUP_USERS_INFO_0 *i0 = NULL;
1714 struct GROUP_USERS_INFO_1 *i1 = NULL;
1716 int i, k;
1718 NTSTATUS status = NT_STATUS_OK;
1719 NTSTATUS result = NT_STATUS_OK;
1720 WERROR werr;
1722 ZERO_STRUCT(connect_handle);
1723 ZERO_STRUCT(domain_handle);
1724 ZERO_STRUCT(group_handle);
1726 if (!r->in.buffer) {
1727 return WERR_INVALID_PARAM;
1730 switch (r->in.level) {
1731 case 0:
1732 case 1:
1733 break;
1734 default:
1735 return WERR_UNKNOWN_LEVEL;
1738 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1739 &ndr_table_samr,
1740 &pipe_cli);
1741 if (!W_ERROR_IS_OK(werr)) {
1742 goto done;
1745 b = pipe_cli->binding_handle;
1747 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1748 SAMR_ACCESS_ENUM_DOMAINS |
1749 SAMR_ACCESS_LOOKUP_DOMAIN,
1750 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1751 &connect_handle,
1752 &domain_handle,
1753 &domain_sid);
1754 if (!W_ERROR_IS_OK(werr)) {
1755 goto done;
1758 init_lsa_String(&lsa_account_name, r->in.group_name);
1760 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1761 &domain_handle,
1763 &lsa_account_name,
1764 &group_rids,
1765 &group_types,
1766 &result);
1767 if (!NT_STATUS_IS_OK(status)) {
1768 werr = ntstatus_to_werror(status);
1769 goto done;
1771 if (!NT_STATUS_IS_OK(result)) {
1772 werr = ntstatus_to_werror(result);
1773 goto done;
1775 if (group_rids.count != 1) {
1776 werr = WERR_BAD_NET_RESP;
1777 goto done;
1779 if (group_types.count != 1) {
1780 werr = WERR_BAD_NET_RESP;
1781 goto done;
1784 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1785 &domain_handle,
1786 SAMR_GROUP_ACCESS_GET_MEMBERS |
1787 SAMR_GROUP_ACCESS_ADD_MEMBER |
1788 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1789 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1790 group_rids.ids[0],
1791 &group_handle,
1792 &result);
1793 if (!NT_STATUS_IS_OK(status)) {
1794 werr = ntstatus_to_werror(status);
1795 goto done;
1797 if (!NT_STATUS_IS_OK(result)) {
1798 werr = ntstatus_to_werror(result);
1799 goto done;
1802 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
1803 &group_handle,
1804 GROUPINFOATTRIBUTES,
1805 &group_info,
1806 &result);
1807 if (!NT_STATUS_IS_OK(status)) {
1808 werr = ntstatus_to_werror(status);
1809 goto done;
1811 if (!NT_STATUS_IS_OK(result)) {
1812 werr = ntstatus_to_werror(result);
1813 goto done;
1816 switch (r->in.level) {
1817 case 0:
1818 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1819 break;
1820 case 1:
1821 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1822 break;
1825 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1826 if (!lsa_names) {
1827 werr = WERR_NOMEM;
1828 goto done;
1831 for (i=0; i < r->in.num_entries; i++) {
1833 switch (r->in.level) {
1834 case 0:
1835 init_lsa_String(&lsa_names[i], i0->grui0_name);
1836 i0++;
1837 break;
1838 case 1:
1839 init_lsa_String(&lsa_names[i], i1->grui1_name);
1840 i1++;
1841 break;
1845 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1846 &domain_handle,
1847 r->in.num_entries,
1848 lsa_names,
1849 &user_rids,
1850 &name_types,
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;
1861 if (r->in.num_entries != user_rids.count) {
1862 werr = WERR_BAD_NET_RESP;
1863 goto done;
1865 if (r->in.num_entries != name_types.count) {
1866 werr = WERR_BAD_NET_RESP;
1867 goto done;
1870 member_rids = user_rids.ids;
1872 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1873 &group_handle,
1874 &rid_array,
1875 &result);
1876 if (!NT_STATUS_IS_OK(status)) {
1877 werr = ntstatus_to_werror(status);
1878 goto done;
1880 if (!NT_STATUS_IS_OK(result)) {
1881 werr = ntstatus_to_werror(result);
1882 goto done;
1885 /* add list */
1887 for (i=0; i < r->in.num_entries; i++) {
1888 bool already_member = false;
1889 for (k=0; k < rid_array->count; k++) {
1890 if (member_rids[i] == rid_array->rids[k]) {
1891 already_member = true;
1892 break;
1895 if (!already_member) {
1896 if (!add_rid_to_array_unique(ctx,
1897 member_rids[i],
1898 &add_rids, &num_add_rids)) {
1899 werr = WERR_GENERAL_FAILURE;
1900 goto done;
1905 /* del list */
1907 for (k=0; k < rid_array->count; k++) {
1908 bool keep_member = false;
1909 for (i=0; i < r->in.num_entries; i++) {
1910 if (member_rids[i] == rid_array->rids[k]) {
1911 keep_member = true;
1912 break;
1915 if (!keep_member) {
1916 if (!add_rid_to_array_unique(ctx,
1917 rid_array->rids[k],
1918 &del_rids, &num_del_rids)) {
1919 werr = WERR_GENERAL_FAILURE;
1920 goto done;
1925 /* add list */
1927 for (i=0; i < num_add_rids; i++) {
1928 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
1929 &group_handle,
1930 add_rids[i],
1931 7 /* ? */,
1932 &result);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 werr = ntstatus_to_werror(status);
1935 goto done;
1937 if (!NT_STATUS_IS_OK(result)) {
1938 werr = ntstatus_to_werror(result);
1939 goto done;
1943 /* del list */
1945 for (i=0; i < num_del_rids; i++) {
1946 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1947 &group_handle,
1948 del_rids[i],
1949 &result);
1950 if (!NT_STATUS_IS_OK(status)) {
1951 werr = ntstatus_to_werror(status);
1952 goto done;
1954 if (!NT_STATUS_IS_OK(result)) {
1955 werr = ntstatus_to_werror(result);
1956 goto done;
1960 werr = WERR_OK;
1962 done:
1963 if (is_valid_policy_hnd(&group_handle)) {
1964 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1967 if (ctx->disable_policy_handle_cache) {
1968 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1969 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1972 return werr;
1975 /****************************************************************
1976 ****************************************************************/
1978 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1979 struct NetGroupSetUsers *r)
1981 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);