2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Guenther Deschner 2008
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
27 /****************************************************************
28 ****************************************************************/
30 WERROR
NetGroupAdd_r(struct libnetapi_ctx
*ctx
,
31 struct NetGroupAdd
*r
)
33 struct rpc_pipe_client
*pipe_cli
= NULL
;
36 struct policy_handle connect_handle
, domain_handle
, group_handle
;
37 struct lsa_String lsa_group_name
;
38 struct dom_sid2
*domain_sid
= NULL
;
41 struct GROUP_INFO_0
*info0
= NULL
;
42 struct GROUP_INFO_1
*info1
= NULL
;
43 struct GROUP_INFO_2
*info2
= NULL
;
44 struct GROUP_INFO_3
*info3
= NULL
;
45 union samr_GroupInfo info
;
47 ZERO_STRUCT(connect_handle
);
48 ZERO_STRUCT(domain_handle
);
49 ZERO_STRUCT(group_handle
);
52 return WERR_INVALID_PARAM
;
55 switch (r
->in
.level
) {
57 info0
= (struct GROUP_INFO_0
*)r
->in
.buffer
;
60 info1
= (struct GROUP_INFO_1
*)r
->in
.buffer
;
63 info2
= (struct GROUP_INFO_2
*)r
->in
.buffer
;
66 info3
= (struct GROUP_INFO_3
*)r
->in
.buffer
;
69 werr
= WERR_UNKNOWN_LEVEL
;
73 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
74 &ndr_table_samr
.syntax_id
,
76 if (!W_ERROR_IS_OK(werr
)) {
80 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
81 SAMR_ACCESS_ENUM_DOMAINS
|
82 SAMR_ACCESS_LOOKUP_DOMAIN
,
83 SAMR_DOMAIN_ACCESS_CREATE_GROUP
|
84 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
88 if (!W_ERROR_IS_OK(werr
)) {
92 switch (r
->in
.level
) {
94 init_lsa_String(&lsa_group_name
, info0
->grpi0_name
);
97 init_lsa_String(&lsa_group_name
, info1
->grpi1_name
);
100 init_lsa_String(&lsa_group_name
, info2
->grpi2_name
);
103 init_lsa_String(&lsa_group_name
, info3
->grpi3_name
);
107 status
= rpccli_samr_CreateDomainGroup(pipe_cli
, ctx
,
111 SAMR_GROUP_ACCESS_SET_INFO
,
115 if (!NT_STATUS_IS_OK(status
)) {
116 werr
= ntstatus_to_werror(status
);
120 switch (r
->in
.level
) {
122 if (info1
->grpi1_comment
) {
123 init_lsa_String(&info
.description
,
124 info1
->grpi1_comment
);
126 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
128 GROUPINFODESCRIPTION
,
133 if (info2
->grpi2_comment
) {
134 init_lsa_String(&info
.description
,
135 info2
->grpi2_comment
);
137 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
139 GROUPINFODESCRIPTION
,
141 if (!NT_STATUS_IS_OK(status
)) {
142 werr
= ntstatus_to_werror(status
);
147 if (info2
->grpi2_attributes
!= 0) {
148 info
.attributes
.attributes
= info2
->grpi2_attributes
;
149 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
157 if (info3
->grpi3_comment
) {
158 init_lsa_String(&info
.description
,
159 info3
->grpi3_comment
);
161 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
163 GROUPINFODESCRIPTION
,
165 if (!NT_STATUS_IS_OK(status
)) {
166 werr
= ntstatus_to_werror(status
);
171 if (info3
->grpi3_attributes
!= 0) {
172 info
.attributes
.attributes
= info3
->grpi3_attributes
;
173 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
183 if (!NT_STATUS_IS_OK(status
)) {
184 werr
= ntstatus_to_werror(status
);
192 rpccli_samr_DeleteDomainGroup(pipe_cli
, ctx
,
196 if (is_valid_policy_hnd(&group_handle
)) {
197 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
200 if (ctx
->disable_policy_handle_cache
) {
201 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
202 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
208 /****************************************************************
209 ****************************************************************/
211 WERROR
NetGroupAdd_l(struct libnetapi_ctx
*ctx
,
212 struct NetGroupAdd
*r
)
214 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupAdd
);
217 /****************************************************************
218 ****************************************************************/
220 WERROR
NetGroupDel_r(struct libnetapi_ctx
*ctx
,
221 struct NetGroupDel
*r
)
223 struct rpc_pipe_client
*pipe_cli
= NULL
;
226 struct policy_handle connect_handle
, domain_handle
, group_handle
;
227 struct lsa_String lsa_group_name
;
228 struct dom_sid2
*domain_sid
= NULL
;
231 struct samr_Ids rids
;
232 struct samr_Ids types
;
233 union samr_GroupInfo
*info
= NULL
;
234 struct samr_RidTypeArray
*rid_array
= NULL
;
236 ZERO_STRUCT(connect_handle
);
237 ZERO_STRUCT(domain_handle
);
238 ZERO_STRUCT(group_handle
);
240 if (!r
->in
.group_name
) {
241 return WERR_INVALID_PARAM
;
244 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
245 &ndr_table_samr
.syntax_id
,
247 if (!W_ERROR_IS_OK(werr
)) {
251 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
252 SAMR_ACCESS_ENUM_DOMAINS
|
253 SAMR_ACCESS_LOOKUP_DOMAIN
,
254 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
258 if (!W_ERROR_IS_OK(werr
)) {
262 init_lsa_String(&lsa_group_name
, r
->in
.group_name
);
264 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
270 if (!NT_STATUS_IS_OK(status
)) {
271 werr
= ntstatus_to_werror(status
);
275 if (types
.ids
[0] != SID_NAME_DOM_GRP
) {
276 werr
= WERR_INVALID_DATATYPE
;
280 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
283 SAMR_GROUP_ACCESS_GET_MEMBERS
|
284 SAMR_GROUP_ACCESS_REMOVE_MEMBER
|
285 SAMR_GROUP_ACCESS_ADD_MEMBER
|
286 SAMR_GROUP_ACCESS_LOOKUP_INFO
,
289 if (!NT_STATUS_IS_OK(status
)) {
290 werr
= ntstatus_to_werror(status
);
294 status
= rpccli_samr_QueryGroupInfo(pipe_cli
, ctx
,
298 if (!NT_STATUS_IS_OK(status
)) {
299 werr
= ntstatus_to_werror(status
);
304 /* breaks against NT4 */
305 if (!(info
->attributes
.attributes
& SE_GROUP_ENABLED
)) {
306 werr
= WERR_ACCESS_DENIED
;
310 status
= rpccli_samr_QueryGroupMember(pipe_cli
, ctx
,
313 if (!NT_STATUS_IS_OK(status
)) {
314 werr
= ntstatus_to_werror(status
);
319 struct lsa_Strings names
;
320 struct samr_Ids member_types
;
322 status
= rpccli_samr_LookupRids(pipe_cli
, ctx
,
328 if (!NT_STATUS_IS_OK(status
)) {
329 werr
= ntstatus_to_werror(status
);
334 for (i
=0; i
< rid_array
->count
; i
++) {
336 status
= rpccli_samr_DeleteGroupMember(pipe_cli
, ctx
,
339 if (!NT_STATUS_IS_OK(status
)) {
340 werr
= ntstatus_to_werror(status
);
345 status
= rpccli_samr_DeleteDomainGroup(pipe_cli
, ctx
,
347 if (!NT_STATUS_IS_OK(status
)) {
348 werr
= ntstatus_to_werror(status
);
352 ZERO_STRUCT(group_handle
);
357 if (is_valid_policy_hnd(&group_handle
)) {
358 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
361 if (ctx
->disable_policy_handle_cache
) {
362 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
363 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
369 /****************************************************************
370 ****************************************************************/
372 WERROR
NetGroupDel_l(struct libnetapi_ctx
*ctx
,
373 struct NetGroupDel
*r
)
375 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupDel
);
378 /****************************************************************
379 ****************************************************************/
381 WERROR
NetGroupSetInfo_r(struct libnetapi_ctx
*ctx
,
382 struct NetGroupSetInfo
*r
)
384 struct rpc_pipe_client
*pipe_cli
= NULL
;
387 struct policy_handle connect_handle
, domain_handle
, group_handle
;
388 struct lsa_String lsa_group_name
;
389 struct dom_sid2
*domain_sid
= NULL
;
391 struct samr_Ids rids
;
392 struct samr_Ids types
;
393 union samr_GroupInfo info
;
394 struct GROUP_INFO_0
*g0
;
395 struct GROUP_INFO_1
*g1
;
396 struct GROUP_INFO_2
*g2
;
397 struct GROUP_INFO_3
*g3
;
398 struct GROUP_INFO_1002
*g1002
;
399 struct GROUP_INFO_1005
*g1005
;
401 ZERO_STRUCT(connect_handle
);
402 ZERO_STRUCT(domain_handle
);
403 ZERO_STRUCT(group_handle
);
405 if (!r
->in
.group_name
) {
406 return WERR_INVALID_PARAM
;
409 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
410 &ndr_table_samr
.syntax_id
,
412 if (!W_ERROR_IS_OK(werr
)) {
416 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
417 SAMR_ACCESS_ENUM_DOMAINS
|
418 SAMR_ACCESS_LOOKUP_DOMAIN
,
419 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
423 if (!W_ERROR_IS_OK(werr
)) {
427 init_lsa_String(&lsa_group_name
, r
->in
.group_name
);
429 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
435 if (!NT_STATUS_IS_OK(status
)) {
436 werr
= ntstatus_to_werror(status
);
440 if (types
.ids
[0] != SID_NAME_DOM_GRP
) {
441 werr
= WERR_INVALID_DATATYPE
;
445 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
447 SAMR_GROUP_ACCESS_SET_INFO
|
448 SAMR_GROUP_ACCESS_LOOKUP_INFO
,
451 if (!NT_STATUS_IS_OK(status
)) {
452 werr
= ntstatus_to_werror(status
);
456 switch (r
->in
.level
) {
458 g0
= (struct GROUP_INFO_0
*)r
->in
.buffer
;
459 init_lsa_String(&info
.name
, g0
->grpi0_name
);
460 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
466 g1
= (struct GROUP_INFO_1
*)r
->in
.buffer
;
467 init_lsa_String(&info
.description
, g1
->grpi1_comment
);
468 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
470 GROUPINFODESCRIPTION
,
474 g2
= (struct GROUP_INFO_2
*)r
->in
.buffer
;
475 init_lsa_String(&info
.description
, g2
->grpi2_comment
);
476 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
478 GROUPINFODESCRIPTION
,
480 if (!NT_STATUS_IS_OK(status
)) {
481 werr
= ntstatus_to_werror(status
);
484 info
.attributes
.attributes
= g2
->grpi2_attributes
;
485 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
491 g3
= (struct GROUP_INFO_3
*)r
->in
.buffer
;
492 init_lsa_String(&info
.description
, g3
->grpi3_comment
);
493 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
495 GROUPINFODESCRIPTION
,
497 if (!NT_STATUS_IS_OK(status
)) {
498 werr
= ntstatus_to_werror(status
);
501 info
.attributes
.attributes
= g3
->grpi3_attributes
;
502 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
508 g1002
= (struct GROUP_INFO_1002
*)r
->in
.buffer
;
509 init_lsa_String(&info
.description
, g1002
->grpi1002_comment
);
510 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
512 GROUPINFODESCRIPTION
,
516 g1005
= (struct GROUP_INFO_1005
*)r
->in
.buffer
;
517 info
.attributes
.attributes
= g1005
->grpi1005_attributes
;
518 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
524 status
= NT_STATUS_INVALID_LEVEL
;
528 if (!NT_STATUS_IS_OK(status
)) {
529 werr
= ntstatus_to_werror(status
);
536 if (is_valid_policy_hnd(&group_handle
)) {
537 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
540 if (ctx
->disable_policy_handle_cache
) {
541 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
542 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
548 /****************************************************************
549 ****************************************************************/
551 WERROR
NetGroupSetInfo_l(struct libnetapi_ctx
*ctx
,
552 struct NetGroupSetInfo
*r
)
554 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupSetInfo
);
557 /****************************************************************
558 ****************************************************************/
560 static WERROR
map_group_info_to_buffer(TALLOC_CTX
*mem_ctx
,
562 struct samr_GroupInfoAll
*info
,
563 struct dom_sid2
*domain_sid
,
567 struct GROUP_INFO_0 info0
;
568 struct GROUP_INFO_1 info1
;
569 struct GROUP_INFO_2 info2
;
570 struct GROUP_INFO_3 info3
;
575 info0
.grpi0_name
= info
->name
.string
;
577 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, &info0
, sizeof(info0
));
581 info1
.grpi1_name
= info
->name
.string
;
582 info1
.grpi1_comment
= info
->description
.string
;
584 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, &info1
, sizeof(info1
));
588 info2
.grpi2_name
= info
->name
.string
;
589 info2
.grpi2_comment
= info
->description
.string
;
590 info2
.grpi2_group_id
= rid
;
591 info2
.grpi2_attributes
= info
->attributes
;
593 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, &info2
, sizeof(info2
));
597 if (!sid_compose(&sid
, domain_sid
, rid
)) {
601 info3
.grpi3_name
= info
->name
.string
;
602 info3
.grpi3_comment
= info
->description
.string
;
603 info3
.grpi3_attributes
= info
->attributes
;
604 info3
.grpi3_group_sid
= (struct domsid
*)sid_dup_talloc(mem_ctx
, &sid
);
606 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, &info3
, sizeof(info3
));
610 return WERR_UNKNOWN_LEVEL
;
613 W_ERROR_HAVE_NO_MEMORY(*buffer
);
618 /****************************************************************
619 ****************************************************************/
621 WERROR
NetGroupGetInfo_r(struct libnetapi_ctx
*ctx
,
622 struct NetGroupGetInfo
*r
)
624 struct rpc_pipe_client
*pipe_cli
= NULL
;
627 struct policy_handle connect_handle
, domain_handle
, group_handle
;
628 struct lsa_String lsa_group_name
;
629 struct dom_sid2
*domain_sid
= NULL
;
631 struct samr_Ids rids
;
632 struct samr_Ids types
;
633 union samr_GroupInfo
*info
= NULL
;
634 bool group_info_all
= false;
636 ZERO_STRUCT(connect_handle
);
637 ZERO_STRUCT(domain_handle
);
638 ZERO_STRUCT(group_handle
);
640 if (!r
->in
.group_name
) {
641 return WERR_INVALID_PARAM
;
644 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
645 &ndr_table_samr
.syntax_id
,
647 if (!W_ERROR_IS_OK(werr
)) {
651 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
652 SAMR_ACCESS_ENUM_DOMAINS
|
653 SAMR_ACCESS_LOOKUP_DOMAIN
,
654 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
658 if (!W_ERROR_IS_OK(werr
)) {
662 init_lsa_String(&lsa_group_name
, r
->in
.group_name
);
664 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
670 if (!NT_STATUS_IS_OK(status
)) {
671 werr
= ntstatus_to_werror(status
);
675 if (types
.ids
[0] != SID_NAME_DOM_GRP
) {
676 werr
= WERR_INVALID_DATATYPE
;
680 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
682 SAMR_GROUP_ACCESS_LOOKUP_INFO
,
685 if (!NT_STATUS_IS_OK(status
)) {
686 werr
= ntstatus_to_werror(status
);
690 status
= rpccli_samr_QueryGroupInfo(pipe_cli
, ctx
,
694 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_INFO_CLASS
)) {
695 status
= rpccli_samr_QueryGroupInfo(pipe_cli
, ctx
,
699 group_info_all
= true;
702 if (!NT_STATUS_IS_OK(status
)) {
703 werr
= ntstatus_to_werror(status
);
707 werr
= map_group_info_to_buffer(ctx
, r
->in
.level
,
708 group_info_all
? &info
->all
: &info
->all2
,
709 domain_sid
, rids
.ids
[0],
711 if (!W_ERROR_IS_OK(werr
)) {
715 if (is_valid_policy_hnd(&group_handle
)) {
716 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
719 if (ctx
->disable_policy_handle_cache
) {
720 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
721 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
727 /****************************************************************
728 ****************************************************************/
730 WERROR
NetGroupGetInfo_l(struct libnetapi_ctx
*ctx
,
731 struct NetGroupGetInfo
*r
)
733 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupGetInfo
);
736 /****************************************************************
737 ****************************************************************/
739 WERROR
NetGroupAddUser_r(struct libnetapi_ctx
*ctx
,
740 struct NetGroupAddUser
*r
)
742 struct rpc_pipe_client
*pipe_cli
= NULL
;
745 struct policy_handle connect_handle
, domain_handle
, group_handle
;
746 struct lsa_String lsa_group_name
, lsa_user_name
;
747 struct dom_sid2
*domain_sid
= NULL
;
749 struct samr_Ids rids
;
750 struct samr_Ids types
;
752 ZERO_STRUCT(connect_handle
);
753 ZERO_STRUCT(domain_handle
);
754 ZERO_STRUCT(group_handle
);
756 if (!r
->in
.group_name
) {
757 return WERR_INVALID_PARAM
;
760 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
761 &ndr_table_samr
.syntax_id
,
763 if (!W_ERROR_IS_OK(werr
)) {
767 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
768 SAMR_ACCESS_ENUM_DOMAINS
|
769 SAMR_ACCESS_LOOKUP_DOMAIN
,
770 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
774 if (!W_ERROR_IS_OK(werr
)) {
778 init_lsa_String(&lsa_group_name
, r
->in
.group_name
);
780 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
786 if (!NT_STATUS_IS_OK(status
)) {
787 werr
= WERR_GROUP_NOT_FOUND
;
791 if (types
.ids
[0] != SID_NAME_DOM_GRP
) {
792 werr
= WERR_GROUP_NOT_FOUND
;
796 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
798 SAMR_GROUP_ACCESS_ADD_MEMBER
,
801 if (!NT_STATUS_IS_OK(status
)) {
802 werr
= ntstatus_to_werror(status
);
806 init_lsa_String(&lsa_user_name
, r
->in
.user_name
);
808 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
814 if (!NT_STATUS_IS_OK(status
)) {
815 werr
= WERR_USER_NOT_FOUND
;
819 if (types
.ids
[0] != SID_NAME_USER
) {
820 werr
= WERR_USER_NOT_FOUND
;
824 status
= rpccli_samr_AddGroupMember(pipe_cli
, ctx
,
828 if (!NT_STATUS_IS_OK(status
)) {
829 werr
= ntstatus_to_werror(status
);
836 if (is_valid_policy_hnd(&group_handle
)) {
837 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
840 if (ctx
->disable_policy_handle_cache
) {
841 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
842 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
848 /****************************************************************
849 ****************************************************************/
851 WERROR
NetGroupAddUser_l(struct libnetapi_ctx
*ctx
,
852 struct NetGroupAddUser
*r
)
854 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupAddUser
);
857 /****************************************************************
858 ****************************************************************/
860 WERROR
NetGroupDelUser_r(struct libnetapi_ctx
*ctx
,
861 struct NetGroupDelUser
*r
)
863 struct rpc_pipe_client
*pipe_cli
= NULL
;
866 struct policy_handle connect_handle
, domain_handle
, group_handle
;
867 struct lsa_String lsa_group_name
, lsa_user_name
;
868 struct dom_sid2
*domain_sid
= NULL
;
870 struct samr_Ids rids
;
871 struct samr_Ids types
;
873 ZERO_STRUCT(connect_handle
);
874 ZERO_STRUCT(domain_handle
);
875 ZERO_STRUCT(group_handle
);
877 if (!r
->in
.group_name
) {
878 return WERR_INVALID_PARAM
;
881 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
882 &ndr_table_samr
.syntax_id
,
884 if (!W_ERROR_IS_OK(werr
)) {
888 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
889 SAMR_ACCESS_ENUM_DOMAINS
|
890 SAMR_ACCESS_LOOKUP_DOMAIN
,
891 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
895 if (!W_ERROR_IS_OK(werr
)) {
899 init_lsa_String(&lsa_group_name
, r
->in
.group_name
);
901 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
907 if (!NT_STATUS_IS_OK(status
)) {
908 werr
= WERR_GROUP_NOT_FOUND
;
912 if (types
.ids
[0] != SID_NAME_DOM_GRP
) {
913 werr
= WERR_GROUP_NOT_FOUND
;
917 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
919 SAMR_GROUP_ACCESS_REMOVE_MEMBER
,
922 if (!NT_STATUS_IS_OK(status
)) {
923 werr
= ntstatus_to_werror(status
);
927 init_lsa_String(&lsa_user_name
, r
->in
.user_name
);
929 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
935 if (!NT_STATUS_IS_OK(status
)) {
936 werr
= WERR_USER_NOT_FOUND
;
940 if (types
.ids
[0] != SID_NAME_USER
) {
941 werr
= WERR_USER_NOT_FOUND
;
945 status
= rpccli_samr_DeleteGroupMember(pipe_cli
, ctx
,
948 if (!NT_STATUS_IS_OK(status
)) {
949 werr
= ntstatus_to_werror(status
);
956 if (is_valid_policy_hnd(&group_handle
)) {
957 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
960 if (ctx
->disable_policy_handle_cache
) {
961 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
962 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
968 /****************************************************************
969 ****************************************************************/
971 WERROR
NetGroupDelUser_l(struct libnetapi_ctx
*ctx
,
972 struct NetGroupDelUser
*r
)
974 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupDelUser
);
977 /****************************************************************
978 ****************************************************************/
980 static WERROR
convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX
*mem_ctx
,
981 struct samr_DispInfoFullGroups
*groups
,
984 struct GROUP_INFO_0
*g0
;
987 g0
= TALLOC_ZERO_ARRAY(mem_ctx
, struct GROUP_INFO_0
, groups
->count
);
988 W_ERROR_HAVE_NO_MEMORY(g0
);
990 for (i
=0; i
<groups
->count
; i
++) {
991 g0
[i
].grpi0_name
= talloc_strdup(mem_ctx
,
992 groups
->entries
[i
].account_name
.string
);
993 W_ERROR_HAVE_NO_MEMORY(g0
[i
].grpi0_name
);
996 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, g0
,
997 sizeof(struct GROUP_INFO_0
) * groups
->count
);
998 W_ERROR_HAVE_NO_MEMORY(*buffer
);
1003 /****************************************************************
1004 ****************************************************************/
1006 static WERROR
convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX
*mem_ctx
,
1007 struct samr_DispInfoFullGroups
*groups
,
1010 struct GROUP_INFO_1
*g1
;
1013 g1
= TALLOC_ZERO_ARRAY(mem_ctx
, struct GROUP_INFO_1
, groups
->count
);
1014 W_ERROR_HAVE_NO_MEMORY(g1
);
1016 for (i
=0; i
<groups
->count
; i
++) {
1017 g1
[i
].grpi1_name
= talloc_strdup(mem_ctx
,
1018 groups
->entries
[i
].account_name
.string
);
1019 g1
[i
].grpi1_comment
= talloc_strdup(mem_ctx
,
1020 groups
->entries
[i
].description
.string
);
1021 W_ERROR_HAVE_NO_MEMORY(g1
[i
].grpi1_name
);
1024 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, g1
,
1025 sizeof(struct GROUP_INFO_1
) * groups
->count
);
1026 W_ERROR_HAVE_NO_MEMORY(*buffer
);
1031 /****************************************************************
1032 ****************************************************************/
1034 static WERROR
convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX
*mem_ctx
,
1035 struct samr_DispInfoFullGroups
*groups
,
1038 struct GROUP_INFO_2
*g2
;
1041 g2
= TALLOC_ZERO_ARRAY(mem_ctx
, struct GROUP_INFO_2
, groups
->count
);
1042 W_ERROR_HAVE_NO_MEMORY(g2
);
1044 for (i
=0; i
<groups
->count
; i
++) {
1045 g2
[i
].grpi2_name
= talloc_strdup(mem_ctx
,
1046 groups
->entries
[i
].account_name
.string
);
1047 g2
[i
].grpi2_comment
= talloc_strdup(mem_ctx
,
1048 groups
->entries
[i
].description
.string
);
1049 g2
[i
].grpi2_group_id
= groups
->entries
[i
].rid
;
1050 g2
[i
].grpi2_attributes
= groups
->entries
[i
].acct_flags
;
1051 W_ERROR_HAVE_NO_MEMORY(g2
[i
].grpi2_name
);
1054 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, g2
,
1055 sizeof(struct GROUP_INFO_2
) * groups
->count
);
1056 W_ERROR_HAVE_NO_MEMORY(*buffer
);
1061 /****************************************************************
1062 ****************************************************************/
1064 static WERROR
convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX
*mem_ctx
,
1065 struct samr_DispInfoFullGroups
*groups
,
1066 const struct dom_sid
*domain_sid
,
1069 struct GROUP_INFO_3
*g3
;
1072 g3
= TALLOC_ZERO_ARRAY(mem_ctx
, struct GROUP_INFO_3
, groups
->count
);
1073 W_ERROR_HAVE_NO_MEMORY(g3
);
1075 for (i
=0; i
<groups
->count
; i
++) {
1079 if (!sid_compose(&sid
, domain_sid
, groups
->entries
[i
].rid
)) {
1083 g3
[i
].grpi3_name
= talloc_strdup(mem_ctx
,
1084 groups
->entries
[i
].account_name
.string
);
1085 g3
[i
].grpi3_comment
= talloc_strdup(mem_ctx
,
1086 groups
->entries
[i
].description
.string
);
1087 g3
[i
].grpi3_group_sid
= (struct domsid
*)sid_dup_talloc(mem_ctx
, &sid
);
1088 g3
[i
].grpi3_attributes
= groups
->entries
[i
].acct_flags
;
1089 W_ERROR_HAVE_NO_MEMORY(g3
[i
].grpi3_name
);
1092 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, g3
,
1093 sizeof(struct GROUP_INFO_3
) * groups
->count
);
1094 W_ERROR_HAVE_NO_MEMORY(*buffer
);
1099 /****************************************************************
1100 ****************************************************************/
1102 static WERROR
convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX
*mem_ctx
,
1104 struct samr_DispInfoFullGroups
*groups
,
1105 const struct dom_sid
*domain_sid
,
1106 uint32_t *entries_read
,
1110 *entries_read
= groups
->count
;
1115 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx
, groups
, buffer
);
1117 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx
, groups
, buffer
);
1119 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx
, groups
, buffer
);
1121 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx
, groups
, domain_sid
, buffer
);
1123 return WERR_UNKNOWN_LEVEL
;
1127 /****************************************************************
1128 ****************************************************************/
1130 WERROR
NetGroupEnum_r(struct libnetapi_ctx
*ctx
,
1131 struct NetGroupEnum
*r
)
1133 struct rpc_pipe_client
*pipe_cli
= NULL
;
1134 struct policy_handle connect_handle
;
1135 struct dom_sid2
*domain_sid
= NULL
;
1136 struct policy_handle domain_handle
;
1137 union samr_DispInfo info
;
1138 union samr_DomainInfo
*domain_info
= NULL
;
1140 uint32_t total_size
= 0;
1141 uint32_t returned_size
= 0;
1143 NTSTATUS status
= NT_STATUS_OK
;
1144 WERROR werr
, tmp_werr
;
1146 ZERO_STRUCT(connect_handle
);
1147 ZERO_STRUCT(domain_handle
);
1149 switch (r
->in
.level
) {
1156 return WERR_UNKNOWN_LEVEL
;
1159 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
1160 &ndr_table_samr
.syntax_id
,
1162 if (!W_ERROR_IS_OK(werr
)) {
1166 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
1167 SAMR_ACCESS_ENUM_DOMAINS
|
1168 SAMR_ACCESS_LOOKUP_DOMAIN
,
1169 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2
|
1170 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
|
1171 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
1175 if (!W_ERROR_IS_OK(werr
)) {
1179 status
= rpccli_samr_QueryDomainInfo(pipe_cli
, ctx
,
1183 if (!NT_STATUS_IS_OK(status
)) {
1184 werr
= ntstatus_to_werror(status
);
1188 if (r
->out
.total_entries
) {
1189 *r
->out
.total_entries
= domain_info
->general
.num_groups
;
1192 status
= rpccli_samr_QueryDisplayInfo2(pipe_cli
,
1196 r
->in
.resume_handle
?
1197 *r
->in
.resume_handle
: 0,
1203 werr
= ntstatus_to_werror(status
);
1204 if (NT_STATUS_IS_ERR(status
)) {
1208 if (r
->out
.resume_handle
&& info
.info3
.count
> 0) {
1209 *r
->out
.resume_handle
=
1210 info
.info3
.entries
[info
.info3
.count
-1].idx
;
1213 tmp_werr
= convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx
,
1217 r
->out
.entries_read
,
1219 if (!W_ERROR_IS_OK(tmp_werr
)) {
1226 if (NT_STATUS_IS_OK(status
) ||
1227 NT_STATUS_IS_ERR(status
)) {
1229 if (ctx
->disable_policy_handle_cache
) {
1230 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
1231 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
1238 /****************************************************************
1239 ****************************************************************/
1241 WERROR
NetGroupEnum_l(struct libnetapi_ctx
*ctx
,
1242 struct NetGroupEnum
*r
)
1244 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupEnum
);
1247 /****************************************************************
1248 ****************************************************************/
1250 WERROR
NetGroupGetUsers_r(struct libnetapi_ctx
*ctx
,
1251 struct NetGroupGetUsers
*r
)
1253 /* FIXME: this call needs to cope with large replies */
1255 struct rpc_pipe_client
*pipe_cli
= NULL
;
1256 struct policy_handle connect_handle
, domain_handle
, group_handle
;
1257 struct lsa_String lsa_account_name
;
1258 struct dom_sid2
*domain_sid
= NULL
;
1259 struct samr_Ids group_rids
, name_types
;
1260 struct samr_RidTypeArray
*rid_array
= NULL
;
1261 struct lsa_Strings names
;
1262 struct samr_Ids member_types
;
1265 uint32_t entries_read
= 0;
1267 NTSTATUS status
= NT_STATUS_OK
;
1270 ZERO_STRUCT(connect_handle
);
1271 ZERO_STRUCT(domain_handle
);
1273 if (!r
->out
.buffer
) {
1274 return WERR_INVALID_PARAM
;
1277 *r
->out
.buffer
= NULL
;
1278 *r
->out
.entries_read
= 0;
1279 *r
->out
.total_entries
= 0;
1281 switch (r
->in
.level
) {
1286 return WERR_UNKNOWN_LEVEL
;
1290 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
1291 &ndr_table_samr
.syntax_id
,
1293 if (!W_ERROR_IS_OK(werr
)) {
1297 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
1298 SAMR_ACCESS_ENUM_DOMAINS
|
1299 SAMR_ACCESS_LOOKUP_DOMAIN
,
1300 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
1304 if (!W_ERROR_IS_OK(werr
)) {
1308 init_lsa_String(&lsa_account_name
, r
->in
.group_name
);
1310 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
1316 if (!NT_STATUS_IS_OK(status
)) {
1317 werr
= ntstatus_to_werror(status
);
1321 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
1323 SAMR_GROUP_ACCESS_GET_MEMBERS
,
1326 if (!NT_STATUS_IS_OK(status
)) {
1327 werr
= ntstatus_to_werror(status
);
1331 status
= rpccli_samr_QueryGroupMember(pipe_cli
, ctx
,
1334 if (!NT_STATUS_IS_OK(status
)) {
1335 werr
= ntstatus_to_werror(status
);
1339 status
= rpccli_samr_LookupRids(pipe_cli
, ctx
,
1345 if (!NT_STATUS_IS_OK(status
)) {
1346 werr
= ntstatus_to_werror(status
);
1350 for (i
=0; i
< names
.count
; i
++) {
1352 if (member_types
.ids
[i
] != SID_NAME_USER
) {
1356 status
= add_GROUP_USERS_INFO_X_buffer(ctx
,
1358 names
.names
[i
].string
,
1362 if (!NT_STATUS_IS_OK(status
)) {
1363 werr
= ntstatus_to_werror(status
);
1368 *r
->out
.entries_read
= entries_read
;
1369 *r
->out
.total_entries
= entries_read
;
1374 if (is_valid_policy_hnd(&group_handle
)) {
1375 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
1378 if (ctx
->disable_policy_handle_cache
) {
1379 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
1380 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
1386 /****************************************************************
1387 ****************************************************************/
1389 WERROR
NetGroupGetUsers_l(struct libnetapi_ctx
*ctx
,
1390 struct NetGroupGetUsers
*r
)
1392 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupGetUsers
);
1395 /****************************************************************
1396 ****************************************************************/
1398 WERROR
NetGroupSetUsers_r(struct libnetapi_ctx
*ctx
,
1399 struct NetGroupSetUsers
*r
)
1401 struct rpc_pipe_client
*pipe_cli
= NULL
;
1402 struct policy_handle connect_handle
, domain_handle
, group_handle
;
1403 struct lsa_String lsa_account_name
;
1404 struct dom_sid2
*domain_sid
= NULL
;
1405 union samr_GroupInfo
*group_info
= NULL
;
1406 struct samr_Ids user_rids
, name_types
;
1407 struct samr_Ids group_rids
, group_types
;
1408 struct samr_RidTypeArray
*rid_array
= NULL
;
1409 struct lsa_String
*lsa_names
= NULL
;
1411 uint32_t *add_rids
= NULL
;
1412 uint32_t *del_rids
= NULL
;
1413 size_t num_add_rids
= 0;
1414 size_t num_del_rids
= 0;
1416 uint32_t *member_rids
= NULL
;
1417 size_t num_member_rids
= 0;
1419 struct GROUP_USERS_INFO_0
*i0
= NULL
;
1420 struct GROUP_USERS_INFO_1
*i1
= NULL
;
1424 NTSTATUS status
= NT_STATUS_OK
;
1427 ZERO_STRUCT(connect_handle
);
1428 ZERO_STRUCT(domain_handle
);
1430 if (!r
->in
.buffer
) {
1431 return WERR_INVALID_PARAM
;
1434 switch (r
->in
.level
) {
1439 return WERR_UNKNOWN_LEVEL
;
1442 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
1443 &ndr_table_samr
.syntax_id
,
1445 if (!W_ERROR_IS_OK(werr
)) {
1449 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
1450 SAMR_ACCESS_ENUM_DOMAINS
|
1451 SAMR_ACCESS_LOOKUP_DOMAIN
,
1452 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
1456 if (!W_ERROR_IS_OK(werr
)) {
1460 init_lsa_String(&lsa_account_name
, r
->in
.group_name
);
1462 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
1468 if (!NT_STATUS_IS_OK(status
)) {
1469 werr
= ntstatus_to_werror(status
);
1473 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
1475 SAMR_GROUP_ACCESS_GET_MEMBERS
|
1476 SAMR_GROUP_ACCESS_ADD_MEMBER
|
1477 SAMR_GROUP_ACCESS_REMOVE_MEMBER
|
1478 SAMR_GROUP_ACCESS_LOOKUP_INFO
,
1481 if (!NT_STATUS_IS_OK(status
)) {
1482 werr
= ntstatus_to_werror(status
);
1486 status
= rpccli_samr_QueryGroupInfo(pipe_cli
, ctx
,
1488 GROUPINFOATTRIBUTES
,
1490 if (!NT_STATUS_IS_OK(status
)) {
1491 werr
= ntstatus_to_werror(status
);
1495 switch (r
->in
.level
) {
1497 i0
= (struct GROUP_USERS_INFO_0
*)r
->in
.buffer
;
1500 i1
= (struct GROUP_USERS_INFO_1
*)r
->in
.buffer
;
1504 lsa_names
= talloc_array(ctx
, struct lsa_String
, r
->in
.num_entries
);
1510 for (i
=0; i
< r
->in
.num_entries
; i
++) {
1512 switch (r
->in
.level
) {
1514 init_lsa_String(&lsa_names
[i
], i0
->grui0_name
);
1518 init_lsa_String(&lsa_names
[i
], i1
->grui1_name
);
1524 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
1530 if (!NT_STATUS_IS_OK(status
)) {
1531 werr
= ntstatus_to_werror(status
);
1535 member_rids
= user_rids
.ids
;
1536 num_member_rids
= user_rids
.count
;
1538 status
= rpccli_samr_QueryGroupMember(pipe_cli
, ctx
,
1541 if (!NT_STATUS_IS_OK(status
)) {
1542 werr
= ntstatus_to_werror(status
);
1548 for (i
=0; i
< r
->in
.num_entries
; i
++) {
1549 bool already_member
= false;
1550 for (k
=0; k
< rid_array
->count
; k
++) {
1551 if (member_rids
[i
] == rid_array
->rids
[k
]) {
1552 already_member
= true;
1556 if (!already_member
) {
1557 if (!add_rid_to_array_unique(ctx
,
1559 &add_rids
, &num_add_rids
)) {
1560 werr
= WERR_GENERAL_FAILURE
;
1568 for (k
=0; k
< rid_array
->count
; k
++) {
1569 bool keep_member
= false;
1570 for (i
=0; i
< r
->in
.num_entries
; i
++) {
1571 if (member_rids
[i
] == rid_array
->rids
[k
]) {
1577 if (!add_rid_to_array_unique(ctx
,
1579 &del_rids
, &num_del_rids
)) {
1580 werr
= WERR_GENERAL_FAILURE
;
1588 for (i
=0; i
< num_add_rids
; i
++) {
1589 status
= rpccli_samr_AddGroupMember(pipe_cli
, ctx
,
1593 if (!NT_STATUS_IS_OK(status
)) {
1594 werr
= ntstatus_to_werror(status
);
1601 for (i
=0; i
< num_del_rids
; i
++) {
1602 status
= rpccli_samr_DeleteGroupMember(pipe_cli
, ctx
,
1605 if (!NT_STATUS_IS_OK(status
)) {
1606 werr
= ntstatus_to_werror(status
);
1614 if (is_valid_policy_hnd(&group_handle
)) {
1615 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
1618 if (ctx
->disable_policy_handle_cache
) {
1619 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
1620 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
1626 /****************************************************************
1627 ****************************************************************/
1629 WERROR
NetGroupSetUsers_l(struct libnetapi_ctx
*ctx
,
1630 struct NetGroupSetUsers
*r
)
1632 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupSetUsers
);