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 cli_state *cli = NULL;
34 struct rpc_pipe_client *pipe_cli = NULL;
37 POLICY_HND connect_handle, domain_handle, group_handle;
38 struct lsa_String lsa_group_name;
39 struct dom_sid2 *domain_sid = NULL;
42 struct GROUP_INFO_0 *info0 = NULL;
43 struct GROUP_INFO_1 *info1 = NULL;
44 struct GROUP_INFO_2 *info2 = NULL;
45 struct GROUP_INFO_3 *info3 = NULL;
46 union samr_GroupInfo info;
48 ZERO_STRUCT(connect_handle);
49 ZERO_STRUCT(domain_handle);
50 ZERO_STRUCT(group_handle);
53 return WERR_INVALID_PARAM;
56 switch (r->in.level) {
58 info0 = (struct GROUP_INFO_0 *)r->in.buffer;
61 info1 = (struct GROUP_INFO_1 *)r->in.buffer;
64 info2 = (struct GROUP_INFO_2 *)r->in.buffer;
67 info3 = (struct GROUP_INFO_3 *)r->in.buffer;
70 werr = WERR_UNKNOWN_LEVEL;
74 werr = libnetapi_open_pipe(ctx, r->in.server_name,
75 &ndr_table_samr.syntax_id,
78 if (!W_ERROR_IS_OK(werr)) {
82 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
83 SAMR_ACCESS_ENUM_DOMAINS |
84 SAMR_ACCESS_OPEN_DOMAIN,
85 SAMR_DOMAIN_ACCESS_CREATE_GROUP |
86 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
90 if (!W_ERROR_IS_OK(werr)) {
94 switch (r->in.level) {
96 init_lsa_String(&lsa_group_name, info0->grpi0_name);
99 init_lsa_String(&lsa_group_name, info1->grpi1_name);
102 init_lsa_String(&lsa_group_name, info2->grpi2_name);
105 init_lsa_String(&lsa_group_name, info3->grpi3_name);
109 status = rpccli_samr_CreateDomainGroup(pipe_cli, ctx,
113 SAMR_GROUP_ACCESS_SET_INFO,
117 if (!NT_STATUS_IS_OK(status)) {
118 werr = ntstatus_to_werror(status);
122 switch (r->in.level) {
124 if (info1->grpi1_comment) {
125 init_lsa_String(&info.description,
126 info1->grpi1_comment);
128 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
130 GROUPINFODESCRIPTION,
135 if (info2->grpi2_comment) {
136 init_lsa_String(&info.description,
137 info2->grpi2_comment);
139 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
141 GROUPINFODESCRIPTION,
143 if (!NT_STATUS_IS_OK(status)) {
144 werr = ntstatus_to_werror(status);
149 if (info2->grpi2_attributes != 0) {
150 info.attributes.attributes = info2->grpi2_attributes;
151 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
159 if (info3->grpi3_comment) {
160 init_lsa_String(&info.description,
161 info3->grpi3_comment);
163 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
165 GROUPINFODESCRIPTION,
167 if (!NT_STATUS_IS_OK(status)) {
168 werr = ntstatus_to_werror(status);
173 if (info3->grpi3_attributes != 0) {
174 info.attributes.attributes = info3->grpi3_attributes;
175 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
185 if (!NT_STATUS_IS_OK(status)) {
186 werr = ntstatus_to_werror(status);
194 rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
202 if (is_valid_policy_hnd(&group_handle)) {
203 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
206 if (ctx->disable_policy_handle_cache) {
207 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
208 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
214 /****************************************************************
215 ****************************************************************/
217 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
218 struct NetGroupAdd *r)
220 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
223 /****************************************************************
224 ****************************************************************/
226 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
227 struct NetGroupDel *r)
229 struct cli_state *cli = NULL;
230 struct rpc_pipe_client *pipe_cli = NULL;
233 POLICY_HND connect_handle, domain_handle, group_handle;
234 struct lsa_String lsa_group_name;
235 struct dom_sid2 *domain_sid = NULL;
238 struct samr_Ids rids;
239 struct samr_Ids types;
240 union samr_GroupInfo *info = NULL;
241 struct samr_RidTypeArray *rid_array = NULL;
243 ZERO_STRUCT(connect_handle);
244 ZERO_STRUCT(domain_handle);
245 ZERO_STRUCT(group_handle);
247 if (!r->in.group_name) {
248 return WERR_INVALID_PARAM;
251 werr = libnetapi_open_pipe(ctx, r->in.server_name,
252 &ndr_table_samr.syntax_id,
255 if (!W_ERROR_IS_OK(werr)) {
259 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
260 SAMR_ACCESS_ENUM_DOMAINS |
261 SAMR_ACCESS_OPEN_DOMAIN,
262 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
266 if (!W_ERROR_IS_OK(werr)) {
270 init_lsa_String(&lsa_group_name, r->in.group_name);
272 status = rpccli_samr_LookupNames(pipe_cli, ctx,
278 if (!NT_STATUS_IS_OK(status)) {
279 werr = ntstatus_to_werror(status);
283 if (types.ids[0] != SID_NAME_DOM_GRP) {
284 werr = WERR_INVALID_DATATYPE;
288 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
291 SAMR_GROUP_ACCESS_GET_MEMBERS |
292 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
293 SAMR_GROUP_ACCESS_ADD_MEMBER |
294 SAMR_GROUP_ACCESS_LOOKUP_INFO,
297 if (!NT_STATUS_IS_OK(status)) {
298 werr = ntstatus_to_werror(status);
302 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
306 if (!NT_STATUS_IS_OK(status)) {
307 werr = ntstatus_to_werror(status);
312 /* breaks against NT4 */
313 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
314 werr = WERR_ACCESS_DENIED;
318 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
321 if (!NT_STATUS_IS_OK(status)) {
322 werr = ntstatus_to_werror(status);
327 struct lsa_Strings names;
328 struct samr_Ids member_types;
330 status = rpccli_samr_LookupRids(pipe_cli, ctx,
336 if (!NT_STATUS_IS_OK(status)) {
337 werr = ntstatus_to_werror(status);
342 for (i=0; i < rid_array->count; i++) {
344 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
347 if (!NT_STATUS_IS_OK(status)) {
348 werr = ntstatus_to_werror(status);
353 status = rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
355 if (!NT_STATUS_IS_OK(status)) {
356 werr = ntstatus_to_werror(status);
360 ZERO_STRUCT(group_handle);
369 if (is_valid_policy_hnd(&group_handle)) {
370 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
373 if (ctx->disable_policy_handle_cache) {
374 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
375 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
381 /****************************************************************
382 ****************************************************************/
384 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
385 struct NetGroupDel *r)
387 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
390 /****************************************************************
391 ****************************************************************/
393 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
394 struct NetGroupSetInfo *r)
396 struct cli_state *cli = NULL;
397 struct rpc_pipe_client *pipe_cli = NULL;
400 POLICY_HND connect_handle, domain_handle, group_handle;
401 struct lsa_String lsa_group_name;
402 struct dom_sid2 *domain_sid = NULL;
404 struct samr_Ids rids;
405 struct samr_Ids types;
406 union samr_GroupInfo info;
407 struct GROUP_INFO_0 *g0;
408 struct GROUP_INFO_1 *g1;
409 struct GROUP_INFO_2 *g2;
410 struct GROUP_INFO_3 *g3;
411 struct GROUP_INFO_1002 *g1002;
412 struct GROUP_INFO_1005 *g1005;
414 ZERO_STRUCT(connect_handle);
415 ZERO_STRUCT(domain_handle);
416 ZERO_STRUCT(group_handle);
418 if (!r->in.group_name) {
419 return WERR_INVALID_PARAM;
422 werr = libnetapi_open_pipe(ctx, r->in.server_name,
423 &ndr_table_samr.syntax_id,
426 if (!W_ERROR_IS_OK(werr)) {
430 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
431 SAMR_ACCESS_ENUM_DOMAINS |
432 SAMR_ACCESS_OPEN_DOMAIN,
433 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
437 if (!W_ERROR_IS_OK(werr)) {
441 init_lsa_String(&lsa_group_name, r->in.group_name);
443 status = rpccli_samr_LookupNames(pipe_cli, ctx,
449 if (!NT_STATUS_IS_OK(status)) {
450 werr = ntstatus_to_werror(status);
454 if (types.ids[0] != SID_NAME_DOM_GRP) {
455 werr = WERR_INVALID_DATATYPE;
459 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
461 SAMR_GROUP_ACCESS_SET_INFO |
462 SAMR_GROUP_ACCESS_LOOKUP_INFO,
465 if (!NT_STATUS_IS_OK(status)) {
466 werr = ntstatus_to_werror(status);
470 switch (r->in.level) {
472 g0 = (struct GROUP_INFO_0 *)r->in.buffer;
473 init_lsa_String(&info.name, g0->grpi0_name);
474 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
480 g1 = (struct GROUP_INFO_1 *)r->in.buffer;
481 init_lsa_String(&info.description, g1->grpi1_comment);
482 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
484 GROUPINFODESCRIPTION,
488 g2 = (struct GROUP_INFO_2 *)r->in.buffer;
489 init_lsa_String(&info.description, g2->grpi2_comment);
490 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
492 GROUPINFODESCRIPTION,
494 if (!NT_STATUS_IS_OK(status)) {
495 werr = ntstatus_to_werror(status);
498 info.attributes.attributes = g2->grpi2_attributes;
499 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
505 g3 = (struct GROUP_INFO_3 *)r->in.buffer;
506 init_lsa_String(&info.description, g3->grpi3_comment);
507 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
509 GROUPINFODESCRIPTION,
511 if (!NT_STATUS_IS_OK(status)) {
512 werr = ntstatus_to_werror(status);
515 info.attributes.attributes = g3->grpi3_attributes;
516 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
522 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
523 init_lsa_String(&info.description, g1002->grpi1002_comment);
524 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
526 GROUPINFODESCRIPTION,
530 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
531 info.attributes.attributes = g1005->grpi1005_attributes;
532 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
538 status = NT_STATUS_INVALID_LEVEL;
542 if (!NT_STATUS_IS_OK(status)) {
543 werr = ntstatus_to_werror(status);
554 if (is_valid_policy_hnd(&group_handle)) {
555 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
558 if (ctx->disable_policy_handle_cache) {
559 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
560 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
566 /****************************************************************
567 ****************************************************************/
569 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
570 struct NetGroupSetInfo *r)
572 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
575 /****************************************************************
576 ****************************************************************/
578 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
580 struct samr_GroupInfoAll *info,
581 struct dom_sid2 *domain_sid,
585 struct GROUP_INFO_0 info0;
586 struct GROUP_INFO_1 info1;
587 struct GROUP_INFO_2 info2;
588 struct GROUP_INFO_3 info3;
593 info0.grpi0_name = info->name.string;
595 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
599 info1.grpi1_name = info->name.string;
600 info1.grpi1_comment = info->description.string;
602 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
606 info2.grpi2_name = info->name.string;
607 info2.grpi2_comment = info->description.string;
608 info2.grpi2_group_id = rid;
609 info2.grpi2_attributes = info->attributes;
611 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
615 if (!sid_compose(&sid, domain_sid, rid)) {
619 info3.grpi3_name = info->name.string;
620 info3.grpi3_comment = info->description.string;
621 info3.grpi3_attributes = info->attributes;
622 info3.grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
624 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
628 return WERR_UNKNOWN_LEVEL;
631 W_ERROR_HAVE_NO_MEMORY(*buffer);
636 /****************************************************************
637 ****************************************************************/
639 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
640 struct NetGroupGetInfo *r)
642 struct cli_state *cli = NULL;
643 struct rpc_pipe_client *pipe_cli = NULL;
646 POLICY_HND connect_handle, domain_handle, group_handle;
647 struct lsa_String lsa_group_name;
648 struct dom_sid2 *domain_sid = NULL;
650 struct samr_Ids rids;
651 struct samr_Ids types;
652 union samr_GroupInfo *info = NULL;
653 bool group_info_all = false;
655 ZERO_STRUCT(connect_handle);
656 ZERO_STRUCT(domain_handle);
657 ZERO_STRUCT(group_handle);
659 if (!r->in.group_name) {
660 return WERR_INVALID_PARAM;
663 werr = libnetapi_open_pipe(ctx, r->in.server_name,
664 &ndr_table_samr.syntax_id,
667 if (!W_ERROR_IS_OK(werr)) {
671 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
672 SAMR_ACCESS_ENUM_DOMAINS |
673 SAMR_ACCESS_OPEN_DOMAIN,
674 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
678 if (!W_ERROR_IS_OK(werr)) {
682 init_lsa_String(&lsa_group_name, r->in.group_name);
684 status = rpccli_samr_LookupNames(pipe_cli, ctx,
690 if (!NT_STATUS_IS_OK(status)) {
691 werr = ntstatus_to_werror(status);
695 if (types.ids[0] != SID_NAME_DOM_GRP) {
696 werr = WERR_INVALID_DATATYPE;
700 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
702 SAMR_GROUP_ACCESS_LOOKUP_INFO,
705 if (!NT_STATUS_IS_OK(status)) {
706 werr = ntstatus_to_werror(status);
710 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
714 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
715 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
719 group_info_all = true;
722 if (!NT_STATUS_IS_OK(status)) {
723 werr = ntstatus_to_werror(status);
727 werr = map_group_info_to_buffer(ctx, r->in.level,
728 group_info_all ? &info->all : &info->all2,
729 domain_sid, rids.ids[0],
731 if (!W_ERROR_IS_OK(werr)) {
739 if (is_valid_policy_hnd(&group_handle)) {
740 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
743 if (ctx->disable_policy_handle_cache) {
744 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
745 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
751 /****************************************************************
752 ****************************************************************/
754 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
755 struct NetGroupGetInfo *r)
757 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
760 /****************************************************************
761 ****************************************************************/
763 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
764 struct NetGroupAddUser *r)
766 struct cli_state *cli = NULL;
767 struct rpc_pipe_client *pipe_cli = NULL;
770 POLICY_HND connect_handle, domain_handle, group_handle;
771 struct lsa_String lsa_group_name, lsa_user_name;
772 struct dom_sid2 *domain_sid = NULL;
774 struct samr_Ids rids;
775 struct samr_Ids types;
777 ZERO_STRUCT(connect_handle);
778 ZERO_STRUCT(domain_handle);
779 ZERO_STRUCT(group_handle);
781 if (!r->in.group_name) {
782 return WERR_INVALID_PARAM;
785 werr = libnetapi_open_pipe(ctx, r->in.server_name,
786 &ndr_table_samr.syntax_id,
789 if (!W_ERROR_IS_OK(werr)) {
793 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
794 SAMR_ACCESS_ENUM_DOMAINS |
795 SAMR_ACCESS_OPEN_DOMAIN,
796 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
800 if (!W_ERROR_IS_OK(werr)) {
804 init_lsa_String(&lsa_group_name, r->in.group_name);
806 status = rpccli_samr_LookupNames(pipe_cli, ctx,
812 if (!NT_STATUS_IS_OK(status)) {
813 werr = WERR_GROUP_NOT_FOUND;
817 if (types.ids[0] != SID_NAME_DOM_GRP) {
818 werr = WERR_GROUP_NOT_FOUND;
822 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
824 SAMR_GROUP_ACCESS_ADD_MEMBER,
827 if (!NT_STATUS_IS_OK(status)) {
828 werr = ntstatus_to_werror(status);
832 init_lsa_String(&lsa_user_name, r->in.user_name);
834 status = rpccli_samr_LookupNames(pipe_cli, ctx,
840 if (!NT_STATUS_IS_OK(status)) {
841 werr = WERR_USER_NOT_FOUND;
845 if (types.ids[0] != SID_NAME_USER) {
846 werr = WERR_USER_NOT_FOUND;
850 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
854 if (!NT_STATUS_IS_OK(status)) {
855 werr = ntstatus_to_werror(status);
866 if (is_valid_policy_hnd(&group_handle)) {
867 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
870 if (ctx->disable_policy_handle_cache) {
871 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
872 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
878 /****************************************************************
879 ****************************************************************/
881 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
882 struct NetGroupAddUser *r)
884 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
887 /****************************************************************
888 ****************************************************************/
890 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
891 struct NetGroupDelUser *r)
893 struct cli_state *cli = NULL;
894 struct rpc_pipe_client *pipe_cli = NULL;
897 POLICY_HND connect_handle, domain_handle, group_handle;
898 struct lsa_String lsa_group_name, lsa_user_name;
899 struct dom_sid2 *domain_sid = NULL;
901 struct samr_Ids rids;
902 struct samr_Ids types;
904 ZERO_STRUCT(connect_handle);
905 ZERO_STRUCT(domain_handle);
906 ZERO_STRUCT(group_handle);
908 if (!r->in.group_name) {
909 return WERR_INVALID_PARAM;
912 werr = libnetapi_open_pipe(ctx, r->in.server_name,
913 &ndr_table_samr.syntax_id,
916 if (!W_ERROR_IS_OK(werr)) {
920 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
921 SAMR_ACCESS_ENUM_DOMAINS |
922 SAMR_ACCESS_OPEN_DOMAIN,
923 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
927 if (!W_ERROR_IS_OK(werr)) {
931 init_lsa_String(&lsa_group_name, r->in.group_name);
933 status = rpccli_samr_LookupNames(pipe_cli, ctx,
939 if (!NT_STATUS_IS_OK(status)) {
940 werr = WERR_GROUP_NOT_FOUND;
944 if (types.ids[0] != SID_NAME_DOM_GRP) {
945 werr = WERR_GROUP_NOT_FOUND;
949 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
951 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
954 if (!NT_STATUS_IS_OK(status)) {
955 werr = ntstatus_to_werror(status);
959 init_lsa_String(&lsa_user_name, r->in.user_name);
961 status = rpccli_samr_LookupNames(pipe_cli, ctx,
967 if (!NT_STATUS_IS_OK(status)) {
968 werr = WERR_USER_NOT_FOUND;
972 if (types.ids[0] != SID_NAME_USER) {
973 werr = WERR_USER_NOT_FOUND;
977 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
980 if (!NT_STATUS_IS_OK(status)) {
981 werr = ntstatus_to_werror(status);
992 if (is_valid_policy_hnd(&group_handle)) {
993 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
996 if (ctx->disable_policy_handle_cache) {
997 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
998 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1004 /****************************************************************
1005 ****************************************************************/
1007 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1008 struct NetGroupDelUser *r)
1010 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
1013 /****************************************************************
1014 ****************************************************************/
1016 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
1017 struct samr_DispInfoFullGroups *groups,
1020 struct GROUP_INFO_0 *g0;
1023 g0 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_0, groups->count);
1024 W_ERROR_HAVE_NO_MEMORY(g0);
1026 for (i=0; i<groups->count; i++) {
1027 g0[i].grpi0_name = talloc_strdup(mem_ctx,
1028 groups->entries[i].account_name.string);
1029 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
1032 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
1033 sizeof(struct GROUP_INFO_0) * groups->count);
1034 W_ERROR_HAVE_NO_MEMORY(*buffer);
1039 /****************************************************************
1040 ****************************************************************/
1042 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1043 struct samr_DispInfoFullGroups *groups,
1046 struct GROUP_INFO_1 *g1;
1049 g1 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_1, groups->count);
1050 W_ERROR_HAVE_NO_MEMORY(g1);
1052 for (i=0; i<groups->count; i++) {
1053 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1054 groups->entries[i].account_name.string);
1055 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1056 groups->entries[i].description.string);
1057 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1060 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1061 sizeof(struct GROUP_INFO_1) * groups->count);
1062 W_ERROR_HAVE_NO_MEMORY(*buffer);
1067 /****************************************************************
1068 ****************************************************************/
1070 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1071 struct samr_DispInfoFullGroups *groups,
1074 struct GROUP_INFO_2 *g2;
1077 g2 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_2, groups->count);
1078 W_ERROR_HAVE_NO_MEMORY(g2);
1080 for (i=0; i<groups->count; i++) {
1081 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1082 groups->entries[i].account_name.string);
1083 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1084 groups->entries[i].description.string);
1085 g2[i].grpi2_group_id = groups->entries[i].rid;
1086 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1087 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1090 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1091 sizeof(struct GROUP_INFO_2) * groups->count);
1092 W_ERROR_HAVE_NO_MEMORY(*buffer);
1097 /****************************************************************
1098 ****************************************************************/
1100 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1101 struct samr_DispInfoFullGroups *groups,
1102 const struct dom_sid *domain_sid,
1105 struct GROUP_INFO_3 *g3;
1108 g3 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_3, groups->count);
1109 W_ERROR_HAVE_NO_MEMORY(g3);
1111 for (i=0; i<groups->count; i++) {
1115 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1119 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1120 groups->entries[i].account_name.string);
1121 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1122 groups->entries[i].description.string);
1123 g3[i].grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
1124 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1125 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1128 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1129 sizeof(struct GROUP_INFO_3) * groups->count);
1130 W_ERROR_HAVE_NO_MEMORY(*buffer);
1135 /****************************************************************
1136 ****************************************************************/
1138 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1140 struct samr_DispInfoFullGroups *groups,
1141 const struct dom_sid *domain_sid,
1142 uint32_t *entries_read,
1146 *entries_read = groups->count;
1151 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1153 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1155 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1157 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1159 return WERR_UNKNOWN_LEVEL;
1163 /****************************************************************
1164 ****************************************************************/
1166 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1167 struct NetGroupEnum *r)
1169 struct cli_state *cli = NULL;
1170 struct rpc_pipe_client *pipe_cli = NULL;
1171 struct policy_handle connect_handle;
1172 struct dom_sid2 *domain_sid = NULL;
1173 struct policy_handle domain_handle;
1174 union samr_DispInfo info;
1175 union samr_DomainInfo *domain_info = NULL;
1177 uint32_t total_size = 0;
1178 uint32_t returned_size = 0;
1180 NTSTATUS status = NT_STATUS_OK;
1181 WERROR werr, tmp_werr;
1183 ZERO_STRUCT(connect_handle);
1184 ZERO_STRUCT(domain_handle);
1186 switch (r->in.level) {
1193 return WERR_UNKNOWN_LEVEL;
1196 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1197 &ndr_table_samr.syntax_id,
1200 if (!W_ERROR_IS_OK(werr)) {
1204 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1205 SAMR_ACCESS_ENUM_DOMAINS |
1206 SAMR_ACCESS_OPEN_DOMAIN,
1207 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1208 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1209 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1213 if (!W_ERROR_IS_OK(werr)) {
1217 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
1221 if (!NT_STATUS_IS_OK(status)) {
1222 werr = ntstatus_to_werror(status);
1226 if (r->out.total_entries) {
1227 *r->out.total_entries = domain_info->info2.num_groups;
1230 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1234 r->in.resume_handle ?
1235 *r->in.resume_handle : 0,
1241 werr = ntstatus_to_werror(status);
1242 if (NT_STATUS_IS_ERR(status)) {
1246 if (r->out.resume_handle) {
1247 *r->out.resume_handle =
1248 info.info3.entries[info.info3.count-1].idx;
1251 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1255 r->out.entries_read,
1257 if (!W_ERROR_IS_OK(tmp_werr)) {
1268 if (NT_STATUS_IS_OK(status) ||
1269 NT_STATUS_IS_ERR(status)) {
1271 if (ctx->disable_policy_handle_cache) {
1272 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1273 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1280 /****************************************************************
1281 ****************************************************************/
1283 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1284 struct NetGroupEnum *r)
1286 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1289 /****************************************************************
1290 ****************************************************************/
1292 WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1293 struct NetGroupGetUsers *r)
1295 /* FIXME: this call needs to cope with large replies */
1297 struct cli_state *cli = NULL;
1298 struct rpc_pipe_client *pipe_cli = NULL;
1299 struct policy_handle connect_handle, domain_handle, group_handle;
1300 struct lsa_String lsa_account_name;
1301 struct dom_sid2 *domain_sid = NULL;
1302 struct samr_Ids group_rids, name_types;
1303 struct samr_RidTypeArray *rid_array = NULL;
1304 struct lsa_Strings names;
1305 struct samr_Ids member_types;
1308 uint32_t entries_read = 0;
1310 NTSTATUS status = NT_STATUS_OK;
1313 ZERO_STRUCT(connect_handle);
1314 ZERO_STRUCT(domain_handle);
1316 if (!r->out.buffer) {
1317 return WERR_INVALID_PARAM;
1320 *r->out.buffer = NULL;
1321 *r->out.entries_read = 0;
1323 switch (r->in.level) {
1328 return WERR_UNKNOWN_LEVEL;
1332 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1333 &ndr_table_samr.syntax_id,
1336 if (!W_ERROR_IS_OK(werr)) {
1340 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1341 SAMR_ACCESS_ENUM_DOMAINS |
1342 SAMR_ACCESS_OPEN_DOMAIN,
1343 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1347 if (!W_ERROR_IS_OK(werr)) {
1351 init_lsa_String(&lsa_account_name, r->in.group_name);
1353 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1359 if (!NT_STATUS_IS_OK(status)) {
1360 werr = ntstatus_to_werror(status);
1364 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1366 SAMR_GROUP_ACCESS_GET_MEMBERS,
1369 if (!NT_STATUS_IS_OK(status)) {
1370 werr = ntstatus_to_werror(status);
1374 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1377 if (!NT_STATUS_IS_OK(status)) {
1378 werr = ntstatus_to_werror(status);
1382 status = rpccli_samr_LookupRids(pipe_cli, ctx,
1388 if (!NT_STATUS_IS_OK(status)) {
1389 werr = ntstatus_to_werror(status);
1393 for (i=0; i < names.count; i++) {
1395 if (member_types.ids[i] != SID_NAME_USER) {
1399 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1401 names.names[i].string,
1405 if (!NT_STATUS_IS_OK(status)) {
1406 werr = ntstatus_to_werror(status);
1411 if (r->out.entries_read) {
1412 *r->out.entries_read = entries_read;
1415 if (r->out.total_entries) {
1416 *r->out.total_entries = entries_read;
1426 if (is_valid_policy_hnd(&group_handle)) {
1427 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1430 if (ctx->disable_policy_handle_cache) {
1431 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1432 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1438 /****************************************************************
1439 ****************************************************************/
1441 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1442 struct NetGroupGetUsers *r)
1444 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1447 /****************************************************************
1448 ****************************************************************/
1450 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1451 struct NetGroupSetUsers *r)
1453 struct cli_state *cli = NULL;
1454 struct rpc_pipe_client *pipe_cli = NULL;
1455 struct policy_handle connect_handle, domain_handle, group_handle;
1456 struct lsa_String lsa_account_name;
1457 struct dom_sid2 *domain_sid = NULL;
1458 union samr_GroupInfo *group_info = NULL;
1459 struct samr_Ids user_rids, name_types;
1460 struct samr_Ids group_rids, group_types;
1461 struct samr_RidTypeArray *rid_array = NULL;
1462 struct lsa_String *lsa_names = NULL;
1464 uint32_t *add_rids = NULL;
1465 uint32_t *del_rids = NULL;
1466 size_t num_add_rids = 0;
1467 size_t num_del_rids = 0;
1469 uint32_t *member_rids = NULL;
1470 size_t num_member_rids = 0;
1472 struct GROUP_USERS_INFO_0 *i0 = NULL;
1473 struct GROUP_USERS_INFO_1 *i1 = NULL;
1477 NTSTATUS status = NT_STATUS_OK;
1480 ZERO_STRUCT(connect_handle);
1481 ZERO_STRUCT(domain_handle);
1483 if (!r->in.buffer) {
1484 return WERR_INVALID_PARAM;
1487 switch (r->in.level) {
1492 return WERR_UNKNOWN_LEVEL;
1495 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1496 &ndr_table_samr.syntax_id,
1499 if (!W_ERROR_IS_OK(werr)) {
1503 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1504 SAMR_ACCESS_ENUM_DOMAINS |
1505 SAMR_ACCESS_OPEN_DOMAIN,
1506 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1510 if (!W_ERROR_IS_OK(werr)) {
1514 init_lsa_String(&lsa_account_name, r->in.group_name);
1516 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1522 if (!NT_STATUS_IS_OK(status)) {
1523 werr = ntstatus_to_werror(status);
1527 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
1529 SAMR_GROUP_ACCESS_GET_MEMBERS |
1530 SAMR_GROUP_ACCESS_ADD_MEMBER |
1531 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1532 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1535 if (!NT_STATUS_IS_OK(status)) {
1536 werr = ntstatus_to_werror(status);
1540 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
1542 GROUPINFOATTRIBUTES,
1544 if (!NT_STATUS_IS_OK(status)) {
1545 werr = ntstatus_to_werror(status);
1549 switch (r->in.level) {
1551 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1554 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1558 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1564 for (i=0; i < r->in.num_entries; i++) {
1566 switch (r->in.level) {
1568 init_lsa_String(&lsa_names[i], i0->grui0_name);
1572 init_lsa_String(&lsa_names[i], i1->grui1_name);
1578 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1584 if (!NT_STATUS_IS_OK(status)) {
1585 werr = ntstatus_to_werror(status);
1589 member_rids = user_rids.ids;
1590 num_member_rids = user_rids.count;
1592 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
1595 if (!NT_STATUS_IS_OK(status)) {
1596 werr = ntstatus_to_werror(status);
1602 for (i=0; i < r->in.num_entries; i++) {
1603 bool already_member = false;
1604 for (k=0; k < rid_array->count; k++) {
1605 if (member_rids[i] == rid_array->rids[k]) {
1606 already_member = true;
1610 if (!already_member) {
1611 if (!add_rid_to_array_unique(ctx,
1613 &add_rids, &num_add_rids)) {
1614 werr = WERR_GENERAL_FAILURE;
1622 for (k=0; k < rid_array->count; k++) {
1623 bool keep_member = false;
1624 for (i=0; i < r->in.num_entries; i++) {
1625 if (member_rids[i] == rid_array->rids[k]) {
1631 if (!add_rid_to_array_unique(ctx,
1633 &del_rids, &num_del_rids)) {
1634 werr = WERR_GENERAL_FAILURE;
1642 for (i=0; i < num_add_rids; i++) {
1643 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
1647 if (!NT_STATUS_IS_OK(status)) {
1648 werr = ntstatus_to_werror(status);
1655 for (i=0; i < num_del_rids; i++) {
1656 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
1659 if (!NT_STATUS_IS_OK(status)) {
1660 werr = ntstatus_to_werror(status);
1672 if (is_valid_policy_hnd(&group_handle)) {
1673 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1676 if (ctx->disable_policy_handle_cache) {
1677 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1678 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1684 /****************************************************************
1685 ****************************************************************/
1687 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1688 struct NetGroupSetUsers *r)
1690 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);