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"
26 #include "../librpc/gen_ndr/cli_samr.h"
27 #include "rpc_client/init_lsa.h"
28 #include "../libcli/security/dom_sid.h"
30 /****************************************************************
31 ****************************************************************/
33 WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
34 struct NetGroupAdd *r)
36 struct rpc_pipe_client *pipe_cli = NULL;
39 struct policy_handle connect_handle, domain_handle, group_handle;
40 struct lsa_String lsa_group_name;
41 struct dom_sid2 *domain_sid = NULL;
44 struct GROUP_INFO_0 *info0 = NULL;
45 struct GROUP_INFO_1 *info1 = NULL;
46 struct GROUP_INFO_2 *info2 = NULL;
47 struct GROUP_INFO_3 *info3 = NULL;
48 union samr_GroupInfo info;
50 ZERO_STRUCT(connect_handle);
51 ZERO_STRUCT(domain_handle);
52 ZERO_STRUCT(group_handle);
55 return WERR_INVALID_PARAM;
58 switch (r->in.level) {
60 info0 = (struct GROUP_INFO_0 *)r->in.buffer;
63 info1 = (struct GROUP_INFO_1 *)r->in.buffer;
66 info2 = (struct GROUP_INFO_2 *)r->in.buffer;
69 info3 = (struct GROUP_INFO_3 *)r->in.buffer;
72 werr = WERR_UNKNOWN_LEVEL;
76 werr = libnetapi_open_pipe(ctx, r->in.server_name,
77 &ndr_table_samr.syntax_id,
79 if (!W_ERROR_IS_OK(werr)) {
83 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
84 SAMR_ACCESS_ENUM_DOMAINS |
85 SAMR_ACCESS_LOOKUP_DOMAIN,
86 SAMR_DOMAIN_ACCESS_CREATE_GROUP |
87 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
91 if (!W_ERROR_IS_OK(werr)) {
95 switch (r->in.level) {
97 init_lsa_String(&lsa_group_name, info0->grpi0_name);
100 init_lsa_String(&lsa_group_name, info1->grpi1_name);
103 init_lsa_String(&lsa_group_name, info2->grpi2_name);
106 init_lsa_String(&lsa_group_name, info3->grpi3_name);
110 status = rpccli_samr_CreateDomainGroup(pipe_cli, ctx,
114 SAMR_GROUP_ACCESS_SET_INFO,
118 if (!NT_STATUS_IS_OK(status)) {
119 werr = ntstatus_to_werror(status);
123 switch (r->in.level) {
125 if (info1->grpi1_comment) {
126 init_lsa_String(&info.description,
127 info1->grpi1_comment);
129 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
131 GROUPINFODESCRIPTION,
136 if (info2->grpi2_comment) {
137 init_lsa_String(&info.description,
138 info2->grpi2_comment);
140 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
142 GROUPINFODESCRIPTION,
144 if (!NT_STATUS_IS_OK(status)) {
145 werr = ntstatus_to_werror(status);
150 if (info2->grpi2_attributes != 0) {
151 info.attributes.attributes = info2->grpi2_attributes;
152 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
160 if (info3->grpi3_comment) {
161 init_lsa_String(&info.description,
162 info3->grpi3_comment);
164 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
166 GROUPINFODESCRIPTION,
168 if (!NT_STATUS_IS_OK(status)) {
169 werr = ntstatus_to_werror(status);
174 if (info3->grpi3_attributes != 0) {
175 info.attributes.attributes = info3->grpi3_attributes;
176 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
186 if (!NT_STATUS_IS_OK(status)) {
187 werr = ntstatus_to_werror(status);
195 rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
199 if (is_valid_policy_hnd(&group_handle)) {
200 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
203 if (ctx->disable_policy_handle_cache) {
204 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
205 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
211 /****************************************************************
212 ****************************************************************/
214 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
215 struct NetGroupAdd *r)
217 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
220 /****************************************************************
221 ****************************************************************/
223 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
224 struct NetGroupDel *r)
226 struct rpc_pipe_client *pipe_cli = NULL;
229 struct policy_handle connect_handle, domain_handle, group_handle;
230 struct lsa_String lsa_group_name;
231 struct dom_sid2 *domain_sid = NULL;
234 struct samr_Ids rids;
235 struct samr_Ids types;
236 union samr_GroupInfo *info = NULL;
237 struct samr_RidTypeArray *rid_array = NULL;
239 ZERO_STRUCT(connect_handle);
240 ZERO_STRUCT(domain_handle);
241 ZERO_STRUCT(group_handle);
243 if (!r->in.group_name) {
244 return WERR_INVALID_PARAM;
247 werr = libnetapi_open_pipe(ctx, r->in.server_name,
248 &ndr_table_samr.syntax_id,
250 if (!W_ERROR_IS_OK(werr)) {
254 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
255 SAMR_ACCESS_ENUM_DOMAINS |
256 SAMR_ACCESS_LOOKUP_DOMAIN,
257 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
261 if (!W_ERROR_IS_OK(werr)) {
265 init_lsa_String(&lsa_group_name, r->in.group_name);
267 status = rpccli_samr_LookupNames(pipe_cli, ctx,
273 if (!NT_STATUS_IS_OK(status)) {
274 werr = ntstatus_to_werror(status);
278 if (types.ids[0] != SID_NAME_DOM_GRP) {
279 werr = WERR_INVALID_DATATYPE;
283 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
286 SAMR_GROUP_ACCESS_GET_MEMBERS |
287 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
288 SAMR_GROUP_ACCESS_ADD_MEMBER |
289 SAMR_GROUP_ACCESS_LOOKUP_INFO,
292 if (!NT_STATUS_IS_OK(status)) {
293 werr = ntstatus_to_werror(status);
297 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
301 if (!NT_STATUS_IS_OK(status)) {
302 werr = ntstatus_to_werror(status);
307 /* breaks against NT4 */
308 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
309 werr = WERR_ACCESS_DENIED;
313 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
316 if (!NT_STATUS_IS_OK(status)) {
317 werr = ntstatus_to_werror(status);
322 struct lsa_Strings names;
323 struct samr_Ids member_types;
325 status = rpccli_samr_LookupRids(pipe_cli, ctx,
331 if (!NT_STATUS_IS_OK(status)) {
332 werr = ntstatus_to_werror(status);
337 for (i=0; i < rid_array->count; i++) {
339 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
342 if (!NT_STATUS_IS_OK(status)) {
343 werr = ntstatus_to_werror(status);
348 status = rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
350 if (!NT_STATUS_IS_OK(status)) {
351 werr = ntstatus_to_werror(status);
355 ZERO_STRUCT(group_handle);
360 if (is_valid_policy_hnd(&group_handle)) {
361 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
364 if (ctx->disable_policy_handle_cache) {
365 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
366 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
372 /****************************************************************
373 ****************************************************************/
375 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
376 struct NetGroupDel *r)
378 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
381 /****************************************************************
382 ****************************************************************/
384 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
385 struct NetGroupSetInfo *r)
387 struct rpc_pipe_client *pipe_cli = NULL;
390 struct policy_handle connect_handle, domain_handle, group_handle;
391 struct lsa_String lsa_group_name;
392 struct dom_sid2 *domain_sid = NULL;
394 struct samr_Ids rids;
395 struct samr_Ids types;
396 union samr_GroupInfo info;
397 struct GROUP_INFO_0 *g0;
398 struct GROUP_INFO_1 *g1;
399 struct GROUP_INFO_2 *g2;
400 struct GROUP_INFO_3 *g3;
401 struct GROUP_INFO_1002 *g1002;
402 struct GROUP_INFO_1005 *g1005;
404 ZERO_STRUCT(connect_handle);
405 ZERO_STRUCT(domain_handle);
406 ZERO_STRUCT(group_handle);
408 if (!r->in.group_name) {
409 return WERR_INVALID_PARAM;
412 werr = libnetapi_open_pipe(ctx, r->in.server_name,
413 &ndr_table_samr.syntax_id,
415 if (!W_ERROR_IS_OK(werr)) {
419 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
420 SAMR_ACCESS_ENUM_DOMAINS |
421 SAMR_ACCESS_LOOKUP_DOMAIN,
422 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
426 if (!W_ERROR_IS_OK(werr)) {
430 init_lsa_String(&lsa_group_name, r->in.group_name);
432 status = rpccli_samr_LookupNames(pipe_cli, ctx,
438 if (!NT_STATUS_IS_OK(status)) {
439 werr = ntstatus_to_werror(status);
443 if (types.ids[0] != SID_NAME_DOM_GRP) {
444 werr = WERR_INVALID_DATATYPE;
448 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
450 SAMR_GROUP_ACCESS_SET_INFO |
451 SAMR_GROUP_ACCESS_LOOKUP_INFO,
454 if (!NT_STATUS_IS_OK(status)) {
455 werr = ntstatus_to_werror(status);
459 switch (r->in.level) {
461 g0 = (struct GROUP_INFO_0 *)r->in.buffer;
462 init_lsa_String(&info.name, g0->grpi0_name);
463 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
469 g1 = (struct GROUP_INFO_1 *)r->in.buffer;
470 init_lsa_String(&info.description, g1->grpi1_comment);
471 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
473 GROUPINFODESCRIPTION,
477 g2 = (struct GROUP_INFO_2 *)r->in.buffer;
478 init_lsa_String(&info.description, g2->grpi2_comment);
479 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
481 GROUPINFODESCRIPTION,
483 if (!NT_STATUS_IS_OK(status)) {
484 werr = ntstatus_to_werror(status);
487 info.attributes.attributes = g2->grpi2_attributes;
488 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
494 g3 = (struct GROUP_INFO_3 *)r->in.buffer;
495 init_lsa_String(&info.description, g3->grpi3_comment);
496 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
498 GROUPINFODESCRIPTION,
500 if (!NT_STATUS_IS_OK(status)) {
501 werr = ntstatus_to_werror(status);
504 info.attributes.attributes = g3->grpi3_attributes;
505 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
511 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
512 init_lsa_String(&info.description, g1002->grpi1002_comment);
513 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
515 GROUPINFODESCRIPTION,
519 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
520 info.attributes.attributes = g1005->grpi1005_attributes;
521 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
527 status = NT_STATUS_INVALID_LEVEL;
531 if (!NT_STATUS_IS_OK(status)) {
532 werr = ntstatus_to_werror(status);
539 if (is_valid_policy_hnd(&group_handle)) {
540 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
543 if (ctx->disable_policy_handle_cache) {
544 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
545 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
551 /****************************************************************
552 ****************************************************************/
554 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
555 struct NetGroupSetInfo *r)
557 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
560 /****************************************************************
561 ****************************************************************/
563 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
565 struct samr_GroupInfoAll *info,
566 struct dom_sid2 *domain_sid,
570 struct GROUP_INFO_0 info0;
571 struct GROUP_INFO_1 info1;
572 struct GROUP_INFO_2 info2;
573 struct GROUP_INFO_3 info3;
578 info0.grpi0_name = info->name.string;
580 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
584 info1.grpi1_name = info->name.string;
585 info1.grpi1_comment = info->description.string;
587 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
591 info2.grpi2_name = info->name.string;
592 info2.grpi2_comment = info->description.string;
593 info2.grpi2_group_id = rid;
594 info2.grpi2_attributes = info->attributes;
596 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
600 if (!sid_compose(&sid, domain_sid, rid)) {
604 info3.grpi3_name = info->name.string;
605 info3.grpi3_comment = info->description.string;
606 info3.grpi3_attributes = info->attributes;
607 info3.grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
609 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
613 return WERR_UNKNOWN_LEVEL;
616 W_ERROR_HAVE_NO_MEMORY(*buffer);
621 /****************************************************************
622 ****************************************************************/
624 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
625 struct NetGroupGetInfo *r)
627 struct rpc_pipe_client *pipe_cli = NULL;
630 struct policy_handle connect_handle, domain_handle, group_handle;
631 struct lsa_String lsa_group_name;
632 struct dom_sid2 *domain_sid = NULL;
634 struct samr_Ids rids;
635 struct samr_Ids types;
636 union samr_GroupInfo *info = NULL;
637 bool group_info_all = false;
639 ZERO_STRUCT(connect_handle);
640 ZERO_STRUCT(domain_handle);
641 ZERO_STRUCT(group_handle);
643 if (!r->in.group_name) {
644 return WERR_INVALID_PARAM;
647 werr = libnetapi_open_pipe(ctx, r->in.server_name,
648 &ndr_table_samr.syntax_id,
650 if (!W_ERROR_IS_OK(werr)) {
654 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
655 SAMR_ACCESS_ENUM_DOMAINS |
656 SAMR_ACCESS_LOOKUP_DOMAIN,
657 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
661 if (!W_ERROR_IS_OK(werr)) {
665 init_lsa_String(&lsa_group_name, r->in.group_name);
667 status = rpccli_samr_LookupNames(pipe_cli, ctx,
673 if (!NT_STATUS_IS_OK(status)) {
674 werr = ntstatus_to_werror(status);
678 if (types.ids[0] != SID_NAME_DOM_GRP) {
679 werr = WERR_INVALID_DATATYPE;
683 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
685 SAMR_GROUP_ACCESS_LOOKUP_INFO,
688 if (!NT_STATUS_IS_OK(status)) {
689 werr = ntstatus_to_werror(status);
693 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
697 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
698 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
702 group_info_all = true;
705 if (!NT_STATUS_IS_OK(status)) {
706 werr = ntstatus_to_werror(status);
710 werr = map_group_info_to_buffer(ctx, r->in.level,
711 group_info_all ? &info->all : &info->all2,
712 domain_sid, rids.ids[0],
714 if (!W_ERROR_IS_OK(werr)) {
718 if (is_valid_policy_hnd(&group_handle)) {
719 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
722 if (ctx->disable_policy_handle_cache) {
723 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
724 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
730 /****************************************************************
731 ****************************************************************/
733 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
734 struct NetGroupGetInfo *r)
736 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
739 /****************************************************************
740 ****************************************************************/
742 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
743 struct NetGroupAddUser *r)
745 struct rpc_pipe_client *pipe_cli = NULL;
748 struct policy_handle connect_handle, domain_handle, group_handle;
749 struct lsa_String lsa_group_name, lsa_user_name;
750 struct dom_sid2 *domain_sid = NULL;
752 struct samr_Ids rids;
753 struct samr_Ids types;
755 ZERO_STRUCT(connect_handle);
756 ZERO_STRUCT(domain_handle);
757 ZERO_STRUCT(group_handle);
759 if (!r->in.group_name) {
760 return WERR_INVALID_PARAM;
763 werr = libnetapi_open_pipe(ctx, r->in.server_name,
764 &ndr_table_samr.syntax_id,
766 if (!W_ERROR_IS_OK(werr)) {
770 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
771 SAMR_ACCESS_ENUM_DOMAINS |
772 SAMR_ACCESS_LOOKUP_DOMAIN,
773 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
777 if (!W_ERROR_IS_OK(werr)) {
781 init_lsa_String(&lsa_group_name, r->in.group_name);
783 status = rpccli_samr_LookupNames(pipe_cli, ctx,
789 if (!NT_STATUS_IS_OK(status)) {
790 werr = WERR_GROUPNOTFOUND;
794 if (types.ids[0] != SID_NAME_DOM_GRP) {
795 werr = WERR_GROUPNOTFOUND;
799 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
801 SAMR_GROUP_ACCESS_ADD_MEMBER,
804 if (!NT_STATUS_IS_OK(status)) {
805 werr = ntstatus_to_werror(status);
809 init_lsa_String(&lsa_user_name, r->in.user_name);
811 status = rpccli_samr_LookupNames(pipe_cli, ctx,
817 if (!NT_STATUS_IS_OK(status)) {
818 werr = WERR_USER_NOT_FOUND;
822 if (types.ids[0] != SID_NAME_USER) {
823 werr = WERR_USER_NOT_FOUND;
827 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
831 if (!NT_STATUS_IS_OK(status)) {
832 werr = ntstatus_to_werror(status);
839 if (is_valid_policy_hnd(&group_handle)) {
840 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
843 if (ctx->disable_policy_handle_cache) {
844 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
845 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
851 /****************************************************************
852 ****************************************************************/
854 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
855 struct NetGroupAddUser *r)
857 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
860 /****************************************************************
861 ****************************************************************/
863 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
864 struct NetGroupDelUser *r)
866 struct rpc_pipe_client *pipe_cli = NULL;
869 struct policy_handle connect_handle, domain_handle, group_handle;
870 struct lsa_String lsa_group_name, lsa_user_name;
871 struct dom_sid2 *domain_sid = NULL;
873 struct samr_Ids rids;
874 struct samr_Ids types;
876 ZERO_STRUCT(connect_handle);
877 ZERO_STRUCT(domain_handle);
878 ZERO_STRUCT(group_handle);
880 if (!r->in.group_name) {
881 return WERR_INVALID_PARAM;
884 werr = libnetapi_open_pipe(ctx, r->in.server_name,
885 &ndr_table_samr.syntax_id,
887 if (!W_ERROR_IS_OK(werr)) {
891 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
892 SAMR_ACCESS_ENUM_DOMAINS |
893 SAMR_ACCESS_LOOKUP_DOMAIN,
894 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
898 if (!W_ERROR_IS_OK(werr)) {
902 init_lsa_String(&lsa_group_name, r->in.group_name);
904 status = rpccli_samr_LookupNames(pipe_cli, ctx,
910 if (!NT_STATUS_IS_OK(status)) {
911 werr = WERR_GROUPNOTFOUND;
915 if (types.ids[0] != SID_NAME_DOM_GRP) {
916 werr = WERR_GROUPNOTFOUND;
920 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
922 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
925 if (!NT_STATUS_IS_OK(status)) {
926 werr = ntstatus_to_werror(status);
930 init_lsa_String(&lsa_user_name, r->in.user_name);
932 status = rpccli_samr_LookupNames(pipe_cli, ctx,
938 if (!NT_STATUS_IS_OK(status)) {
939 werr = WERR_USER_NOT_FOUND;
943 if (types.ids[0] != SID_NAME_USER) {
944 werr = WERR_USER_NOT_FOUND;
948 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
951 if (!NT_STATUS_IS_OK(status)) {
952 werr = ntstatus_to_werror(status);
959 if (is_valid_policy_hnd(&group_handle)) {
960 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
963 if (ctx->disable_policy_handle_cache) {
964 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
965 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
971 /****************************************************************
972 ****************************************************************/
974 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
975 struct NetGroupDelUser *r)
977 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
980 /****************************************************************
981 ****************************************************************/
983 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
984 struct samr_DispInfoFullGroups *groups,
987 struct GROUP_INFO_0 *g0;
990 g0 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_0, groups->count);
991 W_ERROR_HAVE_NO_MEMORY(g0);
993 for (i=0; i<groups->count; i++) {
994 g0[i].grpi0_name = talloc_strdup(mem_ctx,
995 groups->entries[i].account_name.string);
996 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
999 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
1000 sizeof(struct GROUP_INFO_0) * groups->count);
1001 W_ERROR_HAVE_NO_MEMORY(*buffer);
1006 /****************************************************************
1007 ****************************************************************/
1009 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1010 struct samr_DispInfoFullGroups *groups,
1013 struct GROUP_INFO_1 *g1;
1016 g1 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_1, groups->count);
1017 W_ERROR_HAVE_NO_MEMORY(g1);
1019 for (i=0; i<groups->count; i++) {
1020 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1021 groups->entries[i].account_name.string);
1022 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1023 groups->entries[i].description.string);
1024 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1027 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1028 sizeof(struct GROUP_INFO_1) * groups->count);
1029 W_ERROR_HAVE_NO_MEMORY(*buffer);
1034 /****************************************************************
1035 ****************************************************************/
1037 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1038 struct samr_DispInfoFullGroups *groups,
1041 struct GROUP_INFO_2 *g2;
1044 g2 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_2, groups->count);
1045 W_ERROR_HAVE_NO_MEMORY(g2);
1047 for (i=0; i<groups->count; i++) {
1048 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1049 groups->entries[i].account_name.string);
1050 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1051 groups->entries[i].description.string);
1052 g2[i].grpi2_group_id = groups->entries[i].rid;
1053 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1054 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1057 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1058 sizeof(struct GROUP_INFO_2) * groups->count);
1059 W_ERROR_HAVE_NO_MEMORY(*buffer);
1064 /****************************************************************
1065 ****************************************************************/
1067 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1068 struct samr_DispInfoFullGroups *groups,
1069 const struct dom_sid *domain_sid,
1072 struct GROUP_INFO_3 *g3;
1075 g3 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_3, groups->count);
1076 W_ERROR_HAVE_NO_MEMORY(g3);
1078 for (i=0; i<groups->count; i++) {
1082 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1086 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1087 groups->entries[i].account_name.string);
1088 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1089 groups->entries[i].description.string);
1090 g3[i].grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
1091 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1092 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1095 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1096 sizeof(struct GROUP_INFO_3) * groups->count);
1097 W_ERROR_HAVE_NO_MEMORY(*buffer);
1102 /****************************************************************
1103 ****************************************************************/
1105 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1107 struct samr_DispInfoFullGroups *groups,
1108 const struct dom_sid *domain_sid,
1109 uint32_t *entries_read,
1113 *entries_read = groups->count;
1118 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1120 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1122 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1124 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1126 return WERR_UNKNOWN_LEVEL;
1130 /****************************************************************
1131 ****************************************************************/
1133 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1134 struct NetGroupEnum *r)
1136 struct rpc_pipe_client *pipe_cli = NULL;
1137 struct policy_handle connect_handle;
1138 struct dom_sid2 *domain_sid = NULL;
1139 struct policy_handle domain_handle;
1140 union samr_DispInfo info;
1141 union samr_DomainInfo *domain_info = NULL;
1143 uint32_t total_size = 0;
1144 uint32_t returned_size = 0;
1146 NTSTATUS status = NT_STATUS_OK;
1147 WERROR werr, tmp_werr;
1149 ZERO_STRUCT(connect_handle);
1150 ZERO_STRUCT(domain_handle);
1152 switch (r->in.level) {
1159 return WERR_UNKNOWN_LEVEL;
1162 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1163 &ndr_table_samr.syntax_id,
1165 if (!W_ERROR_IS_OK(werr)) {
1169 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1170 SAMR_ACCESS_ENUM_DOMAINS |
1171 SAMR_ACCESS_LOOKUP_DOMAIN,
1172 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1173 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1174 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1178 if (!W_ERROR_IS_OK(werr)) {
1182 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
1186 if (!NT_STATUS_IS_OK(status)) {
1187 werr = ntstatus_to_werror(status);
1191 if (r->out.total_entries) {
1192 *r->out.total_entries = domain_info->general.num_groups;
1195 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1199 r->in.resume_handle ?
1200 *r->in.resume_handle : 0,
1206 werr = ntstatus_to_werror(status);
1207 if (NT_STATUS_IS_ERR(status)) {
1211 if (r->out.resume_handle && info.info3.count > 0) {
1212 *r->out.resume_handle =
1213 info.info3.entries[info.info3.count-1].idx;
1216 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1220 r->out.entries_read,
1222 if (!W_ERROR_IS_OK(tmp_werr)) {
1229 if (NT_STATUS_IS_OK(status) ||
1230 NT_STATUS_IS_ERR(status)) {
1232 if (ctx->disable_policy_handle_cache) {
1233 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1234 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1241 /****************************************************************
1242 ****************************************************************/
1244 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1245 struct NetGroupEnum *r)
1247 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1250 /****************************************************************
1251 ****************************************************************/
1253 WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1254 struct NetGroupGetUsers *r)
1256 /* FIXME: this call needs to cope with large replies */
1258 struct rpc_pipe_client *pipe_cli = NULL;
1259 struct policy_handle connect_handle, domain_handle, group_handle;
1260 struct lsa_String lsa_account_name;
1261 struct dom_sid2 *domain_sid = NULL;
1262 struct samr_Ids group_rids, name_types;
1263 struct samr_RidTypeArray *rid_array = NULL;
1264 struct lsa_Strings names;
1265 struct samr_Ids member_types;
1268 uint32_t entries_read = 0;
1270 NTSTATUS status = NT_STATUS_OK;
1273 ZERO_STRUCT(connect_handle);
1274 ZERO_STRUCT(domain_handle);
1276 if (!r->out.buffer) {
1277 return WERR_INVALID_PARAM;
1280 *r->out.buffer = NULL;
1281 *r->out.entries_read = 0;
1282 *r->out.total_entries = 0;
1284 switch (r->in.level) {
1289 return WERR_UNKNOWN_LEVEL;
1293 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1294 &ndr_table_samr.syntax_id,
1296 if (!W_ERROR_IS_OK(werr)) {
1300 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1301 SAMR_ACCESS_ENUM_DOMAINS |
1302 SAMR_ACCESS_LOOKUP_DOMAIN,
1303 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1307 if (!W_ERROR_IS_OK(werr)) {
1311 init_lsa_String(&lsa_account_name, r->in.group_name);
1313 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1319 if (!NT_STATUS_IS_OK(status)) {
1320 werr = ntstatus_to_werror(status);
1324 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1326 SAMR_GROUP_ACCESS_GET_MEMBERS,
1329 if (!NT_STATUS_IS_OK(status)) {
1330 werr = ntstatus_to_werror(status);
1334 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1337 if (!NT_STATUS_IS_OK(status)) {
1338 werr = ntstatus_to_werror(status);
1342 status = rpccli_samr_LookupRids(pipe_cli, ctx,
1348 if (!NT_STATUS_IS_OK(status)) {
1349 werr = ntstatus_to_werror(status);
1353 for (i=0; i < names.count; i++) {
1355 if (member_types.ids[i] != SID_NAME_USER) {
1359 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1361 names.names[i].string,
1365 if (!NT_STATUS_IS_OK(status)) {
1366 werr = ntstatus_to_werror(status);
1371 *r->out.entries_read = entries_read;
1372 *r->out.total_entries = entries_read;
1377 if (is_valid_policy_hnd(&group_handle)) {
1378 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1381 if (ctx->disable_policy_handle_cache) {
1382 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1383 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1389 /****************************************************************
1390 ****************************************************************/
1392 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1393 struct NetGroupGetUsers *r)
1395 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1398 /****************************************************************
1399 ****************************************************************/
1401 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1402 struct NetGroupSetUsers *r)
1404 struct rpc_pipe_client *pipe_cli = NULL;
1405 struct policy_handle connect_handle, domain_handle, group_handle;
1406 struct lsa_String lsa_account_name;
1407 struct dom_sid2 *domain_sid = NULL;
1408 union samr_GroupInfo *group_info = NULL;
1409 struct samr_Ids user_rids, name_types;
1410 struct samr_Ids group_rids, group_types;
1411 struct samr_RidTypeArray *rid_array = NULL;
1412 struct lsa_String *lsa_names = NULL;
1414 uint32_t *add_rids = NULL;
1415 uint32_t *del_rids = NULL;
1416 size_t num_add_rids = 0;
1417 size_t num_del_rids = 0;
1419 uint32_t *member_rids = NULL;
1421 struct GROUP_USERS_INFO_0 *i0 = NULL;
1422 struct GROUP_USERS_INFO_1 *i1 = NULL;
1426 NTSTATUS status = NT_STATUS_OK;
1429 ZERO_STRUCT(connect_handle);
1430 ZERO_STRUCT(domain_handle);
1432 if (!r->in.buffer) {
1433 return WERR_INVALID_PARAM;
1436 switch (r->in.level) {
1441 return WERR_UNKNOWN_LEVEL;
1444 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1445 &ndr_table_samr.syntax_id,
1447 if (!W_ERROR_IS_OK(werr)) {
1451 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1452 SAMR_ACCESS_ENUM_DOMAINS |
1453 SAMR_ACCESS_LOOKUP_DOMAIN,
1454 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1458 if (!W_ERROR_IS_OK(werr)) {
1462 init_lsa_String(&lsa_account_name, r->in.group_name);
1464 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1470 if (!NT_STATUS_IS_OK(status)) {
1471 werr = ntstatus_to_werror(status);
1475 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1477 SAMR_GROUP_ACCESS_GET_MEMBERS |
1478 SAMR_GROUP_ACCESS_ADD_MEMBER |
1479 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1480 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1483 if (!NT_STATUS_IS_OK(status)) {
1484 werr = ntstatus_to_werror(status);
1488 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
1490 GROUPINFOATTRIBUTES,
1492 if (!NT_STATUS_IS_OK(status)) {
1493 werr = ntstatus_to_werror(status);
1497 switch (r->in.level) {
1499 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1502 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1506 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1512 for (i=0; i < r->in.num_entries; i++) {
1514 switch (r->in.level) {
1516 init_lsa_String(&lsa_names[i], i0->grui0_name);
1520 init_lsa_String(&lsa_names[i], i1->grui1_name);
1526 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1532 if (!NT_STATUS_IS_OK(status)) {
1533 werr = ntstatus_to_werror(status);
1537 member_rids = user_rids.ids;
1539 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1542 if (!NT_STATUS_IS_OK(status)) {
1543 werr = ntstatus_to_werror(status);
1549 for (i=0; i < r->in.num_entries; i++) {
1550 bool already_member = false;
1551 for (k=0; k < rid_array->count; k++) {
1552 if (member_rids[i] == rid_array->rids[k]) {
1553 already_member = true;
1557 if (!already_member) {
1558 if (!add_rid_to_array_unique(ctx,
1560 &add_rids, &num_add_rids)) {
1561 werr = WERR_GENERAL_FAILURE;
1569 for (k=0; k < rid_array->count; k++) {
1570 bool keep_member = false;
1571 for (i=0; i < r->in.num_entries; i++) {
1572 if (member_rids[i] == rid_array->rids[k]) {
1578 if (!add_rid_to_array_unique(ctx,
1580 &del_rids, &num_del_rids)) {
1581 werr = WERR_GENERAL_FAILURE;
1589 for (i=0; i < num_add_rids; i++) {
1590 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
1594 if (!NT_STATUS_IS_OK(status)) {
1595 werr = ntstatus_to_werror(status);
1602 for (i=0; i < num_del_rids; i++) {
1603 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
1606 if (!NT_STATUS_IS_OK(status)) {
1607 werr = ntstatus_to_werror(status);
1615 if (is_valid_policy_hnd(&group_handle)) {
1616 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1619 if (ctx->disable_policy_handle_cache) {
1620 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1621 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1627 /****************************************************************
1628 ****************************************************************/
1630 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1631 struct NetGroupSetUsers *r)
1633 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);