Refactoring: libnetapi_open_pipe takes an interface instead of pipe_idx
[Samba/wip.git] / source3 / lib / netapi / group.c
blob04ffb7c8074fe450bf2a84ed65a52c0923f19359
1 /*
2 * Unix SMB/CIFS implementation.
3 * NetApi Group Support
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/>.
20 #include "includes.h"
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;
35 NTSTATUS status;
36 WERROR werr;
37 POLICY_HND connect_handle, domain_handle, group_handle;
38 struct lsa_String lsa_group_name;
39 struct dom_sid2 *domain_sid = NULL;
40 uint32_t rid = 0;
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);
52 if (!r->in.buf) {
53 return WERR_INVALID_PARAM;
56 switch (r->in.level) {
57 case 0:
58 info0 = (struct GROUP_INFO_0 *)r->in.buf;
59 break;
60 case 1:
61 info1 = (struct GROUP_INFO_1 *)r->in.buf;
62 break;
63 case 2:
64 info2 = (struct GROUP_INFO_2 *)r->in.buf;
65 break;
66 case 3:
67 info3 = (struct GROUP_INFO_3 *)r->in.buf;
68 break;
69 default:
70 werr = WERR_UNKNOWN_LEVEL;
71 goto done;
74 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
75 if (!W_ERROR_IS_OK(werr)) {
76 goto done;
79 werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
80 &pipe_cli);
81 if (!W_ERROR_IS_OK(werr)) {
82 goto done;
85 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
86 SAMR_ACCESS_ENUM_DOMAINS |
87 SAMR_ACCESS_OPEN_DOMAIN,
88 SAMR_DOMAIN_ACCESS_CREATE_GROUP |
89 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
90 &connect_handle,
91 &domain_handle,
92 &domain_sid);
93 if (!W_ERROR_IS_OK(werr)) {
94 goto done;
97 switch (r->in.level) {
98 case 0:
99 init_lsa_String(&lsa_group_name, info0->grpi0_name);
100 break;
101 case 1:
102 init_lsa_String(&lsa_group_name, info1->grpi1_name);
103 break;
104 case 2:
105 init_lsa_String(&lsa_group_name, info2->grpi2_name);
106 break;
107 case 3:
108 init_lsa_String(&lsa_group_name, info3->grpi3_name);
109 break;
112 status = rpccli_samr_CreateDomainGroup(pipe_cli, ctx,
113 &domain_handle,
114 &lsa_group_name,
115 SEC_STD_DELETE |
116 SAMR_GROUP_ACCESS_SET_INFO,
117 &group_handle,
118 &rid);
120 if (!NT_STATUS_IS_OK(status)) {
121 werr = ntstatus_to_werror(status);
122 goto done;
125 switch (r->in.level) {
126 case 1:
127 if (info1->grpi1_comment) {
128 init_lsa_String(&info.description,
129 info1->grpi1_comment);
131 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
132 &group_handle,
133 GROUPINFODESCRIPTION,
134 &info);
136 break;
137 case 2:
138 if (info2->grpi2_comment) {
139 init_lsa_String(&info.description,
140 info2->grpi2_comment);
142 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
143 &group_handle,
144 GROUPINFODESCRIPTION,
145 &info);
146 if (!NT_STATUS_IS_OK(status)) {
147 werr = ntstatus_to_werror(status);
148 goto failed;
152 if (info2->grpi2_attributes != 0) {
153 info.attributes.attributes = info2->grpi2_attributes;
154 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
155 &group_handle,
156 GROUPINFOATTRIBUTES,
157 &info);
160 break;
161 case 3:
162 if (info3->grpi3_comment) {
163 init_lsa_String(&info.description,
164 info3->grpi3_comment);
166 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
167 &group_handle,
168 GROUPINFODESCRIPTION,
169 &info);
170 if (!NT_STATUS_IS_OK(status)) {
171 werr = ntstatus_to_werror(status);
172 goto failed;
176 if (info3->grpi3_attributes != 0) {
177 info.attributes.attributes = info3->grpi3_attributes;
178 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
179 &group_handle,
180 GROUPINFOATTRIBUTES,
181 &info);
183 break;
184 default:
185 break;
188 if (!NT_STATUS_IS_OK(status)) {
189 werr = ntstatus_to_werror(status);
190 goto failed;
193 werr = WERR_OK;
194 goto done;
196 failed:
197 rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
198 &group_handle);
200 done:
201 if (!cli) {
202 return werr;
205 if (is_valid_policy_hnd(&group_handle)) {
206 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
209 if (ctx->disable_policy_handle_cache) {
210 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
211 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
214 return werr;
217 /****************************************************************
218 ****************************************************************/
220 WERROR NetGroupAdd_l(struct libnetapi_ctx *ctx,
221 struct NetGroupAdd *r)
223 return NetGroupAdd_r(ctx, r);
226 /****************************************************************
227 ****************************************************************/
229 WERROR NetGroupDel_r(struct libnetapi_ctx *ctx,
230 struct NetGroupDel *r)
232 struct cli_state *cli = NULL;
233 struct rpc_pipe_client *pipe_cli = NULL;
234 NTSTATUS status;
235 WERROR werr;
236 POLICY_HND connect_handle, domain_handle, group_handle;
237 struct lsa_String lsa_group_name;
238 struct dom_sid2 *domain_sid = NULL;
239 int i = 0;
241 struct samr_Ids rids;
242 struct samr_Ids types;
243 union samr_GroupInfo *info = NULL;
244 struct samr_RidTypeArray *rid_array = NULL;
246 ZERO_STRUCT(connect_handle);
247 ZERO_STRUCT(domain_handle);
248 ZERO_STRUCT(group_handle);
250 if (!r->in.group_name) {
251 return WERR_INVALID_PARAM;
254 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
255 if (!W_ERROR_IS_OK(werr)) {
256 goto done;
259 werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
260 &pipe_cli);
261 if (!W_ERROR_IS_OK(werr)) {
262 goto done;
265 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
266 SAMR_ACCESS_ENUM_DOMAINS |
267 SAMR_ACCESS_OPEN_DOMAIN,
268 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
269 &connect_handle,
270 &domain_handle,
271 &domain_sid);
272 if (!W_ERROR_IS_OK(werr)) {
273 goto done;
276 init_lsa_String(&lsa_group_name, r->in.group_name);
278 status = rpccli_samr_LookupNames(pipe_cli, ctx,
279 &domain_handle,
281 &lsa_group_name,
282 &rids,
283 &types);
284 if (!NT_STATUS_IS_OK(status)) {
285 werr = ntstatus_to_werror(status);
286 goto done;
289 if (types.ids[0] != SID_NAME_DOM_GRP) {
290 werr = WERR_INVALID_DATATYPE;
291 goto done;
294 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
295 &domain_handle,
296 SEC_STD_DELETE |
297 SAMR_GROUP_ACCESS_GET_MEMBERS |
298 SAMR_GROUP_ACCESS_REMOVE_MEMBER |
299 SAMR_GROUP_ACCESS_ADD_MEMBER |
300 SAMR_GROUP_ACCESS_LOOKUP_INFO,
301 rids.ids[0],
302 &group_handle);
303 if (!NT_STATUS_IS_OK(status)) {
304 werr = ntstatus_to_werror(status);
305 goto done;
308 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
309 &group_handle,
310 GROUPINFOATTRIBUTES,
311 &info);
312 if (!NT_STATUS_IS_OK(status)) {
313 werr = ntstatus_to_werror(status);
314 goto done;
317 #if 0
318 /* breaks against NT4 */
319 if (!(info->attributes.attributes & SE_GROUP_ENABLED)) {
320 werr = WERR_ACCESS_DENIED;
321 goto done;
323 #endif
324 status = rpccli_samr_QueryGroupMember(pipe_cli, ctx,
325 &group_handle,
326 &rid_array);
327 if (!NT_STATUS_IS_OK(status)) {
328 werr = ntstatus_to_werror(status);
329 goto done;
333 struct lsa_Strings names;
334 struct samr_Ids member_types;
336 status = rpccli_samr_LookupRids(pipe_cli, ctx,
337 &domain_handle,
338 rid_array->count,
339 rid_array->rids,
340 &names,
341 &member_types);
342 if (!NT_STATUS_IS_OK(status)) {
343 werr = ntstatus_to_werror(status);
344 goto done;
348 for (i=0; i < rid_array->count; i++) {
350 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
351 &group_handle,
352 rid_array->rids[i]);
353 if (!NT_STATUS_IS_OK(status)) {
354 werr = ntstatus_to_werror(status);
355 goto done;
359 status = rpccli_samr_DeleteDomainGroup(pipe_cli, ctx,
360 &group_handle);
361 if (!NT_STATUS_IS_OK(status)) {
362 werr = ntstatus_to_werror(status);
363 goto done;
366 ZERO_STRUCT(group_handle);
368 werr = WERR_OK;
370 done:
371 if (!cli) {
372 return werr;
375 if (is_valid_policy_hnd(&group_handle)) {
376 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
379 if (ctx->disable_policy_handle_cache) {
380 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
381 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
384 return werr;
387 /****************************************************************
388 ****************************************************************/
390 WERROR NetGroupDel_l(struct libnetapi_ctx *ctx,
391 struct NetGroupDel *r)
393 return NetGroupDel_r(ctx, r);
396 /****************************************************************
397 ****************************************************************/
399 WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx,
400 struct NetGroupSetInfo *r)
402 struct cli_state *cli = NULL;
403 struct rpc_pipe_client *pipe_cli = NULL;
404 NTSTATUS status;
405 WERROR werr;
406 POLICY_HND connect_handle, domain_handle, group_handle;
407 struct lsa_String lsa_group_name;
408 struct dom_sid2 *domain_sid = NULL;
410 struct samr_Ids rids;
411 struct samr_Ids types;
412 union samr_GroupInfo info;
413 struct GROUP_INFO_0 *g0;
414 struct GROUP_INFO_1 *g1;
415 struct GROUP_INFO_2 *g2;
416 struct GROUP_INFO_3 *g3;
417 struct GROUP_INFO_1002 *g1002;
418 struct GROUP_INFO_1005 *g1005;
420 ZERO_STRUCT(connect_handle);
421 ZERO_STRUCT(domain_handle);
422 ZERO_STRUCT(group_handle);
424 if (!r->in.group_name) {
425 return WERR_INVALID_PARAM;
428 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
429 if (!W_ERROR_IS_OK(werr)) {
430 goto done;
433 werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
434 &pipe_cli);
435 if (!W_ERROR_IS_OK(werr)) {
436 goto done;
439 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
440 SAMR_ACCESS_ENUM_DOMAINS |
441 SAMR_ACCESS_OPEN_DOMAIN,
442 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
443 &connect_handle,
444 &domain_handle,
445 &domain_sid);
446 if (!W_ERROR_IS_OK(werr)) {
447 goto done;
450 init_lsa_String(&lsa_group_name, r->in.group_name);
452 status = rpccli_samr_LookupNames(pipe_cli, ctx,
453 &domain_handle,
455 &lsa_group_name,
456 &rids,
457 &types);
458 if (!NT_STATUS_IS_OK(status)) {
459 werr = ntstatus_to_werror(status);
460 goto done;
463 if (types.ids[0] != SID_NAME_DOM_GRP) {
464 werr = WERR_INVALID_DATATYPE;
465 goto done;
468 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
469 &domain_handle,
470 SAMR_GROUP_ACCESS_SET_INFO |
471 SAMR_GROUP_ACCESS_LOOKUP_INFO,
472 rids.ids[0],
473 &group_handle);
474 if (!NT_STATUS_IS_OK(status)) {
475 werr = ntstatus_to_werror(status);
476 goto done;
479 switch (r->in.level) {
480 case 0:
481 g0 = (struct GROUP_INFO_0 *)r->in.buf;
482 init_lsa_String(&info.name, g0->grpi0_name);
483 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
484 &group_handle,
485 GROUPINFONAME,
486 &info);
487 break;
488 case 1:
489 g1 = (struct GROUP_INFO_1 *)r->in.buf;
490 init_lsa_String(&info.description, g1->grpi1_comment);
491 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
492 &group_handle,
493 GROUPINFODESCRIPTION,
494 &info);
495 break;
496 case 2:
497 g2 = (struct GROUP_INFO_2 *)r->in.buf;
498 init_lsa_String(&info.description, g2->grpi2_comment);
499 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
500 &group_handle,
501 GROUPINFODESCRIPTION,
502 &info);
503 if (!NT_STATUS_IS_OK(status)) {
504 werr = ntstatus_to_werror(status);
505 goto done;
507 info.attributes.attributes = g2->grpi2_attributes;
508 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
509 &group_handle,
510 GROUPINFOATTRIBUTES,
511 &info);
512 break;
513 case 3:
514 g3 = (struct GROUP_INFO_3 *)r->in.buf;
515 init_lsa_String(&info.description, g3->grpi3_comment);
516 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
517 &group_handle,
518 GROUPINFODESCRIPTION,
519 &info);
520 if (!NT_STATUS_IS_OK(status)) {
521 werr = ntstatus_to_werror(status);
522 goto done;
524 info.attributes.attributes = g3->grpi3_attributes;
525 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
526 &group_handle,
527 GROUPINFOATTRIBUTES,
528 &info);
529 break;
530 case 1002:
531 g1002 = (struct GROUP_INFO_1002 *)r->in.buf;
532 init_lsa_String(&info.description, g1002->grpi1002_comment);
533 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
534 &group_handle,
535 GROUPINFODESCRIPTION,
536 &info);
537 break;
538 case 1005:
539 g1005 = (struct GROUP_INFO_1005 *)r->in.buf;
540 info.attributes.attributes = g1005->grpi1005_attributes;
541 status = rpccli_samr_SetGroupInfo(pipe_cli, ctx,
542 &group_handle,
543 GROUPINFOATTRIBUTES,
544 &info);
545 break;
546 default:
547 status = NT_STATUS_INVALID_LEVEL;
548 break;
551 if (!NT_STATUS_IS_OK(status)) {
552 werr = ntstatus_to_werror(status);
553 goto done;
556 werr = WERR_OK;
558 done:
559 if (!cli) {
560 return werr;
563 if (is_valid_policy_hnd(&group_handle)) {
564 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
567 if (ctx->disable_policy_handle_cache) {
568 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
569 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
572 return werr;
575 /****************************************************************
576 ****************************************************************/
578 WERROR NetGroupSetInfo_l(struct libnetapi_ctx *ctx,
579 struct NetGroupSetInfo *r)
581 return NetGroupSetInfo_r(ctx, r);
584 /****************************************************************
585 ****************************************************************/
587 static WERROR map_group_info_to_buffer(TALLOC_CTX *mem_ctx,
588 uint32_t level,
589 struct samr_GroupInfoAll *info,
590 struct dom_sid2 *domain_sid,
591 uint32_t rid,
592 uint8_t **buffer)
594 struct GROUP_INFO_0 info0;
595 struct GROUP_INFO_1 info1;
596 struct GROUP_INFO_2 info2;
597 struct GROUP_INFO_3 info3;
598 struct dom_sid sid;
600 switch (level) {
601 case 0:
602 info0.grpi0_name = info->name.string;
604 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0, sizeof(info0));
606 break;
607 case 1:
608 info1.grpi1_name = info->name.string;
609 info1.grpi1_comment = info->description.string;
611 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1, sizeof(info1));
613 break;
614 case 2:
615 info2.grpi2_name = info->name.string;
616 info2.grpi2_comment = info->description.string;
617 info2.grpi2_group_id = rid;
618 info2.grpi2_attributes = info->attributes;
620 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2, sizeof(info2));
622 break;
623 case 3:
624 if (!sid_compose(&sid, domain_sid, rid)) {
625 return WERR_NOMEM;
628 info3.grpi3_name = info->name.string;
629 info3.grpi3_comment = info->description.string;
630 info3.grpi3_attributes = info->attributes;
631 info3.grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
633 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3, sizeof(info3));
635 break;
636 default:
637 return WERR_UNKNOWN_LEVEL;
640 W_ERROR_HAVE_NO_MEMORY(*buffer);
642 return WERR_OK;
645 /****************************************************************
646 ****************************************************************/
648 WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx,
649 struct NetGroupGetInfo *r)
651 struct cli_state *cli = NULL;
652 struct rpc_pipe_client *pipe_cli = NULL;
653 NTSTATUS status;
654 WERROR werr;
655 POLICY_HND connect_handle, domain_handle, group_handle;
656 struct lsa_String lsa_group_name;
657 struct dom_sid2 *domain_sid = NULL;
659 struct samr_Ids rids;
660 struct samr_Ids types;
661 union samr_GroupInfo *info = NULL;
662 bool group_info_all = false;
664 ZERO_STRUCT(connect_handle);
665 ZERO_STRUCT(domain_handle);
666 ZERO_STRUCT(group_handle);
668 if (!r->in.group_name) {
669 return WERR_INVALID_PARAM;
672 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
673 if (!W_ERROR_IS_OK(werr)) {
674 goto done;
677 werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
678 &pipe_cli);
679 if (!W_ERROR_IS_OK(werr)) {
680 goto done;
683 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
684 SAMR_ACCESS_ENUM_DOMAINS |
685 SAMR_ACCESS_OPEN_DOMAIN,
686 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
687 &connect_handle,
688 &domain_handle,
689 &domain_sid);
690 if (!W_ERROR_IS_OK(werr)) {
691 goto done;
694 init_lsa_String(&lsa_group_name, r->in.group_name);
696 status = rpccli_samr_LookupNames(pipe_cli, ctx,
697 &domain_handle,
699 &lsa_group_name,
700 &rids,
701 &types);
702 if (!NT_STATUS_IS_OK(status)) {
703 werr = ntstatus_to_werror(status);
704 goto done;
707 if (types.ids[0] != SID_NAME_DOM_GRP) {
708 werr = WERR_INVALID_DATATYPE;
709 goto done;
712 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
713 &domain_handle,
714 SAMR_GROUP_ACCESS_LOOKUP_INFO,
715 rids.ids[0],
716 &group_handle);
717 if (!NT_STATUS_IS_OK(status)) {
718 werr = ntstatus_to_werror(status);
719 goto done;
722 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
723 &group_handle,
724 GROUPINFOALL2,
725 &info);
726 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
727 status = rpccli_samr_QueryGroupInfo(pipe_cli, ctx,
728 &group_handle,
729 GROUPINFOALL,
730 &info);
731 group_info_all = true;
734 if (!NT_STATUS_IS_OK(status)) {
735 werr = ntstatus_to_werror(status);
736 goto done;
739 werr = map_group_info_to_buffer(ctx, r->in.level,
740 group_info_all ? &info->all : &info->all2,
741 domain_sid, rids.ids[0],
742 r->out.buf);
743 if (!W_ERROR_IS_OK(werr)) {
744 goto done;
746 done:
747 if (!cli) {
748 return werr;
751 if (is_valid_policy_hnd(&group_handle)) {
752 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
755 if (ctx->disable_policy_handle_cache) {
756 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
757 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
760 return werr;
763 /****************************************************************
764 ****************************************************************/
766 WERROR NetGroupGetInfo_l(struct libnetapi_ctx *ctx,
767 struct NetGroupGetInfo *r)
769 return NetGroupGetInfo_r(ctx, r);
772 /****************************************************************
773 ****************************************************************/
775 WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx,
776 struct NetGroupAddUser *r)
778 struct cli_state *cli = NULL;
779 struct rpc_pipe_client *pipe_cli = NULL;
780 NTSTATUS status;
781 WERROR werr;
782 POLICY_HND connect_handle, domain_handle, group_handle;
783 struct lsa_String lsa_group_name, lsa_user_name;
784 struct dom_sid2 *domain_sid = NULL;
786 struct samr_Ids rids;
787 struct samr_Ids types;
789 ZERO_STRUCT(connect_handle);
790 ZERO_STRUCT(domain_handle);
791 ZERO_STRUCT(group_handle);
793 if (!r->in.group_name) {
794 return WERR_INVALID_PARAM;
797 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
798 if (!W_ERROR_IS_OK(werr)) {
799 goto done;
802 werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
803 &pipe_cli);
804 if (!W_ERROR_IS_OK(werr)) {
805 goto done;
808 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
809 SAMR_ACCESS_ENUM_DOMAINS |
810 SAMR_ACCESS_OPEN_DOMAIN,
811 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
812 &connect_handle,
813 &domain_handle,
814 &domain_sid);
815 if (!W_ERROR_IS_OK(werr)) {
816 goto done;
819 init_lsa_String(&lsa_group_name, r->in.group_name);
821 status = rpccli_samr_LookupNames(pipe_cli, ctx,
822 &domain_handle,
824 &lsa_group_name,
825 &rids,
826 &types);
827 if (!NT_STATUS_IS_OK(status)) {
828 werr = WERR_GROUP_NOT_FOUND;
829 goto done;
832 if (types.ids[0] != SID_NAME_DOM_GRP) {
833 werr = WERR_GROUP_NOT_FOUND;
834 goto done;
837 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
838 &domain_handle,
839 SAMR_GROUP_ACCESS_ADD_MEMBER,
840 rids.ids[0],
841 &group_handle);
842 if (!NT_STATUS_IS_OK(status)) {
843 werr = ntstatus_to_werror(status);
844 goto done;
847 init_lsa_String(&lsa_user_name, r->in.user_name);
849 status = rpccli_samr_LookupNames(pipe_cli, ctx,
850 &domain_handle,
852 &lsa_user_name,
853 &rids,
854 &types);
855 if (!NT_STATUS_IS_OK(status)) {
856 werr = WERR_USER_NOT_FOUND;
857 goto done;
860 if (types.ids[0] != SID_NAME_USER) {
861 werr = WERR_USER_NOT_FOUND;
862 goto done;
865 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
866 &group_handle,
867 rids.ids[0],
868 7); /* why ? */
869 if (!NT_STATUS_IS_OK(status)) {
870 werr = ntstatus_to_werror(status);
871 goto done;
874 werr = WERR_OK;
876 done:
877 if (!cli) {
878 return werr;
881 if (is_valid_policy_hnd(&group_handle)) {
882 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
885 if (ctx->disable_policy_handle_cache) {
886 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
887 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
890 return werr;
893 /****************************************************************
894 ****************************************************************/
896 WERROR NetGroupAddUser_l(struct libnetapi_ctx *ctx,
897 struct NetGroupAddUser *r)
899 return NetGroupAddUser_r(ctx, r);
902 /****************************************************************
903 ****************************************************************/
905 WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx,
906 struct NetGroupDelUser *r)
908 struct cli_state *cli = NULL;
909 struct rpc_pipe_client *pipe_cli = NULL;
910 NTSTATUS status;
911 WERROR werr;
912 POLICY_HND connect_handle, domain_handle, group_handle;
913 struct lsa_String lsa_group_name, lsa_user_name;
914 struct dom_sid2 *domain_sid = NULL;
916 struct samr_Ids rids;
917 struct samr_Ids types;
919 ZERO_STRUCT(connect_handle);
920 ZERO_STRUCT(domain_handle);
921 ZERO_STRUCT(group_handle);
923 if (!r->in.group_name) {
924 return WERR_INVALID_PARAM;
927 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
928 if (!W_ERROR_IS_OK(werr)) {
929 goto done;
932 werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
933 &pipe_cli);
934 if (!W_ERROR_IS_OK(werr)) {
935 goto done;
938 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
939 SAMR_ACCESS_ENUM_DOMAINS |
940 SAMR_ACCESS_OPEN_DOMAIN,
941 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
942 &connect_handle,
943 &domain_handle,
944 &domain_sid);
945 if (!W_ERROR_IS_OK(werr)) {
946 goto done;
949 init_lsa_String(&lsa_group_name, r->in.group_name);
951 status = rpccli_samr_LookupNames(pipe_cli, ctx,
952 &domain_handle,
954 &lsa_group_name,
955 &rids,
956 &types);
957 if (!NT_STATUS_IS_OK(status)) {
958 werr = WERR_GROUP_NOT_FOUND;
959 goto done;
962 if (types.ids[0] != SID_NAME_DOM_GRP) {
963 werr = WERR_GROUP_NOT_FOUND;
964 goto done;
967 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
968 &domain_handle,
969 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
970 rids.ids[0],
971 &group_handle);
972 if (!NT_STATUS_IS_OK(status)) {
973 werr = ntstatus_to_werror(status);
974 goto done;
977 init_lsa_String(&lsa_user_name, r->in.user_name);
979 status = rpccli_samr_LookupNames(pipe_cli, ctx,
980 &domain_handle,
982 &lsa_user_name,
983 &rids,
984 &types);
985 if (!NT_STATUS_IS_OK(status)) {
986 werr = WERR_USER_NOT_FOUND;
987 goto done;
990 if (types.ids[0] != SID_NAME_USER) {
991 werr = WERR_USER_NOT_FOUND;
992 goto done;
995 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
996 &group_handle,
997 rids.ids[0]);
998 if (!NT_STATUS_IS_OK(status)) {
999 werr = ntstatus_to_werror(status);
1000 goto done;
1003 werr = WERR_OK;
1005 done:
1006 if (!cli) {
1007 return werr;
1010 if (is_valid_policy_hnd(&group_handle)) {
1011 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
1014 if (ctx->disable_policy_handle_cache) {
1015 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1016 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1019 return werr;
1022 /****************************************************************
1023 ****************************************************************/
1025 WERROR NetGroupDelUser_l(struct libnetapi_ctx *ctx,
1026 struct NetGroupDelUser *r)
1028 return NetGroupDelUser_r(ctx, r);
1031 /****************************************************************
1032 ****************************************************************/
1034 static WERROR convert_samr_disp_groups_to_GROUP_INFO_0_buffer(TALLOC_CTX *mem_ctx,
1035 struct samr_DispInfoFullGroups *groups,
1036 uint8_t **buffer)
1038 struct GROUP_INFO_0 *g0;
1039 int i;
1041 g0 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_0, groups->count);
1042 W_ERROR_HAVE_NO_MEMORY(g0);
1044 for (i=0; i<groups->count; i++) {
1045 g0[i].grpi0_name = talloc_strdup(mem_ctx,
1046 groups->entries[i].account_name.string);
1047 W_ERROR_HAVE_NO_MEMORY(g0[i].grpi0_name);
1050 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g0,
1051 sizeof(struct GROUP_INFO_0) * groups->count);
1052 W_ERROR_HAVE_NO_MEMORY(*buffer);
1054 return WERR_OK;
1057 /****************************************************************
1058 ****************************************************************/
1060 static WERROR convert_samr_disp_groups_to_GROUP_INFO_1_buffer(TALLOC_CTX *mem_ctx,
1061 struct samr_DispInfoFullGroups *groups,
1062 uint8_t **buffer)
1064 struct GROUP_INFO_1 *g1;
1065 int i;
1067 g1 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_1, groups->count);
1068 W_ERROR_HAVE_NO_MEMORY(g1);
1070 for (i=0; i<groups->count; i++) {
1071 g1[i].grpi1_name = talloc_strdup(mem_ctx,
1072 groups->entries[i].account_name.string);
1073 g1[i].grpi1_comment = talloc_strdup(mem_ctx,
1074 groups->entries[i].description.string);
1075 W_ERROR_HAVE_NO_MEMORY(g1[i].grpi1_name);
1078 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g1,
1079 sizeof(struct GROUP_INFO_1) * groups->count);
1080 W_ERROR_HAVE_NO_MEMORY(*buffer);
1082 return WERR_OK;
1085 /****************************************************************
1086 ****************************************************************/
1088 static WERROR convert_samr_disp_groups_to_GROUP_INFO_2_buffer(TALLOC_CTX *mem_ctx,
1089 struct samr_DispInfoFullGroups *groups,
1090 uint8_t **buffer)
1092 struct GROUP_INFO_2 *g2;
1093 int i;
1095 g2 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_2, groups->count);
1096 W_ERROR_HAVE_NO_MEMORY(g2);
1098 for (i=0; i<groups->count; i++) {
1099 g2[i].grpi2_name = talloc_strdup(mem_ctx,
1100 groups->entries[i].account_name.string);
1101 g2[i].grpi2_comment = talloc_strdup(mem_ctx,
1102 groups->entries[i].description.string);
1103 g2[i].grpi2_group_id = groups->entries[i].rid;
1104 g2[i].grpi2_attributes = groups->entries[i].acct_flags;
1105 W_ERROR_HAVE_NO_MEMORY(g2[i].grpi2_name);
1108 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g2,
1109 sizeof(struct GROUP_INFO_2) * groups->count);
1110 W_ERROR_HAVE_NO_MEMORY(*buffer);
1112 return WERR_OK;
1115 /****************************************************************
1116 ****************************************************************/
1118 static WERROR convert_samr_disp_groups_to_GROUP_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1119 struct samr_DispInfoFullGroups *groups,
1120 const struct dom_sid *domain_sid,
1121 uint8_t **buffer)
1123 struct GROUP_INFO_3 *g3;
1124 int i;
1126 g3 = TALLOC_ZERO_ARRAY(mem_ctx, struct GROUP_INFO_3, groups->count);
1127 W_ERROR_HAVE_NO_MEMORY(g3);
1129 for (i=0; i<groups->count; i++) {
1131 struct dom_sid sid;
1133 if (!sid_compose(&sid, domain_sid, groups->entries[i].rid)) {
1134 return WERR_NOMEM;
1137 g3[i].grpi3_name = talloc_strdup(mem_ctx,
1138 groups->entries[i].account_name.string);
1139 g3[i].grpi3_comment = talloc_strdup(mem_ctx,
1140 groups->entries[i].description.string);
1141 g3[i].grpi3_group_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
1142 g3[i].grpi3_attributes = groups->entries[i].acct_flags;
1143 W_ERROR_HAVE_NO_MEMORY(g3[i].grpi3_name);
1146 *buffer = (uint8_t *)talloc_memdup(mem_ctx, g3,
1147 sizeof(struct GROUP_INFO_3) * groups->count);
1148 W_ERROR_HAVE_NO_MEMORY(*buffer);
1150 return WERR_OK;
1153 /****************************************************************
1154 ****************************************************************/
1156 static WERROR convert_samr_disp_groups_to_GROUP_INFO_buffer(TALLOC_CTX *mem_ctx,
1157 uint32_t level,
1158 struct samr_DispInfoFullGroups *groups,
1159 const struct dom_sid *domain_sid,
1160 uint32_t *entries_read,
1161 uint8_t **buffer)
1163 if (entries_read) {
1164 *entries_read = groups->count;
1167 switch (level) {
1168 case 0:
1169 return convert_samr_disp_groups_to_GROUP_INFO_0_buffer(mem_ctx, groups, buffer);
1170 case 1:
1171 return convert_samr_disp_groups_to_GROUP_INFO_1_buffer(mem_ctx, groups, buffer);
1172 case 2:
1173 return convert_samr_disp_groups_to_GROUP_INFO_2_buffer(mem_ctx, groups, buffer);
1174 case 3:
1175 return convert_samr_disp_groups_to_GROUP_INFO_3_buffer(mem_ctx, groups, domain_sid, buffer);
1176 default:
1177 return WERR_UNKNOWN_LEVEL;
1181 /****************************************************************
1182 ****************************************************************/
1184 WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx,
1185 struct NetGroupEnum *r)
1187 struct cli_state *cli = NULL;
1188 struct rpc_pipe_client *pipe_cli = NULL;
1189 struct policy_handle connect_handle;
1190 struct dom_sid2 *domain_sid = NULL;
1191 struct policy_handle domain_handle;
1192 union samr_DispInfo info;
1193 union samr_DomainInfo *domain_info = NULL;
1195 uint32_t total_size = 0;
1196 uint32_t returned_size = 0;
1198 NTSTATUS status = NT_STATUS_OK;
1199 WERROR werr, tmp_werr;
1201 ZERO_STRUCT(connect_handle);
1202 ZERO_STRUCT(domain_handle);
1204 switch (r->in.level) {
1205 case 0:
1206 case 1:
1207 case 2:
1208 case 3:
1209 break;
1210 default:
1211 return WERR_UNKNOWN_LEVEL;
1214 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
1215 if (!W_ERROR_IS_OK(werr)) {
1216 goto done;
1219 werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
1220 &pipe_cli);
1221 if (!W_ERROR_IS_OK(werr)) {
1222 goto done;
1225 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1226 SAMR_ACCESS_ENUM_DOMAINS |
1227 SAMR_ACCESS_OPEN_DOMAIN,
1228 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1229 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1230 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1231 &connect_handle,
1232 &domain_handle,
1233 &domain_sid);
1234 if (!W_ERROR_IS_OK(werr)) {
1235 goto done;
1238 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
1239 &domain_handle,
1241 &domain_info);
1242 if (!NT_STATUS_IS_OK(status)) {
1243 werr = ntstatus_to_werror(status);
1244 goto done;
1247 if (r->out.total_entries) {
1248 *r->out.total_entries = domain_info->info2.num_groups;
1251 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1252 ctx,
1253 &domain_handle,
1255 r->in.resume_handle ?
1256 *r->in.resume_handle : 0,
1257 (uint32_t)-1,
1258 r->in.prefmaxlen,
1259 &total_size,
1260 &returned_size,
1261 &info);
1262 werr = ntstatus_to_werror(status);
1263 if (NT_STATUS_IS_ERR(status)) {
1264 goto done;
1267 if (r->out.resume_handle) {
1268 *r->out.resume_handle =
1269 info.info3.entries[info.info3.count-1].idx;
1272 tmp_werr = convert_samr_disp_groups_to_GROUP_INFO_buffer(ctx,
1273 r->in.level,
1274 &info.info3,
1275 domain_sid,
1276 r->out.entries_read,
1277 r->out.buffer);
1278 if (!W_ERROR_IS_OK(tmp_werr)) {
1279 werr = tmp_werr;
1280 goto done;
1283 done:
1284 if (!cli) {
1285 return werr;
1288 /* if last query */
1289 if (NT_STATUS_IS_OK(status) ||
1290 NT_STATUS_IS_ERR(status)) {
1292 if (ctx->disable_policy_handle_cache) {
1293 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1294 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1298 return werr;
1301 /****************************************************************
1302 ****************************************************************/
1304 WERROR NetGroupEnum_l(struct libnetapi_ctx *ctx,
1305 struct NetGroupEnum *r)
1307 return NetGroupEnum_r(ctx, r);