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 "rpc_client/rpc_client.h"
27 #include "../librpc/gen_ndr/ndr_samr_c.h"
28 #include "rpc_client/init_lsa.h"
29 #include "../libcli/security/security.h"
31 /****************************************************************
32 ****************************************************************/
34 WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx,
35 struct NetGroupAdd *r)
37 struct rpc_pipe_client *pipe_cli = NULL;
38 NTSTATUS status, result;
40 struct policy_handle connect_handle, domain_handle, group_handle;
41 struct lsa_String lsa_group_name;
42 struct dom_sid2 *domain_sid = NULL;
44 struct dcerpc_binding_handle *b = NULL;
46 struct GROUP_INFO_0 *info0 = NULL;
47 struct GROUP_INFO_1 *info1 = NULL;
48 struct GROUP_INFO_2 *info2 = NULL;
49 struct GROUP_INFO_3 *info3 = NULL;
50 union samr_GroupInfo info;
52 ZERO_STRUCT(connect_handle);
53 ZERO_STRUCT(domain_handle);
54 ZERO_STRUCT(group_handle);
57 return WERR_INVALID_PARAM;
60 switch (r->in.level) {
62 info0 = (struct GROUP_INFO_0 *)r->in.buffer;
65 info1 = (struct GROUP_INFO_1 *)r->in.buffer;
68 info2 = (struct GROUP_INFO_2 *)r->in.buffer;
71 info3 = (struct GROUP_INFO_3 *)r->in.buffer;
74 werr = WERR_UNKNOWN_LEVEL;
78 werr = libnetapi_open_pipe(ctx, r->in.server_name,
79 &ndr_table_samr.syntax_id,
81 if (!W_ERROR_IS_OK(werr)) {
85 b = pipe_cli->binding_handle;
87 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
88 SAMR_ACCESS_ENUM_DOMAINS |
89 SAMR_ACCESS_LOOKUP_DOMAIN,
90 SAMR_DOMAIN_ACCESS_CREATE_GROUP |
91 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
95 if (!W_ERROR_IS_OK(werr)) {
99 switch (r->in.level) {
101 init_lsa_String(&lsa_group_name, info0->grpi0_name);
104 init_lsa_String(&lsa_group_name, info1->grpi1_name);
107 init_lsa_String(&lsa_group_name, info2->grpi2_name);
110 init_lsa_String(&lsa_group_name, info3->grpi3_name);
114 status = dcerpc_samr_CreateDomainGroup(b, talloc_tos(),
118 SAMR_GROUP_ACCESS_SET_INFO,
123 if (!NT_STATUS_IS_OK(status)) {
124 werr = ntstatus_to_werror(status);
127 if (!NT_STATUS_IS_OK(result)) {
128 werr = ntstatus_to_werror(result);
132 switch (r->in.level) {
134 if (info1->grpi1_comment) {
135 init_lsa_String(&info.description,
136 info1->grpi1_comment);
138 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
140 GROUPINFODESCRIPTION,
146 if (info2->grpi2_comment) {
147 init_lsa_String(&info.description,
148 info2->grpi2_comment);
150 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
152 GROUPINFODESCRIPTION,
155 if (!NT_STATUS_IS_OK(status)) {
156 werr = ntstatus_to_werror(status);
159 if (!NT_STATUS_IS_OK(result)) {
160 werr = ntstatus_to_werror(result);
165 if (info2->grpi2_attributes != 0) {
166 info.attributes.attributes = info2->grpi2_attributes;
167 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
176 if (info3->grpi3_comment) {
177 init_lsa_String(&info.description,
178 info3->grpi3_comment);
180 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
182 GROUPINFODESCRIPTION,
185 if (!NT_STATUS_IS_OK(status)) {
186 werr = ntstatus_to_werror(status);
189 if (!NT_STATUS_IS_OK(result)) {
190 werr = ntstatus_to_werror(result);
195 if (info3->grpi3_attributes != 0) {
196 info.attributes.attributes = info3->grpi3_attributes;
197 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
208 if (!NT_STATUS_IS_OK(status)) {
209 werr = ntstatus_to_werror(status);
212 if (!NT_STATUS_IS_OK(result)) {
213 werr = ntstatus_to_werror(result);
221 dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
222 &group_handle, &result);
225 if (is_valid_policy_hnd(&group_handle)) {
226 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
229 if (ctx->disable_policy_handle_cache) {
230 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
231 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
237 /****************************************************************
238 ****************************************************************/
240 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
241 struct NetGroupAdd *r)
243 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAdd);
246 /****************************************************************
247 ****************************************************************/
249 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
250 struct NetGroupDel *r)
252 struct rpc_pipe_client *pipe_cli = NULL;
253 NTSTATUS status, result;
255 struct policy_handle connect_handle, domain_handle, group_handle;
256 struct lsa_String lsa_group_name;
257 struct dom_sid2 *domain_sid = NULL;
259 struct dcerpc_binding_handle *b = NULL;
261 struct samr_Ids rids;
262 struct samr_Ids types;
263 union samr_GroupInfo *info = NULL;
264 struct samr_RidAttrArray *rid_array = NULL;
266 ZERO_STRUCT(connect_handle);
267 ZERO_STRUCT(domain_handle);
268 ZERO_STRUCT(group_handle);
270 if (!r->in.group_name) {
271 return WERR_INVALID_PARAM;
274 werr = libnetapi_open_pipe(ctx, r->in.server_name,
275 &ndr_table_samr.syntax_id,
277 if (!W_ERROR_IS_OK(werr)) {
281 b = pipe_cli->binding_handle;
283 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
284 SAMR_ACCESS_ENUM_DOMAINS |
285 SAMR_ACCESS_LOOKUP_DOMAIN,
286 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
290 if (!W_ERROR_IS_OK(werr)) {
294 init_lsa_String(&lsa_group_name, r->in.group_name);
296 status = dcerpc_samr_LookupNames(b, talloc_tos(),
303 if (!NT_STATUS_IS_OK(status)) {
304 werr = ntstatus_to_werror(status);
307 if (!NT_STATUS_IS_OK(result)) {
308 werr = ntstatus_to_werror(result);
312 if (types.ids[0] != SID_NAME_DOM_GRP) {
313 werr = WERR_INVALID_DATATYPE;
317 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
320 SAMR_GROUP_ACCESS_GET_MEMBERS |
321 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
322 SAMR_GROUP_ACCESS_ADD_MEMBER |
323 SAMR_GROUP_ACCESS_LOOKUP_INFO,
327 if (!NT_STATUS_IS_OK(status)) {
328 werr = ntstatus_to_werror(status);
331 if (!NT_STATUS_IS_OK(result)) {
332 werr = ntstatus_to_werror(result);
336 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
341 if (!NT_STATUS_IS_OK(status)) {
342 werr = ntstatus_to_werror(status);
345 if (!NT_STATUS_IS_OK(result)) {
346 werr = ntstatus_to_werror(result);
351 /* breaks against NT4 */
352 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
353 werr = WERR_ACCESS_DENIED;
357 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
361 if (!NT_STATUS_IS_OK(status)) {
362 werr = ntstatus_to_werror(status);
365 if (!NT_STATUS_IS_OK(result)) {
366 werr = ntstatus_to_werror(result);
371 struct lsa_Strings names;
372 struct samr_Ids member_types;
374 status = dcerpc_samr_LookupRids(b, talloc_tos(),
381 if (!NT_STATUS_IS_OK(status)) {
382 werr = ntstatus_to_werror(status);
385 if (!NT_STATUS_IS_OK(result)) {
386 werr = ntstatus_to_werror(result);
391 for (i=0; i < rid_array->count; i++) {
393 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
397 if (!NT_STATUS_IS_OK(status)) {
398 werr = ntstatus_to_werror(status);
401 if (!NT_STATUS_IS_OK(result)) {
402 werr = ntstatus_to_werror(result);
407 status = dcerpc_samr_DeleteDomainGroup(b, talloc_tos(),
410 if (!NT_STATUS_IS_OK(status)) {
411 werr = ntstatus_to_werror(status);
414 if (!NT_STATUS_IS_OK(result)) {
415 werr = ntstatus_to_werror(result);
419 ZERO_STRUCT(group_handle);
424 if (is_valid_policy_hnd(&group_handle)) {
425 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
428 if (ctx->disable_policy_handle_cache) {
429 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
430 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
436 /****************************************************************
437 ****************************************************************/
439 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
440 struct NetGroupDel *r)
442 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDel);
445 /****************************************************************
446 ****************************************************************/
448 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
449 struct NetGroupSetInfo *r)
451 struct rpc_pipe_client *pipe_cli = NULL;
452 NTSTATUS status, result;
454 struct policy_handle connect_handle, domain_handle, group_handle;
455 struct lsa_String lsa_group_name;
456 struct dom_sid2 *domain_sid = NULL;
457 struct dcerpc_binding_handle *b = NULL;
459 struct samr_Ids rids;
460 struct samr_Ids types;
461 union samr_GroupInfo info;
462 struct GROUP_INFO_0 *g0;
463 struct GROUP_INFO_1 *g1;
464 struct GROUP_INFO_2 *g2;
465 struct GROUP_INFO_3 *g3;
466 struct GROUP_INFO_1002 *g1002;
467 struct GROUP_INFO_1005 *g1005;
469 ZERO_STRUCT(connect_handle);
470 ZERO_STRUCT(domain_handle);
471 ZERO_STRUCT(group_handle);
473 if (!r->in.group_name) {
474 return WERR_INVALID_PARAM;
477 werr = libnetapi_open_pipe(ctx, r->in.server_name,
478 &ndr_table_samr.syntax_id,
480 if (!W_ERROR_IS_OK(werr)) {
484 b = pipe_cli->binding_handle;
486 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
487 SAMR_ACCESS_ENUM_DOMAINS |
488 SAMR_ACCESS_LOOKUP_DOMAIN,
489 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
493 if (!W_ERROR_IS_OK(werr)) {
497 init_lsa_String(&lsa_group_name, r->in.group_name);
499 status = dcerpc_samr_LookupNames(b, talloc_tos(),
506 if (!NT_STATUS_IS_OK(status)) {
507 werr = ntstatus_to_werror(status);
510 if (!NT_STATUS_IS_OK(result)) {
511 werr = ntstatus_to_werror(result);
515 if (types.ids[0] != SID_NAME_DOM_GRP) {
516 werr = WERR_INVALID_DATATYPE;
520 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
522 SAMR_GROUP_ACCESS_SET_INFO |
523 SAMR_GROUP_ACCESS_LOOKUP_INFO,
527 if (!NT_STATUS_IS_OK(status)) {
528 werr = ntstatus_to_werror(status);
531 if (!NT_STATUS_IS_OK(result)) {
532 werr = ntstatus_to_werror(result);
536 switch (r->in.level) {
538 g0 = (struct GROUP_INFO_0 *)r->in.buffer;
539 init_lsa_String(&info.name, g0->grpi0_name);
540 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
547 g1 = (struct GROUP_INFO_1 *)r->in.buffer;
548 init_lsa_String(&info.description, g1->grpi1_comment);
549 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
551 GROUPINFODESCRIPTION,
556 g2 = (struct GROUP_INFO_2 *)r->in.buffer;
557 init_lsa_String(&info.description, g2->grpi2_comment);
558 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
560 GROUPINFODESCRIPTION,
563 if (!NT_STATUS_IS_OK(status)) {
564 werr = ntstatus_to_werror(status);
567 if (!NT_STATUS_IS_OK(result)) {
568 werr = ntstatus_to_werror(result);
572 info.attributes.attributes = g2->grpi2_attributes;
573 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
580 g3 = (struct GROUP_INFO_3 *)r->in.buffer;
581 init_lsa_String(&info.description, g3->grpi3_comment);
582 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
584 GROUPINFODESCRIPTION,
587 if (!NT_STATUS_IS_OK(status)) {
588 werr = ntstatus_to_werror(status);
591 if (!NT_STATUS_IS_OK(result)) {
592 werr = ntstatus_to_werror(result);
596 info.attributes.attributes = g3->grpi3_attributes;
597 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
604 g1002 = (struct GROUP_INFO_1002 *)r->in.buffer;
605 init_lsa_String(&info.description, g1002->grpi1002_comment);
606 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
608 GROUPINFODESCRIPTION,
613 g1005 = (struct GROUP_INFO_1005 *)r->in.buffer;
614 info.attributes.attributes = g1005->grpi1005_attributes;
615 status = dcerpc_samr_SetGroupInfo(b, talloc_tos(),
622 status = NT_STATUS_INVALID_LEVEL;
626 if (!NT_STATUS_IS_OK(status)) {
627 werr = ntstatus_to_werror(status);
630 if (!NT_STATUS_IS_OK(result)) {
631 werr = ntstatus_to_werror(result);
638 if (is_valid_policy_hnd(&group_handle)) {
639 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
642 if (ctx->disable_policy_handle_cache) {
643 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
644 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
650 /****************************************************************
651 ****************************************************************/
653 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
654 struct NetGroupSetInfo *r)
656 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetInfo);
659 /****************************************************************
660 ****************************************************************/
662 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
664 struct samr_GroupInfoAll *info,
665 struct dom_sid2 *domain_sid,
669 struct GROUP_INFO_0 info0;
670 struct GROUP_INFO_1 info1;
671 struct GROUP_INFO_2 info2;
672 struct GROUP_INFO_3 info3;
677 info0.grpi0_name = info->name.string;
679 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
683 info1.grpi1_name = info->name.string;
684 info1.grpi1_comment = info->description.string;
686 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
690 info2.grpi2_name = info->name.string;
691 info2.grpi2_comment = info->description.string;
692 info2.grpi2_group_id = rid;
693 info2.grpi2_attributes = info->attributes;
695 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
699 if (!sid_compose(&sid, domain_sid, rid)) {
703 info3.grpi3_name = info->name.string;
704 info3.grpi3_comment = info->description.string;
705 info3.grpi3_attributes = info->attributes;
706 info3.grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
708 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
712 return WERR_UNKNOWN_LEVEL;
715 W_ERROR_HAVE_NO_MEMORY(*buffer);
720 /****************************************************************
721 ****************************************************************/
723 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
724 struct NetGroupGetInfo *r)
726 struct rpc_pipe_client *pipe_cli = NULL;
727 NTSTATUS status, result;
729 struct policy_handle connect_handle, domain_handle, group_handle;
730 struct lsa_String lsa_group_name;
731 struct dom_sid2 *domain_sid = NULL;
732 struct dcerpc_binding_handle *b = NULL;
734 struct samr_Ids rids;
735 struct samr_Ids types;
736 union samr_GroupInfo *info = NULL;
737 bool group_info_all = false;
739 ZERO_STRUCT(connect_handle);
740 ZERO_STRUCT(domain_handle);
741 ZERO_STRUCT(group_handle);
743 if (!r->in.group_name) {
744 return WERR_INVALID_PARAM;
747 werr = libnetapi_open_pipe(ctx, r->in.server_name,
748 &ndr_table_samr.syntax_id,
750 if (!W_ERROR_IS_OK(werr)) {
754 b = pipe_cli->binding_handle;
756 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
757 SAMR_ACCESS_ENUM_DOMAINS |
758 SAMR_ACCESS_LOOKUP_DOMAIN,
759 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
763 if (!W_ERROR_IS_OK(werr)) {
767 init_lsa_String(&lsa_group_name, r->in.group_name);
769 status = dcerpc_samr_LookupNames(b, talloc_tos(),
776 if (!NT_STATUS_IS_OK(status)) {
777 werr = ntstatus_to_werror(status);
780 if (!NT_STATUS_IS_OK(result)) {
781 werr = ntstatus_to_werror(result);
785 if (types.ids[0] != SID_NAME_DOM_GRP) {
786 werr = WERR_INVALID_DATATYPE;
790 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
792 SAMR_GROUP_ACCESS_LOOKUP_INFO,
796 if (!NT_STATUS_IS_OK(status)) {
797 werr = ntstatus_to_werror(status);
800 if (!NT_STATUS_IS_OK(result)) {
801 werr = ntstatus_to_werror(result);
805 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
810 if (!NT_STATUS_IS_OK(status)) {
811 werr = ntstatus_to_werror(status);
815 if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS)) {
816 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
821 group_info_all = true;
822 if (!NT_STATUS_IS_OK(status)) {
823 werr = ntstatus_to_werror(status);
828 if (!NT_STATUS_IS_OK(result)) {
829 werr = ntstatus_to_werror(result);
833 werr = map_group_info_to_buffer(ctx, r->in.level,
834 group_info_all ? &info->all : &info->all2,
835 domain_sid, rids.ids[0],
837 if (!W_ERROR_IS_OK(werr)) {
841 if (is_valid_policy_hnd(&group_handle)) {
842 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
845 if (ctx->disable_policy_handle_cache) {
846 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
847 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
853 /****************************************************************
854 ****************************************************************/
856 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
857 struct NetGroupGetInfo *r)
859 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetInfo);
862 /****************************************************************
863 ****************************************************************/
865 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
866 struct NetGroupAddUser *r)
868 struct rpc_pipe_client *pipe_cli = NULL;
869 NTSTATUS status, result;
871 struct policy_handle connect_handle, domain_handle, group_handle;
872 struct lsa_String lsa_group_name, lsa_user_name;
873 struct dom_sid2 *domain_sid = NULL;
874 struct dcerpc_binding_handle *b = NULL;
876 struct samr_Ids rids;
877 struct samr_Ids types;
879 ZERO_STRUCT(connect_handle);
880 ZERO_STRUCT(domain_handle);
881 ZERO_STRUCT(group_handle);
883 if (!r->in.group_name) {
884 return WERR_INVALID_PARAM;
887 werr = libnetapi_open_pipe(ctx, r->in.server_name,
888 &ndr_table_samr.syntax_id,
890 if (!W_ERROR_IS_OK(werr)) {
894 b = pipe_cli->binding_handle;
896 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
897 SAMR_ACCESS_ENUM_DOMAINS |
898 SAMR_ACCESS_LOOKUP_DOMAIN,
899 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
903 if (!W_ERROR_IS_OK(werr)) {
907 init_lsa_String(&lsa_group_name, r->in.group_name);
909 status = dcerpc_samr_LookupNames(b, talloc_tos(),
916 if (!NT_STATUS_IS_OK(status)) {
917 werr = ntstatus_to_werror(status);
920 if (!NT_STATUS_IS_OK(result)) {
921 werr = WERR_GROUPNOTFOUND;
925 if (types.ids[0] != SID_NAME_DOM_GRP) {
926 werr = WERR_GROUPNOTFOUND;
930 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
932 SAMR_GROUP_ACCESS_ADD_MEMBER,
936 if (!NT_STATUS_IS_OK(status)) {
937 werr = ntstatus_to_werror(status);
940 if (!NT_STATUS_IS_OK(result)) {
941 werr = ntstatus_to_werror(result);
945 init_lsa_String(&lsa_user_name, r->in.user_name);
947 status = dcerpc_samr_LookupNames(b, talloc_tos(),
954 if (!NT_STATUS_IS_OK(status)) {
955 werr = ntstatus_to_werror(status);
958 if (!NT_STATUS_IS_OK(result)) {
959 werr = WERR_USER_NOT_FOUND;
963 if (types.ids[0] != SID_NAME_USER) {
964 werr = WERR_USER_NOT_FOUND;
968 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
973 if (!NT_STATUS_IS_OK(status)) {
974 werr = ntstatus_to_werror(status);
977 if (!NT_STATUS_IS_OK(result)) {
978 werr = ntstatus_to_werror(result);
985 if (is_valid_policy_hnd(&group_handle)) {
986 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
989 if (ctx->disable_policy_handle_cache) {
990 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
991 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
997 /****************************************************************
998 ****************************************************************/
1000 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
1001 struct NetGroupAddUser *r)
1003 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupAddUser);
1006 /****************************************************************
1007 ****************************************************************/
1009 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
1010 struct NetGroupDelUser *r)
1012 struct rpc_pipe_client *pipe_cli = NULL;
1013 NTSTATUS status, result;
1015 struct policy_handle connect_handle, domain_handle, group_handle;
1016 struct lsa_String lsa_group_name, lsa_user_name;
1017 struct dom_sid2 *domain_sid = NULL;
1018 struct dcerpc_binding_handle *b = NULL;
1020 struct samr_Ids rids;
1021 struct samr_Ids types;
1023 ZERO_STRUCT(connect_handle);
1024 ZERO_STRUCT(domain_handle);
1025 ZERO_STRUCT(group_handle);
1027 if (!r->in.group_name) {
1028 return WERR_INVALID_PARAM;
1031 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1032 &ndr_table_samr.syntax_id,
1034 if (!W_ERROR_IS_OK(werr)) {
1038 b = pipe_cli->binding_handle;
1040 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1041 SAMR_ACCESS_ENUM_DOMAINS |
1042 SAMR_ACCESS_LOOKUP_DOMAIN,
1043 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1047 if (!W_ERROR_IS_OK(werr)) {
1051 init_lsa_String(&lsa_group_name, r->in.group_name);
1053 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1060 if (!NT_STATUS_IS_OK(status)) {
1061 werr = ntstatus_to_werror(status);
1064 if (!NT_STATUS_IS_OK(result)) {
1065 werr = WERR_GROUPNOTFOUND;
1069 if (types.ids[0] != SID_NAME_DOM_GRP) {
1070 werr = WERR_GROUPNOTFOUND;
1074 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1076 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
1080 if (!NT_STATUS_IS_OK(status)) {
1081 werr = ntstatus_to_werror(status);
1084 if (!NT_STATUS_IS_OK(result)) {
1085 werr = ntstatus_to_werror(result);
1089 init_lsa_String(&lsa_user_name, r->in.user_name);
1091 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1098 if (!NT_STATUS_IS_OK(status)) {
1099 werr = ntstatus_to_werror(status);
1103 if (!NT_STATUS_IS_OK(result)) {
1104 werr = WERR_USER_NOT_FOUND;
1108 if (types.ids[0] != SID_NAME_USER) {
1109 werr = WERR_USER_NOT_FOUND;
1113 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1117 if (!NT_STATUS_IS_OK(status)) {
1118 werr = ntstatus_to_werror(status);
1121 if (!NT_STATUS_IS_OK(result)) {
1122 werr = ntstatus_to_werror(result);
1129 if (is_valid_policy_hnd(&group_handle)) {
1130 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1133 if (ctx->disable_policy_handle_cache) {
1134 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1135 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1141 /****************************************************************
1142 ****************************************************************/
1144 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1145 struct NetGroupDelUser *r)
1147 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupDelUser);
1150 /****************************************************************
1151 ****************************************************************/
1153 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
1154 struct samr_DispInfoFullGroups *groups,
1157 struct GROUP_INFO_0 *g0;
1160 g0 = talloc_zero_array(mem_ctx, struct GROUP_INFO_0, groups->count);
1161 W_ERROR_HAVE_NO_MEMORY(g0);
1163 for (i=0; i<groups->count; i++) {
1164 g0[i].grpi0_name = talloc_strdup(mem_ctx,
1165 groups->entries[i].account_name.string);
1166 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
1169 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
1170 sizeof(struct GROUP_INFO_0) * groups->count);
1171 W_ERROR_HAVE_NO_MEMORY(*buffer);
1176 /****************************************************************
1177 ****************************************************************/
1179 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1180 struct samr_DispInfoFullGroups *groups,
1183 struct GROUP_INFO_1 *g1;
1186 g1 = talloc_zero_array(mem_ctx, struct GROUP_INFO_1, groups->count);
1187 W_ERROR_HAVE_NO_MEMORY(g1);
1189 for (i=0; i<groups->count; i++) {
1190 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1191 groups->entries[i].account_name.string);
1192 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1193 groups->entries[i].description.string);
1194 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1197 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1198 sizeof(struct GROUP_INFO_1) * groups->count);
1199 W_ERROR_HAVE_NO_MEMORY(*buffer);
1204 /****************************************************************
1205 ****************************************************************/
1207 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1208 struct samr_DispInfoFullGroups *groups,
1211 struct GROUP_INFO_2 *g2;
1214 g2 = talloc_zero_array(mem_ctx, struct GROUP_INFO_2, groups->count);
1215 W_ERROR_HAVE_NO_MEMORY(g2);
1217 for (i=0; i<groups->count; i++) {
1218 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1219 groups->entries[i].account_name.string);
1220 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1221 groups->entries[i].description.string);
1222 g2[i].grpi2_group_id = groups->entries[i].rid;
1223 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1224 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1227 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1228 sizeof(struct GROUP_INFO_2) * groups->count);
1229 W_ERROR_HAVE_NO_MEMORY(*buffer);
1234 /****************************************************************
1235 ****************************************************************/
1237 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1238 struct samr_DispInfoFullGroups *groups,
1239 const struct dom_sid *domain_sid,
1242 struct GROUP_INFO_3 *g3;
1245 g3 = talloc_zero_array(mem_ctx, struct GROUP_INFO_3, groups->count);
1246 W_ERROR_HAVE_NO_MEMORY(g3);
1248 for (i=0; i<groups->count; i++) {
1252 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1256 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1257 groups->entries[i].account_name.string);
1258 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1259 groups->entries[i].description.string);
1260 g3[i].grpi3_group_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
1261 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1262 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1265 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1266 sizeof(struct GROUP_INFO_3) * groups->count);
1267 W_ERROR_HAVE_NO_MEMORY(*buffer);
1272 /****************************************************************
1273 ****************************************************************/
1275 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1277 struct samr_DispInfoFullGroups *groups,
1278 const struct dom_sid *domain_sid,
1279 uint32_t *entries_read,
1283 *entries_read = groups->count;
1288 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1290 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1292 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1294 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1296 return WERR_UNKNOWN_LEVEL;
1300 /****************************************************************
1301 ****************************************************************/
1303 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1304 struct NetGroupEnum *r)
1306 struct rpc_pipe_client *pipe_cli = NULL;
1307 struct policy_handle connect_handle;
1308 struct dom_sid2 *domain_sid = NULL;
1309 struct policy_handle domain_handle;
1310 union samr_DispInfo info;
1311 union samr_DomainInfo *domain_info = NULL;
1312 struct dcerpc_binding_handle *b = NULL;
1314 uint32_t total_size = 0;
1315 uint32_t returned_size = 0;
1317 NTSTATUS result = NT_STATUS_OK;
1318 NTSTATUS status = NT_STATUS_OK;
1319 WERROR werr, tmp_werr;
1321 ZERO_STRUCT(connect_handle);
1322 ZERO_STRUCT(domain_handle);
1324 switch (r->in.level) {
1331 return WERR_UNKNOWN_LEVEL;
1334 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1335 &ndr_table_samr.syntax_id,
1337 if (!W_ERROR_IS_OK(werr)) {
1341 b = pipe_cli->binding_handle;
1343 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1344 SAMR_ACCESS_ENUM_DOMAINS |
1345 SAMR_ACCESS_LOOKUP_DOMAIN,
1346 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1347 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1348 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1352 if (!W_ERROR_IS_OK(werr)) {
1356 status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
1361 if (!NT_STATUS_IS_OK(status)) {
1362 werr = ntstatus_to_werror(status);
1365 if (!NT_STATUS_IS_OK(result)) {
1366 werr = ntstatus_to_werror(result);
1370 if (r->out.total_entries) {
1371 *r->out.total_entries = domain_info->general.num_groups;
1374 status = dcerpc_samr_QueryDisplayInfo2(b,
1378 r->in.resume_handle ?
1379 *r->in.resume_handle : 0,
1386 if (!NT_STATUS_IS_OK(status)) {
1387 werr = ntstatus_to_werror(status);
1391 werr = ntstatus_to_werror(result);
1392 if (NT_STATUS_IS_ERR(result)) {
1396 if (r->out.resume_handle && info.info3.count > 0) {
1397 *r->out.resume_handle =
1398 info.info3.entries[info.info3.count-1].idx;
1401 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1405 r->out.entries_read,
1407 if (!W_ERROR_IS_OK(tmp_werr)) {
1414 if (NT_STATUS_IS_OK(result) ||
1415 NT_STATUS_IS_ERR(result)) {
1417 if (ctx->disable_policy_handle_cache) {
1418 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1419 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1426 /****************************************************************
1427 ****************************************************************/
1429 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1430 struct NetGroupEnum *r)
1432 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupEnum);
1435 /****************************************************************
1436 ****************************************************************/
1438 WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx,
1439 struct NetGroupGetUsers *r)
1441 /* FIXME: this call needs to cope with large replies */
1443 struct rpc_pipe_client *pipe_cli = NULL;
1444 struct policy_handle connect_handle, domain_handle, group_handle;
1445 struct lsa_String lsa_account_name;
1446 struct dom_sid2 *domain_sid = NULL;
1447 struct samr_Ids group_rids, name_types;
1448 struct samr_RidAttrArray *rid_array = NULL;
1449 struct lsa_Strings names;
1450 struct samr_Ids member_types;
1451 struct dcerpc_binding_handle *b = NULL;
1454 uint32_t entries_read = 0;
1456 NTSTATUS status = NT_STATUS_OK;
1457 NTSTATUS result = NT_STATUS_OK;
1460 ZERO_STRUCT(connect_handle);
1461 ZERO_STRUCT(domain_handle);
1463 if (!r->out.buffer) {
1464 return WERR_INVALID_PARAM;
1467 *r->out.buffer = NULL;
1468 *r->out.entries_read = 0;
1469 *r->out.total_entries = 0;
1471 switch (r->in.level) {
1476 return WERR_UNKNOWN_LEVEL;
1480 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1481 &ndr_table_samr.syntax_id,
1483 if (!W_ERROR_IS_OK(werr)) {
1487 b = pipe_cli->binding_handle;
1489 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1490 SAMR_ACCESS_ENUM_DOMAINS |
1491 SAMR_ACCESS_LOOKUP_DOMAIN,
1492 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1496 if (!W_ERROR_IS_OK(werr)) {
1500 init_lsa_String(&lsa_account_name, r->in.group_name);
1502 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1509 if (!NT_STATUS_IS_OK(status)) {
1510 werr = ntstatus_to_werror(status);
1513 if (!NT_STATUS_IS_OK(result)) {
1514 werr = ntstatus_to_werror(result);
1518 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1520 SAMR_GROUP_ACCESS_GET_MEMBERS,
1524 if (!NT_STATUS_IS_OK(status)) {
1525 werr = ntstatus_to_werror(status);
1528 if (!NT_STATUS_IS_OK(result)) {
1529 werr = ntstatus_to_werror(result);
1533 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1537 if (!NT_STATUS_IS_OK(status)) {
1538 werr = ntstatus_to_werror(status);
1541 if (!NT_STATUS_IS_OK(result)) {
1542 werr = ntstatus_to_werror(result);
1546 status = dcerpc_samr_LookupRids(b, talloc_tos(),
1553 if (!NT_STATUS_IS_OK(status)) {
1554 werr = ntstatus_to_werror(status);
1557 if (!NT_STATUS_IS_OK(result)) {
1558 werr = ntstatus_to_werror(result);
1562 for (i=0; i < names.count; i++) {
1564 if (member_types.ids[i] != SID_NAME_USER) {
1568 status = add_GROUP_USERS_INFO_X_buffer(ctx,
1570 names.names[i].string,
1574 if (!NT_STATUS_IS_OK(status)) {
1575 werr = ntstatus_to_werror(status);
1580 *r->out.entries_read = entries_read;
1581 *r->out.total_entries = entries_read;
1586 if (is_valid_policy_hnd(&group_handle)) {
1587 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1590 if (ctx->disable_policy_handle_cache) {
1591 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1592 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1598 /****************************************************************
1599 ****************************************************************/
1601 WERROR NetGroupGetUsers_l(struct libnetapi_ctx *ctx,
1602 struct NetGroupGetUsers *r)
1604 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupGetUsers);
1607 /****************************************************************
1608 ****************************************************************/
1610 WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx,
1611 struct NetGroupSetUsers *r)
1613 struct rpc_pipe_client *pipe_cli = NULL;
1614 struct policy_handle connect_handle, domain_handle, group_handle;
1615 struct lsa_String lsa_account_name;
1616 struct dom_sid2 *domain_sid = NULL;
1617 union samr_GroupInfo *group_info = NULL;
1618 struct samr_Ids user_rids, name_types;
1619 struct samr_Ids group_rids, group_types;
1620 struct samr_RidAttrArray *rid_array = NULL;
1621 struct lsa_String *lsa_names = NULL;
1622 struct dcerpc_binding_handle *b = NULL;
1624 uint32_t *add_rids = NULL;
1625 uint32_t *del_rids = NULL;
1626 size_t num_add_rids = 0;
1627 size_t num_del_rids = 0;
1629 uint32_t *member_rids = NULL;
1631 struct GROUP_USERS_INFO_0 *i0 = NULL;
1632 struct GROUP_USERS_INFO_1 *i1 = NULL;
1636 NTSTATUS status = NT_STATUS_OK;
1637 NTSTATUS result = NT_STATUS_OK;
1640 ZERO_STRUCT(connect_handle);
1641 ZERO_STRUCT(domain_handle);
1643 if (!r->in.buffer) {
1644 return WERR_INVALID_PARAM;
1647 switch (r->in.level) {
1652 return WERR_UNKNOWN_LEVEL;
1655 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1656 &ndr_table_samr.syntax_id,
1658 if (!W_ERROR_IS_OK(werr)) {
1662 b = pipe_cli->binding_handle;
1664 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1665 SAMR_ACCESS_ENUM_DOMAINS |
1666 SAMR_ACCESS_LOOKUP_DOMAIN,
1667 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1671 if (!W_ERROR_IS_OK(werr)) {
1675 init_lsa_String(&lsa_account_name, r->in.group_name);
1677 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1684 if (!NT_STATUS_IS_OK(status)) {
1685 werr = ntstatus_to_werror(status);
1688 if (!NT_STATUS_IS_OK(result)) {
1689 werr = ntstatus_to_werror(result);
1693 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
1695 SAMR_GROUP_ACCESS_GET_MEMBERS |
1696 SAMR_GROUP_ACCESS_ADD_MEMBER |
1697 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
1698 SAMR_GROUP_ACCESS_LOOKUP_INFO,
1702 if (!NT_STATUS_IS_OK(status)) {
1703 werr = ntstatus_to_werror(status);
1706 if (!NT_STATUS_IS_OK(result)) {
1707 werr = ntstatus_to_werror(result);
1711 status = dcerpc_samr_QueryGroupInfo(b, talloc_tos(),
1713 GROUPINFOATTRIBUTES,
1716 if (!NT_STATUS_IS_OK(status)) {
1717 werr = ntstatus_to_werror(status);
1720 if (!NT_STATUS_IS_OK(result)) {
1721 werr = ntstatus_to_werror(result);
1725 switch (r->in.level) {
1727 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
1730 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
1734 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
1740 for (i=0; i < r->in.num_entries; i++) {
1742 switch (r->in.level) {
1744 init_lsa_String(&lsa_names[i], i0->grui0_name);
1748 init_lsa_String(&lsa_names[i], i1->grui1_name);
1754 status = dcerpc_samr_LookupNames(b, talloc_tos(),
1761 if (!NT_STATUS_IS_OK(status)) {
1762 werr = ntstatus_to_werror(status);
1765 if (!NT_STATUS_IS_OK(result)) {
1766 werr = ntstatus_to_werror(result);
1770 member_rids = user_rids.ids;
1772 status = dcerpc_samr_QueryGroupMember(b, talloc_tos(),
1776 if (!NT_STATUS_IS_OK(status)) {
1777 werr = ntstatus_to_werror(status);
1780 if (!NT_STATUS_IS_OK(result)) {
1781 werr = ntstatus_to_werror(result);
1787 for (i=0; i < r->in.num_entries; i++) {
1788 bool already_member = false;
1789 for (k=0; k < rid_array->count; k++) {
1790 if (member_rids[i] == rid_array->rids[k]) {
1791 already_member = true;
1795 if (!already_member) {
1796 if (!add_rid_to_array_unique(ctx,
1798 &add_rids, &num_add_rids)) {
1799 werr = WERR_GENERAL_FAILURE;
1807 for (k=0; k < rid_array->count; k++) {
1808 bool keep_member = false;
1809 for (i=0; i < r->in.num_entries; i++) {
1810 if (member_rids[i] == rid_array->rids[k]) {
1816 if (!add_rid_to_array_unique(ctx,
1818 &del_rids, &num_del_rids)) {
1819 werr = WERR_GENERAL_FAILURE;
1827 for (i=0; i < num_add_rids; i++) {
1828 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
1833 if (!NT_STATUS_IS_OK(status)) {
1834 werr = ntstatus_to_werror(status);
1837 if (!NT_STATUS_IS_OK(result)) {
1838 werr = ntstatus_to_werror(result);
1845 for (i=0; i < num_del_rids; i++) {
1846 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
1850 if (!NT_STATUS_IS_OK(status)) {
1851 werr = ntstatus_to_werror(status);
1854 if (!NT_STATUS_IS_OK(result)) {
1855 werr = ntstatus_to_werror(result);
1863 if (is_valid_policy_hnd(&group_handle)) {
1864 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
1867 if (ctx->disable_policy_handle_cache) {
1868 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1869 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1875 /****************************************************************
1876 ****************************************************************/
1878 WERROR NetGroupSetUsers_l(struct libnetapi_ctx *ctx,
1879 struct NetGroupSetUsers *r)
1881 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetGroupSetUsers);