s3/docs: Fix typo.
[Samba/gebeck_regimport.git] / source3 / lib / netapi / localgroup.c
blobd389c1f4a2b44aa6ea5227e2ff6a50a78475e7c7
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 rpc_pipe_client *pipe_cli = NULL;
117 NTSTATUS status;
118 WERROR werr;
119 struct lsa_String lsa_account_name;
120 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
121 struct dom_sid2 *domain_sid = NULL;
122 uint32_t rid;
124 struct LOCALGROUP_INFO_0 *info0 = NULL;
125 struct LOCALGROUP_INFO_1 *info1 = NULL;
127 const char *alias_name = NULL;
129 if (!r->in.buffer) {
130 return WERR_INVALID_PARAM;
133 switch (r->in.level) {
134 case 0:
135 info0 = (struct LOCALGROUP_INFO_0 *)r->in.buffer;
136 alias_name = info0->lgrpi0_name;
137 break;
138 case 1:
139 info1 = (struct LOCALGROUP_INFO_1 *)r->in.buffer;
140 alias_name = info1->lgrpi1_name;
141 break;
142 default:
143 werr = WERR_UNKNOWN_LEVEL;
144 goto done;
147 ZERO_STRUCT(connect_handle);
148 ZERO_STRUCT(builtin_handle);
149 ZERO_STRUCT(domain_handle);
150 ZERO_STRUCT(alias_handle);
152 werr = libnetapi_open_pipe(ctx, r->in.server_name,
153 &ndr_table_samr.syntax_id,
154 &pipe_cli);
155 if (!W_ERROR_IS_OK(werr)) {
156 goto done;
159 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
160 SAMR_ACCESS_LOOKUP_DOMAIN |
161 SAMR_ACCESS_ENUM_DOMAINS,
162 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
163 &connect_handle,
164 &builtin_handle);
165 if (!W_ERROR_IS_OK(werr)) {
166 goto done;
169 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
170 &builtin_handle,
171 alias_name,
172 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
173 &alias_handle);
174 if (ctx->disable_policy_handle_cache) {
175 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
178 if (NT_STATUS_IS_OK(status)) {
179 werr = WERR_ALIAS_EXISTS;
180 goto done;
183 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
184 SAMR_ACCESS_ENUM_DOMAINS |
185 SAMR_ACCESS_LOOKUP_DOMAIN,
186 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
187 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
188 &connect_handle,
189 &domain_handle,
190 &domain_sid);
191 if (!W_ERROR_IS_OK(werr)) {
192 goto done;
195 init_lsa_String(&lsa_account_name, alias_name);
197 status = rpccli_samr_CreateDomAlias(pipe_cli, ctx,
198 &domain_handle,
199 &lsa_account_name,
200 SEC_STD_DELETE |
201 SAMR_ALIAS_ACCESS_SET_INFO,
202 &alias_handle,
203 &rid);
204 if (!NT_STATUS_IS_OK(status)) {
205 werr = ntstatus_to_werror(status);
206 goto done;
209 if (r->in.level == 1 && info1->lgrpi1_comment) {
211 union samr_AliasInfo alias_info;
213 init_lsa_String(&alias_info.description, info1->lgrpi1_comment);
215 status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
216 &alias_handle,
217 ALIASINFODESCRIPTION,
218 &alias_info);
219 if (!NT_STATUS_IS_OK(status)) {
220 werr = ntstatus_to_werror(status);
221 goto done;
225 werr = WERR_OK;
227 done:
228 if (is_valid_policy_hnd(&alias_handle)) {
229 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
232 if (ctx->disable_policy_handle_cache) {
233 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
234 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
235 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
238 return werr;
241 /****************************************************************
242 ****************************************************************/
244 WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
245 struct NetLocalGroupAdd *r)
247 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAdd);
250 /****************************************************************
251 ****************************************************************/
254 WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
255 struct NetLocalGroupDel *r)
257 struct rpc_pipe_client *pipe_cli = NULL;
258 NTSTATUS status;
259 WERROR werr;
260 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
261 struct dom_sid2 *domain_sid = NULL;
263 if (!r->in.group_name) {
264 return WERR_INVALID_PARAM;
267 ZERO_STRUCT(connect_handle);
268 ZERO_STRUCT(builtin_handle);
269 ZERO_STRUCT(domain_handle);
270 ZERO_STRUCT(alias_handle);
272 werr = libnetapi_open_pipe(ctx, r->in.server_name,
273 &ndr_table_samr.syntax_id,
274 &pipe_cli);
275 if (!W_ERROR_IS_OK(werr)) {
276 goto done;
279 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
280 SAMR_ACCESS_LOOKUP_DOMAIN |
281 SAMR_ACCESS_ENUM_DOMAINS,
282 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
283 &connect_handle,
284 &builtin_handle);
285 if (!W_ERROR_IS_OK(werr)) {
286 goto done;
289 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
290 &builtin_handle,
291 r->in.group_name,
292 SEC_STD_DELETE,
293 &alias_handle);
295 if (ctx->disable_policy_handle_cache) {
296 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
299 if (NT_STATUS_IS_OK(status)) {
300 goto delete_alias;
303 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
304 SAMR_ACCESS_ENUM_DOMAINS |
305 SAMR_ACCESS_LOOKUP_DOMAIN,
306 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
307 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
308 &connect_handle,
309 &domain_handle,
310 &domain_sid);
311 if (!W_ERROR_IS_OK(werr)) {
312 goto done;
315 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
316 &domain_handle,
317 r->in.group_name,
318 SEC_STD_DELETE,
319 &alias_handle);
321 if (ctx->disable_policy_handle_cache) {
322 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
325 if (!NT_STATUS_IS_OK(status)) {
326 werr = ntstatus_to_werror(status);
327 goto done;
331 delete_alias:
332 status = rpccli_samr_DeleteDomAlias(pipe_cli, ctx,
333 &alias_handle);
334 if (!NT_STATUS_IS_OK(status)) {
335 werr = ntstatus_to_werror(status);
336 goto done;
339 ZERO_STRUCT(alias_handle);
341 werr = WERR_OK;
343 done:
344 if (is_valid_policy_hnd(&alias_handle)) {
345 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
348 if (ctx->disable_policy_handle_cache) {
349 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
350 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
351 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
354 return werr;
357 /****************************************************************
358 ****************************************************************/
360 WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
361 struct NetLocalGroupDel *r)
363 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDel);
366 /****************************************************************
367 ****************************************************************/
369 static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
370 const char *alias_name,
371 struct samr_AliasInfoAll *info,
372 uint32_t level,
373 uint32_t *entries_read,
374 uint8_t **buffer)
376 struct LOCALGROUP_INFO_0 g0;
377 struct LOCALGROUP_INFO_1 g1;
378 struct LOCALGROUP_INFO_1002 g1002;
380 switch (level) {
381 case 0:
382 g0.lgrpi0_name = talloc_strdup(mem_ctx, alias_name);
383 W_ERROR_HAVE_NO_MEMORY(g0.lgrpi0_name);
385 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_0, g0,
386 (struct LOCALGROUP_INFO_0 **)buffer, entries_read);
388 break;
389 case 1:
390 g1.lgrpi1_name = talloc_strdup(mem_ctx, alias_name);
391 g1.lgrpi1_comment = talloc_strdup(mem_ctx, info->description.string);
392 W_ERROR_HAVE_NO_MEMORY(g1.lgrpi1_name);
394 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1, g1,
395 (struct LOCALGROUP_INFO_1 **)buffer, entries_read);
397 break;
398 case 1002:
399 g1002.lgrpi1002_comment = talloc_strdup(mem_ctx, info->description.string);
401 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1002, g1002,
402 (struct LOCALGROUP_INFO_1002 **)buffer, entries_read);
404 break;
405 default:
406 return WERR_UNKNOWN_LEVEL;
409 return WERR_OK;
412 /****************************************************************
413 ****************************************************************/
415 WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
416 struct NetLocalGroupGetInfo *r)
418 struct rpc_pipe_client *pipe_cli = NULL;
419 NTSTATUS status;
420 WERROR werr;
421 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
422 struct dom_sid2 *domain_sid = NULL;
423 union samr_AliasInfo *alias_info = NULL;
424 uint32_t entries_read = 0;
426 if (!r->in.group_name) {
427 return WERR_INVALID_PARAM;
430 switch (r->in.level) {
431 case 0:
432 case 1:
433 case 1002:
434 break;
435 default:
436 return WERR_UNKNOWN_LEVEL;
439 ZERO_STRUCT(connect_handle);
440 ZERO_STRUCT(builtin_handle);
441 ZERO_STRUCT(domain_handle);
442 ZERO_STRUCT(alias_handle);
444 werr = libnetapi_open_pipe(ctx, r->in.server_name,
445 &ndr_table_samr.syntax_id,
446 &pipe_cli);
447 if (!W_ERROR_IS_OK(werr)) {
448 goto done;
451 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
452 SAMR_ACCESS_LOOKUP_DOMAIN |
453 SAMR_ACCESS_ENUM_DOMAINS,
454 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
455 &connect_handle,
456 &builtin_handle);
457 if (!W_ERROR_IS_OK(werr)) {
458 goto done;
461 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
462 &builtin_handle,
463 r->in.group_name,
464 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
465 &alias_handle);
467 if (ctx->disable_policy_handle_cache) {
468 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
471 if (NT_STATUS_IS_OK(status)) {
472 goto query_alias;
475 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
476 SAMR_ACCESS_ENUM_DOMAINS |
477 SAMR_ACCESS_LOOKUP_DOMAIN,
478 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
479 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
480 &connect_handle,
481 &domain_handle,
482 &domain_sid);
483 if (!W_ERROR_IS_OK(werr)) {
484 goto done;
487 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
488 &domain_handle,
489 r->in.group_name,
490 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
491 &alias_handle);
493 if (ctx->disable_policy_handle_cache) {
494 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
497 if (!NT_STATUS_IS_OK(status)) {
498 werr = ntstatus_to_werror(status);
499 goto done;
502 query_alias:
503 status = rpccli_samr_QueryAliasInfo(pipe_cli, ctx,
504 &alias_handle,
505 ALIASINFOALL,
506 &alias_info);
507 if (!NT_STATUS_IS_OK(status)) {
508 werr = ntstatus_to_werror(status);
509 goto done;
512 werr = map_alias_info_to_buffer(ctx,
513 r->in.group_name,
514 &alias_info->all,
515 r->in.level, &entries_read,
516 r->out.buffer);
518 done:
519 if (is_valid_policy_hnd(&alias_handle)) {
520 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
523 if (ctx->disable_policy_handle_cache) {
524 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
525 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
526 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
529 return werr;
532 /****************************************************************
533 ****************************************************************/
535 WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
536 struct NetLocalGroupGetInfo *r)
538 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetInfo);
541 /****************************************************************
542 ****************************************************************/
544 static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
545 uint32_t level,
546 uint8_t *buffer,
547 enum samr_AliasInfoEnum *alias_level,
548 union samr_AliasInfo **alias_info)
550 struct LOCALGROUP_INFO_0 *info0;
551 struct LOCALGROUP_INFO_1 *info1;
552 struct LOCALGROUP_INFO_1002 *info1002;
553 union samr_AliasInfo *info = NULL;
555 info = TALLOC_ZERO_P(mem_ctx, union samr_AliasInfo);
556 W_ERROR_HAVE_NO_MEMORY(info);
558 switch (level) {
559 case 0:
560 info0 = (struct LOCALGROUP_INFO_0 *)buffer;
561 init_lsa_String(&info->name, info0->lgrpi0_name);
562 *alias_level = ALIASINFONAME;
563 break;
564 case 1:
565 info1 = (struct LOCALGROUP_INFO_1 *)buffer;
566 /* group name will be ignored */
567 init_lsa_String(&info->description, info1->lgrpi1_comment);
568 *alias_level = ALIASINFODESCRIPTION;
569 break;
570 case 1002:
571 info1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
572 init_lsa_String(&info->description, info1002->lgrpi1002_comment);
573 *alias_level = ALIASINFODESCRIPTION;
574 break;
577 *alias_info = info;
579 return WERR_OK;
582 /****************************************************************
583 ****************************************************************/
585 WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
586 struct NetLocalGroupSetInfo *r)
588 struct rpc_pipe_client *pipe_cli = NULL;
589 NTSTATUS status;
590 WERROR werr;
591 struct lsa_String lsa_account_name;
592 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
593 struct dom_sid2 *domain_sid = NULL;
594 enum samr_AliasInfoEnum alias_level = 0;
595 union samr_AliasInfo *alias_info = NULL;
597 if (!r->in.group_name) {
598 return WERR_INVALID_PARAM;
601 switch (r->in.level) {
602 case 0:
603 case 1:
604 case 1002:
605 break;
606 default:
607 return WERR_UNKNOWN_LEVEL;
610 ZERO_STRUCT(connect_handle);
611 ZERO_STRUCT(builtin_handle);
612 ZERO_STRUCT(domain_handle);
613 ZERO_STRUCT(alias_handle);
615 werr = libnetapi_open_pipe(ctx, r->in.server_name,
616 &ndr_table_samr.syntax_id,
617 &pipe_cli);
618 if (!W_ERROR_IS_OK(werr)) {
619 goto done;
622 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
623 SAMR_ACCESS_LOOKUP_DOMAIN |
624 SAMR_ACCESS_ENUM_DOMAINS,
625 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
626 &connect_handle,
627 &builtin_handle);
628 if (!W_ERROR_IS_OK(werr)) {
629 goto done;
632 init_lsa_String(&lsa_account_name, r->in.group_name);
634 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
635 &builtin_handle,
636 r->in.group_name,
637 SAMR_ALIAS_ACCESS_SET_INFO,
638 &alias_handle);
640 if (ctx->disable_policy_handle_cache) {
641 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
644 if (NT_STATUS_IS_OK(status)) {
645 goto set_alias;
648 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
649 SAMR_ACCESS_ENUM_DOMAINS |
650 SAMR_ACCESS_LOOKUP_DOMAIN,
651 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
652 &connect_handle,
653 &domain_handle,
654 &domain_sid);
655 if (!W_ERROR_IS_OK(werr)) {
656 goto done;
659 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
660 &domain_handle,
661 r->in.group_name,
662 SAMR_ALIAS_ACCESS_SET_INFO,
663 &alias_handle);
664 if (!NT_STATUS_IS_OK(status)) {
665 werr = ntstatus_to_werror(status);
666 goto done;
669 if (ctx->disable_policy_handle_cache) {
670 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
673 set_alias:
675 werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buffer,
676 &alias_level, &alias_info);
677 if (!W_ERROR_IS_OK(werr)) {
678 goto done;
681 status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
682 &alias_handle,
683 alias_level,
684 alias_info);
685 if (!NT_STATUS_IS_OK(status)) {
686 werr = ntstatus_to_werror(status);
687 goto done;
690 werr = WERR_OK;
692 done:
693 if (is_valid_policy_hnd(&alias_handle)) {
694 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
697 if (ctx->disable_policy_handle_cache) {
698 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
699 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
700 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
703 return werr;
706 /****************************************************************
707 ****************************************************************/
709 WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
710 struct NetLocalGroupSetInfo *r)
712 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetInfo);
715 /****************************************************************
716 ****************************************************************/
718 WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
719 struct NetLocalGroupEnum *r)
721 struct rpc_pipe_client *pipe_cli = NULL;
722 NTSTATUS status;
723 WERROR werr;
724 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
725 struct dom_sid2 *domain_sid = NULL;
726 uint32_t entries_read = 0;
727 union samr_DomainInfo *domain_info = NULL;
728 union samr_DomainInfo *builtin_info = NULL;
729 struct samr_SamArray *domain_sam_array = NULL;
730 struct samr_SamArray *builtin_sam_array = NULL;
731 int i;
733 if (!r->out.buffer) {
734 return WERR_INVALID_PARAM;
737 switch (r->in.level) {
738 case 0:
739 case 1:
740 break;
741 default:
742 return WERR_UNKNOWN_LEVEL;
745 if (r->out.total_entries) {
746 *r->out.total_entries = 0;
748 if (r->out.entries_read) {
749 *r->out.entries_read = 0;
752 ZERO_STRUCT(connect_handle);
753 ZERO_STRUCT(builtin_handle);
754 ZERO_STRUCT(domain_handle);
755 ZERO_STRUCT(alias_handle);
757 werr = libnetapi_open_pipe(ctx, r->in.server_name,
758 &ndr_table_samr.syntax_id,
759 &pipe_cli);
760 if (!W_ERROR_IS_OK(werr)) {
761 goto done;
764 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
765 SAMR_ACCESS_LOOKUP_DOMAIN |
766 SAMR_ACCESS_ENUM_DOMAINS,
767 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
768 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
769 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
770 &connect_handle,
771 &builtin_handle);
772 if (!W_ERROR_IS_OK(werr)) {
773 goto done;
776 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
777 SAMR_ACCESS_LOOKUP_DOMAIN |
778 SAMR_ACCESS_ENUM_DOMAINS,
779 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
780 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
781 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
782 &connect_handle,
783 &domain_handle,
784 &domain_sid);
785 if (!W_ERROR_IS_OK(werr)) {
786 goto done;
789 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
790 &builtin_handle,
792 &builtin_info);
793 if (!NT_STATUS_IS_OK(status)) {
794 werr = ntstatus_to_werror(status);
795 goto done;
798 if (r->out.total_entries) {
799 *r->out.total_entries += builtin_info->general.num_aliases;
802 status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
803 &domain_handle,
805 &domain_info);
806 if (!NT_STATUS_IS_OK(status)) {
807 werr = ntstatus_to_werror(status);
808 goto done;
811 if (r->out.total_entries) {
812 *r->out.total_entries += domain_info->general.num_aliases;
815 status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
816 &builtin_handle,
817 r->in.resume_handle,
818 &builtin_sam_array,
819 r->in.prefmaxlen,
820 &entries_read);
821 if (!NT_STATUS_IS_OK(status)) {
822 werr = ntstatus_to_werror(status);
823 goto done;
826 for (i=0; i<builtin_sam_array->count; i++) {
827 union samr_AliasInfo *alias_info = NULL;
829 if (r->in.level == 1) {
831 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
832 &builtin_handle,
833 builtin_sam_array->entries[i].idx,
834 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
835 ALIASINFOALL,
836 &alias_info);
837 if (!NT_STATUS_IS_OK(status)) {
838 werr = ntstatus_to_werror(status);
839 goto done;
843 werr = map_alias_info_to_buffer(ctx,
844 builtin_sam_array->entries[i].name.string,
845 alias_info ? &alias_info->all : NULL,
846 r->in.level,
847 r->out.entries_read,
848 r->out.buffer);
851 status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
852 &domain_handle,
853 r->in.resume_handle,
854 &domain_sam_array,
855 r->in.prefmaxlen,
856 &entries_read);
857 if (!NT_STATUS_IS_OK(status)) {
858 werr = ntstatus_to_werror(status);
859 goto done;
862 for (i=0; i<domain_sam_array->count; i++) {
864 union samr_AliasInfo *alias_info = NULL;
866 if (r->in.level == 1) {
867 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
868 &domain_handle,
869 domain_sam_array->entries[i].idx,
870 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
871 ALIASINFOALL,
872 &alias_info);
873 if (!NT_STATUS_IS_OK(status)) {
874 werr = ntstatus_to_werror(status);
875 goto done;
879 werr = map_alias_info_to_buffer(ctx,
880 domain_sam_array->entries[i].name.string,
881 alias_info ? &alias_info->all : NULL,
882 r->in.level,
883 r->out.entries_read,
884 r->out.buffer);
887 done:
888 if (ctx->disable_policy_handle_cache) {
889 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
890 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
891 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
894 return werr;
897 /****************************************************************
898 ****************************************************************/
900 WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
901 struct NetLocalGroupEnum *r)
903 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupEnum);
906 /****************************************************************
907 ****************************************************************/
909 static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx,
910 struct rpc_pipe_client *lsa_pipe,
911 const char *name,
912 struct dom_sid *sid)
914 NTSTATUS status;
915 struct policy_handle lsa_handle;
917 struct lsa_RefDomainList *domains = NULL;
918 struct lsa_TransSidArray3 sids;
919 uint32_t count = 0;
921 struct lsa_String names;
922 uint32_t num_names = 1;
924 if (!sid || !name) {
925 return NT_STATUS_INVALID_PARAMETER;
928 ZERO_STRUCT(sids);
930 init_lsa_String(&names, name);
932 status = rpccli_lsa_open_policy2(lsa_pipe, mem_ctx,
933 false,
934 STD_RIGHT_READ_CONTROL_ACCESS |
935 LSA_POLICY_VIEW_LOCAL_INFORMATION |
936 LSA_POLICY_LOOKUP_NAMES,
937 &lsa_handle);
938 NT_STATUS_NOT_OK_RETURN(status);
940 status = rpccli_lsa_LookupNames3(lsa_pipe, mem_ctx,
941 &lsa_handle,
942 num_names,
943 &names,
944 &domains,
945 &sids,
946 LSA_LOOKUP_NAMES_ALL, /* sure ? */
947 &count,
948 0, 0);
949 NT_STATUS_NOT_OK_RETURN(status);
951 if (count != 1 || sids.count != 1) {
952 return NT_STATUS_NONE_MAPPED;
955 sid_copy(sid, sids.sids[0].sid);
957 return NT_STATUS_OK;
960 /****************************************************************
961 ****************************************************************/
963 static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
964 struct NetLocalGroupAddMembers *add,
965 struct NetLocalGroupDelMembers *del,
966 struct NetLocalGroupSetMembers *set)
968 struct NetLocalGroupAddMembers *r = NULL;
970 struct rpc_pipe_client *pipe_cli = NULL;
971 struct rpc_pipe_client *lsa_pipe = NULL;
972 NTSTATUS status;
973 WERROR werr;
974 struct lsa_String lsa_account_name;
975 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
976 struct dom_sid2 *domain_sid = NULL;
977 struct dom_sid *member_sids = NULL;
978 int i = 0, k = 0;
980 struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
981 struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
983 struct dom_sid *add_sids = NULL;
984 struct dom_sid *del_sids = NULL;
985 size_t num_add_sids = 0;
986 size_t num_del_sids = 0;
988 if ((!add && !del && !set) || (add && del && set)) {
989 return WERR_INVALID_PARAM;
992 if (add) {
993 r = add;
996 if (del) {
997 r = (struct NetLocalGroupAddMembers *)del;
1000 if (set) {
1001 r = (struct NetLocalGroupAddMembers *)set;
1004 if (!r->in.group_name) {
1005 return WERR_INVALID_PARAM;
1008 switch (r->in.level) {
1009 case 0:
1010 case 3:
1011 break;
1012 default:
1013 return WERR_UNKNOWN_LEVEL;
1016 if (r->in.total_entries == 0 || !r->in.buffer) {
1017 return WERR_INVALID_PARAM;
1020 ZERO_STRUCT(connect_handle);
1021 ZERO_STRUCT(builtin_handle);
1022 ZERO_STRUCT(domain_handle);
1023 ZERO_STRUCT(alias_handle);
1025 member_sids = TALLOC_ZERO_ARRAY(ctx, struct dom_sid,
1026 r->in.total_entries);
1027 W_ERROR_HAVE_NO_MEMORY(member_sids);
1029 switch (r->in.level) {
1030 case 0:
1031 info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
1032 for (i=0; i < r->in.total_entries; i++) {
1033 sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
1035 break;
1036 case 3:
1037 info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
1038 break;
1039 default:
1040 break;
1043 if (r->in.level == 3) {
1044 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1045 &ndr_table_lsarpc.syntax_id,
1046 &lsa_pipe);
1047 if (!W_ERROR_IS_OK(werr)) {
1048 goto done;
1051 for (i=0; i < r->in.total_entries; i++) {
1052 status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
1053 info3[i].lgrmi3_domainandname,
1054 &member_sids[i]);
1055 if (!NT_STATUS_IS_OK(status)) {
1056 werr = ntstatus_to_werror(status);
1057 goto done;
1060 TALLOC_FREE(lsa_pipe);
1063 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1064 &ndr_table_samr.syntax_id,
1065 &pipe_cli);
1066 if (!W_ERROR_IS_OK(werr)) {
1067 goto done;
1070 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1071 SAMR_ACCESS_LOOKUP_DOMAIN |
1072 SAMR_ACCESS_ENUM_DOMAINS,
1073 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1074 &connect_handle,
1075 &builtin_handle);
1076 if (!W_ERROR_IS_OK(werr)) {
1077 goto done;
1080 init_lsa_String(&lsa_account_name, r->in.group_name);
1082 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1083 &builtin_handle,
1084 r->in.group_name,
1085 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1086 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1087 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1088 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1089 &alias_handle);
1091 if (ctx->disable_policy_handle_cache) {
1092 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1095 if (NT_STATUS_IS_OK(status)) {
1096 goto modify_membership;
1099 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1100 SAMR_ACCESS_ENUM_DOMAINS |
1101 SAMR_ACCESS_LOOKUP_DOMAIN,
1102 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1103 &connect_handle,
1104 &domain_handle,
1105 &domain_sid);
1106 if (!W_ERROR_IS_OK(werr)) {
1107 goto done;
1110 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1111 &domain_handle,
1112 r->in.group_name,
1113 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1114 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1115 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1116 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1117 &alias_handle);
1118 if (!NT_STATUS_IS_OK(status)) {
1119 werr = ntstatus_to_werror(status);
1120 goto done;
1123 if (ctx->disable_policy_handle_cache) {
1124 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1127 modify_membership:
1129 if (add) {
1130 for (i=0; i < r->in.total_entries; i++) {
1131 status = add_sid_to_array_unique(ctx, &member_sids[i],
1132 &add_sids,
1133 &num_add_sids);
1134 if (!NT_STATUS_IS_OK(status)) {
1135 werr = ntstatus_to_werror(status);
1136 goto done;
1141 if (del) {
1142 for (i=0; i < r->in.total_entries; i++) {
1143 status = add_sid_to_array_unique(ctx, &member_sids[i],
1144 &del_sids,
1145 &num_del_sids);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 werr = ntstatus_to_werror(status);
1148 goto done;
1153 if (set) {
1155 struct lsa_SidArray current_sids;
1157 status = rpccli_samr_GetMembersInAlias(pipe_cli, ctx,
1158 &alias_handle,
1159 &current_sids);
1160 if (!NT_STATUS_IS_OK(status)) {
1161 werr = ntstatus_to_werror(status);
1162 goto done;
1165 /* add list */
1167 for (i=0; i < r->in.total_entries; i++) {
1168 bool already_member = false;
1169 for (k=0; k < current_sids.num_sids; k++) {
1170 if (sid_equal(&member_sids[i],
1171 current_sids.sids[k].sid)) {
1172 already_member = true;
1173 break;
1176 if (!already_member) {
1177 status = add_sid_to_array_unique(ctx,
1178 &member_sids[i],
1179 &add_sids, &num_add_sids);
1180 if (!NT_STATUS_IS_OK(status)) {
1181 werr = ntstatus_to_werror(status);
1182 goto done;
1187 /* del list */
1189 for (k=0; k < current_sids.num_sids; k++) {
1190 bool keep_member = false;
1191 for (i=0; i < r->in.total_entries; i++) {
1192 if (sid_equal(&member_sids[i],
1193 current_sids.sids[k].sid)) {
1194 keep_member = true;
1195 break;
1198 if (!keep_member) {
1199 status = add_sid_to_array_unique(ctx,
1200 current_sids.sids[k].sid,
1201 &del_sids, &num_del_sids);
1202 if (!NT_STATUS_IS_OK(status)) {
1203 werr = ntstatus_to_werror(status);
1204 goto done;
1210 /* add list */
1212 for (i=0; i < num_add_sids; i++) {
1213 status = rpccli_samr_AddAliasMember(pipe_cli, ctx,
1214 &alias_handle,
1215 &add_sids[i]);
1216 if (!NT_STATUS_IS_OK(status)) {
1217 werr = ntstatus_to_werror(status);
1218 goto done;
1222 /* del list */
1224 for (i=0; i < num_del_sids; i++) {
1225 status = rpccli_samr_DeleteAliasMember(pipe_cli, ctx,
1226 &alias_handle,
1227 &del_sids[i]);
1228 if (!NT_STATUS_IS_OK(status)) {
1229 werr = ntstatus_to_werror(status);
1230 goto done;
1234 werr = WERR_OK;
1236 done:
1237 if (is_valid_policy_hnd(&alias_handle)) {
1238 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
1241 if (ctx->disable_policy_handle_cache) {
1242 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1243 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1244 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1247 return werr;
1250 /****************************************************************
1251 ****************************************************************/
1253 WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
1254 struct NetLocalGroupAddMembers *r)
1256 return NetLocalGroupModifyMembers_r(ctx, r, NULL, NULL);
1259 /****************************************************************
1260 ****************************************************************/
1262 WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
1263 struct NetLocalGroupAddMembers *r)
1265 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAddMembers);
1268 /****************************************************************
1269 ****************************************************************/
1271 WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
1272 struct NetLocalGroupDelMembers *r)
1274 return NetLocalGroupModifyMembers_r(ctx, NULL, r, NULL);
1277 /****************************************************************
1278 ****************************************************************/
1280 WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
1281 struct NetLocalGroupDelMembers *r)
1283 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDelMembers);
1286 /****************************************************************
1287 ****************************************************************/
1289 WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
1290 struct NetLocalGroupGetMembers *r)
1292 return WERR_NOT_SUPPORTED;
1295 /****************************************************************
1296 ****************************************************************/
1298 WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
1299 struct NetLocalGroupGetMembers *r)
1301 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetMembers);
1304 /****************************************************************
1305 ****************************************************************/
1307 WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
1308 struct NetLocalGroupSetMembers *r)
1310 return NetLocalGroupModifyMembers_r(ctx, NULL, NULL, r);
1313 /****************************************************************
1314 ****************************************************************/
1316 WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
1317 struct NetLocalGroupSetMembers *r)
1319 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetMembers);