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
++) {
1394 status
= add_GROUP_USERS_INFO_X_buffer(ctx
,
1396 names
.names
[i
].string
,
1397 member_types
.ids
[i
],
1400 if (!NT_STATUS_IS_OK(status
)) {
1401 werr
= ntstatus_to_werror(status
);
1406 if (r
->out
.entries_read
) {
1407 *r
->out
.entries_read
= entries_read
;
1410 if (r
->out
.total_entries
) {
1411 *r
->out
.total_entries
= entries_read
;
1421 if (is_valid_policy_hnd(&group_handle
)) {
1422 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
1425 if (ctx
->disable_policy_handle_cache
) {
1426 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
1427 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
1433 /****************************************************************
1434 ****************************************************************/
1436 WERROR
NetGroupGetUsers_l(struct libnetapi_ctx
*ctx
,
1437 struct NetGroupGetUsers
*r
)
1439 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupGetUsers
);
1442 /****************************************************************
1443 ****************************************************************/
1445 WERROR
NetGroupSetUsers_r(struct libnetapi_ctx
*ctx
,
1446 struct NetGroupSetUsers
*r
)
1448 struct cli_state
*cli
= NULL
;
1449 struct rpc_pipe_client
*pipe_cli
= NULL
;
1450 struct policy_handle connect_handle
, domain_handle
, group_handle
;
1451 struct lsa_String lsa_account_name
;
1452 struct dom_sid2
*domain_sid
= NULL
;
1453 union samr_GroupInfo
*group_info
= NULL
;
1454 struct samr_Ids user_rids
, name_types
;
1455 struct samr_Ids group_rids
, group_types
;
1456 struct samr_RidTypeArray
*rid_array
= NULL
;
1457 struct lsa_String
*lsa_names
= NULL
;
1459 uint32_t *add_rids
= NULL
;
1460 uint32_t *del_rids
= NULL
;
1461 size_t num_add_rids
= 0;
1462 size_t num_del_rids
= 0;
1464 uint32_t *member_rids
= NULL
;
1465 size_t num_member_rids
= 0;
1467 struct GROUP_USERS_INFO_0
*i0
= NULL
;
1468 struct GROUP_USERS_INFO_1
*i1
= NULL
;
1472 NTSTATUS status
= NT_STATUS_OK
;
1475 ZERO_STRUCT(connect_handle
);
1476 ZERO_STRUCT(domain_handle
);
1478 if (!r
->in
.buffer
) {
1479 return WERR_INVALID_PARAM
;
1482 switch (r
->in
.level
) {
1487 return WERR_UNKNOWN_LEVEL
;
1490 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
1491 &ndr_table_samr
.syntax_id
,
1494 if (!W_ERROR_IS_OK(werr
)) {
1498 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
1499 SAMR_ACCESS_ENUM_DOMAINS
|
1500 SAMR_ACCESS_OPEN_DOMAIN
,
1501 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
1505 if (!W_ERROR_IS_OK(werr
)) {
1509 init_lsa_String(&lsa_account_name
, r
->in
.group_name
);
1511 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
1517 if (!NT_STATUS_IS_OK(status
)) {
1518 werr
= ntstatus_to_werror(status
);
1522 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
1524 SAMR_GROUP_ACCESS_GET_MEMBERS
|
1525 SAMR_GROUP_ACCESS_ADD_MEMBER
|
1526 SAMR_GROUP_ACCESS_REMOVE_MEMBER
|
1527 SAMR_GROUP_ACCESS_LOOKUP_INFO
,
1530 if (!NT_STATUS_IS_OK(status
)) {
1531 werr
= ntstatus_to_werror(status
);
1535 status
= rpccli_samr_QueryGroupInfo(pipe_cli
, ctx
,
1537 GROUPINFOATTRIBUTES
,
1539 if (!NT_STATUS_IS_OK(status
)) {
1540 werr
= ntstatus_to_werror(status
);
1544 switch (r
->in
.level
) {
1546 i0
= (struct GROUP_USERS_INFO_0
*)r
->in
.buffer
;
1549 i1
= (struct GROUP_USERS_INFO_1
*)r
->in
.buffer
;
1553 lsa_names
= talloc_array(ctx
, struct lsa_String
, r
->in
.num_entries
);
1559 for (i
=0; i
< r
->in
.num_entries
; i
++) {
1561 switch (r
->in
.level
) {
1563 init_lsa_String(&lsa_names
[i
], i0
->grui0_name
);
1567 init_lsa_String(&lsa_names
[i
], i1
->grui1_name
);
1573 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
1579 if (!NT_STATUS_IS_OK(status
)) {
1580 werr
= ntstatus_to_werror(status
);
1584 member_rids
= user_rids
.ids
;
1585 num_member_rids
= user_rids
.count
;
1587 status
= rpccli_samr_QueryGroupMember(pipe_cli
, ctx
,
1590 if (!NT_STATUS_IS_OK(status
)) {
1591 werr
= ntstatus_to_werror(status
);
1597 for (i
=0; i
< r
->in
.num_entries
; i
++) {
1598 bool already_member
= false;
1599 for (k
=0; k
< rid_array
->count
; k
++) {
1600 if (member_rids
[i
] == rid_array
->rids
[k
]) {
1601 already_member
= true;
1605 if (!already_member
) {
1606 if (!add_rid_to_array_unique(ctx
,
1608 &add_rids
, &num_add_rids
)) {
1609 werr
= WERR_GENERAL_FAILURE
;
1617 for (k
=0; k
< rid_array
->count
; k
++) {
1618 bool keep_member
= false;
1619 for (i
=0; i
< r
->in
.num_entries
; i
++) {
1620 if (member_rids
[i
] == rid_array
->rids
[k
]) {
1626 if (!add_rid_to_array_unique(ctx
,
1628 &del_rids
, &num_del_rids
)) {
1629 werr
= WERR_GENERAL_FAILURE
;
1637 for (i
=0; i
< num_add_rids
; i
++) {
1638 status
= rpccli_samr_AddGroupMember(pipe_cli
, ctx
,
1642 if (!NT_STATUS_IS_OK(status
)) {
1643 werr
= ntstatus_to_werror(status
);
1650 for (i
=0; i
< num_del_rids
; i
++) {
1651 status
= rpccli_samr_DeleteGroupMember(pipe_cli
, ctx
,
1654 if (!NT_STATUS_IS_OK(status
)) {
1655 werr
= ntstatus_to_werror(status
);
1667 if (is_valid_policy_hnd(&group_handle
)) {
1668 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
1671 if (ctx
->disable_policy_handle_cache
) {
1672 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
1673 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
1679 /****************************************************************
1680 ****************************************************************/
1682 WERROR
NetGroupSetUsers_l(struct libnetapi_ctx
*ctx
,
1683 struct NetGroupSetUsers
*r
)
1685 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupSetUsers
);