2 * Unix SMB/CIFS implementation.
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/>.
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
27 /****************************************************************
28 ****************************************************************/
30 WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
31 struct NetGroupAdd *r)
33 struct rpc_pipe_client *pipe_cli = NULL;
36 POLICY_HND connect_handle, domain_handle, group_handle;
37 struct lsa_String lsa_group_name;
38 struct dom_sid2 *domain_sid = NULL;
41 struct GROUP_INFO_0 *info0 = NULL;
42 struct GROUP_INFO_1 *info1 = NULL;
43 struct GROUP_INFO_2 *info2 = NULL;
44 struct GROUP_INFO_3 *info3 = NULL;
45 union samr_GroupInfo info;
47 ZERO_STRUCT(connect_handle);
48 ZERO_STRUCT(domain_handle);
49 ZERO_STRUCT(group_handle);
52 return WERR_INVALID_PARAM;
55 switch (r->in.level) {
57 info0 = (struct GROUP_INFO_0 *)r->in.buffer;
60 info1 = (struct GROUP_INFO_1 *)r->in.buffer;
63 info2 = (struct GROUP_INFO_2 *)r->in.buffer;
66 info3 = (struct GROUP_INFO_3 *)r->in.buffer;
69 werr = WERR_UNKNOWN_LEVEL;
73 werr = libnetapi_open_pipe(ctx, r->in.server_name,
74 &ndr_table_samr.syntax_id,
76 if (!W_ERROR_IS_OK(werr)) {
80 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
81 SAMR_ACCESS_ENUM_DOMAINS |
82 SAMR_ACCESS_OPEN_DOMAIN,
83 SAMR_DOMAIN_ACCESS_CREATE_GROUP |
84 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
88 if (!W_ERROR_IS_OK(werr)) {
92 switch (r->in.level) {
94 init_lsa_String(&lsa_group_name, info0->grpi0_name);
97 init_lsa_String(&lsa_group_name, info1->grpi1_name);
100 init_lsa_String(&lsa_group_name, info2->grpi2_name);
103 init_lsa_String(&lsa_group_name, info3->grpi3_name);
107 status = rpccli_samr_CreateDomainGroup(pipe_cli, ctx,
111 SAMR_GROUP_ACCESS_SET_INFO,
115 if (!NT_STATUS_IS_OK(status)) {
116 werr = ntstatus_to_werror(status);
120 switch (r->in.level) {
122 if (info1->grpi1_comment) {
123 init_lsa_String(&info.description,
124 info1->grpi1_comment);
126 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
128 GROUPINFODESCRIPTION,
133 if (info2->grpi2_comment) {
134 init_lsa_String(&info.description,
135 info2->grpi2_comment);
137 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
139 GROUPINFODESCRIPTION,
141 if (!NT_STATUS_IS_OK(status)) {
142 werr = ntstatus_to_werror(status);
147 if (info2->grpi2_attributes != 0) {
148 info.attributes.attributes = info2->grpi2_attributes;
149 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
157 if (info3->grpi3_comment) {
158 init_lsa_String(&info.description,
159 info3->grpi3_comment);
161 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
163 GROUPINFODESCRIPTION,
165 if (!NT_STATUS_IS_OK(status)) {
166 werr = ntstatus_to_werror(status);
171 if (info3->grpi3_attributes != 0) {
172 info.attributes.attributes = info3->grpi3_attributes;
173 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
183 if (!NT_STATUS_IS_OK(status)) {
184 werr = ntstatus_to_werror(status);
192 rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
196 if (is_valid_policy_hnd(&group_handle)) {
197 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
200 if (ctx->disable_policy_handle_cache) {
201 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
202 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
208 /****************************************************************
209 ****************************************************************/
211 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
212 struct NetGroupAdd *r)
214 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
217 /****************************************************************
218 ****************************************************************/
220 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
221 struct NetGroupDel *r)
223 struct rpc_pipe_client *pipe_cli = NULL;
226 POLICY_HND connect_handle, domain_handle, group_handle;
227 struct lsa_String lsa_group_name;
228 struct dom_sid2 *domain_sid = NULL;
231 struct samr_Ids rids;
232 struct samr_Ids types;
233 union samr_GroupInfo *info = NULL;
234 struct samr_RidTypeArray *rid_array = NULL;
236 ZERO_STRUCT(connect_handle);
237 ZERO_STRUCT(domain_handle);
238 ZERO_STRUCT(group_handle);
240 if (!r->in.group_name) {
241 return WERR_INVALID_PARAM;
244 werr = libnetapi_open_pipe(ctx, r->in.server_name,
245 &ndr_table_samr.syntax_id,
247 if (!W_ERROR_IS_OK(werr)) {
251 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
252 SAMR_ACCESS_ENUM_DOMAINS |
253 SAMR_ACCESS_OPEN_DOMAIN,
254 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
258 if (!W_ERROR_IS_OK(werr)) {
262 init_lsa_String(&lsa_group_name, r->in.group_name);
264 status = rpccli_samr_LookupNames(pipe_cli, ctx,
270 if (!NT_STATUS_IS_OK(status)) {
271 werr = ntstatus_to_werror(status);
275 if (types.ids[0] != SID_NAME_DOM_GRP) {
276 werr = WERR_INVALID_DATATYPE;
280 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
283 SAMR_GROUP_ACCESS_GET_MEMBERS |
284 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
285 SAMR_GROUP_ACCESS_ADD_MEMBER |
286 SAMR_GROUP_ACCESS_LOOKUP_INFO,
289 if (!NT_STATUS_IS_OK(status)) {
290 werr = ntstatus_to_werror(status);
294 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
298 if (!NT_STATUS_IS_OK(status)) {
299 werr = ntstatus_to_werror(status);
304 /* breaks against NT4 */
305 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
306 werr = WERR_ACCESS_DENIED;
310 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
313 if (!NT_STATUS_IS_OK(status)) {
314 werr = ntstatus_to_werror(status);
319 struct lsa_Strings names;
320 struct samr_Ids member_types;
322 status = rpccli_samr_LookupRids(pipe_cli, ctx,
328 if (!NT_STATUS_IS_OK(status)) {
329 werr = ntstatus_to_werror(status);
334 for (i=0; i < rid_array->count; i++) {
336 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
339 if (!NT_STATUS_IS_OK(status)) {
340 werr = ntstatus_to_werror(status);
345 status = rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
347 if (!NT_STATUS_IS_OK(status)) {
348 werr = ntstatus_to_werror(status);
352 ZERO_STRUCT(group_handle);
357 if (is_valid_policy_hnd(&group_handle)) {
358 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
361 if (ctx->disable_policy_handle_cache) {
362 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
363 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
369 /****************************************************************
370 ****************************************************************/
372 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
373 struct NetGroupDel *r)
375 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
378 /****************************************************************
379 ****************************************************************/
381 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
382 struct NetGroupSetInfo *r)
384 struct rpc_pipe_client *pipe_cli = NULL;
387 POLICY_HND connect_handle, domain_handle, group_handle;
388 struct lsa_String lsa_group_name;
389 struct dom_sid2 *domain_sid = NULL;
391 struct samr_Ids rids;
392 struct samr_Ids types;
393 union samr_GroupInfo info;
394 struct GROUP_INFO_0 *g0;
395 struct GROUP_INFO_1 *g1;
396 struct GROUP_INFO_2 *g2;
397 struct GROUP_INFO_3 *g3;
398 struct GROUP_INFO_1002 *g1002;
399 struct GROUP_INFO_1005 *g1005;
401 ZERO_STRUCT(connect_handle);
402 ZERO_STRUCT(domain_handle);
403 ZERO_STRUCT(group_handle);
405 if (!r->in.group_name) {
406 return WERR_INVALID_PARAM;
409 werr = libnetapi_open_pipe(ctx, r->in.server_name,
410 &ndr_table_samr.syntax_id,
412 if (!W_ERROR_IS_OK(werr)) {
416 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
417 SAMR_ACCESS_ENUM_DOMAINS |
418 SAMR_ACCESS_OPEN_DOMAIN,
419 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
423 if (!W_ERROR_IS_OK(werr)) {
427 init_lsa_String(&lsa_group_name, r->in.group_name);
429 status = rpccli_samr_LookupNames(pipe_cli, ctx,
435 if (!NT_STATUS_IS_OK(status)) {
436 werr = ntstatus_to_werror(status);
440 if (types.ids[0] != SID_NAME_DOM_GRP) {
441 werr = WERR_INVALID_DATATYPE;
445 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
447 SAMR_GROUP_ACCESS_SET_INFO |
448 SAMR_GROUP_ACCESS_LOOKUP_INFO,
451 if (!NT_STATUS_IS_OK(status)) {
452 werr = ntstatus_to_werror(status);
456 switch (r->in.level) {
458 g0 = (struct GROUP_INFO_0 *)r->in.buffer;
459 init_lsa_String(&info.name, g0->grpi0_name);
460 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
466 g1 = (struct GROUP_INFO_1 *)r->in.buffer;
467 init_lsa_String(&info.description, g1->grpi1_comment);
468 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
470 GROUPINFODESCRIPTION,
474 g2 = (struct GROUP_INFO_2 *)r->in.buffer;
475 init_lsa_String(&info.description, g2->grpi2_comment);
476 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
478 GROUPINFODESCRIPTION,
480 if (!NT_STATUS_IS_OK(status)) {
481 werr = ntstatus_to_werror(status);
484 info.attributes.attributes = g2->grpi2_attributes;
485 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
491 g3 = (struct GROUP_INFO_3 *)r->in.buffer;
492 init_lsa_String(&info.description, g3->grpi3_comment);
493 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
495 GROUPINFODESCRIPTION,
497 if (!NT_STATUS_IS_OK(status)) {
498 werr = ntstatus_to_werror(status);
501 info.attributes.attributes = g3->grpi3_attributes;
502 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
508 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
509 init_lsa_String(&info.description, g1002->grpi1002_comment);
510 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
512 GROUPINFODESCRIPTION,
516 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
517 info.attributes.attributes = g1005->grpi1005_attributes;
518 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
524 status = NT_STATUS_INVALID_LEVEL;
528 if (!NT_STATUS_IS_OK(status)) {
529 werr = ntstatus_to_werror(status);
536 if (is_valid_policy_hnd(&group_handle)) {
537 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
540 if (ctx->disable_policy_handle_cache) {
541 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
542 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
548 /****************************************************************
549 ****************************************************************/
551 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
552 struct NetGroupSetInfo *r)
554 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
557 /****************************************************************
558 ****************************************************************/
560 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
562 struct samr_GroupInfoAll *info,
563 struct dom_sid2 *domain_sid,
567 struct GROUP_INFO_0 info0;
568 struct GROUP_INFO_1 info1;
569 struct GROUP_INFO_2 info2;
570 struct GROUP_INFO_3 info3;
575 info0.grpi0_name = info->name.string;
577 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
581 info1.grpi1_name = info->name.string;
582 info1.grpi1_comment = info->description.string;
584 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
588 info2.grpi2_name = info->name.string;
589 info2.grpi2_comment = info->description.string;
590 info2.grpi2_group_id = rid;
591 info2.grpi2_attributes = info->attributes;
593 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
597 if (!sid_compose(&sid, domain_sid, rid)) {
601 info3.grpi3_name = info->name.string;
602 info3.grpi3_comment = info->description.string;
603 info3.grpi3_attributes = info->attributes;
604 info3.grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
606 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
610 return WERR_UNKNOWN_LEVEL;
613 W_ERROR_HAVE_NO_MEMORY(*buffer);
618 /****************************************************************
619 ****************************************************************/
621 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
622 struct NetGroupGetInfo *r)
624 struct rpc_pipe_client *pipe_cli = NULL;
627 POLICY_HND connect_handle, domain_handle, group_handle;
628 struct lsa_String lsa_group_name;
629 struct dom_sid2 *domain_sid = NULL;
631 struct samr_Ids rids;
632 struct samr_Ids types;
633 union samr_GroupInfo *info = NULL;
634 bool group_info_all = false;
636 ZERO_STRUCT(connect_handle);
637 ZERO_STRUCT(domain_handle);
638 ZERO_STRUCT(group_handle);
640 if (!r->in.group_name) {
641 return WERR_INVALID_PARAM;
644 werr = libnetapi_open_pipe(ctx, r->in.server_name,
645 &ndr_table_samr.syntax_id,
647 if (!W_ERROR_IS_OK(werr)) {
651 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
652 SAMR_ACCESS_ENUM_DOMAINS |
653 SAMR_ACCESS_OPEN_DOMAIN,
654 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
658 if (!W_ERROR_IS_OK(werr)) {
662 init_lsa_String(&lsa_group_name, r->in.group_name);
664 status = rpccli_samr_LookupNames(pipe_cli, ctx,
670 if (!NT_STATUS_IS_OK(status)) {
671 werr = ntstatus_to_werror(status);
675 if (types.ids[0] != SID_NAME_DOM_GRP) {
676 werr = WERR_INVALID_DATATYPE;
680 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
682 SAMR_GROUP_ACCESS_LOOKUP_INFO,
685 if (!NT_STATUS_IS_OK(status)) {
686 werr = ntstatus_to_werror(status);
690 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
694 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
695 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
699 group_info_all = true;
702 if (!NT_STATUS_IS_OK(status)) {
703 werr = ntstatus_to_werror(status);
707 werr = map_group_info_to_buffer(ctx, r->in.level,
708 group_info_all ? &info->all : &info->all2,
709 domain_sid, rids.ids[0],
711 if (!W_ERROR_IS_OK(werr)) {
715 if (is_valid_policy_hnd(&group_handle)) {
716 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
719 if (ctx->disable_policy_handle_cache) {
720 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
721 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
727 /****************************************************************
728 ****************************************************************/
730 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
731 struct NetGroupGetInfo *r)
733 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
736 /****************************************************************
737 ****************************************************************/
739 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
740 struct NetGroupAddUser *r)
742 struct rpc_pipe_client *pipe_cli = NULL;
745 POLICY_HND connect_handle, domain_handle, group_handle;
746 struct lsa_String lsa_group_name, lsa_user_name;
747 struct dom_sid2 *domain_sid = NULL;
749 struct samr_Ids rids;
750 struct samr_Ids types;
752 ZERO_STRUCT(connect_handle);
753 ZERO_STRUCT(domain_handle);
754 ZERO_STRUCT(group_handle);
756 if (!r->in.group_name) {
757 return WERR_INVALID_PARAM;
760 werr = libnetapi_open_pipe(ctx, r->in.server_name,
761 &ndr_table_samr.syntax_id,
763 if (!W_ERROR_IS_OK(werr)) {
767 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
768 SAMR_ACCESS_ENUM_DOMAINS |
769 SAMR_ACCESS_OPEN_DOMAIN,
770 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
774 if (!W_ERROR_IS_OK(werr)) {
778 init_lsa_String(&lsa_group_name, r->in.group_name);
780 status = rpccli_samr_LookupNames(pipe_cli, ctx,
786 if (!NT_STATUS_IS_OK(status)) {
787 werr = WERR_GROUP_NOT_FOUND;
791 if (types.ids[0] != SID_NAME_DOM_GRP) {
792 werr = WERR_GROUP_NOT_FOUND;
796 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
798 SAMR_GROUP_ACCESS_ADD_MEMBER,
801 if (!NT_STATUS_IS_OK(status)) {
802 werr = ntstatus_to_werror(status);
806 init_lsa_String(&lsa_user_name, r->in.user_name);
808 status = rpccli_samr_LookupNames(pipe_cli, ctx,
814 if (!NT_STATUS_IS_OK(status)) {
815 werr = WERR_USER_NOT_FOUND;
819 if (types.ids[0] != SID_NAME_USER) {
820 werr = WERR_USER_NOT_FOUND;
824 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
828 if (!NT_STATUS_IS_OK(status)) {
829 werr = ntstatus_to_werror(status);
836 if (is_valid_policy_hnd(&group_handle)) {
837 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
840 if (ctx->disable_policy_handle_cache) {
841 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
842 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
848 /****************************************************************
849 ****************************************************************/
851 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
852 struct NetGroupAddUser *r)
854 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
857 /****************************************************************
858 ****************************************************************/
860 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
861 struct NetGroupDelUser *r)
863 struct rpc_pipe_client *pipe_cli = NULL;
866 POLICY_HND connect_handle, domain_handle, group_handle;
867 struct lsa_String lsa_group_name, lsa_user_name;
868 struct dom_sid2 *domain_sid = NULL;
870 struct samr_Ids rids;
871 struct samr_Ids types;
873 ZERO_STRUCT(connect_handle);
874 ZERO_STRUCT(domain_handle);
875 ZERO_STRUCT(group_handle);
877 if (!r->in.group_name) {
878 return WERR_INVALID_PARAM;
881 werr = libnetapi_open_pipe(ctx, r->in.server_name,
882 &ndr_table_samr.syntax_id,
884 if (!W_ERROR_IS_OK(werr)) {
888 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
889 SAMR_ACCESS_ENUM_DOMAINS |
890 SAMR_ACCESS_OPEN_DOMAIN,
891 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
895 if (!W_ERROR_IS_OK(werr)) {
899 init_lsa_String(&lsa_group_name, r->in.group_name);
901 status = rpccli_samr_LookupNames(pipe_cli, ctx,
907 if (!NT_STATUS_IS_OK(status)) {
908 werr = WERR_GROUP_NOT_FOUND;
912 if (types.ids[0] != SID_NAME_DOM_GRP) {
913 werr = WERR_GROUP_NOT_FOUND;
917 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
919 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
922 if (!NT_STATUS_IS_OK(status)) {
923 werr = ntstatus_to_werror(status);
927 init_lsa_String(&lsa_user_name, r->in.user_name);
929 status = rpccli_samr_LookupNames(pipe_cli, ctx,
935 if (!NT_STATUS_IS_OK(status)) {
936 werr = WERR_USER_NOT_FOUND;
940 if (types.ids[0] != SID_NAME_USER) {
941 werr = WERR_USER_NOT_FOUND;
945 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
948 if (!NT_STATUS_IS_OK(status)) {
949 werr = ntstatus_to_werror(status);
956 if (is_valid_policy_hnd(&group_handle)) {
957 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
960 if (ctx->disable_policy_handle_cache) {
961 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
962 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
968 /****************************************************************
969 ****************************************************************/
971 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
972 struct NetGroupDelUser *r)
974 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
977 /****************************************************************
978 ****************************************************************/
980 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
981 struct samr_DispInfoFullGroups *groups,
984 struct GROUP_INFO_0 *g0;
987 g0 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_0, groups->count);
988 W_ERROR_HAVE_NO_MEMORY(g0);
990 for (i=0; i<groups->count; i++) {
991 g0[i].grpi0_name = talloc_strdup(mem_ctx,
992 groups->entries[i].account_name.string);
993 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
996 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
997 sizeof(struct GROUP_INFO_0) * groups->count);
998 W_ERROR_HAVE_NO_MEMORY(*buffer);
1003 /****************************************************************
1004 ****************************************************************/
1006 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1007 struct samr_DispInfoFullGroups *groups,
1010 struct GROUP_INFO_1 *g1;
1013 g1 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_1, groups->count);
1014 W_ERROR_HAVE_NO_MEMORY(g1);
1016 for (i=0; i<groups->count; i++) {
1017 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1018 groups->entries[i].account_name.string);
1019 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1020 groups->entries[i].description.string);
1021 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1024 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1025 sizeof(struct GROUP_INFO_1) * groups->count);
1026 W_ERROR_HAVE_NO_MEMORY(*buffer);
1031 /****************************************************************
1032 ****************************************************************/
1034 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1035 struct samr_DispInfoFullGroups *groups,
1038 struct GROUP_INFO_2 *g2;
1041 g2 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_2, groups->count);
1042 W_ERROR_HAVE_NO_MEMORY(g2);
1044 for (i=0; i<groups->count; i++) {
1045 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1046 groups->entries[i].account_name.string);
1047 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1048 groups->entries[i].description.string);
1049 g2[i].grpi2_group_id = groups->entries[i].rid;
1050 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1051 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1054 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1055 sizeof(struct GROUP_INFO_2) * groups->count);
1056 W_ERROR_HAVE_NO_MEMORY(*buffer);
1061 /****************************************************************
1062 ****************************************************************/
1064 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1065 struct samr_DispInfoFullGroups *groups,
1066 const struct dom_sid *domain_sid,
1069 struct GROUP_INFO_3 *g3;
1072 g3 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_3, groups->count);
1073 W_ERROR_HAVE_NO_MEMORY(g3);
1075 for (i=0; i<groups->count; i++) {
1079 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1083 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1084 groups->entries[i].account_name.string);
1085 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1086 groups->entries[i].description.string);
1087 g3[i].grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
1088 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1089 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1092 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1093 sizeof(struct GROUP_INFO_3) * groups->count);
1094 W_ERROR_HAVE_NO_MEMORY(*buffer);
1099 /****************************************************************
1100 ****************************************************************/
1102 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1104 struct samr_DispInfoFullGroups *groups,
1105 const struct dom_sid *domain_sid,
1106 uint32_t *entries_read,
1110 *entries_read = groups->count;
1115 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1117 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1119 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1121 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1123 return WERR_UNKNOWN_LEVEL;
1127 /****************************************************************
1128 ****************************************************************/
1130 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1131 struct NetGroupEnum *r)
1133 struct rpc_pipe_client *pipe_cli = NULL;
1134 struct policy_handle connect_handle;
1135 struct dom_sid2 *domain_sid = NULL;
1136 struct policy_handle domain_handle;
1137 union samr_DispInfo info;
1138 union samr_DomainInfo *domain_info = NULL;
1140 uint32_t total_size = 0;
1141 uint32_t returned_size = 0;
1143 NTSTATUS status = NT_STATUS_OK;
1144 WERROR werr, tmp_werr;
1146 ZERO_STRUCT(connect_handle);
1147 ZERO_STRUCT(domain_handle);
1149 switch (r->in.level) {
1156 return WERR_UNKNOWN_LEVEL;
1159 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1160 &ndr_table_samr.syntax_id,
1162 if (!W_ERROR_IS_OK(werr)) {
1166 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1167 SAMR_ACCESS_ENUM_DOMAINS |
1168 SAMR_ACCESS_OPEN_DOMAIN,
1169 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1170 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1171 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1175 if (!W_ERROR_IS_OK(werr)) {
1179 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
1183 if (!NT_STATUS_IS_OK(status)) {
1184 werr = ntstatus_to_werror(status);
1188 if (r->out.total_entries) {
1189 *r->out.total_entries = domain_info->general.num_groups;
1192 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1196 r->in.resume_handle ?
1197 *r->in.resume_handle : 0,
1203 werr = ntstatus_to_werror(status);
1204 if (NT_STATUS_IS_ERR(status)) {
1208 if (r->out.resume_handle && info.info3.count > 0) {
1209 *r->out.resume_handle =
1210 info.info3.entries[info.info3.count-1].idx;
1213 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1217 r->out.entries_read,
1219 if (!W_ERROR_IS_OK(tmp_werr)) {
1226 if (NT_STATUS_IS_OK(status) ||
1227 NT_STATUS_IS_ERR(status)) {
1229 if (ctx->disable_policy_handle_cache) {
1230 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1231 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1238 /****************************************************************
1239 ****************************************************************/
1241 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1242 struct NetGroupEnum *r)
1244 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1247 /****************************************************************
1248 ****************************************************************/
1250 WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1251 struct NetGroupGetUsers *r)
1253 /* FIXME: this call needs to cope with large replies */
1255 struct rpc_pipe_client *pipe_cli = NULL;
1256 struct policy_handle connect_handle, domain_handle, group_handle;
1257 struct lsa_String lsa_account_name;
1258 struct dom_sid2 *domain_sid = NULL;
1259 struct samr_Ids group_rids, name_types;
1260 struct samr_RidTypeArray *rid_array = NULL;
1261 struct lsa_Strings names;
1262 struct samr_Ids member_types;
1265 uint32_t entries_read = 0;
1267 NTSTATUS status = NT_STATUS_OK;
1270 ZERO_STRUCT(connect_handle);
1271 ZERO_STRUCT(domain_handle);
1273 if (!r->out.buffer) {
1274 return WERR_INVALID_PARAM;
1277 *r->out.buffer = NULL;
1278 *r->out.entries_read = 0;
1280 switch (r->in.level) {
1285 return WERR_UNKNOWN_LEVEL;
1289 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1290 &ndr_table_samr.syntax_id,
1292 if (!W_ERROR_IS_OK(werr)) {
1296 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1297 SAMR_ACCESS_ENUM_DOMAINS |
1298 SAMR_ACCESS_OPEN_DOMAIN,
1299 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1303 if (!W_ERROR_IS_OK(werr)) {
1307 init_lsa_String(&lsa_account_name, r->in.group_name);
1309 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1315 if (!NT_STATUS_IS_OK(status)) {
1316 werr = ntstatus_to_werror(status);
1320 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1322 SAMR_GROUP_ACCESS_GET_MEMBERS,
1325 if (!NT_STATUS_IS_OK(status)) {
1326 werr = ntstatus_to_werror(status);
1330 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1333 if (!NT_STATUS_IS_OK(status)) {
1334 werr = ntstatus_to_werror(status);
1338 status = rpccli_samr_LookupRids(pipe_cli, ctx,
1344 if (!NT_STATUS_IS_OK(status)) {
1345 werr = ntstatus_to_werror(status);
1349 for (i=0; i < names.count; i++) {
1351 if (member_types.ids[i] != SID_NAME_USER) {
1355 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1357 names.names[i].string,
1361 if (!NT_STATUS_IS_OK(status)) {
1362 werr = ntstatus_to_werror(status);
1367 if (r->out.entries_read) {
1368 *r->out.entries_read = entries_read;
1371 if (r->out.total_entries) {
1372 *r->out.total_entries = entries_read;
1378 if (is_valid_policy_hnd(&group_handle)) {
1379 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1382 if (ctx->disable_policy_handle_cache) {
1383 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1384 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1390 /****************************************************************
1391 ****************************************************************/
1393 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1394 struct NetGroupGetUsers *r)
1396 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1399 /****************************************************************
1400 ****************************************************************/
1402 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1403 struct NetGroupSetUsers *r)
1405 struct rpc_pipe_client *pipe_cli = NULL;
1406 struct policy_handle connect_handle, domain_handle, group_handle;
1407 struct lsa_String lsa_account_name;
1408 struct dom_sid2 *domain_sid = NULL;
1409 union samr_GroupInfo *group_info = NULL;
1410 struct samr_Ids user_rids, name_types;
1411 struct samr_Ids group_rids, group_types;
1412 struct samr_RidTypeArray *rid_array = NULL;
1413 struct lsa_String *lsa_names = NULL;
1415 uint32_t *add_rids = NULL;
1416 uint32_t *del_rids = NULL;
1417 size_t num_add_rids = 0;
1418 size_t num_del_rids = 0;
1420 uint32_t *member_rids = NULL;
1421 size_t num_member_rids = 0;
1423 struct GROUP_USERS_INFO_0 *i0 = NULL;
1424 struct GROUP_USERS_INFO_1 *i1 = NULL;
1428 NTSTATUS status = NT_STATUS_OK;
1431 ZERO_STRUCT(connect_handle);
1432 ZERO_STRUCT(domain_handle);
1434 if (!r->in.buffer) {
1435 return WERR_INVALID_PARAM;
1438 switch (r->in.level) {
1443 return WERR_UNKNOWN_LEVEL;
1446 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1447 &ndr_table_samr.syntax_id,
1449 if (!W_ERROR_IS_OK(werr)) {
1453 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1454 SAMR_ACCESS_ENUM_DOMAINS |
1455 SAMR_ACCESS_OPEN_DOMAIN,
1456 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1460 if (!W_ERROR_IS_OK(werr)) {
1464 init_lsa_String(&lsa_account_name, r->in.group_name);
1466 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1472 if (!NT_STATUS_IS_OK(status)) {
1473 werr = ntstatus_to_werror(status);
1477 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1479 SAMR_GROUP_ACCESS_GET_MEMBERS |
1480 SAMR_GROUP_ACCESS_ADD_MEMBER |
1481 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1482 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1485 if (!NT_STATUS_IS_OK(status)) {
1486 werr = ntstatus_to_werror(status);
1490 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
1492 GROUPINFOATTRIBUTES,
1494 if (!NT_STATUS_IS_OK(status)) {
1495 werr = ntstatus_to_werror(status);
1499 switch (r->in.level) {
1501 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1504 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1508 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1514 for (i=0; i < r->in.num_entries; i++) {
1516 switch (r->in.level) {
1518 init_lsa_String(&lsa_names[i], i0->grui0_name);
1522 init_lsa_String(&lsa_names[i], i1->grui1_name);
1528 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1534 if (!NT_STATUS_IS_OK(status)) {
1535 werr = ntstatus_to_werror(status);
1539 member_rids = user_rids.ids;
1540 num_member_rids = user_rids.count;
1542 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1545 if (!NT_STATUS_IS_OK(status)) {
1546 werr = ntstatus_to_werror(status);
1552 for (i=0; i < r->in.num_entries; i++) {
1553 bool already_member = false;
1554 for (k=0; k < rid_array->count; k++) {
1555 if (member_rids[i] == rid_array->rids[k]) {
1556 already_member = true;
1560 if (!already_member) {
1561 if (!add_rid_to_array_unique(ctx,
1563 &add_rids, &num_add_rids)) {
1564 werr = WERR_GENERAL_FAILURE;
1572 for (k=0; k < rid_array->count; k++) {
1573 bool keep_member = false;
1574 for (i=0; i < r->in.num_entries; i++) {
1575 if (member_rids[i] == rid_array->rids[k]) {
1581 if (!add_rid_to_array_unique(ctx,
1583 &del_rids, &num_del_rids)) {
1584 werr = WERR_GENERAL_FAILURE;
1592 for (i=0; i < num_add_rids; i++) {
1593 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
1597 if (!NT_STATUS_IS_OK(status)) {
1598 werr = ntstatus_to_werror(status);
1605 for (i=0; i < num_del_rids; i++) {
1606 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
1609 if (!NT_STATUS_IS_OK(status)) {
1610 werr = ntstatus_to_werror(status);
1618 if (is_valid_policy_hnd(&group_handle)) {
1619 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1622 if (ctx->disable_policy_handle_cache) {
1623 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1624 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1630 /****************************************************************
1631 ****************************************************************/
1633 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1634 struct NetGroupSetUsers *r)
1636 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);