Fix bug #9147 - winbind can't fetch user or group info from AD via LDAP
[Samba.git] / source3 / lib / netapi / localgroup.c
blob03f9da50e4f23a925e5d6902fd3a110ad7c551fe
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"
29 static NTSTATUS libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
30 struct rpc_pipe_client *pipe_cli,
31 struct policy_handle *domain_handle,
32 const char *group_name,
33 uint32_t access_rights,
34 struct policy_handle *alias_handle)
36 NTSTATUS status;
38 struct lsa_String lsa_account_name;
39 struct samr_Ids user_rids, name_types;
41 init_lsa_String(&lsa_account_name, group_name);
43 status = rpccli_samr_LookupNames(pipe_cli, mem_ctx,
44 domain_handle,
46 &lsa_account_name,
47 &user_rids,
48 &name_types);
49 if (!NT_STATUS_IS_OK(status)) {
50 return status;
53 switch (name_types.ids[0]) {
54 case SID_NAME_ALIAS:
55 case SID_NAME_WKN_GRP:
56 break;
57 default:
58 return NT_STATUS_INVALID_SID;
61 return rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
62 domain_handle,
63 access_rights,
64 user_rids.ids[0],
65 alias_handle);
68 /****************************************************************
69 ****************************************************************/
71 static NTSTATUS libnetapi_samr_open_alias_queryinfo(TALLOC_CTX *mem_ctx,
72 struct rpc_pipe_client *pipe_cli,
73 struct policy_handle *handle,
74 uint32_t rid,
75 uint32_t access_rights,
76 enum samr_AliasInfoEnum level,
77 union samr_AliasInfo **alias_info)
79 NTSTATUS status;
80 struct policy_handle alias_handle;
81 union samr_AliasInfo *_alias_info = NULL;
83 ZERO_STRUCT(alias_handle);
85 status = rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
86 handle,
87 access_rights,
88 rid,
89 &alias_handle);
90 if (!NT_STATUS_IS_OK(status)) {
91 goto done;
94 status = rpccli_samr_QueryAliasInfo(pipe_cli, mem_ctx,
95 &alias_handle,
96 level,
97 &_alias_info);
98 if (!NT_STATUS_IS_OK(status)) {
99 goto done;
102 *alias_info = _alias_info;
104 done:
105 if (is_valid_policy_hnd(&alias_handle)) {
106 rpccli_samr_Close(pipe_cli, mem_ctx, &alias_handle);
109 return status;
112 /****************************************************************
113 ****************************************************************/
115 WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
116 struct NetLocalGroupAdd *r)
118 struct rpc_pipe_client *pipe_cli = NULL;
119 NTSTATUS status;
120 WERROR werr;
121 struct lsa_String lsa_account_name;
122 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
123 struct dom_sid2 *domain_sid = NULL;
124 uint32_t rid;
126 struct LOCALGROUP_INFO_0 *info0 = NULL;
127 struct LOCALGROUP_INFO_1 *info1 = NULL;
129 const char *alias_name = NULL;
131 if (!r->in.buffer) {
132 return WERR_INVALID_PARAM;
135 switch (r->in.level) {
136 case 0:
137 info0 = (struct LOCALGROUP_INFO_0 *)r->in.buffer;
138 alias_name = info0->lgrpi0_name;
139 break;
140 case 1:
141 info1 = (struct LOCALGROUP_INFO_1 *)r->in.buffer;
142 alias_name = info1->lgrpi1_name;
143 break;
144 default:
145 werr = WERR_UNKNOWN_LEVEL;
146 goto done;
149 ZERO_STRUCT(connect_handle);
150 ZERO_STRUCT(builtin_handle);
151 ZERO_STRUCT(domain_handle);
152 ZERO_STRUCT(alias_handle);
154 werr = libnetapi_open_pipe(ctx, r->in.server_name,
155 &ndr_table_samr.syntax_id,
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, talloc_tos(),
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, talloc_tos(),
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 (is_valid_policy_hnd(&alias_handle)) {
231 rpccli_samr_Close(pipe_cli, talloc_tos(), &alias_handle);
234 if (ctx->disable_policy_handle_cache) {
235 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
236 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
237 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
240 return werr;
243 /****************************************************************
244 ****************************************************************/
246 WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
247 struct NetLocalGroupAdd *r)
249 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAdd);
252 /****************************************************************
253 ****************************************************************/
256 WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
257 struct NetLocalGroupDel *r)
259 struct rpc_pipe_client *pipe_cli = NULL;
260 NTSTATUS status;
261 WERROR werr;
262 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
263 struct dom_sid2 *domain_sid = NULL;
265 if (!r->in.group_name) {
266 return WERR_INVALID_PARAM;
269 ZERO_STRUCT(connect_handle);
270 ZERO_STRUCT(builtin_handle);
271 ZERO_STRUCT(domain_handle);
272 ZERO_STRUCT(alias_handle);
274 werr = libnetapi_open_pipe(ctx, r->in.server_name,
275 &ndr_table_samr.syntax_id,
276 &pipe_cli);
277 if (!W_ERROR_IS_OK(werr)) {
278 goto done;
281 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
282 SAMR_ACCESS_LOOKUP_DOMAIN |
283 SAMR_ACCESS_ENUM_DOMAINS,
284 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
285 &connect_handle,
286 &builtin_handle);
287 if (!W_ERROR_IS_OK(werr)) {
288 goto done;
291 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
292 &builtin_handle,
293 r->in.group_name,
294 SEC_STD_DELETE,
295 &alias_handle);
297 if (ctx->disable_policy_handle_cache) {
298 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
301 if (NT_STATUS_IS_OK(status)) {
302 goto delete_alias;
305 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
306 SAMR_ACCESS_ENUM_DOMAINS |
307 SAMR_ACCESS_LOOKUP_DOMAIN,
308 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
309 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
310 &connect_handle,
311 &domain_handle,
312 &domain_sid);
313 if (!W_ERROR_IS_OK(werr)) {
314 goto done;
317 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
318 &domain_handle,
319 r->in.group_name,
320 SEC_STD_DELETE,
321 &alias_handle);
323 if (ctx->disable_policy_handle_cache) {
324 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
327 if (!NT_STATUS_IS_OK(status)) {
328 werr = ntstatus_to_werror(status);
329 goto done;
333 delete_alias:
334 status = rpccli_samr_DeleteDomAlias(pipe_cli, talloc_tos(),
335 &alias_handle);
336 if (!NT_STATUS_IS_OK(status)) {
337 werr = ntstatus_to_werror(status);
338 goto done;
341 ZERO_STRUCT(alias_handle);
343 werr = WERR_OK;
345 done:
346 if (is_valid_policy_hnd(&alias_handle)) {
347 rpccli_samr_Close(pipe_cli, talloc_tos(), &alias_handle);
350 if (ctx->disable_policy_handle_cache) {
351 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
352 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
353 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
356 return werr;
359 /****************************************************************
360 ****************************************************************/
362 WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
363 struct NetLocalGroupDel *r)
365 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDel);
368 /****************************************************************
369 ****************************************************************/
371 static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
372 const char *alias_name,
373 struct samr_AliasInfoAll *info,
374 uint32_t level,
375 uint32_t *entries_read,
376 uint8_t **buffer)
378 struct LOCALGROUP_INFO_0 g0;
379 struct LOCALGROUP_INFO_1 g1;
380 struct LOCALGROUP_INFO_1002 g1002;
382 switch (level) {
383 case 0:
384 g0.lgrpi0_name = talloc_strdup(mem_ctx, alias_name);
385 W_ERROR_HAVE_NO_MEMORY(g0.lgrpi0_name);
387 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_0, g0,
388 (struct LOCALGROUP_INFO_0 **)buffer, entries_read);
390 break;
391 case 1:
392 g1.lgrpi1_name = talloc_strdup(mem_ctx, alias_name);
393 g1.lgrpi1_comment = talloc_strdup(mem_ctx, info->description.string);
394 W_ERROR_HAVE_NO_MEMORY(g1.lgrpi1_name);
396 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1, g1,
397 (struct LOCALGROUP_INFO_1 **)buffer, entries_read);
399 break;
400 case 1002:
401 g1002.lgrpi1002_comment = talloc_strdup(mem_ctx, info->description.string);
403 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1002, g1002,
404 (struct LOCALGROUP_INFO_1002 **)buffer, entries_read);
406 break;
407 default:
408 return WERR_UNKNOWN_LEVEL;
411 return WERR_OK;
414 /****************************************************************
415 ****************************************************************/
417 WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
418 struct NetLocalGroupGetInfo *r)
420 struct rpc_pipe_client *pipe_cli = NULL;
421 NTSTATUS status;
422 WERROR werr;
423 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
424 struct dom_sid2 *domain_sid = NULL;
425 union samr_AliasInfo *alias_info = NULL;
426 uint32_t entries_read = 0;
428 if (!r->in.group_name) {
429 return WERR_INVALID_PARAM;
432 switch (r->in.level) {
433 case 0:
434 case 1:
435 case 1002:
436 break;
437 default:
438 return WERR_UNKNOWN_LEVEL;
441 ZERO_STRUCT(connect_handle);
442 ZERO_STRUCT(builtin_handle);
443 ZERO_STRUCT(domain_handle);
444 ZERO_STRUCT(alias_handle);
446 werr = libnetapi_open_pipe(ctx, r->in.server_name,
447 &ndr_table_samr.syntax_id,
448 &pipe_cli);
449 if (!W_ERROR_IS_OK(werr)) {
450 goto done;
453 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
454 SAMR_ACCESS_LOOKUP_DOMAIN |
455 SAMR_ACCESS_ENUM_DOMAINS,
456 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
457 &connect_handle,
458 &builtin_handle);
459 if (!W_ERROR_IS_OK(werr)) {
460 goto done;
463 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
464 &builtin_handle,
465 r->in.group_name,
466 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
467 &alias_handle);
469 if (ctx->disable_policy_handle_cache) {
470 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
473 if (NT_STATUS_IS_OK(status)) {
474 goto query_alias;
477 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
478 SAMR_ACCESS_ENUM_DOMAINS |
479 SAMR_ACCESS_LOOKUP_DOMAIN,
480 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
481 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
482 &connect_handle,
483 &domain_handle,
484 &domain_sid);
485 if (!W_ERROR_IS_OK(werr)) {
486 goto done;
489 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
490 &domain_handle,
491 r->in.group_name,
492 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
493 &alias_handle);
495 if (ctx->disable_policy_handle_cache) {
496 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
499 if (!NT_STATUS_IS_OK(status)) {
500 werr = ntstatus_to_werror(status);
501 goto done;
504 query_alias:
505 status = rpccli_samr_QueryAliasInfo(pipe_cli, talloc_tos(),
506 &alias_handle,
507 ALIASINFOALL,
508 &alias_info);
509 if (!NT_STATUS_IS_OK(status)) {
510 werr = ntstatus_to_werror(status);
511 goto done;
514 werr = map_alias_info_to_buffer(ctx,
515 r->in.group_name,
516 &alias_info->all,
517 r->in.level, &entries_read,
518 r->out.buffer);
520 done:
521 if (is_valid_policy_hnd(&alias_handle)) {
522 rpccli_samr_Close(pipe_cli, talloc_tos(), &alias_handle);
525 if (ctx->disable_policy_handle_cache) {
526 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
527 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
528 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
531 return werr;
534 /****************************************************************
535 ****************************************************************/
537 WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
538 struct NetLocalGroupGetInfo *r)
540 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetInfo);
543 /****************************************************************
544 ****************************************************************/
546 static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
547 uint32_t level,
548 uint8_t *buffer,
549 enum samr_AliasInfoEnum *alias_level,
550 union samr_AliasInfo **alias_info)
552 struct LOCALGROUP_INFO_0 *info0;
553 struct LOCALGROUP_INFO_1 *info1;
554 struct LOCALGROUP_INFO_1002 *info1002;
555 union samr_AliasInfo *info = NULL;
557 info = TALLOC_ZERO_P(mem_ctx, union samr_AliasInfo);
558 W_ERROR_HAVE_NO_MEMORY(info);
560 switch (level) {
561 case 0:
562 info0 = (struct LOCALGROUP_INFO_0 *)buffer;
563 init_lsa_String(&info->name, info0->lgrpi0_name);
564 *alias_level = ALIASINFONAME;
565 break;
566 case 1:
567 info1 = (struct LOCALGROUP_INFO_1 *)buffer;
568 /* group name will be ignored */
569 init_lsa_String(&info->description, info1->lgrpi1_comment);
570 *alias_level = ALIASINFODESCRIPTION;
571 break;
572 case 1002:
573 info1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
574 init_lsa_String(&info->description, info1002->lgrpi1002_comment);
575 *alias_level = ALIASINFODESCRIPTION;
576 break;
579 *alias_info = info;
581 return WERR_OK;
584 /****************************************************************
585 ****************************************************************/
587 WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
588 struct NetLocalGroupSetInfo *r)
590 struct rpc_pipe_client *pipe_cli = NULL;
591 NTSTATUS status;
592 WERROR werr;
593 struct lsa_String lsa_account_name;
594 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
595 struct dom_sid2 *domain_sid = NULL;
596 enum samr_AliasInfoEnum alias_level = 0;
597 union samr_AliasInfo *alias_info = NULL;
599 if (!r->in.group_name) {
600 return WERR_INVALID_PARAM;
603 switch (r->in.level) {
604 case 0:
605 case 1:
606 case 1002:
607 break;
608 default:
609 return WERR_UNKNOWN_LEVEL;
612 ZERO_STRUCT(connect_handle);
613 ZERO_STRUCT(builtin_handle);
614 ZERO_STRUCT(domain_handle);
615 ZERO_STRUCT(alias_handle);
617 werr = libnetapi_open_pipe(ctx, r->in.server_name,
618 &ndr_table_samr.syntax_id,
619 &pipe_cli);
620 if (!W_ERROR_IS_OK(werr)) {
621 goto done;
624 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
625 SAMR_ACCESS_LOOKUP_DOMAIN |
626 SAMR_ACCESS_ENUM_DOMAINS,
627 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
628 &connect_handle,
629 &builtin_handle);
630 if (!W_ERROR_IS_OK(werr)) {
631 goto done;
634 init_lsa_String(&lsa_account_name, r->in.group_name);
636 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
637 &builtin_handle,
638 r->in.group_name,
639 SAMR_ALIAS_ACCESS_SET_INFO,
640 &alias_handle);
642 if (ctx->disable_policy_handle_cache) {
643 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
646 if (NT_STATUS_IS_OK(status)) {
647 goto set_alias;
650 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
651 SAMR_ACCESS_ENUM_DOMAINS |
652 SAMR_ACCESS_LOOKUP_DOMAIN,
653 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
654 &connect_handle,
655 &domain_handle,
656 &domain_sid);
657 if (!W_ERROR_IS_OK(werr)) {
658 goto done;
661 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
662 &domain_handle,
663 r->in.group_name,
664 SAMR_ALIAS_ACCESS_SET_INFO,
665 &alias_handle);
666 if (!NT_STATUS_IS_OK(status)) {
667 werr = ntstatus_to_werror(status);
668 goto done;
671 if (ctx->disable_policy_handle_cache) {
672 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
675 set_alias:
677 werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buffer,
678 &alias_level, &alias_info);
679 if (!W_ERROR_IS_OK(werr)) {
680 goto done;
683 status = rpccli_samr_SetAliasInfo(pipe_cli, talloc_tos(),
684 &alias_handle,
685 alias_level,
686 alias_info);
687 if (!NT_STATUS_IS_OK(status)) {
688 werr = ntstatus_to_werror(status);
689 goto done;
692 werr = WERR_OK;
694 done:
695 if (is_valid_policy_hnd(&alias_handle)) {
696 rpccli_samr_Close(pipe_cli, talloc_tos(), &alias_handle);
699 if (ctx->disable_policy_handle_cache) {
700 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
701 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
702 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
705 return werr;
708 /****************************************************************
709 ****************************************************************/
711 WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
712 struct NetLocalGroupSetInfo *r)
714 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetInfo);
717 /****************************************************************
718 ****************************************************************/
720 WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
721 struct NetLocalGroupEnum *r)
723 struct rpc_pipe_client *pipe_cli = NULL;
724 NTSTATUS status;
725 WERROR werr;
726 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
727 struct dom_sid2 *domain_sid = NULL;
728 uint32_t entries_read = 0;
729 union samr_DomainInfo *domain_info = NULL;
730 union samr_DomainInfo *builtin_info = NULL;
731 struct samr_SamArray *domain_sam_array = NULL;
732 struct samr_SamArray *builtin_sam_array = NULL;
733 int i;
735 if (!r->out.buffer) {
736 return WERR_INVALID_PARAM;
739 switch (r->in.level) {
740 case 0:
741 case 1:
742 break;
743 default:
744 return WERR_UNKNOWN_LEVEL;
747 if (r->out.total_entries) {
748 *r->out.total_entries = 0;
750 if (r->out.entries_read) {
751 *r->out.entries_read = 0;
754 ZERO_STRUCT(connect_handle);
755 ZERO_STRUCT(builtin_handle);
756 ZERO_STRUCT(domain_handle);
757 ZERO_STRUCT(alias_handle);
759 werr = libnetapi_open_pipe(ctx, r->in.server_name,
760 &ndr_table_samr.syntax_id,
761 &pipe_cli);
762 if (!W_ERROR_IS_OK(werr)) {
763 goto done;
766 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
767 SAMR_ACCESS_LOOKUP_DOMAIN |
768 SAMR_ACCESS_ENUM_DOMAINS,
769 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
770 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
771 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
772 &connect_handle,
773 &builtin_handle);
774 if (!W_ERROR_IS_OK(werr)) {
775 goto done;
778 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
779 SAMR_ACCESS_LOOKUP_DOMAIN |
780 SAMR_ACCESS_ENUM_DOMAINS,
781 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
782 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
783 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
784 &connect_handle,
785 &domain_handle,
786 &domain_sid);
787 if (!W_ERROR_IS_OK(werr)) {
788 goto done;
791 status = rpccli_samr_QueryDomainInfo(pipe_cli, talloc_tos(),
792 &builtin_handle,
794 &builtin_info);
795 if (!NT_STATUS_IS_OK(status)) {
796 werr = ntstatus_to_werror(status);
797 goto done;
800 if (r->out.total_entries) {
801 *r->out.total_entries += builtin_info->general.num_aliases;
804 status = rpccli_samr_QueryDomainInfo(pipe_cli, talloc_tos(),
805 &domain_handle,
807 &domain_info);
808 if (!NT_STATUS_IS_OK(status)) {
809 werr = ntstatus_to_werror(status);
810 goto done;
813 if (r->out.total_entries) {
814 *r->out.total_entries += domain_info->general.num_aliases;
817 status = rpccli_samr_EnumDomainAliases(pipe_cli, talloc_tos(),
818 &builtin_handle,
819 r->in.resume_handle,
820 &builtin_sam_array,
821 r->in.prefmaxlen,
822 &entries_read);
823 if (!NT_STATUS_IS_OK(status)) {
824 werr = ntstatus_to_werror(status);
825 goto done;
828 for (i=0; i<builtin_sam_array->count; i++) {
829 union samr_AliasInfo *alias_info = NULL;
831 if (r->in.level == 1) {
833 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
834 &builtin_handle,
835 builtin_sam_array->entries[i].idx,
836 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
837 ALIASINFOALL,
838 &alias_info);
839 if (!NT_STATUS_IS_OK(status)) {
840 werr = ntstatus_to_werror(status);
841 goto done;
845 werr = map_alias_info_to_buffer(ctx,
846 builtin_sam_array->entries[i].name.string,
847 alias_info ? &alias_info->all : NULL,
848 r->in.level,
849 r->out.entries_read,
850 r->out.buffer);
853 status = rpccli_samr_EnumDomainAliases(pipe_cli, talloc_tos(),
854 &domain_handle,
855 r->in.resume_handle,
856 &domain_sam_array,
857 r->in.prefmaxlen,
858 &entries_read);
859 if (!NT_STATUS_IS_OK(status)) {
860 werr = ntstatus_to_werror(status);
861 goto done;
864 for (i=0; i<domain_sam_array->count; i++) {
866 union samr_AliasInfo *alias_info = NULL;
868 if (r->in.level == 1) {
869 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
870 &domain_handle,
871 domain_sam_array->entries[i].idx,
872 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
873 ALIASINFOALL,
874 &alias_info);
875 if (!NT_STATUS_IS_OK(status)) {
876 werr = ntstatus_to_werror(status);
877 goto done;
881 werr = map_alias_info_to_buffer(ctx,
882 domain_sam_array->entries[i].name.string,
883 alias_info ? &alias_info->all : NULL,
884 r->in.level,
885 r->out.entries_read,
886 r->out.buffer);
889 done:
890 if (ctx->disable_policy_handle_cache) {
891 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
892 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
893 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
896 return werr;
899 /****************************************************************
900 ****************************************************************/
902 WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
903 struct NetLocalGroupEnum *r)
905 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupEnum);
908 /****************************************************************
909 ****************************************************************/
911 static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx,
912 struct rpc_pipe_client *lsa_pipe,
913 const char *name,
914 struct dom_sid *sid)
916 NTSTATUS status;
917 struct policy_handle lsa_handle;
919 struct lsa_RefDomainList *domains = NULL;
920 struct lsa_TransSidArray3 sids;
921 uint32_t count = 0;
923 struct lsa_String names;
924 uint32_t num_names = 1;
926 if (!sid || !name) {
927 return NT_STATUS_INVALID_PARAMETER;
930 ZERO_STRUCT(sids);
932 init_lsa_String(&names, name);
934 status = rpccli_lsa_open_policy2(lsa_pipe, mem_ctx,
935 false,
936 STD_RIGHT_READ_CONTROL_ACCESS |
937 LSA_POLICY_VIEW_LOCAL_INFORMATION |
938 LSA_POLICY_LOOKUP_NAMES,
939 &lsa_handle);
940 NT_STATUS_NOT_OK_RETURN(status);
942 status = rpccli_lsa_LookupNames3(lsa_pipe, mem_ctx,
943 &lsa_handle,
944 num_names,
945 &names,
946 &domains,
947 &sids,
948 LSA_LOOKUP_NAMES_ALL, /* sure ? */
949 &count,
950 0, 0);
951 NT_STATUS_NOT_OK_RETURN(status);
953 if (count != 1 || sids.count != 1) {
954 return NT_STATUS_NONE_MAPPED;
957 sid_copy(sid, sids.sids[0].sid);
959 return NT_STATUS_OK;
962 /****************************************************************
963 ****************************************************************/
965 static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
966 struct NetLocalGroupAddMembers *add,
967 struct NetLocalGroupDelMembers *del,
968 struct NetLocalGroupSetMembers *set)
970 struct NetLocalGroupAddMembers *r = NULL;
972 struct rpc_pipe_client *pipe_cli = NULL;
973 struct rpc_pipe_client *lsa_pipe = NULL;
974 NTSTATUS status;
975 WERROR werr;
976 struct lsa_String lsa_account_name;
977 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
978 struct dom_sid2 *domain_sid = NULL;
979 struct dom_sid *member_sids = NULL;
980 int i = 0, k = 0;
982 struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
983 struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
985 struct dom_sid *add_sids = NULL;
986 struct dom_sid *del_sids = NULL;
987 size_t num_add_sids = 0;
988 size_t num_del_sids = 0;
990 if ((!add && !del && !set) || (add && del && set)) {
991 return WERR_INVALID_PARAM;
994 if (add) {
995 r = add;
998 if (del) {
999 r = (struct NetLocalGroupAddMembers *)del;
1002 if (set) {
1003 r = (struct NetLocalGroupAddMembers *)set;
1006 if (!r->in.group_name) {
1007 return WERR_INVALID_PARAM;
1010 switch (r->in.level) {
1011 case 0:
1012 case 3:
1013 break;
1014 default:
1015 return WERR_UNKNOWN_LEVEL;
1018 if (r->in.total_entries == 0 || !r->in.buffer) {
1019 return WERR_INVALID_PARAM;
1022 ZERO_STRUCT(connect_handle);
1023 ZERO_STRUCT(builtin_handle);
1024 ZERO_STRUCT(domain_handle);
1025 ZERO_STRUCT(alias_handle);
1027 member_sids = TALLOC_ZERO_ARRAY(ctx, struct dom_sid,
1028 r->in.total_entries);
1029 W_ERROR_HAVE_NO_MEMORY(member_sids);
1031 switch (r->in.level) {
1032 case 0:
1033 info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
1034 for (i=0; i < r->in.total_entries; i++) {
1035 sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
1037 break;
1038 case 3:
1039 info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
1040 break;
1041 default:
1042 break;
1045 if (r->in.level == 3) {
1046 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1047 &ndr_table_lsarpc.syntax_id,
1048 &lsa_pipe);
1049 if (!W_ERROR_IS_OK(werr)) {
1050 goto done;
1053 for (i=0; i < r->in.total_entries; i++) {
1054 status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
1055 info3[i].lgrmi3_domainandname,
1056 &member_sids[i]);
1057 if (!NT_STATUS_IS_OK(status)) {
1058 werr = ntstatus_to_werror(status);
1059 goto done;
1062 TALLOC_FREE(lsa_pipe);
1065 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1066 &ndr_table_samr.syntax_id,
1067 &pipe_cli);
1068 if (!W_ERROR_IS_OK(werr)) {
1069 goto done;
1072 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1073 SAMR_ACCESS_LOOKUP_DOMAIN |
1074 SAMR_ACCESS_ENUM_DOMAINS,
1075 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1076 &connect_handle,
1077 &builtin_handle);
1078 if (!W_ERROR_IS_OK(werr)) {
1079 goto done;
1082 init_lsa_String(&lsa_account_name, r->in.group_name);
1084 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1085 &builtin_handle,
1086 r->in.group_name,
1087 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1088 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1089 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1090 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1091 &alias_handle);
1093 if (ctx->disable_policy_handle_cache) {
1094 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1097 if (NT_STATUS_IS_OK(status)) {
1098 goto modify_membership;
1101 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1102 SAMR_ACCESS_ENUM_DOMAINS |
1103 SAMR_ACCESS_LOOKUP_DOMAIN,
1104 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1105 &connect_handle,
1106 &domain_handle,
1107 &domain_sid);
1108 if (!W_ERROR_IS_OK(werr)) {
1109 goto done;
1112 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1113 &domain_handle,
1114 r->in.group_name,
1115 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1116 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1117 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1118 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1119 &alias_handle);
1120 if (!NT_STATUS_IS_OK(status)) {
1121 werr = ntstatus_to_werror(status);
1122 goto done;
1125 if (ctx->disable_policy_handle_cache) {
1126 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1129 modify_membership:
1131 if (add) {
1132 for (i=0; i < r->in.total_entries; i++) {
1133 status = add_sid_to_array_unique(ctx, &member_sids[i],
1134 &add_sids,
1135 &num_add_sids);
1136 if (!NT_STATUS_IS_OK(status)) {
1137 werr = ntstatus_to_werror(status);
1138 goto done;
1143 if (del) {
1144 for (i=0; i < r->in.total_entries; i++) {
1145 status = add_sid_to_array_unique(ctx, &member_sids[i],
1146 &del_sids,
1147 &num_del_sids);
1148 if (!NT_STATUS_IS_OK(status)) {
1149 werr = ntstatus_to_werror(status);
1150 goto done;
1155 if (set) {
1157 struct lsa_SidArray current_sids;
1159 status = rpccli_samr_GetMembersInAlias(pipe_cli, talloc_tos(),
1160 &alias_handle,
1161 &current_sids);
1162 if (!NT_STATUS_IS_OK(status)) {
1163 werr = ntstatus_to_werror(status);
1164 goto done;
1167 /* add list */
1169 for (i=0; i < r->in.total_entries; i++) {
1170 bool already_member = false;
1171 for (k=0; k < current_sids.num_sids; k++) {
1172 if (sid_equal(&member_sids[i],
1173 current_sids.sids[k].sid)) {
1174 already_member = true;
1175 break;
1178 if (!already_member) {
1179 status = add_sid_to_array_unique(ctx,
1180 &member_sids[i],
1181 &add_sids, &num_add_sids);
1182 if (!NT_STATUS_IS_OK(status)) {
1183 werr = ntstatus_to_werror(status);
1184 goto done;
1189 /* del list */
1191 for (k=0; k < current_sids.num_sids; k++) {
1192 bool keep_member = false;
1193 for (i=0; i < r->in.total_entries; i++) {
1194 if (sid_equal(&member_sids[i],
1195 current_sids.sids[k].sid)) {
1196 keep_member = true;
1197 break;
1200 if (!keep_member) {
1201 status = add_sid_to_array_unique(ctx,
1202 current_sids.sids[k].sid,
1203 &del_sids, &num_del_sids);
1204 if (!NT_STATUS_IS_OK(status)) {
1205 werr = ntstatus_to_werror(status);
1206 goto done;
1212 /* add list */
1214 for (i=0; i < num_add_sids; i++) {
1215 status = rpccli_samr_AddAliasMember(pipe_cli, talloc_tos(),
1216 &alias_handle,
1217 &add_sids[i]);
1218 if (!NT_STATUS_IS_OK(status)) {
1219 werr = ntstatus_to_werror(status);
1220 goto done;
1224 /* del list */
1226 for (i=0; i < num_del_sids; i++) {
1227 status = rpccli_samr_DeleteAliasMember(pipe_cli, talloc_tos(),
1228 &alias_handle,
1229 &del_sids[i]);
1230 if (!NT_STATUS_IS_OK(status)) {
1231 werr = ntstatus_to_werror(status);
1232 goto done;
1236 werr = WERR_OK;
1238 done:
1239 if (is_valid_policy_hnd(&alias_handle)) {
1240 rpccli_samr_Close(pipe_cli, talloc_tos(), &alias_handle);
1243 if (ctx->disable_policy_handle_cache) {
1244 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1245 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1246 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1249 return werr;
1252 /****************************************************************
1253 ****************************************************************/
1255 WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
1256 struct NetLocalGroupAddMembers *r)
1258 return NetLocalGroupModifyMembers_r(ctx, r, NULL, NULL);
1261 /****************************************************************
1262 ****************************************************************/
1264 WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
1265 struct NetLocalGroupAddMembers *r)
1267 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAddMembers);
1270 /****************************************************************
1271 ****************************************************************/
1273 WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
1274 struct NetLocalGroupDelMembers *r)
1276 return NetLocalGroupModifyMembers_r(ctx, NULL, r, NULL);
1279 /****************************************************************
1280 ****************************************************************/
1282 WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
1283 struct NetLocalGroupDelMembers *r)
1285 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDelMembers);
1288 /****************************************************************
1289 ****************************************************************/
1291 WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
1292 struct NetLocalGroupGetMembers *r)
1294 return WERR_NOT_SUPPORTED;
1297 /****************************************************************
1298 ****************************************************************/
1300 WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
1301 struct NetLocalGroupGetMembers *r)
1303 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetMembers);
1306 /****************************************************************
1307 ****************************************************************/
1309 WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
1310 struct NetLocalGroupSetMembers *r)
1312 return NetLocalGroupModifyMembers_r(ctx, NULL, NULL, r);
1315 /****************************************************************
1316 ****************************************************************/
1318 WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
1319 struct NetLocalGroupSetMembers *r)
1321 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetMembers);