s3-util_sid: use shared dom_sid_compare_auth and dom_sid_equal_X functions.
[Samba.git] / source3 / lib / netapi / localgroup.c
blobc9e1b722bd324d08456b5aaa14c2aeeb902cb7b2
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"
26 #include "../librpc/gen_ndr/cli_samr.h"
27 #include "../librpc/gen_ndr/cli_lsa.h"
28 #include "rpc_client/cli_lsarpc.h"
29 #include "rpc_client/init_lsa.h"
30 #include "../libcli/security/dom_sid.h"
32 static NTSTATUS libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
33 struct rpc_pipe_client *pipe_cli,
34 struct policy_handle *domain_handle,
35 const char *group_name,
36 uint32_t access_rights,
37 struct policy_handle *alias_handle)
39 NTSTATUS status;
41 struct lsa_String lsa_account_name;
42 struct samr_Ids user_rids, name_types;
44 init_lsa_String(&lsa_account_name, group_name);
46 status = rpccli_samr_LookupNames(pipe_cli, mem_ctx,
47 domain_handle,
49 &lsa_account_name,
50 &user_rids,
51 &name_types);
52 if (!NT_STATUS_IS_OK(status)) {
53 return status;
56 switch (name_types.ids[0]) {
57 case SID_NAME_ALIAS:
58 case SID_NAME_WKN_GRP:
59 break;
60 default:
61 return NT_STATUS_INVALID_SID;
64 return rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
65 domain_handle,
66 access_rights,
67 user_rids.ids[0],
68 alias_handle);
71 /****************************************************************
72 ****************************************************************/
74 static NTSTATUS libnetapi_samr_open_alias_queryinfo(TALLOC_CTX *mem_ctx,
75 struct rpc_pipe_client *pipe_cli,
76 struct policy_handle *handle,
77 uint32_t rid,
78 uint32_t access_rights,
79 enum samr_AliasInfoEnum level,
80 union samr_AliasInfo **alias_info)
82 NTSTATUS status;
83 struct policy_handle alias_handle;
84 union samr_AliasInfo *_alias_info = NULL;
86 ZERO_STRUCT(alias_handle);
88 status = rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
89 handle,
90 access_rights,
91 rid,
92 &alias_handle);
93 if (!NT_STATUS_IS_OK(status)) {
94 goto done;
97 status = rpccli_samr_QueryAliasInfo(pipe_cli, mem_ctx,
98 &alias_handle,
99 level,
100 &_alias_info);
101 if (!NT_STATUS_IS_OK(status)) {
102 goto done;
105 *alias_info = _alias_info;
107 done:
108 if (is_valid_policy_hnd(&alias_handle)) {
109 rpccli_samr_Close(pipe_cli, mem_ctx, &alias_handle);
112 return status;
115 /****************************************************************
116 ****************************************************************/
118 WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
119 struct NetLocalGroupAdd *r)
121 struct rpc_pipe_client *pipe_cli = NULL;
122 NTSTATUS status;
123 WERROR werr;
124 struct lsa_String lsa_account_name;
125 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
126 struct dom_sid2 *domain_sid = NULL;
127 uint32_t rid;
129 struct LOCALGROUP_INFO_0 *info0 = NULL;
130 struct LOCALGROUP_INFO_1 *info1 = NULL;
132 const char *alias_name = NULL;
134 if (!r->in.buffer) {
135 return WERR_INVALID_PARAM;
138 switch (r->in.level) {
139 case 0:
140 info0 = (struct LOCALGROUP_INFO_0 *)r->in.buffer;
141 alias_name = info0->lgrpi0_name;
142 break;
143 case 1:
144 info1 = (struct LOCALGROUP_INFO_1 *)r->in.buffer;
145 alias_name = info1->lgrpi1_name;
146 break;
147 default:
148 werr = WERR_UNKNOWN_LEVEL;
149 goto done;
152 ZERO_STRUCT(connect_handle);
153 ZERO_STRUCT(builtin_handle);
154 ZERO_STRUCT(domain_handle);
155 ZERO_STRUCT(alias_handle);
157 werr = libnetapi_open_pipe(ctx, r->in.server_name,
158 &ndr_table_samr.syntax_id,
159 &pipe_cli);
160 if (!W_ERROR_IS_OK(werr)) {
161 goto done;
164 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
165 SAMR_ACCESS_LOOKUP_DOMAIN |
166 SAMR_ACCESS_ENUM_DOMAINS,
167 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
168 &connect_handle,
169 &builtin_handle);
170 if (!W_ERROR_IS_OK(werr)) {
171 goto done;
174 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
175 &builtin_handle,
176 alias_name,
177 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
178 &alias_handle);
179 if (ctx->disable_policy_handle_cache) {
180 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
183 if (NT_STATUS_IS_OK(status)) {
184 werr = WERR_ALIAS_EXISTS;
185 goto done;
188 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
189 SAMR_ACCESS_ENUM_DOMAINS |
190 SAMR_ACCESS_LOOKUP_DOMAIN,
191 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
192 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
193 &connect_handle,
194 &domain_handle,
195 &domain_sid);
196 if (!W_ERROR_IS_OK(werr)) {
197 goto done;
200 init_lsa_String(&lsa_account_name, alias_name);
202 status = rpccli_samr_CreateDomAlias(pipe_cli, ctx,
203 &domain_handle,
204 &lsa_account_name,
205 SEC_STD_DELETE |
206 SAMR_ALIAS_ACCESS_SET_INFO,
207 &alias_handle,
208 &rid);
209 if (!NT_STATUS_IS_OK(status)) {
210 werr = ntstatus_to_werror(status);
211 goto done;
214 if (r->in.level == 1 && info1->lgrpi1_comment) {
216 union samr_AliasInfo alias_info;
218 init_lsa_String(&alias_info.description, info1->lgrpi1_comment);
220 status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
221 &alias_handle,
222 ALIASINFODESCRIPTION,
223 &alias_info);
224 if (!NT_STATUS_IS_OK(status)) {
225 werr = ntstatus_to_werror(status);
226 goto done;
230 werr = WERR_OK;
232 done:
233 if (is_valid_policy_hnd(&alias_handle)) {
234 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
237 if (ctx->disable_policy_handle_cache) {
238 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
239 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
240 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
243 return werr;
246 /****************************************************************
247 ****************************************************************/
249 WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
250 struct NetLocalGroupAdd *r)
252 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAdd);
255 /****************************************************************
256 ****************************************************************/
259 WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
260 struct NetLocalGroupDel *r)
262 struct rpc_pipe_client *pipe_cli = NULL;
263 NTSTATUS status;
264 WERROR werr;
265 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
266 struct dom_sid2 *domain_sid = NULL;
268 if (!r->in.group_name) {
269 return WERR_INVALID_PARAM;
272 ZERO_STRUCT(connect_handle);
273 ZERO_STRUCT(builtin_handle);
274 ZERO_STRUCT(domain_handle);
275 ZERO_STRUCT(alias_handle);
277 werr = libnetapi_open_pipe(ctx, r->in.server_name,
278 &ndr_table_samr.syntax_id,
279 &pipe_cli);
280 if (!W_ERROR_IS_OK(werr)) {
281 goto done;
284 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
285 SAMR_ACCESS_LOOKUP_DOMAIN |
286 SAMR_ACCESS_ENUM_DOMAINS,
287 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
288 &connect_handle,
289 &builtin_handle);
290 if (!W_ERROR_IS_OK(werr)) {
291 goto done;
294 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
295 &builtin_handle,
296 r->in.group_name,
297 SEC_STD_DELETE,
298 &alias_handle);
300 if (ctx->disable_policy_handle_cache) {
301 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
304 if (NT_STATUS_IS_OK(status)) {
305 goto delete_alias;
308 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
309 SAMR_ACCESS_ENUM_DOMAINS |
310 SAMR_ACCESS_LOOKUP_DOMAIN,
311 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
312 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
313 &connect_handle,
314 &domain_handle,
315 &domain_sid);
316 if (!W_ERROR_IS_OK(werr)) {
317 goto done;
320 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
321 &domain_handle,
322 r->in.group_name,
323 SEC_STD_DELETE,
324 &alias_handle);
326 if (ctx->disable_policy_handle_cache) {
327 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
330 if (!NT_STATUS_IS_OK(status)) {
331 werr = ntstatus_to_werror(status);
332 goto done;
336 delete_alias:
337 status = rpccli_samr_DeleteDomAlias(pipe_cli, ctx,
338 &alias_handle);
339 if (!NT_STATUS_IS_OK(status)) {
340 werr = ntstatus_to_werror(status);
341 goto done;
344 ZERO_STRUCT(alias_handle);
346 werr = WERR_OK;
348 done:
349 if (is_valid_policy_hnd(&alias_handle)) {
350 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
353 if (ctx->disable_policy_handle_cache) {
354 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
355 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
356 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
359 return werr;
362 /****************************************************************
363 ****************************************************************/
365 WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
366 struct NetLocalGroupDel *r)
368 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDel);
371 /****************************************************************
372 ****************************************************************/
374 static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
375 const char *alias_name,
376 struct samr_AliasInfoAll *info,
377 uint32_t level,
378 uint32_t *entries_read,
379 uint8_t **buffer)
381 struct LOCALGROUP_INFO_0 g0;
382 struct LOCALGROUP_INFO_1 g1;
383 struct LOCALGROUP_INFO_1002 g1002;
385 switch (level) {
386 case 0:
387 g0.lgrpi0_name = talloc_strdup(mem_ctx, alias_name);
388 W_ERROR_HAVE_NO_MEMORY(g0.lgrpi0_name);
390 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_0, g0,
391 (struct LOCALGROUP_INFO_0 **)buffer, entries_read);
393 break;
394 case 1:
395 g1.lgrpi1_name = talloc_strdup(mem_ctx, alias_name);
396 g1.lgrpi1_comment = talloc_strdup(mem_ctx, info->description.string);
397 W_ERROR_HAVE_NO_MEMORY(g1.lgrpi1_name);
399 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1, g1,
400 (struct LOCALGROUP_INFO_1 **)buffer, entries_read);
402 break;
403 case 1002:
404 g1002.lgrpi1002_comment = talloc_strdup(mem_ctx, info->description.string);
406 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1002, g1002,
407 (struct LOCALGROUP_INFO_1002 **)buffer, entries_read);
409 break;
410 default:
411 return WERR_UNKNOWN_LEVEL;
414 return WERR_OK;
417 /****************************************************************
418 ****************************************************************/
420 WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
421 struct NetLocalGroupGetInfo *r)
423 struct rpc_pipe_client *pipe_cli = NULL;
424 NTSTATUS status;
425 WERROR werr;
426 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
427 struct dom_sid2 *domain_sid = NULL;
428 union samr_AliasInfo *alias_info = NULL;
429 uint32_t entries_read = 0;
431 if (!r->in.group_name) {
432 return WERR_INVALID_PARAM;
435 switch (r->in.level) {
436 case 0:
437 case 1:
438 case 1002:
439 break;
440 default:
441 return WERR_UNKNOWN_LEVEL;
444 ZERO_STRUCT(connect_handle);
445 ZERO_STRUCT(builtin_handle);
446 ZERO_STRUCT(domain_handle);
447 ZERO_STRUCT(alias_handle);
449 werr = libnetapi_open_pipe(ctx, r->in.server_name,
450 &ndr_table_samr.syntax_id,
451 &pipe_cli);
452 if (!W_ERROR_IS_OK(werr)) {
453 goto done;
456 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
457 SAMR_ACCESS_LOOKUP_DOMAIN |
458 SAMR_ACCESS_ENUM_DOMAINS,
459 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
460 &connect_handle,
461 &builtin_handle);
462 if (!W_ERROR_IS_OK(werr)) {
463 goto done;
466 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
467 &builtin_handle,
468 r->in.group_name,
469 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
470 &alias_handle);
472 if (ctx->disable_policy_handle_cache) {
473 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
476 if (NT_STATUS_IS_OK(status)) {
477 goto query_alias;
480 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
481 SAMR_ACCESS_ENUM_DOMAINS |
482 SAMR_ACCESS_LOOKUP_DOMAIN,
483 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
484 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
485 &connect_handle,
486 &domain_handle,
487 &domain_sid);
488 if (!W_ERROR_IS_OK(werr)) {
489 goto done;
492 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
493 &domain_handle,
494 r->in.group_name,
495 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
496 &alias_handle);
498 if (ctx->disable_policy_handle_cache) {
499 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
502 if (!NT_STATUS_IS_OK(status)) {
503 werr = ntstatus_to_werror(status);
504 goto done;
507 query_alias:
508 status = rpccli_samr_QueryAliasInfo(pipe_cli, ctx,
509 &alias_handle,
510 ALIASINFOALL,
511 &alias_info);
512 if (!NT_STATUS_IS_OK(status)) {
513 werr = ntstatus_to_werror(status);
514 goto done;
517 werr = map_alias_info_to_buffer(ctx,
518 r->in.group_name,
519 &alias_info->all,
520 r->in.level, &entries_read,
521 r->out.buffer);
523 done:
524 if (is_valid_policy_hnd(&alias_handle)) {
525 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
528 if (ctx->disable_policy_handle_cache) {
529 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
530 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
531 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
534 return werr;
537 /****************************************************************
538 ****************************************************************/
540 WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
541 struct NetLocalGroupGetInfo *r)
543 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetInfo);
546 /****************************************************************
547 ****************************************************************/
549 static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
550 uint32_t level,
551 uint8_t *buffer,
552 enum samr_AliasInfoEnum *alias_level,
553 union samr_AliasInfo **alias_info)
555 struct LOCALGROUP_INFO_0 *info0;
556 struct LOCALGROUP_INFO_1 *info1;
557 struct LOCALGROUP_INFO_1002 *info1002;
558 union samr_AliasInfo *info = NULL;
560 info = TALLOC_ZERO_P(mem_ctx, union samr_AliasInfo);
561 W_ERROR_HAVE_NO_MEMORY(info);
563 switch (level) {
564 case 0:
565 info0 = (struct LOCALGROUP_INFO_0 *)buffer;
566 init_lsa_String(&info->name, info0->lgrpi0_name);
567 *alias_level = ALIASINFONAME;
568 break;
569 case 1:
570 info1 = (struct LOCALGROUP_INFO_1 *)buffer;
571 /* group name will be ignored */
572 init_lsa_String(&info->description, info1->lgrpi1_comment);
573 *alias_level = ALIASINFODESCRIPTION;
574 break;
575 case 1002:
576 info1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
577 init_lsa_String(&info->description, info1002->lgrpi1002_comment);
578 *alias_level = ALIASINFODESCRIPTION;
579 break;
582 *alias_info = info;
584 return WERR_OK;
587 /****************************************************************
588 ****************************************************************/
590 WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
591 struct NetLocalGroupSetInfo *r)
593 struct rpc_pipe_client *pipe_cli = NULL;
594 NTSTATUS status;
595 WERROR werr;
596 struct lsa_String lsa_account_name;
597 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
598 struct dom_sid2 *domain_sid = NULL;
599 enum samr_AliasInfoEnum alias_level = 0;
600 union samr_AliasInfo *alias_info = NULL;
602 if (!r->in.group_name) {
603 return WERR_INVALID_PARAM;
606 switch (r->in.level) {
607 case 0:
608 case 1:
609 case 1002:
610 break;
611 default:
612 return WERR_UNKNOWN_LEVEL;
615 ZERO_STRUCT(connect_handle);
616 ZERO_STRUCT(builtin_handle);
617 ZERO_STRUCT(domain_handle);
618 ZERO_STRUCT(alias_handle);
620 werr = libnetapi_open_pipe(ctx, r->in.server_name,
621 &ndr_table_samr.syntax_id,
622 &pipe_cli);
623 if (!W_ERROR_IS_OK(werr)) {
624 goto done;
627 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
628 SAMR_ACCESS_LOOKUP_DOMAIN |
629 SAMR_ACCESS_ENUM_DOMAINS,
630 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
631 &connect_handle,
632 &builtin_handle);
633 if (!W_ERROR_IS_OK(werr)) {
634 goto done;
637 init_lsa_String(&lsa_account_name, r->in.group_name);
639 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
640 &builtin_handle,
641 r->in.group_name,
642 SAMR_ALIAS_ACCESS_SET_INFO,
643 &alias_handle);
645 if (ctx->disable_policy_handle_cache) {
646 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
649 if (NT_STATUS_IS_OK(status)) {
650 goto set_alias;
653 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
654 SAMR_ACCESS_ENUM_DOMAINS |
655 SAMR_ACCESS_LOOKUP_DOMAIN,
656 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
657 &connect_handle,
658 &domain_handle,
659 &domain_sid);
660 if (!W_ERROR_IS_OK(werr)) {
661 goto done;
664 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
665 &domain_handle,
666 r->in.group_name,
667 SAMR_ALIAS_ACCESS_SET_INFO,
668 &alias_handle);
669 if (!NT_STATUS_IS_OK(status)) {
670 werr = ntstatus_to_werror(status);
671 goto done;
674 if (ctx->disable_policy_handle_cache) {
675 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
678 set_alias:
680 werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buffer,
681 &alias_level, &alias_info);
682 if (!W_ERROR_IS_OK(werr)) {
683 goto done;
686 status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
687 &alias_handle,
688 alias_level,
689 alias_info);
690 if (!NT_STATUS_IS_OK(status)) {
691 werr = ntstatus_to_werror(status);
692 goto done;
695 werr = WERR_OK;
697 done:
698 if (is_valid_policy_hnd(&alias_handle)) {
699 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
702 if (ctx->disable_policy_handle_cache) {
703 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
704 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
705 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
708 return werr;
711 /****************************************************************
712 ****************************************************************/
714 WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
715 struct NetLocalGroupSetInfo *r)
717 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetInfo);
720 /****************************************************************
721 ****************************************************************/
723 WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
724 struct NetLocalGroupEnum *r)
726 struct rpc_pipe_client *pipe_cli = NULL;
727 NTSTATUS status;
728 WERROR werr;
729 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
730 struct dom_sid2 *domain_sid = NULL;
731 uint32_t entries_read = 0;
732 union samr_DomainInfo *domain_info = NULL;
733 union samr_DomainInfo *builtin_info = NULL;
734 struct samr_SamArray *domain_sam_array = NULL;
735 struct samr_SamArray *builtin_sam_array = NULL;
736 int i;
738 if (!r->out.buffer) {
739 return WERR_INVALID_PARAM;
742 switch (r->in.level) {
743 case 0:
744 case 1:
745 break;
746 default:
747 return WERR_UNKNOWN_LEVEL;
750 if (r->out.total_entries) {
751 *r->out.total_entries = 0;
753 if (r->out.entries_read) {
754 *r->out.entries_read = 0;
757 ZERO_STRUCT(connect_handle);
758 ZERO_STRUCT(builtin_handle);
759 ZERO_STRUCT(domain_handle);
760 ZERO_STRUCT(alias_handle);
762 werr = libnetapi_open_pipe(ctx, r->in.server_name,
763 &ndr_table_samr.syntax_id,
764 &pipe_cli);
765 if (!W_ERROR_IS_OK(werr)) {
766 goto done;
769 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
770 SAMR_ACCESS_LOOKUP_DOMAIN |
771 SAMR_ACCESS_ENUM_DOMAINS,
772 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
773 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
774 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
775 &connect_handle,
776 &builtin_handle);
777 if (!W_ERROR_IS_OK(werr)) {
778 goto done;
781 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
782 SAMR_ACCESS_LOOKUP_DOMAIN |
783 SAMR_ACCESS_ENUM_DOMAINS,
784 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
785 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
786 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
787 &connect_handle,
788 &domain_handle,
789 &domain_sid);
790 if (!W_ERROR_IS_OK(werr)) {
791 goto done;
794 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
795 &builtin_handle,
797 &builtin_info);
798 if (!NT_STATUS_IS_OK(status)) {
799 werr = ntstatus_to_werror(status);
800 goto done;
803 if (r->out.total_entries) {
804 *r->out.total_entries += builtin_info->general.num_aliases;
807 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
808 &domain_handle,
810 &domain_info);
811 if (!NT_STATUS_IS_OK(status)) {
812 werr = ntstatus_to_werror(status);
813 goto done;
816 if (r->out.total_entries) {
817 *r->out.total_entries += domain_info->general.num_aliases;
820 status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
821 &builtin_handle,
822 r->in.resume_handle,
823 &builtin_sam_array,
824 r->in.prefmaxlen,
825 &entries_read);
826 if (!NT_STATUS_IS_OK(status)) {
827 werr = ntstatus_to_werror(status);
828 goto done;
831 for (i=0; i<builtin_sam_array->count; i++) {
832 union samr_AliasInfo *alias_info = NULL;
834 if (r->in.level == 1) {
836 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
837 &builtin_handle,
838 builtin_sam_array->entries[i].idx,
839 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
840 ALIASINFOALL,
841 &alias_info);
842 if (!NT_STATUS_IS_OK(status)) {
843 werr = ntstatus_to_werror(status);
844 goto done;
848 werr = map_alias_info_to_buffer(ctx,
849 builtin_sam_array->entries[i].name.string,
850 alias_info ? &alias_info->all : NULL,
851 r->in.level,
852 r->out.entries_read,
853 r->out.buffer);
856 status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
857 &domain_handle,
858 r->in.resume_handle,
859 &domain_sam_array,
860 r->in.prefmaxlen,
861 &entries_read);
862 if (!NT_STATUS_IS_OK(status)) {
863 werr = ntstatus_to_werror(status);
864 goto done;
867 for (i=0; i<domain_sam_array->count; i++) {
869 union samr_AliasInfo *alias_info = NULL;
871 if (r->in.level == 1) {
872 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
873 &domain_handle,
874 domain_sam_array->entries[i].idx,
875 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
876 ALIASINFOALL,
877 &alias_info);
878 if (!NT_STATUS_IS_OK(status)) {
879 werr = ntstatus_to_werror(status);
880 goto done;
884 werr = map_alias_info_to_buffer(ctx,
885 domain_sam_array->entries[i].name.string,
886 alias_info ? &alias_info->all : NULL,
887 r->in.level,
888 r->out.entries_read,
889 r->out.buffer);
892 done:
893 if (ctx->disable_policy_handle_cache) {
894 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
895 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
896 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
899 return werr;
902 /****************************************************************
903 ****************************************************************/
905 WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
906 struct NetLocalGroupEnum *r)
908 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupEnum);
911 /****************************************************************
912 ****************************************************************/
914 static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx,
915 struct rpc_pipe_client *lsa_pipe,
916 const char *name,
917 struct dom_sid *sid)
919 NTSTATUS status;
920 struct policy_handle lsa_handle;
922 struct lsa_RefDomainList *domains = NULL;
923 struct lsa_TransSidArray3 sids;
924 uint32_t count = 0;
926 struct lsa_String names;
927 uint32_t num_names = 1;
929 if (!sid || !name) {
930 return NT_STATUS_INVALID_PARAMETER;
933 ZERO_STRUCT(sids);
935 init_lsa_String(&names, name);
937 status = rpccli_lsa_open_policy2(lsa_pipe, mem_ctx,
938 false,
939 SEC_STD_READ_CONTROL |
940 LSA_POLICY_VIEW_LOCAL_INFORMATION |
941 LSA_POLICY_LOOKUP_NAMES,
942 &lsa_handle);
943 NT_STATUS_NOT_OK_RETURN(status);
945 status = rpccli_lsa_LookupNames3(lsa_pipe, mem_ctx,
946 &lsa_handle,
947 num_names,
948 &names,
949 &domains,
950 &sids,
951 LSA_LOOKUP_NAMES_ALL, /* sure ? */
952 &count,
953 0, 0);
954 NT_STATUS_NOT_OK_RETURN(status);
956 if (count != 1 || sids.count != 1) {
957 return NT_STATUS_NONE_MAPPED;
960 sid_copy(sid, sids.sids[0].sid);
962 return NT_STATUS_OK;
965 /****************************************************************
966 ****************************************************************/
968 static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
969 struct NetLocalGroupAddMembers *add,
970 struct NetLocalGroupDelMembers *del,
971 struct NetLocalGroupSetMembers *set)
973 struct NetLocalGroupAddMembers *r = NULL;
975 struct rpc_pipe_client *pipe_cli = NULL;
976 struct rpc_pipe_client *lsa_pipe = NULL;
977 NTSTATUS status;
978 WERROR werr;
979 struct lsa_String lsa_account_name;
980 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
981 struct dom_sid2 *domain_sid = NULL;
982 struct dom_sid *member_sids = NULL;
983 int i = 0, k = 0;
985 struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
986 struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
988 struct dom_sid *add_sids = NULL;
989 struct dom_sid *del_sids = NULL;
990 uint32_t num_add_sids = 0;
991 uint32_t num_del_sids = 0;
993 if ((!add && !del && !set) || (add && del && set)) {
994 return WERR_INVALID_PARAM;
997 if (add) {
998 r = add;
1001 if (del) {
1002 r = (struct NetLocalGroupAddMembers *)del;
1005 if (set) {
1006 r = (struct NetLocalGroupAddMembers *)set;
1009 if (!r->in.group_name) {
1010 return WERR_INVALID_PARAM;
1013 switch (r->in.level) {
1014 case 0:
1015 case 3:
1016 break;
1017 default:
1018 return WERR_UNKNOWN_LEVEL;
1021 if (r->in.total_entries == 0 || !r->in.buffer) {
1022 return WERR_INVALID_PARAM;
1025 ZERO_STRUCT(connect_handle);
1026 ZERO_STRUCT(builtin_handle);
1027 ZERO_STRUCT(domain_handle);
1028 ZERO_STRUCT(alias_handle);
1030 member_sids = TALLOC_ZERO_ARRAY(ctx, struct dom_sid,
1031 r->in.total_entries);
1032 W_ERROR_HAVE_NO_MEMORY(member_sids);
1034 switch (r->in.level) {
1035 case 0:
1036 info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
1037 for (i=0; i < r->in.total_entries; i++) {
1038 sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
1040 break;
1041 case 3:
1042 info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
1043 break;
1044 default:
1045 break;
1048 if (r->in.level == 3) {
1049 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1050 &ndr_table_lsarpc.syntax_id,
1051 &lsa_pipe);
1052 if (!W_ERROR_IS_OK(werr)) {
1053 goto done;
1056 for (i=0; i < r->in.total_entries; i++) {
1057 status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
1058 info3[i].lgrmi3_domainandname,
1059 &member_sids[i]);
1060 if (!NT_STATUS_IS_OK(status)) {
1061 werr = ntstatus_to_werror(status);
1062 goto done;
1065 TALLOC_FREE(lsa_pipe);
1068 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1069 &ndr_table_samr.syntax_id,
1070 &pipe_cli);
1071 if (!W_ERROR_IS_OK(werr)) {
1072 goto done;
1075 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1076 SAMR_ACCESS_LOOKUP_DOMAIN |
1077 SAMR_ACCESS_ENUM_DOMAINS,
1078 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1079 &connect_handle,
1080 &builtin_handle);
1081 if (!W_ERROR_IS_OK(werr)) {
1082 goto done;
1085 init_lsa_String(&lsa_account_name, r->in.group_name);
1087 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1088 &builtin_handle,
1089 r->in.group_name,
1090 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1091 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1092 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1093 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1094 &alias_handle);
1096 if (ctx->disable_policy_handle_cache) {
1097 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1100 if (NT_STATUS_IS_OK(status)) {
1101 goto modify_membership;
1104 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1105 SAMR_ACCESS_ENUM_DOMAINS |
1106 SAMR_ACCESS_LOOKUP_DOMAIN,
1107 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1108 &connect_handle,
1109 &domain_handle,
1110 &domain_sid);
1111 if (!W_ERROR_IS_OK(werr)) {
1112 goto done;
1115 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1116 &domain_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);
1123 if (!NT_STATUS_IS_OK(status)) {
1124 werr = ntstatus_to_werror(status);
1125 goto done;
1128 if (ctx->disable_policy_handle_cache) {
1129 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1132 modify_membership:
1134 if (add) {
1135 for (i=0; i < r->in.total_entries; i++) {
1136 status = add_sid_to_array_unique(ctx, &member_sids[i],
1137 &add_sids,
1138 &num_add_sids);
1139 if (!NT_STATUS_IS_OK(status)) {
1140 werr = ntstatus_to_werror(status);
1141 goto done;
1146 if (del) {
1147 for (i=0; i < r->in.total_entries; i++) {
1148 status = add_sid_to_array_unique(ctx, &member_sids[i],
1149 &del_sids,
1150 &num_del_sids);
1151 if (!NT_STATUS_IS_OK(status)) {
1152 werr = ntstatus_to_werror(status);
1153 goto done;
1158 if (set) {
1160 struct lsa_SidArray current_sids;
1162 status = rpccli_samr_GetMembersInAlias(pipe_cli, ctx,
1163 &alias_handle,
1164 &current_sids);
1165 if (!NT_STATUS_IS_OK(status)) {
1166 werr = ntstatus_to_werror(status);
1167 goto done;
1170 /* add list */
1172 for (i=0; i < r->in.total_entries; i++) {
1173 bool already_member = false;
1174 for (k=0; k < current_sids.num_sids; k++) {
1175 if (dom_sid_equal(&member_sids[i],
1176 current_sids.sids[k].sid)) {
1177 already_member = true;
1178 break;
1181 if (!already_member) {
1182 status = add_sid_to_array_unique(ctx,
1183 &member_sids[i],
1184 &add_sids, &num_add_sids);
1185 if (!NT_STATUS_IS_OK(status)) {
1186 werr = ntstatus_to_werror(status);
1187 goto done;
1192 /* del list */
1194 for (k=0; k < current_sids.num_sids; k++) {
1195 bool keep_member = false;
1196 for (i=0; i < r->in.total_entries; i++) {
1197 if (dom_sid_equal(&member_sids[i],
1198 current_sids.sids[k].sid)) {
1199 keep_member = true;
1200 break;
1203 if (!keep_member) {
1204 status = add_sid_to_array_unique(ctx,
1205 current_sids.sids[k].sid,
1206 &del_sids, &num_del_sids);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 werr = ntstatus_to_werror(status);
1209 goto done;
1215 /* add list */
1217 for (i=0; i < num_add_sids; i++) {
1218 status = rpccli_samr_AddAliasMember(pipe_cli, ctx,
1219 &alias_handle,
1220 &add_sids[i]);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 werr = ntstatus_to_werror(status);
1223 goto done;
1227 /* del list */
1229 for (i=0; i < num_del_sids; i++) {
1230 status = rpccli_samr_DeleteAliasMember(pipe_cli, ctx,
1231 &alias_handle,
1232 &del_sids[i]);
1233 if (!NT_STATUS_IS_OK(status)) {
1234 werr = ntstatus_to_werror(status);
1235 goto done;
1239 werr = WERR_OK;
1241 done:
1242 if (is_valid_policy_hnd(&alias_handle)) {
1243 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
1246 if (ctx->disable_policy_handle_cache) {
1247 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1248 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1249 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1252 return werr;
1255 /****************************************************************
1256 ****************************************************************/
1258 WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
1259 struct NetLocalGroupAddMembers *r)
1261 return NetLocalGroupModifyMembers_r(ctx, r, NULL, NULL);
1264 /****************************************************************
1265 ****************************************************************/
1267 WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
1268 struct NetLocalGroupAddMembers *r)
1270 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAddMembers);
1273 /****************************************************************
1274 ****************************************************************/
1276 WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
1277 struct NetLocalGroupDelMembers *r)
1279 return NetLocalGroupModifyMembers_r(ctx, NULL, r, NULL);
1282 /****************************************************************
1283 ****************************************************************/
1285 WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
1286 struct NetLocalGroupDelMembers *r)
1288 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDelMembers);
1291 /****************************************************************
1292 ****************************************************************/
1294 WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
1295 struct NetLocalGroupGetMembers *r)
1297 return WERR_NOT_SUPPORTED;
1300 /****************************************************************
1301 ****************************************************************/
1303 WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
1304 struct NetLocalGroupGetMembers *r)
1306 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetMembers);
1309 /****************************************************************
1310 ****************************************************************/
1312 WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
1313 struct NetLocalGroupSetMembers *r)
1315 return NetLocalGroupModifyMembers_r(ctx, NULL, NULL, r);
1318 /****************************************************************
1319 ****************************************************************/
1321 WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
1322 struct NetLocalGroupSetMembers *r)
1324 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetMembers);