Fix bug #6089 - Winbind samr_OpenDomain not possible with Samba 3.2.6+
[Samba/bb.git] / source / lib / netapi / localgroup.c
blobd571045e6c09e2fb564023bb1f555532188366e8
1 /*
2 * Unix SMB/CIFS implementation.
3 * NetApi LocalGroup 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 static NTSTATUS libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
28 struct rpc_pipe_client *pipe_cli,
29 struct policy_handle *domain_handle,
30 const char *group_name,
31 uint32_t access_rights,
32 struct policy_handle *alias_handle)
34 NTSTATUS status;
36 struct lsa_String lsa_account_name;
37 struct samr_Ids user_rids, name_types;
39 init_lsa_String(&lsa_account_name, group_name);
41 status = rpccli_samr_LookupNames(pipe_cli, mem_ctx,
42 domain_handle,
44 &lsa_account_name,
45 &user_rids,
46 &name_types);
47 if (!NT_STATUS_IS_OK(status)) {
48 return status;
51 switch (name_types.ids[0]) {
52 case SID_NAME_ALIAS:
53 case SID_NAME_WKN_GRP:
54 break;
55 default:
56 return NT_STATUS_INVALID_SID;
59 return rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
60 domain_handle,
61 access_rights,
62 user_rids.ids[0],
63 alias_handle);
66 /****************************************************************
67 ****************************************************************/
69 static NTSTATUS libnetapi_samr_open_alias_queryinfo(TALLOC_CTX *mem_ctx,
70 struct rpc_pipe_client *pipe_cli,
71 struct policy_handle *handle,
72 uint32_t rid,
73 uint32_t access_rights,
74 enum samr_AliasInfoEnum level,
75 union samr_AliasInfo **alias_info)
77 NTSTATUS status;
78 struct policy_handle alias_handle;
79 union samr_AliasInfo *_alias_info = NULL;
81 ZERO_STRUCT(alias_handle);
83 status = rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
84 handle,
85 access_rights,
86 rid,
87 &alias_handle);
88 if (!NT_STATUS_IS_OK(status)) {
89 goto done;
92 status = rpccli_samr_QueryAliasInfo(pipe_cli, mem_ctx,
93 &alias_handle,
94 level,
95 &_alias_info);
96 if (!NT_STATUS_IS_OK(status)) {
97 goto done;
100 *alias_info = _alias_info;
102 done:
103 if (is_valid_policy_hnd(&alias_handle)) {
104 rpccli_samr_Close(pipe_cli, mem_ctx, &alias_handle);
107 return status;
110 /****************************************************************
111 ****************************************************************/
113 WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
114 struct NetLocalGroupAdd *r)
116 struct cli_state *cli = NULL;
117 struct rpc_pipe_client *pipe_cli = NULL;
118 NTSTATUS status;
119 WERROR werr;
120 struct lsa_String lsa_account_name;
121 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
122 struct dom_sid2 *domain_sid = NULL;
123 uint32_t rid;
125 struct LOCALGROUP_INFO_0 *info0 = NULL;
126 struct LOCALGROUP_INFO_1 *info1 = NULL;
128 const char *alias_name = NULL;
130 if (!r->in.buffer) {
131 return WERR_INVALID_PARAM;
134 switch (r->in.level) {
135 case 0:
136 info0 = (struct LOCALGROUP_INFO_0 *)r->in.buffer;
137 alias_name = info0->lgrpi0_name;
138 break;
139 case 1:
140 info1 = (struct LOCALGROUP_INFO_1 *)r->in.buffer;
141 alias_name = info1->lgrpi1_name;
142 break;
143 default:
144 werr = WERR_UNKNOWN_LEVEL;
145 goto done;
148 ZERO_STRUCT(connect_handle);
149 ZERO_STRUCT(builtin_handle);
150 ZERO_STRUCT(domain_handle);
151 ZERO_STRUCT(alias_handle);
153 werr = libnetapi_open_pipe(ctx, r->in.server_name,
154 &ndr_table_samr.syntax_id,
155 &cli,
156 &pipe_cli);
157 if (!W_ERROR_IS_OK(werr)) {
158 goto done;
161 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
162 SAMR_ACCESS_LOOKUP_DOMAIN |
163 SAMR_ACCESS_ENUM_DOMAINS,
164 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
165 &connect_handle,
166 &builtin_handle);
167 if (!W_ERROR_IS_OK(werr)) {
168 goto done;
171 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
172 &builtin_handle,
173 alias_name,
174 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
175 &alias_handle);
176 if (ctx->disable_policy_handle_cache) {
177 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
180 if (NT_STATUS_IS_OK(status)) {
181 werr = WERR_ALIAS_EXISTS;
182 goto done;
185 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
186 SAMR_ACCESS_ENUM_DOMAINS |
187 SAMR_ACCESS_LOOKUP_DOMAIN,
188 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
189 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
190 &connect_handle,
191 &domain_handle,
192 &domain_sid);
193 if (!W_ERROR_IS_OK(werr)) {
194 goto done;
197 init_lsa_String(&lsa_account_name, alias_name);
199 status = rpccli_samr_CreateDomAlias(pipe_cli, ctx,
200 &domain_handle,
201 &lsa_account_name,
202 SEC_STD_DELETE |
203 SAMR_ALIAS_ACCESS_SET_INFO,
204 &alias_handle,
205 &rid);
206 if (!NT_STATUS_IS_OK(status)) {
207 werr = ntstatus_to_werror(status);
208 goto done;
211 if (r->in.level == 1 && info1->lgrpi1_comment) {
213 union samr_AliasInfo alias_info;
215 init_lsa_String(&alias_info.description, info1->lgrpi1_comment);
217 status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
218 &alias_handle,
219 ALIASINFODESCRIPTION,
220 &alias_info);
221 if (!NT_STATUS_IS_OK(status)) {
222 werr = ntstatus_to_werror(status);
223 goto done;
227 werr = WERR_OK;
229 done:
230 if (!cli) {
231 return werr;
234 if (is_valid_policy_hnd(&alias_handle)) {
235 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
238 if (ctx->disable_policy_handle_cache) {
239 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
240 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
241 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
244 return werr;
247 /****************************************************************
248 ****************************************************************/
250 WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
251 struct NetLocalGroupAdd *r)
253 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAdd);
256 /****************************************************************
257 ****************************************************************/
260 WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
261 struct NetLocalGroupDel *r)
263 struct cli_state *cli = NULL;
264 struct rpc_pipe_client *pipe_cli = NULL;
265 NTSTATUS status;
266 WERROR werr;
267 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
268 struct dom_sid2 *domain_sid = NULL;
270 if (!r->in.group_name) {
271 return WERR_INVALID_PARAM;
274 ZERO_STRUCT(connect_handle);
275 ZERO_STRUCT(builtin_handle);
276 ZERO_STRUCT(domain_handle);
277 ZERO_STRUCT(alias_handle);
279 werr = libnetapi_open_pipe(ctx, r->in.server_name,
280 &ndr_table_samr.syntax_id,
281 &cli,
282 &pipe_cli);
283 if (!W_ERROR_IS_OK(werr)) {
284 goto done;
287 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
288 SAMR_ACCESS_LOOKUP_DOMAIN |
289 SAMR_ACCESS_ENUM_DOMAINS,
290 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
291 &connect_handle,
292 &builtin_handle);
293 if (!W_ERROR_IS_OK(werr)) {
294 goto done;
297 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
298 &builtin_handle,
299 r->in.group_name,
300 SEC_STD_DELETE,
301 &alias_handle);
303 if (ctx->disable_policy_handle_cache) {
304 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
307 if (NT_STATUS_IS_OK(status)) {
308 goto delete_alias;
311 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
312 SAMR_ACCESS_ENUM_DOMAINS |
313 SAMR_ACCESS_LOOKUP_DOMAIN,
314 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
315 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
316 &connect_handle,
317 &domain_handle,
318 &domain_sid);
319 if (!W_ERROR_IS_OK(werr)) {
320 goto done;
323 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
324 &domain_handle,
325 r->in.group_name,
326 SEC_STD_DELETE,
327 &alias_handle);
329 if (ctx->disable_policy_handle_cache) {
330 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
333 if (!NT_STATUS_IS_OK(status)) {
334 werr = ntstatus_to_werror(status);
335 goto done;
339 delete_alias:
340 status = rpccli_samr_DeleteDomAlias(pipe_cli, ctx,
341 &alias_handle);
342 if (!NT_STATUS_IS_OK(status)) {
343 werr = ntstatus_to_werror(status);
344 goto done;
347 ZERO_STRUCT(alias_handle);
349 werr = WERR_OK;
351 done:
352 if (!cli) {
353 return werr;
356 if (is_valid_policy_hnd(&alias_handle)) {
357 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
360 if (ctx->disable_policy_handle_cache) {
361 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
362 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
363 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
366 return werr;
369 /****************************************************************
370 ****************************************************************/
372 WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
373 struct NetLocalGroupDel *r)
375 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDel);
378 /****************************************************************
379 ****************************************************************/
381 static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
382 const char *alias_name,
383 struct samr_AliasInfoAll *info,
384 uint32_t level,
385 uint32_t *entries_read,
386 uint8_t **buffer)
388 struct LOCALGROUP_INFO_0 g0;
389 struct LOCALGROUP_INFO_1 g1;
390 struct LOCALGROUP_INFO_1002 g1002;
392 switch (level) {
393 case 0:
394 g0.lgrpi0_name = talloc_strdup(mem_ctx, alias_name);
395 W_ERROR_HAVE_NO_MEMORY(g0.lgrpi0_name);
397 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_0, g0,
398 (struct LOCALGROUP_INFO_0 **)buffer, entries_read);
400 break;
401 case 1:
402 g1.lgrpi1_name = talloc_strdup(mem_ctx, alias_name);
403 g1.lgrpi1_comment = talloc_strdup(mem_ctx, info->description.string);
404 W_ERROR_HAVE_NO_MEMORY(g1.lgrpi1_name);
406 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1, g1,
407 (struct LOCALGROUP_INFO_1 **)buffer, entries_read);
409 break;
410 case 1002:
411 g1002.lgrpi1002_comment = talloc_strdup(mem_ctx, info->description.string);
413 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1002, g1002,
414 (struct LOCALGROUP_INFO_1002 **)buffer, entries_read);
416 break;
417 default:
418 return WERR_UNKNOWN_LEVEL;
421 return WERR_OK;
424 /****************************************************************
425 ****************************************************************/
427 WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
428 struct NetLocalGroupGetInfo *r)
430 struct cli_state *cli = NULL;
431 struct rpc_pipe_client *pipe_cli = NULL;
432 NTSTATUS status;
433 WERROR werr;
434 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
435 struct dom_sid2 *domain_sid = NULL;
436 union samr_AliasInfo *alias_info = NULL;
437 uint32_t entries_read = 0;
439 if (!r->in.group_name) {
440 return WERR_INVALID_PARAM;
443 switch (r->in.level) {
444 case 0:
445 case 1:
446 case 1002:
447 break;
448 default:
449 return WERR_UNKNOWN_LEVEL;
452 ZERO_STRUCT(connect_handle);
453 ZERO_STRUCT(builtin_handle);
454 ZERO_STRUCT(domain_handle);
455 ZERO_STRUCT(alias_handle);
457 werr = libnetapi_open_pipe(ctx, r->in.server_name,
458 &ndr_table_samr.syntax_id,
459 &cli,
460 &pipe_cli);
461 if (!W_ERROR_IS_OK(werr)) {
462 goto done;
465 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
466 SAMR_ACCESS_LOOKUP_DOMAIN |
467 SAMR_ACCESS_ENUM_DOMAINS,
468 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
469 &connect_handle,
470 &builtin_handle);
471 if (!W_ERROR_IS_OK(werr)) {
472 goto done;
475 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
476 &builtin_handle,
477 r->in.group_name,
478 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
479 &alias_handle);
481 if (ctx->disable_policy_handle_cache) {
482 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
485 if (NT_STATUS_IS_OK(status)) {
486 goto query_alias;
489 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
490 SAMR_ACCESS_ENUM_DOMAINS |
491 SAMR_ACCESS_LOOKUP_DOMAIN,
492 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
493 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
494 &connect_handle,
495 &domain_handle,
496 &domain_sid);
497 if (!W_ERROR_IS_OK(werr)) {
498 goto done;
501 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
502 &domain_handle,
503 r->in.group_name,
504 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
505 &alias_handle);
507 if (ctx->disable_policy_handle_cache) {
508 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
511 if (!NT_STATUS_IS_OK(status)) {
512 werr = ntstatus_to_werror(status);
513 goto done;
516 query_alias:
517 status = rpccli_samr_QueryAliasInfo(pipe_cli, ctx,
518 &alias_handle,
519 ALIASINFOALL,
520 &alias_info);
521 if (!NT_STATUS_IS_OK(status)) {
522 werr = ntstatus_to_werror(status);
523 goto done;
526 werr = map_alias_info_to_buffer(ctx,
527 r->in.group_name,
528 &alias_info->all,
529 r->in.level, &entries_read,
530 r->out.buffer);
532 done:
533 if (!cli) {
534 return werr;
537 if (is_valid_policy_hnd(&alias_handle)) {
538 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
541 if (ctx->disable_policy_handle_cache) {
542 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
543 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
544 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
547 return werr;
550 /****************************************************************
551 ****************************************************************/
553 WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
554 struct NetLocalGroupGetInfo *r)
556 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetInfo);
559 /****************************************************************
560 ****************************************************************/
562 static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
563 uint32_t level,
564 uint8_t *buffer,
565 enum samr_AliasInfoEnum *alias_level,
566 union samr_AliasInfo **alias_info)
568 struct LOCALGROUP_INFO_0 *info0;
569 struct LOCALGROUP_INFO_1 *info1;
570 struct LOCALGROUP_INFO_1002 *info1002;
571 union samr_AliasInfo *info = NULL;
573 info = TALLOC_ZERO_P(mem_ctx, union samr_AliasInfo);
574 W_ERROR_HAVE_NO_MEMORY(info);
576 switch (level) {
577 case 0:
578 info0 = (struct LOCALGROUP_INFO_0 *)buffer;
579 init_lsa_String(&info->name, info0->lgrpi0_name);
580 *alias_level = ALIASINFONAME;
581 break;
582 case 1:
583 info1 = (struct LOCALGROUP_INFO_1 *)buffer;
584 /* group name will be ignored */
585 init_lsa_String(&info->description, info1->lgrpi1_comment);
586 *alias_level = ALIASINFODESCRIPTION;
587 break;
588 case 1002:
589 info1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
590 init_lsa_String(&info->description, info1002->lgrpi1002_comment);
591 *alias_level = ALIASINFODESCRIPTION;
592 break;
595 *alias_info = info;
597 return WERR_OK;
600 /****************************************************************
601 ****************************************************************/
603 WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
604 struct NetLocalGroupSetInfo *r)
606 struct cli_state *cli = NULL;
607 struct rpc_pipe_client *pipe_cli = NULL;
608 NTSTATUS status;
609 WERROR werr;
610 struct lsa_String lsa_account_name;
611 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
612 struct dom_sid2 *domain_sid = NULL;
613 enum samr_AliasInfoEnum alias_level = 0;
614 union samr_AliasInfo *alias_info = NULL;
616 if (!r->in.group_name) {
617 return WERR_INVALID_PARAM;
620 switch (r->in.level) {
621 case 0:
622 case 1:
623 case 1002:
624 break;
625 default:
626 return WERR_UNKNOWN_LEVEL;
629 ZERO_STRUCT(connect_handle);
630 ZERO_STRUCT(builtin_handle);
631 ZERO_STRUCT(domain_handle);
632 ZERO_STRUCT(alias_handle);
634 werr = libnetapi_open_pipe(ctx, r->in.server_name,
635 &ndr_table_samr.syntax_id,
636 &cli,
637 &pipe_cli);
638 if (!W_ERROR_IS_OK(werr)) {
639 goto done;
642 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
643 SAMR_ACCESS_LOOKUP_DOMAIN |
644 SAMR_ACCESS_ENUM_DOMAINS,
645 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
646 &connect_handle,
647 &builtin_handle);
648 if (!W_ERROR_IS_OK(werr)) {
649 goto done;
652 init_lsa_String(&lsa_account_name, r->in.group_name);
654 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
655 &builtin_handle,
656 r->in.group_name,
657 SAMR_ALIAS_ACCESS_SET_INFO,
658 &alias_handle);
660 if (ctx->disable_policy_handle_cache) {
661 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
664 if (NT_STATUS_IS_OK(status)) {
665 goto set_alias;
668 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
669 SAMR_ACCESS_ENUM_DOMAINS |
670 SAMR_ACCESS_LOOKUP_DOMAIN,
671 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
672 &connect_handle,
673 &domain_handle,
674 &domain_sid);
675 if (!W_ERROR_IS_OK(werr)) {
676 goto done;
679 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
680 &domain_handle,
681 r->in.group_name,
682 SAMR_ALIAS_ACCESS_SET_INFO,
683 &alias_handle);
684 if (!NT_STATUS_IS_OK(status)) {
685 werr = ntstatus_to_werror(status);
686 goto done;
689 if (ctx->disable_policy_handle_cache) {
690 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
693 set_alias:
695 werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buffer,
696 &alias_level, &alias_info);
697 if (!W_ERROR_IS_OK(werr)) {
698 goto done;
701 status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
702 &alias_handle,
703 alias_level,
704 alias_info);
705 if (!NT_STATUS_IS_OK(status)) {
706 werr = ntstatus_to_werror(status);
707 goto done;
710 werr = WERR_OK;
712 done:
713 if (!cli) {
714 return werr;
717 if (is_valid_policy_hnd(&alias_handle)) {
718 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
721 if (ctx->disable_policy_handle_cache) {
722 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
723 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
724 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
727 return werr;
730 /****************************************************************
731 ****************************************************************/
733 WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
734 struct NetLocalGroupSetInfo *r)
736 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetInfo);
739 /****************************************************************
740 ****************************************************************/
742 WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
743 struct NetLocalGroupEnum *r)
745 struct cli_state *cli = NULL;
746 struct rpc_pipe_client *pipe_cli = NULL;
747 NTSTATUS status;
748 WERROR werr;
749 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
750 struct dom_sid2 *domain_sid = NULL;
751 uint32_t entries_read = 0;
752 union samr_DomainInfo *domain_info = NULL;
753 union samr_DomainInfo *builtin_info = NULL;
754 struct samr_SamArray *domain_sam_array = NULL;
755 struct samr_SamArray *builtin_sam_array = NULL;
756 int i;
758 if (!r->out.buffer) {
759 return WERR_INVALID_PARAM;
762 switch (r->in.level) {
763 case 0:
764 case 1:
765 break;
766 default:
767 return WERR_UNKNOWN_LEVEL;
770 if (r->out.total_entries) {
771 *r->out.total_entries = 0;
773 if (r->out.entries_read) {
774 *r->out.entries_read = 0;
777 ZERO_STRUCT(connect_handle);
778 ZERO_STRUCT(builtin_handle);
779 ZERO_STRUCT(domain_handle);
780 ZERO_STRUCT(alias_handle);
782 werr = libnetapi_open_pipe(ctx, r->in.server_name,
783 &ndr_table_samr.syntax_id,
784 &cli,
785 &pipe_cli);
786 if (!W_ERROR_IS_OK(werr)) {
787 goto done;
790 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
791 SAMR_ACCESS_LOOKUP_DOMAIN |
792 SAMR_ACCESS_ENUM_DOMAINS,
793 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
794 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
795 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
796 &connect_handle,
797 &builtin_handle);
798 if (!W_ERROR_IS_OK(werr)) {
799 goto done;
802 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
803 SAMR_ACCESS_LOOKUP_DOMAIN |
804 SAMR_ACCESS_ENUM_DOMAINS,
805 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
806 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
807 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
808 &connect_handle,
809 &domain_handle,
810 &domain_sid);
811 if (!W_ERROR_IS_OK(werr)) {
812 goto done;
815 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
816 &builtin_handle,
818 &builtin_info);
819 if (!NT_STATUS_IS_OK(status)) {
820 werr = ntstatus_to_werror(status);
821 goto done;
824 if (r->out.total_entries) {
825 *r->out.total_entries += builtin_info->info2.num_aliases;
828 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
829 &domain_handle,
831 &domain_info);
832 if (!NT_STATUS_IS_OK(status)) {
833 werr = ntstatus_to_werror(status);
834 goto done;
837 if (r->out.total_entries) {
838 *r->out.total_entries += domain_info->info2.num_aliases;
841 status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
842 &builtin_handle,
843 r->in.resume_handle,
844 &builtin_sam_array,
845 r->in.prefmaxlen,
846 &entries_read);
847 if (!NT_STATUS_IS_OK(status)) {
848 werr = ntstatus_to_werror(status);
849 goto done;
852 for (i=0; i<builtin_sam_array->count; i++) {
853 union samr_AliasInfo *alias_info = NULL;
855 if (r->in.level == 1) {
857 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
858 &builtin_handle,
859 builtin_sam_array->entries[i].idx,
860 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
861 ALIASINFOALL,
862 &alias_info);
863 if (!NT_STATUS_IS_OK(status)) {
864 werr = ntstatus_to_werror(status);
865 goto done;
869 werr = map_alias_info_to_buffer(ctx,
870 builtin_sam_array->entries[i].name.string,
871 alias_info ? &alias_info->all : NULL,
872 r->in.level,
873 r->out.entries_read,
874 r->out.buffer);
877 status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
878 &domain_handle,
879 r->in.resume_handle,
880 &domain_sam_array,
881 r->in.prefmaxlen,
882 &entries_read);
883 if (!NT_STATUS_IS_OK(status)) {
884 werr = ntstatus_to_werror(status);
885 goto done;
888 for (i=0; i<domain_sam_array->count; i++) {
890 union samr_AliasInfo *alias_info = NULL;
892 if (r->in.level == 1) {
893 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
894 &domain_handle,
895 domain_sam_array->entries[i].idx,
896 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
897 ALIASINFOALL,
898 &alias_info);
899 if (!NT_STATUS_IS_OK(status)) {
900 werr = ntstatus_to_werror(status);
901 goto done;
905 werr = map_alias_info_to_buffer(ctx,
906 domain_sam_array->entries[i].name.string,
907 alias_info ? &alias_info->all : NULL,
908 r->in.level,
909 r->out.entries_read,
910 r->out.buffer);
913 done:
914 if (!cli) {
915 return werr;
918 if (ctx->disable_policy_handle_cache) {
919 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
920 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
921 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
924 return werr;
927 /****************************************************************
928 ****************************************************************/
930 WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
931 struct NetLocalGroupEnum *r)
933 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupEnum);
936 /****************************************************************
937 ****************************************************************/
939 static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx,
940 struct rpc_pipe_client *lsa_pipe,
941 const char *name,
942 struct dom_sid *sid)
944 NTSTATUS status;
945 struct policy_handle lsa_handle;
947 struct lsa_RefDomainList *domains = NULL;
948 struct lsa_TransSidArray3 sids;
949 uint32_t count = 0;
951 struct lsa_String names;
952 uint32_t num_names = 1;
954 if (!sid || !name) {
955 return NT_STATUS_INVALID_PARAMETER;
958 ZERO_STRUCT(sids);
960 init_lsa_String(&names, name);
962 status = rpccli_lsa_open_policy2(lsa_pipe, mem_ctx,
963 false,
964 STD_RIGHT_READ_CONTROL_ACCESS |
965 LSA_POLICY_VIEW_LOCAL_INFORMATION |
966 LSA_POLICY_LOOKUP_NAMES,
967 &lsa_handle);
968 NT_STATUS_NOT_OK_RETURN(status);
970 status = rpccli_lsa_LookupNames3(lsa_pipe, mem_ctx,
971 &lsa_handle,
972 num_names,
973 &names,
974 &domains,
975 &sids,
976 LSA_LOOKUP_NAMES_ALL, /* sure ? */
977 &count,
978 0, 0);
979 NT_STATUS_NOT_OK_RETURN(status);
981 if (count != 1 || sids.count != 1) {
982 return NT_STATUS_NONE_MAPPED;
985 sid_copy(sid, sids.sids[0].sid);
987 return NT_STATUS_OK;
990 /****************************************************************
991 ****************************************************************/
993 static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
994 struct NetLocalGroupAddMembers *add,
995 struct NetLocalGroupDelMembers *del,
996 struct NetLocalGroupSetMembers *set)
998 struct NetLocalGroupAddMembers *r = NULL;
1000 struct cli_state *cli = NULL;
1001 struct rpc_pipe_client *pipe_cli = NULL;
1002 struct rpc_pipe_client *lsa_pipe = NULL;
1003 NTSTATUS status;
1004 WERROR werr;
1005 struct lsa_String lsa_account_name;
1006 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
1007 struct dom_sid2 *domain_sid = NULL;
1008 struct dom_sid *member_sids = NULL;
1009 int i = 0, k = 0;
1011 struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
1012 struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
1014 struct dom_sid *add_sids = NULL;
1015 struct dom_sid *del_sids = NULL;
1016 size_t num_add_sids = 0;
1017 size_t num_del_sids = 0;
1019 if ((!add && !del && !set) || (add && del && set)) {
1020 return WERR_INVALID_PARAM;
1023 if (add) {
1024 r = add;
1027 if (del) {
1028 r = (struct NetLocalGroupAddMembers *)del;
1031 if (set) {
1032 r = (struct NetLocalGroupAddMembers *)set;
1035 if (!r->in.group_name) {
1036 return WERR_INVALID_PARAM;
1039 switch (r->in.level) {
1040 case 0:
1041 case 3:
1042 break;
1043 default:
1044 return WERR_UNKNOWN_LEVEL;
1047 if (r->in.total_entries == 0 || !r->in.buffer) {
1048 return WERR_INVALID_PARAM;
1051 ZERO_STRUCT(connect_handle);
1052 ZERO_STRUCT(builtin_handle);
1053 ZERO_STRUCT(domain_handle);
1054 ZERO_STRUCT(alias_handle);
1056 member_sids = TALLOC_ZERO_ARRAY(ctx, struct dom_sid,
1057 r->in.total_entries);
1058 W_ERROR_HAVE_NO_MEMORY(member_sids);
1060 switch (r->in.level) {
1061 case 0:
1062 info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
1063 for (i=0; i < r->in.total_entries; i++) {
1064 sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
1066 break;
1067 case 3:
1068 info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
1069 break;
1070 default:
1071 break;
1074 if (r->in.level == 3) {
1075 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1076 &ndr_table_lsarpc.syntax_id,
1077 &cli,
1078 &lsa_pipe);
1079 if (!W_ERROR_IS_OK(werr)) {
1080 goto done;
1083 for (i=0; i < r->in.total_entries; i++) {
1084 status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
1085 info3[i].lgrmi3_domainandname,
1086 &member_sids[i]);
1087 if (!NT_STATUS_IS_OK(status)) {
1088 werr = ntstatus_to_werror(status);
1089 goto done;
1092 TALLOC_FREE(lsa_pipe);
1095 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1096 &ndr_table_samr.syntax_id,
1097 &cli,
1098 &pipe_cli);
1099 if (!W_ERROR_IS_OK(werr)) {
1100 goto done;
1103 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1104 SAMR_ACCESS_LOOKUP_DOMAIN |
1105 SAMR_ACCESS_ENUM_DOMAINS,
1106 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1107 &connect_handle,
1108 &builtin_handle);
1109 if (!W_ERROR_IS_OK(werr)) {
1110 goto done;
1113 init_lsa_String(&lsa_account_name, r->in.group_name);
1115 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1116 &builtin_handle,
1117 r->in.group_name,
1118 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1119 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1120 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1121 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1122 &alias_handle);
1124 if (ctx->disable_policy_handle_cache) {
1125 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1128 if (NT_STATUS_IS_OK(status)) {
1129 goto modify_membership;
1132 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1133 SAMR_ACCESS_ENUM_DOMAINS |
1134 SAMR_ACCESS_LOOKUP_DOMAIN,
1135 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1136 &connect_handle,
1137 &domain_handle,
1138 &domain_sid);
1139 if (!W_ERROR_IS_OK(werr)) {
1140 goto done;
1143 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1144 &domain_handle,
1145 r->in.group_name,
1146 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1147 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1148 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1149 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1150 &alias_handle);
1151 if (!NT_STATUS_IS_OK(status)) {
1152 werr = ntstatus_to_werror(status);
1153 goto done;
1156 if (ctx->disable_policy_handle_cache) {
1157 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1160 modify_membership:
1162 if (add) {
1163 for (i=0; i < r->in.total_entries; i++) {
1164 status = add_sid_to_array_unique(ctx, &member_sids[i],
1165 &add_sids,
1166 &num_add_sids);
1167 if (!NT_STATUS_IS_OK(status)) {
1168 werr = ntstatus_to_werror(status);
1169 goto done;
1174 if (del) {
1175 for (i=0; i < r->in.total_entries; i++) {
1176 status = add_sid_to_array_unique(ctx, &member_sids[i],
1177 &del_sids,
1178 &num_del_sids);
1179 if (!NT_STATUS_IS_OK(status)) {
1180 werr = ntstatus_to_werror(status);
1181 goto done;
1186 if (set) {
1188 struct lsa_SidArray current_sids;
1190 status = rpccli_samr_GetMembersInAlias(pipe_cli, ctx,
1191 &alias_handle,
1192 &current_sids);
1193 if (!NT_STATUS_IS_OK(status)) {
1194 werr = ntstatus_to_werror(status);
1195 goto done;
1198 /* add list */
1200 for (i=0; i < r->in.total_entries; i++) {
1201 bool already_member = false;
1202 for (k=0; k < current_sids.num_sids; k++) {
1203 if (sid_equal(&member_sids[i],
1204 current_sids.sids[k].sid)) {
1205 already_member = true;
1206 break;
1209 if (!already_member) {
1210 status = add_sid_to_array_unique(ctx,
1211 &member_sids[i],
1212 &add_sids, &num_add_sids);
1213 if (!NT_STATUS_IS_OK(status)) {
1214 werr = ntstatus_to_werror(status);
1215 goto done;
1220 /* del list */
1222 for (k=0; k < current_sids.num_sids; k++) {
1223 bool keep_member = false;
1224 for (i=0; i < r->in.total_entries; i++) {
1225 if (sid_equal(&member_sids[i],
1226 current_sids.sids[k].sid)) {
1227 keep_member = true;
1228 break;
1231 if (!keep_member) {
1232 status = add_sid_to_array_unique(ctx,
1233 current_sids.sids[k].sid,
1234 &del_sids, &num_del_sids);
1235 if (!NT_STATUS_IS_OK(status)) {
1236 werr = ntstatus_to_werror(status);
1237 goto done;
1243 /* add list */
1245 for (i=0; i < num_add_sids; i++) {
1246 status = rpccli_samr_AddAliasMember(pipe_cli, ctx,
1247 &alias_handle,
1248 &add_sids[i]);
1249 if (!NT_STATUS_IS_OK(status)) {
1250 werr = ntstatus_to_werror(status);
1251 goto done;
1255 /* del list */
1257 for (i=0; i < num_del_sids; i++) {
1258 status = rpccli_samr_DeleteAliasMember(pipe_cli, ctx,
1259 &alias_handle,
1260 &del_sids[i]);
1261 if (!NT_STATUS_IS_OK(status)) {
1262 werr = ntstatus_to_werror(status);
1263 goto done;
1267 werr = WERR_OK;
1269 done:
1270 if (!cli) {
1271 return werr;
1274 if (is_valid_policy_hnd(&alias_handle)) {
1275 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
1278 if (ctx->disable_policy_handle_cache) {
1279 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1280 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1281 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1284 return werr;
1287 /****************************************************************
1288 ****************************************************************/
1290 WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
1291 struct NetLocalGroupAddMembers *r)
1293 return NetLocalGroupModifyMembers_r(ctx, r, NULL, NULL);
1296 /****************************************************************
1297 ****************************************************************/
1299 WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
1300 struct NetLocalGroupAddMembers *r)
1302 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAddMembers);
1305 /****************************************************************
1306 ****************************************************************/
1308 WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
1309 struct NetLocalGroupDelMembers *r)
1311 return NetLocalGroupModifyMembers_r(ctx, NULL, r, NULL);
1314 /****************************************************************
1315 ****************************************************************/
1317 WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
1318 struct NetLocalGroupDelMembers *r)
1320 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDelMembers);
1323 /****************************************************************
1324 ****************************************************************/
1326 WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
1327 struct NetLocalGroupGetMembers *r)
1329 return WERR_NOT_SUPPORTED;
1332 /****************************************************************
1333 ****************************************************************/
1335 WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
1336 struct NetLocalGroupGetMembers *r)
1338 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetMembers);
1341 /****************************************************************
1342 ****************************************************************/
1344 WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
1345 struct NetLocalGroupSetMembers *r)
1347 return NetLocalGroupModifyMembers_r(ctx, NULL, NULL, r);
1350 /****************************************************************
1351 ****************************************************************/
1353 WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
1354 struct NetLocalGroupSetMembers *r)
1356 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetMembers);