2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Guenther Deschner 2008
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
26 #include "../librpc/gen_ndr/cli_samr.h"
28 /****************************************************************
29 ****************************************************************/
31 WERROR
NetGroupAdd_r(struct libnetapi_ctx
*ctx
,
32 struct NetGroupAdd
*r
)
34 struct rpc_pipe_client
*pipe_cli
= NULL
;
37 struct policy_handle 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
,
77 if (!W_ERROR_IS_OK(werr
)) {
81 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
82 SAMR_ACCESS_ENUM_DOMAINS
|
83 SAMR_ACCESS_LOOKUP_DOMAIN
,
84 SAMR_DOMAIN_ACCESS_CREATE_GROUP
|
85 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
89 if (!W_ERROR_IS_OK(werr
)) {
93 switch (r
->in
.level
) {
95 init_lsa_String(&lsa_group_name
, info0
->grpi0_name
);
98 init_lsa_String(&lsa_group_name
, info1
->grpi1_name
);
101 init_lsa_String(&lsa_group_name
, info2
->grpi2_name
);
104 init_lsa_String(&lsa_group_name
, info3
->grpi3_name
);
108 status
= rpccli_samr_CreateDomainGroup(pipe_cli
, ctx
,
112 SAMR_GROUP_ACCESS_SET_INFO
,
116 if (!NT_STATUS_IS_OK(status
)) {
117 werr
= ntstatus_to_werror(status
);
121 switch (r
->in
.level
) {
123 if (info1
->grpi1_comment
) {
124 init_lsa_String(&info
.description
,
125 info1
->grpi1_comment
);
127 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
129 GROUPINFODESCRIPTION
,
134 if (info2
->grpi2_comment
) {
135 init_lsa_String(&info
.description
,
136 info2
->grpi2_comment
);
138 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
140 GROUPINFODESCRIPTION
,
142 if (!NT_STATUS_IS_OK(status
)) {
143 werr
= ntstatus_to_werror(status
);
148 if (info2
->grpi2_attributes
!= 0) {
149 info
.attributes
.attributes
= info2
->grpi2_attributes
;
150 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
158 if (info3
->grpi3_comment
) {
159 init_lsa_String(&info
.description
,
160 info3
->grpi3_comment
);
162 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
164 GROUPINFODESCRIPTION
,
166 if (!NT_STATUS_IS_OK(status
)) {
167 werr
= ntstatus_to_werror(status
);
172 if (info3
->grpi3_attributes
!= 0) {
173 info
.attributes
.attributes
= info3
->grpi3_attributes
;
174 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
184 if (!NT_STATUS_IS_OK(status
)) {
185 werr
= ntstatus_to_werror(status
);
193 rpccli_samr_DeleteDomainGroup(pipe_cli
, ctx
,
197 if (is_valid_policy_hnd(&group_handle
)) {
198 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
201 if (ctx
->disable_policy_handle_cache
) {
202 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
203 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
209 /****************************************************************
210 ****************************************************************/
212 WERROR
NetGroupAdd_l(struct libnetapi_ctx
*ctx
,
213 struct NetGroupAdd
*r
)
215 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupAdd
);
218 /****************************************************************
219 ****************************************************************/
221 WERROR
NetGroupDel_r(struct libnetapi_ctx
*ctx
,
222 struct NetGroupDel
*r
)
224 struct rpc_pipe_client
*pipe_cli
= NULL
;
227 struct policy_handle connect_handle
, domain_handle
, group_handle
;
228 struct lsa_String lsa_group_name
;
229 struct dom_sid2
*domain_sid
= NULL
;
232 struct samr_Ids rids
;
233 struct samr_Ids types
;
234 union samr_GroupInfo
*info
= NULL
;
235 struct samr_RidTypeArray
*rid_array
= NULL
;
237 ZERO_STRUCT(connect_handle
);
238 ZERO_STRUCT(domain_handle
);
239 ZERO_STRUCT(group_handle
);
241 if (!r
->in
.group_name
) {
242 return WERR_INVALID_PARAM
;
245 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
246 &ndr_table_samr
.syntax_id
,
248 if (!W_ERROR_IS_OK(werr
)) {
252 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
253 SAMR_ACCESS_ENUM_DOMAINS
|
254 SAMR_ACCESS_LOOKUP_DOMAIN
,
255 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
259 if (!W_ERROR_IS_OK(werr
)) {
263 init_lsa_String(&lsa_group_name
, r
->in
.group_name
);
265 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
271 if (!NT_STATUS_IS_OK(status
)) {
272 werr
= ntstatus_to_werror(status
);
276 if (types
.ids
[0] != SID_NAME_DOM_GRP
) {
277 werr
= WERR_INVALID_DATATYPE
;
281 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
284 SAMR_GROUP_ACCESS_GET_MEMBERS
|
285 SAMR_GROUP_ACCESS_REMOVE_MEMBER
|
286 SAMR_GROUP_ACCESS_ADD_MEMBER
|
287 SAMR_GROUP_ACCESS_LOOKUP_INFO
,
290 if (!NT_STATUS_IS_OK(status
)) {
291 werr
= ntstatus_to_werror(status
);
295 status
= rpccli_samr_QueryGroupInfo(pipe_cli
, ctx
,
299 if (!NT_STATUS_IS_OK(status
)) {
300 werr
= ntstatus_to_werror(status
);
305 /* breaks against NT4 */
306 if (!(info
->attributes
.attributes
& SE_GROUP_ENABLED
)) {
307 werr
= WERR_ACCESS_DENIED
;
311 status
= rpccli_samr_QueryGroupMember(pipe_cli
, ctx
,
314 if (!NT_STATUS_IS_OK(status
)) {
315 werr
= ntstatus_to_werror(status
);
320 struct lsa_Strings names
;
321 struct samr_Ids member_types
;
323 status
= rpccli_samr_LookupRids(pipe_cli
, ctx
,
329 if (!NT_STATUS_IS_OK(status
)) {
330 werr
= ntstatus_to_werror(status
);
335 for (i
=0; i
< rid_array
->count
; i
++) {
337 status
= rpccli_samr_DeleteGroupMember(pipe_cli
, ctx
,
340 if (!NT_STATUS_IS_OK(status
)) {
341 werr
= ntstatus_to_werror(status
);
346 status
= rpccli_samr_DeleteDomainGroup(pipe_cli
, ctx
,
348 if (!NT_STATUS_IS_OK(status
)) {
349 werr
= ntstatus_to_werror(status
);
353 ZERO_STRUCT(group_handle
);
358 if (is_valid_policy_hnd(&group_handle
)) {
359 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
362 if (ctx
->disable_policy_handle_cache
) {
363 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
364 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
370 /****************************************************************
371 ****************************************************************/
373 WERROR
NetGroupDel_l(struct libnetapi_ctx
*ctx
,
374 struct NetGroupDel
*r
)
376 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupDel
);
379 /****************************************************************
380 ****************************************************************/
382 WERROR
NetGroupSetInfo_r(struct libnetapi_ctx
*ctx
,
383 struct NetGroupSetInfo
*r
)
385 struct rpc_pipe_client
*pipe_cli
= NULL
;
388 struct policy_handle connect_handle
, domain_handle
, group_handle
;
389 struct lsa_String lsa_group_name
;
390 struct dom_sid2
*domain_sid
= NULL
;
392 struct samr_Ids rids
;
393 struct samr_Ids types
;
394 union samr_GroupInfo info
;
395 struct GROUP_INFO_0
*g0
;
396 struct GROUP_INFO_1
*g1
;
397 struct GROUP_INFO_2
*g2
;
398 struct GROUP_INFO_3
*g3
;
399 struct GROUP_INFO_1002
*g1002
;
400 struct GROUP_INFO_1005
*g1005
;
402 ZERO_STRUCT(connect_handle
);
403 ZERO_STRUCT(domain_handle
);
404 ZERO_STRUCT(group_handle
);
406 if (!r
->in
.group_name
) {
407 return WERR_INVALID_PARAM
;
410 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
411 &ndr_table_samr
.syntax_id
,
413 if (!W_ERROR_IS_OK(werr
)) {
417 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
418 SAMR_ACCESS_ENUM_DOMAINS
|
419 SAMR_ACCESS_LOOKUP_DOMAIN
,
420 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
424 if (!W_ERROR_IS_OK(werr
)) {
428 init_lsa_String(&lsa_group_name
, r
->in
.group_name
);
430 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
436 if (!NT_STATUS_IS_OK(status
)) {
437 werr
= ntstatus_to_werror(status
);
441 if (types
.ids
[0] != SID_NAME_DOM_GRP
) {
442 werr
= WERR_INVALID_DATATYPE
;
446 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
448 SAMR_GROUP_ACCESS_SET_INFO
|
449 SAMR_GROUP_ACCESS_LOOKUP_INFO
,
452 if (!NT_STATUS_IS_OK(status
)) {
453 werr
= ntstatus_to_werror(status
);
457 switch (r
->in
.level
) {
459 g0
= (struct GROUP_INFO_0
*)r
->in
.buffer
;
460 init_lsa_String(&info
.name
, g0
->grpi0_name
);
461 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
467 g1
= (struct GROUP_INFO_1
*)r
->in
.buffer
;
468 init_lsa_String(&info
.description
, g1
->grpi1_comment
);
469 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
471 GROUPINFODESCRIPTION
,
475 g2
= (struct GROUP_INFO_2
*)r
->in
.buffer
;
476 init_lsa_String(&info
.description
, g2
->grpi2_comment
);
477 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
479 GROUPINFODESCRIPTION
,
481 if (!NT_STATUS_IS_OK(status
)) {
482 werr
= ntstatus_to_werror(status
);
485 info
.attributes
.attributes
= g2
->grpi2_attributes
;
486 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
492 g3
= (struct GROUP_INFO_3
*)r
->in
.buffer
;
493 init_lsa_String(&info
.description
, g3
->grpi3_comment
);
494 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
496 GROUPINFODESCRIPTION
,
498 if (!NT_STATUS_IS_OK(status
)) {
499 werr
= ntstatus_to_werror(status
);
502 info
.attributes
.attributes
= g3
->grpi3_attributes
;
503 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
509 g1002
= (struct GROUP_INFO_1002
*)r
->in
.buffer
;
510 init_lsa_String(&info
.description
, g1002
->grpi1002_comment
);
511 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
513 GROUPINFODESCRIPTION
,
517 g1005
= (struct GROUP_INFO_1005
*)r
->in
.buffer
;
518 info
.attributes
.attributes
= g1005
->grpi1005_attributes
;
519 status
= rpccli_samr_SetGroupInfo(pipe_cli
, ctx
,
525 status
= NT_STATUS_INVALID_LEVEL
;
529 if (!NT_STATUS_IS_OK(status
)) {
530 werr
= ntstatus_to_werror(status
);
537 if (is_valid_policy_hnd(&group_handle
)) {
538 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
541 if (ctx
->disable_policy_handle_cache
) {
542 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
543 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
549 /****************************************************************
550 ****************************************************************/
552 WERROR
NetGroupSetInfo_l(struct libnetapi_ctx
*ctx
,
553 struct NetGroupSetInfo
*r
)
555 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupSetInfo
);
558 /****************************************************************
559 ****************************************************************/
561 static WERROR
map_group_info_to_buffer(TALLOC_CTX
*mem_ctx
,
563 struct samr_GroupInfoAll
*info
,
564 struct dom_sid2
*domain_sid
,
568 struct GROUP_INFO_0 info0
;
569 struct GROUP_INFO_1 info1
;
570 struct GROUP_INFO_2 info2
;
571 struct GROUP_INFO_3 info3
;
576 info0
.grpi0_name
= info
->name
.string
;
578 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, &info0
, sizeof(info0
));
582 info1
.grpi1_name
= info
->name
.string
;
583 info1
.grpi1_comment
= info
->description
.string
;
585 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, &info1
, sizeof(info1
));
589 info2
.grpi2_name
= info
->name
.string
;
590 info2
.grpi2_comment
= info
->description
.string
;
591 info2
.grpi2_group_id
= rid
;
592 info2
.grpi2_attributes
= info
->attributes
;
594 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, &info2
, sizeof(info2
));
598 if (!sid_compose(&sid
, domain_sid
, rid
)) {
602 info3
.grpi3_name
= info
->name
.string
;
603 info3
.grpi3_comment
= info
->description
.string
;
604 info3
.grpi3_attributes
= info
->attributes
;
605 info3
.grpi3_group_sid
= (struct domsid
*)sid_dup_talloc(mem_ctx
, &sid
);
607 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, &info3
, sizeof(info3
));
611 return WERR_UNKNOWN_LEVEL
;
614 W_ERROR_HAVE_NO_MEMORY(*buffer
);
619 /****************************************************************
620 ****************************************************************/
622 WERROR
NetGroupGetInfo_r(struct libnetapi_ctx
*ctx
,
623 struct NetGroupGetInfo
*r
)
625 struct rpc_pipe_client
*pipe_cli
= NULL
;
628 struct policy_handle connect_handle
, domain_handle
, group_handle
;
629 struct lsa_String lsa_group_name
;
630 struct dom_sid2
*domain_sid
= NULL
;
632 struct samr_Ids rids
;
633 struct samr_Ids types
;
634 union samr_GroupInfo
*info
= NULL
;
635 bool group_info_all
= false;
637 ZERO_STRUCT(connect_handle
);
638 ZERO_STRUCT(domain_handle
);
639 ZERO_STRUCT(group_handle
);
641 if (!r
->in
.group_name
) {
642 return WERR_INVALID_PARAM
;
645 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
646 &ndr_table_samr
.syntax_id
,
648 if (!W_ERROR_IS_OK(werr
)) {
652 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
653 SAMR_ACCESS_ENUM_DOMAINS
|
654 SAMR_ACCESS_LOOKUP_DOMAIN
,
655 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
659 if (!W_ERROR_IS_OK(werr
)) {
663 init_lsa_String(&lsa_group_name
, r
->in
.group_name
);
665 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
671 if (!NT_STATUS_IS_OK(status
)) {
672 werr
= ntstatus_to_werror(status
);
676 if (types
.ids
[0] != SID_NAME_DOM_GRP
) {
677 werr
= WERR_INVALID_DATATYPE
;
681 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
683 SAMR_GROUP_ACCESS_LOOKUP_INFO
,
686 if (!NT_STATUS_IS_OK(status
)) {
687 werr
= ntstatus_to_werror(status
);
691 status
= rpccli_samr_QueryGroupInfo(pipe_cli
, ctx
,
695 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_INFO_CLASS
)) {
696 status
= rpccli_samr_QueryGroupInfo(pipe_cli
, ctx
,
700 group_info_all
= true;
703 if (!NT_STATUS_IS_OK(status
)) {
704 werr
= ntstatus_to_werror(status
);
708 werr
= map_group_info_to_buffer(ctx
, r
->in
.level
,
709 group_info_all
? &info
->all
: &info
->all2
,
710 domain_sid
, rids
.ids
[0],
712 if (!W_ERROR_IS_OK(werr
)) {
716 if (is_valid_policy_hnd(&group_handle
)) {
717 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
720 if (ctx
->disable_policy_handle_cache
) {
721 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
722 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
728 /****************************************************************
729 ****************************************************************/
731 WERROR
NetGroupGetInfo_l(struct libnetapi_ctx
*ctx
,
732 struct NetGroupGetInfo
*r
)
734 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupGetInfo
);
737 /****************************************************************
738 ****************************************************************/
740 WERROR
NetGroupAddUser_r(struct libnetapi_ctx
*ctx
,
741 struct NetGroupAddUser
*r
)
743 struct rpc_pipe_client
*pipe_cli
= NULL
;
746 struct policy_handle connect_handle
, domain_handle
, group_handle
;
747 struct lsa_String lsa_group_name
, lsa_user_name
;
748 struct dom_sid2
*domain_sid
= NULL
;
750 struct samr_Ids rids
;
751 struct samr_Ids types
;
753 ZERO_STRUCT(connect_handle
);
754 ZERO_STRUCT(domain_handle
);
755 ZERO_STRUCT(group_handle
);
757 if (!r
->in
.group_name
) {
758 return WERR_INVALID_PARAM
;
761 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
762 &ndr_table_samr
.syntax_id
,
764 if (!W_ERROR_IS_OK(werr
)) {
768 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
769 SAMR_ACCESS_ENUM_DOMAINS
|
770 SAMR_ACCESS_LOOKUP_DOMAIN
,
771 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
775 if (!W_ERROR_IS_OK(werr
)) {
779 init_lsa_String(&lsa_group_name
, r
->in
.group_name
);
781 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
787 if (!NT_STATUS_IS_OK(status
)) {
788 werr
= WERR_GROUPNOTFOUND
;
792 if (types
.ids
[0] != SID_NAME_DOM_GRP
) {
793 werr
= WERR_GROUPNOTFOUND
;
797 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
799 SAMR_GROUP_ACCESS_ADD_MEMBER
,
802 if (!NT_STATUS_IS_OK(status
)) {
803 werr
= ntstatus_to_werror(status
);
807 init_lsa_String(&lsa_user_name
, r
->in
.user_name
);
809 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
815 if (!NT_STATUS_IS_OK(status
)) {
816 werr
= WERR_USER_NOT_FOUND
;
820 if (types
.ids
[0] != SID_NAME_USER
) {
821 werr
= WERR_USER_NOT_FOUND
;
825 status
= rpccli_samr_AddGroupMember(pipe_cli
, ctx
,
829 if (!NT_STATUS_IS_OK(status
)) {
830 werr
= ntstatus_to_werror(status
);
837 if (is_valid_policy_hnd(&group_handle
)) {
838 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
841 if (ctx
->disable_policy_handle_cache
) {
842 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
843 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
849 /****************************************************************
850 ****************************************************************/
852 WERROR
NetGroupAddUser_l(struct libnetapi_ctx
*ctx
,
853 struct NetGroupAddUser
*r
)
855 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupAddUser
);
858 /****************************************************************
859 ****************************************************************/
861 WERROR
NetGroupDelUser_r(struct libnetapi_ctx
*ctx
,
862 struct NetGroupDelUser
*r
)
864 struct rpc_pipe_client
*pipe_cli
= NULL
;
867 struct policy_handle connect_handle
, domain_handle
, group_handle
;
868 struct lsa_String lsa_group_name
, lsa_user_name
;
869 struct dom_sid2
*domain_sid
= NULL
;
871 struct samr_Ids rids
;
872 struct samr_Ids types
;
874 ZERO_STRUCT(connect_handle
);
875 ZERO_STRUCT(domain_handle
);
876 ZERO_STRUCT(group_handle
);
878 if (!r
->in
.group_name
) {
879 return WERR_INVALID_PARAM
;
882 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
883 &ndr_table_samr
.syntax_id
,
885 if (!W_ERROR_IS_OK(werr
)) {
889 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
890 SAMR_ACCESS_ENUM_DOMAINS
|
891 SAMR_ACCESS_LOOKUP_DOMAIN
,
892 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
896 if (!W_ERROR_IS_OK(werr
)) {
900 init_lsa_String(&lsa_group_name
, r
->in
.group_name
);
902 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
908 if (!NT_STATUS_IS_OK(status
)) {
909 werr
= WERR_GROUPNOTFOUND
;
913 if (types
.ids
[0] != SID_NAME_DOM_GRP
) {
914 werr
= WERR_GROUPNOTFOUND
;
918 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
920 SAMR_GROUP_ACCESS_REMOVE_MEMBER
,
923 if (!NT_STATUS_IS_OK(status
)) {
924 werr
= ntstatus_to_werror(status
);
928 init_lsa_String(&lsa_user_name
, r
->in
.user_name
);
930 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
936 if (!NT_STATUS_IS_OK(status
)) {
937 werr
= WERR_USER_NOT_FOUND
;
941 if (types
.ids
[0] != SID_NAME_USER
) {
942 werr
= WERR_USER_NOT_FOUND
;
946 status
= rpccli_samr_DeleteGroupMember(pipe_cli
, ctx
,
949 if (!NT_STATUS_IS_OK(status
)) {
950 werr
= ntstatus_to_werror(status
);
957 if (is_valid_policy_hnd(&group_handle
)) {
958 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
961 if (ctx
->disable_policy_handle_cache
) {
962 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
963 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
969 /****************************************************************
970 ****************************************************************/
972 WERROR
NetGroupDelUser_l(struct libnetapi_ctx
*ctx
,
973 struct NetGroupDelUser
*r
)
975 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupDelUser
);
978 /****************************************************************
979 ****************************************************************/
981 static WERROR
convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX
*mem_ctx
,
982 struct samr_DispInfoFullGroups
*groups
,
985 struct GROUP_INFO_0
*g0
;
988 g0
= TALLOC_ZERO_ARRAY(mem_ctx
, struct GROUP_INFO_0
, groups
->count
);
989 W_ERROR_HAVE_NO_MEMORY(g0
);
991 for (i
=0; i
<groups
->count
; i
++) {
992 g0
[i
].grpi0_name
= talloc_strdup(mem_ctx
,
993 groups
->entries
[i
].account_name
.string
);
994 W_ERROR_HAVE_NO_MEMORY(g0
[i
].grpi0_name
);
997 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, g0
,
998 sizeof(struct GROUP_INFO_0
) * groups
->count
);
999 W_ERROR_HAVE_NO_MEMORY(*buffer
);
1004 /****************************************************************
1005 ****************************************************************/
1007 static WERROR
convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX
*mem_ctx
,
1008 struct samr_DispInfoFullGroups
*groups
,
1011 struct GROUP_INFO_1
*g1
;
1014 g1
= TALLOC_ZERO_ARRAY(mem_ctx
, struct GROUP_INFO_1
, groups
->count
);
1015 W_ERROR_HAVE_NO_MEMORY(g1
);
1017 for (i
=0; i
<groups
->count
; i
++) {
1018 g1
[i
].grpi1_name
= talloc_strdup(mem_ctx
,
1019 groups
->entries
[i
].account_name
.string
);
1020 g1
[i
].grpi1_comment
= talloc_strdup(mem_ctx
,
1021 groups
->entries
[i
].description
.string
);
1022 W_ERROR_HAVE_NO_MEMORY(g1
[i
].grpi1_name
);
1025 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, g1
,
1026 sizeof(struct GROUP_INFO_1
) * groups
->count
);
1027 W_ERROR_HAVE_NO_MEMORY(*buffer
);
1032 /****************************************************************
1033 ****************************************************************/
1035 static WERROR
convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX
*mem_ctx
,
1036 struct samr_DispInfoFullGroups
*groups
,
1039 struct GROUP_INFO_2
*g2
;
1042 g2
= TALLOC_ZERO_ARRAY(mem_ctx
, struct GROUP_INFO_2
, groups
->count
);
1043 W_ERROR_HAVE_NO_MEMORY(g2
);
1045 for (i
=0; i
<groups
->count
; i
++) {
1046 g2
[i
].grpi2_name
= talloc_strdup(mem_ctx
,
1047 groups
->entries
[i
].account_name
.string
);
1048 g2
[i
].grpi2_comment
= talloc_strdup(mem_ctx
,
1049 groups
->entries
[i
].description
.string
);
1050 g2
[i
].grpi2_group_id
= groups
->entries
[i
].rid
;
1051 g2
[i
].grpi2_attributes
= groups
->entries
[i
].acct_flags
;
1052 W_ERROR_HAVE_NO_MEMORY(g2
[i
].grpi2_name
);
1055 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, g2
,
1056 sizeof(struct GROUP_INFO_2
) * groups
->count
);
1057 W_ERROR_HAVE_NO_MEMORY(*buffer
);
1062 /****************************************************************
1063 ****************************************************************/
1065 static WERROR
convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX
*mem_ctx
,
1066 struct samr_DispInfoFullGroups
*groups
,
1067 const struct dom_sid
*domain_sid
,
1070 struct GROUP_INFO_3
*g3
;
1073 g3
= TALLOC_ZERO_ARRAY(mem_ctx
, struct GROUP_INFO_3
, groups
->count
);
1074 W_ERROR_HAVE_NO_MEMORY(g3
);
1076 for (i
=0; i
<groups
->count
; i
++) {
1080 if (!sid_compose(&sid
, domain_sid
, groups
->entries
[i
].rid
)) {
1084 g3
[i
].grpi3_name
= talloc_strdup(mem_ctx
,
1085 groups
->entries
[i
].account_name
.string
);
1086 g3
[i
].grpi3_comment
= talloc_strdup(mem_ctx
,
1087 groups
->entries
[i
].description
.string
);
1088 g3
[i
].grpi3_group_sid
= (struct domsid
*)sid_dup_talloc(mem_ctx
, &sid
);
1089 g3
[i
].grpi3_attributes
= groups
->entries
[i
].acct_flags
;
1090 W_ERROR_HAVE_NO_MEMORY(g3
[i
].grpi3_name
);
1093 *buffer
= (uint8_t *)talloc_memdup(mem_ctx
, g3
,
1094 sizeof(struct GROUP_INFO_3
) * groups
->count
);
1095 W_ERROR_HAVE_NO_MEMORY(*buffer
);
1100 /****************************************************************
1101 ****************************************************************/
1103 static WERROR
convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX
*mem_ctx
,
1105 struct samr_DispInfoFullGroups
*groups
,
1106 const struct dom_sid
*domain_sid
,
1107 uint32_t *entries_read
,
1111 *entries_read
= groups
->count
;
1116 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx
, groups
, buffer
);
1118 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx
, groups
, buffer
);
1120 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx
, groups
, buffer
);
1122 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx
, groups
, domain_sid
, buffer
);
1124 return WERR_UNKNOWN_LEVEL
;
1128 /****************************************************************
1129 ****************************************************************/
1131 WERROR
NetGroupEnum_r(struct libnetapi_ctx
*ctx
,
1132 struct NetGroupEnum
*r
)
1134 struct rpc_pipe_client
*pipe_cli
= NULL
;
1135 struct policy_handle connect_handle
;
1136 struct dom_sid2
*domain_sid
= NULL
;
1137 struct policy_handle domain_handle
;
1138 union samr_DispInfo info
;
1139 union samr_DomainInfo
*domain_info
= NULL
;
1141 uint32_t total_size
= 0;
1142 uint32_t returned_size
= 0;
1144 NTSTATUS status
= NT_STATUS_OK
;
1145 WERROR werr
, tmp_werr
;
1147 ZERO_STRUCT(connect_handle
);
1148 ZERO_STRUCT(domain_handle
);
1150 switch (r
->in
.level
) {
1157 return WERR_UNKNOWN_LEVEL
;
1160 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
1161 &ndr_table_samr
.syntax_id
,
1163 if (!W_ERROR_IS_OK(werr
)) {
1167 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
1168 SAMR_ACCESS_ENUM_DOMAINS
|
1169 SAMR_ACCESS_LOOKUP_DOMAIN
,
1170 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2
|
1171 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
|
1172 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
1176 if (!W_ERROR_IS_OK(werr
)) {
1180 status
= rpccli_samr_QueryDomainInfo(pipe_cli
, ctx
,
1184 if (!NT_STATUS_IS_OK(status
)) {
1185 werr
= ntstatus_to_werror(status
);
1189 if (r
->out
.total_entries
) {
1190 *r
->out
.total_entries
= domain_info
->general
.num_groups
;
1193 status
= rpccli_samr_QueryDisplayInfo2(pipe_cli
,
1197 r
->in
.resume_handle
?
1198 *r
->in
.resume_handle
: 0,
1204 werr
= ntstatus_to_werror(status
);
1205 if (NT_STATUS_IS_ERR(status
)) {
1209 if (r
->out
.resume_handle
&& info
.info3
.count
> 0) {
1210 *r
->out
.resume_handle
=
1211 info
.info3
.entries
[info
.info3
.count
-1].idx
;
1214 tmp_werr
= convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx
,
1218 r
->out
.entries_read
,
1220 if (!W_ERROR_IS_OK(tmp_werr
)) {
1227 if (NT_STATUS_IS_OK(status
) ||
1228 NT_STATUS_IS_ERR(status
)) {
1230 if (ctx
->disable_policy_handle_cache
) {
1231 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
1232 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
1239 /****************************************************************
1240 ****************************************************************/
1242 WERROR
NetGroupEnum_l(struct libnetapi_ctx
*ctx
,
1243 struct NetGroupEnum
*r
)
1245 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupEnum
);
1248 /****************************************************************
1249 ****************************************************************/
1251 WERROR
NetGroupGetUsers_r(struct libnetapi_ctx
*ctx
,
1252 struct NetGroupGetUsers
*r
)
1254 /* FIXME: this call needs to cope with large replies */
1256 struct rpc_pipe_client
*pipe_cli
= NULL
;
1257 struct policy_handle connect_handle
, domain_handle
, group_handle
;
1258 struct lsa_String lsa_account_name
;
1259 struct dom_sid2
*domain_sid
= NULL
;
1260 struct samr_Ids group_rids
, name_types
;
1261 struct samr_RidTypeArray
*rid_array
= NULL
;
1262 struct lsa_Strings names
;
1263 struct samr_Ids member_types
;
1266 uint32_t entries_read
= 0;
1268 NTSTATUS status
= NT_STATUS_OK
;
1271 ZERO_STRUCT(connect_handle
);
1272 ZERO_STRUCT(domain_handle
);
1274 if (!r
->out
.buffer
) {
1275 return WERR_INVALID_PARAM
;
1278 *r
->out
.buffer
= NULL
;
1279 *r
->out
.entries_read
= 0;
1280 *r
->out
.total_entries
= 0;
1282 switch (r
->in
.level
) {
1287 return WERR_UNKNOWN_LEVEL
;
1291 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
1292 &ndr_table_samr
.syntax_id
,
1294 if (!W_ERROR_IS_OK(werr
)) {
1298 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
1299 SAMR_ACCESS_ENUM_DOMAINS
|
1300 SAMR_ACCESS_LOOKUP_DOMAIN
,
1301 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
1305 if (!W_ERROR_IS_OK(werr
)) {
1309 init_lsa_String(&lsa_account_name
, r
->in
.group_name
);
1311 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
1317 if (!NT_STATUS_IS_OK(status
)) {
1318 werr
= ntstatus_to_werror(status
);
1322 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
1324 SAMR_GROUP_ACCESS_GET_MEMBERS
,
1327 if (!NT_STATUS_IS_OK(status
)) {
1328 werr
= ntstatus_to_werror(status
);
1332 status
= rpccli_samr_QueryGroupMember(pipe_cli
, ctx
,
1335 if (!NT_STATUS_IS_OK(status
)) {
1336 werr
= ntstatus_to_werror(status
);
1340 status
= rpccli_samr_LookupRids(pipe_cli
, ctx
,
1346 if (!NT_STATUS_IS_OK(status
)) {
1347 werr
= ntstatus_to_werror(status
);
1351 for (i
=0; i
< names
.count
; i
++) {
1353 if (member_types
.ids
[i
] != SID_NAME_USER
) {
1357 status
= add_GROUP_USERS_INFO_X_buffer(ctx
,
1359 names
.names
[i
].string
,
1363 if (!NT_STATUS_IS_OK(status
)) {
1364 werr
= ntstatus_to_werror(status
);
1369 *r
->out
.entries_read
= entries_read
;
1370 *r
->out
.total_entries
= entries_read
;
1375 if (is_valid_policy_hnd(&group_handle
)) {
1376 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
1379 if (ctx
->disable_policy_handle_cache
) {
1380 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
1381 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
1387 /****************************************************************
1388 ****************************************************************/
1390 WERROR
NetGroupGetUsers_l(struct libnetapi_ctx
*ctx
,
1391 struct NetGroupGetUsers
*r
)
1393 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupGetUsers
);
1396 /****************************************************************
1397 ****************************************************************/
1399 WERROR
NetGroupSetUsers_r(struct libnetapi_ctx
*ctx
,
1400 struct NetGroupSetUsers
*r
)
1402 struct rpc_pipe_client
*pipe_cli
= NULL
;
1403 struct policy_handle connect_handle
, domain_handle
, group_handle
;
1404 struct lsa_String lsa_account_name
;
1405 struct dom_sid2
*domain_sid
= NULL
;
1406 union samr_GroupInfo
*group_info
= NULL
;
1407 struct samr_Ids user_rids
, name_types
;
1408 struct samr_Ids group_rids
, group_types
;
1409 struct samr_RidTypeArray
*rid_array
= NULL
;
1410 struct lsa_String
*lsa_names
= NULL
;
1412 uint32_t *add_rids
= NULL
;
1413 uint32_t *del_rids
= NULL
;
1414 size_t num_add_rids
= 0;
1415 size_t num_del_rids
= 0;
1417 uint32_t *member_rids
= NULL
;
1418 size_t num_member_rids
= 0;
1420 struct GROUP_USERS_INFO_0
*i0
= NULL
;
1421 struct GROUP_USERS_INFO_1
*i1
= NULL
;
1425 NTSTATUS status
= NT_STATUS_OK
;
1428 ZERO_STRUCT(connect_handle
);
1429 ZERO_STRUCT(domain_handle
);
1431 if (!r
->in
.buffer
) {
1432 return WERR_INVALID_PARAM
;
1435 switch (r
->in
.level
) {
1440 return WERR_UNKNOWN_LEVEL
;
1443 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
1444 &ndr_table_samr
.syntax_id
,
1446 if (!W_ERROR_IS_OK(werr
)) {
1450 werr
= libnetapi_samr_open_domain(ctx
, pipe_cli
,
1451 SAMR_ACCESS_ENUM_DOMAINS
|
1452 SAMR_ACCESS_LOOKUP_DOMAIN
,
1453 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
1457 if (!W_ERROR_IS_OK(werr
)) {
1461 init_lsa_String(&lsa_account_name
, r
->in
.group_name
);
1463 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
1469 if (!NT_STATUS_IS_OK(status
)) {
1470 werr
= ntstatus_to_werror(status
);
1474 status
= rpccli_samr_OpenGroup(pipe_cli
, ctx
,
1476 SAMR_GROUP_ACCESS_GET_MEMBERS
|
1477 SAMR_GROUP_ACCESS_ADD_MEMBER
|
1478 SAMR_GROUP_ACCESS_REMOVE_MEMBER
|
1479 SAMR_GROUP_ACCESS_LOOKUP_INFO
,
1482 if (!NT_STATUS_IS_OK(status
)) {
1483 werr
= ntstatus_to_werror(status
);
1487 status
= rpccli_samr_QueryGroupInfo(pipe_cli
, ctx
,
1489 GROUPINFOATTRIBUTES
,
1491 if (!NT_STATUS_IS_OK(status
)) {
1492 werr
= ntstatus_to_werror(status
);
1496 switch (r
->in
.level
) {
1498 i0
= (struct GROUP_USERS_INFO_0
*)r
->in
.buffer
;
1501 i1
= (struct GROUP_USERS_INFO_1
*)r
->in
.buffer
;
1505 lsa_names
= talloc_array(ctx
, struct lsa_String
, r
->in
.num_entries
);
1511 for (i
=0; i
< r
->in
.num_entries
; i
++) {
1513 switch (r
->in
.level
) {
1515 init_lsa_String(&lsa_names
[i
], i0
->grui0_name
);
1519 init_lsa_String(&lsa_names
[i
], i1
->grui1_name
);
1525 status
= rpccli_samr_LookupNames(pipe_cli
, ctx
,
1531 if (!NT_STATUS_IS_OK(status
)) {
1532 werr
= ntstatus_to_werror(status
);
1536 member_rids
= user_rids
.ids
;
1537 num_member_rids
= user_rids
.count
;
1539 status
= rpccli_samr_QueryGroupMember(pipe_cli
, ctx
,
1542 if (!NT_STATUS_IS_OK(status
)) {
1543 werr
= ntstatus_to_werror(status
);
1549 for (i
=0; i
< r
->in
.num_entries
; i
++) {
1550 bool already_member
= false;
1551 for (k
=0; k
< rid_array
->count
; k
++) {
1552 if (member_rids
[i
] == rid_array
->rids
[k
]) {
1553 already_member
= true;
1557 if (!already_member
) {
1558 if (!add_rid_to_array_unique(ctx
,
1560 &add_rids
, &num_add_rids
)) {
1561 werr
= WERR_GENERAL_FAILURE
;
1569 for (k
=0; k
< rid_array
->count
; k
++) {
1570 bool keep_member
= false;
1571 for (i
=0; i
< r
->in
.num_entries
; i
++) {
1572 if (member_rids
[i
] == rid_array
->rids
[k
]) {
1578 if (!add_rid_to_array_unique(ctx
,
1580 &del_rids
, &num_del_rids
)) {
1581 werr
= WERR_GENERAL_FAILURE
;
1589 for (i
=0; i
< num_add_rids
; i
++) {
1590 status
= rpccli_samr_AddGroupMember(pipe_cli
, ctx
,
1594 if (!NT_STATUS_IS_OK(status
)) {
1595 werr
= ntstatus_to_werror(status
);
1602 for (i
=0; i
< num_del_rids
; i
++) {
1603 status
= rpccli_samr_DeleteGroupMember(pipe_cli
, ctx
,
1606 if (!NT_STATUS_IS_OK(status
)) {
1607 werr
= ntstatus_to_werror(status
);
1615 if (is_valid_policy_hnd(&group_handle
)) {
1616 rpccli_samr_Close(pipe_cli
, ctx
, &group_handle
);
1619 if (ctx
->disable_policy_handle_cache
) {
1620 libnetapi_samr_close_domain_handle(ctx
, &domain_handle
);
1621 libnetapi_samr_close_connect_handle(ctx
, &connect_handle
);
1627 /****************************************************************
1628 ****************************************************************/
1630 WERROR
NetGroupSetUsers_l(struct libnetapi_ctx
*ctx
,
1631 struct NetGroupSetUsers
*r
)
1633 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetGroupSetUsers
);