selftest: Move MIT Kerberos knownfails to separate files in their own directory
[Samba.git] / source3 / lib / netapi / localgroup.c
bloba63fca4366abb3f540b7a3e05e623e8171b11342
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 "rpc_client/rpc_client.h"
27 #include "../librpc/gen_ndr/ndr_samr_c.h"
28 #include "../librpc/gen_ndr/ndr_lsa_c.h"
29 #include "rpc_client/cli_lsarpc.h"
30 #include "rpc_client/init_lsa.h"
31 #include "../libcli/security/security.h"
33 static NTSTATUS libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
34 struct rpc_pipe_client *pipe_cli,
35 struct policy_handle *domain_handle,
36 const char *group_name,
37 uint32_t access_rights,
38 struct policy_handle *alias_handle)
40 NTSTATUS status, result;
42 struct lsa_String lsa_account_name;
43 struct samr_Ids user_rids, name_types;
44 struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
46 init_lsa_String(&lsa_account_name, group_name);
48 status = dcerpc_samr_LookupNames(b, mem_ctx,
49 domain_handle,
51 &lsa_account_name,
52 &user_rids,
53 &name_types,
54 &result);
55 if (any_nt_status_not_ok(status, result, &status)) {
56 return status;
58 if (user_rids.count != 1) {
59 return NT_STATUS_INVALID_NETWORK_RESPONSE;
61 if (name_types.count != 1) {
62 return NT_STATUS_INVALID_NETWORK_RESPONSE;
65 switch (name_types.ids[0]) {
66 case SID_NAME_ALIAS:
67 case SID_NAME_WKN_GRP:
68 break;
69 default:
70 return NT_STATUS_INVALID_SID;
73 status = dcerpc_samr_OpenAlias(b, mem_ctx,
74 domain_handle,
75 access_rights,
76 user_rids.ids[0],
77 alias_handle,
78 &result);
79 if (!NT_STATUS_IS_OK(status)) {
80 return status;
83 return result;
86 /****************************************************************
87 ****************************************************************/
89 static NTSTATUS libnetapi_samr_open_alias_queryinfo(TALLOC_CTX *mem_ctx,
90 struct rpc_pipe_client *pipe_cli,
91 struct policy_handle *handle,
92 uint32_t rid,
93 uint32_t access_rights,
94 enum samr_AliasInfoEnum level,
95 union samr_AliasInfo **alias_info)
97 NTSTATUS status, result;
98 struct policy_handle alias_handle;
99 union samr_AliasInfo *_alias_info = NULL;
100 struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
102 ZERO_STRUCT(alias_handle);
104 status = dcerpc_samr_OpenAlias(b, mem_ctx,
105 handle,
106 access_rights,
107 rid,
108 &alias_handle,
109 &result);
110 if (any_nt_status_not_ok(status, result, &status)) {
111 goto done;
114 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
115 &alias_handle,
116 level,
117 &_alias_info,
118 &result);
119 if (any_nt_status_not_ok(status, result, &status)) {
120 goto done;
123 *alias_info = _alias_info;
125 done:
126 if (is_valid_policy_hnd(&alias_handle)) {
127 dcerpc_samr_Close(b, mem_ctx, &alias_handle, &result);
130 return status;
133 /****************************************************************
134 ****************************************************************/
136 WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
137 struct NetLocalGroupAdd *r)
139 struct rpc_pipe_client *pipe_cli = NULL;
140 NTSTATUS status, result;
141 WERROR werr;
142 struct lsa_String lsa_account_name;
143 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
144 struct dom_sid2 *domain_sid = NULL;
145 uint32_t rid;
146 struct dcerpc_binding_handle *b = NULL;
148 struct LOCALGROUP_INFO_0 *info0 = NULL;
149 struct LOCALGROUP_INFO_1 *info1 = NULL;
151 const char *alias_name = NULL;
153 if (!r->in.buffer) {
154 return WERR_INVALID_PARAMETER;
157 ZERO_STRUCT(connect_handle);
158 ZERO_STRUCT(builtin_handle);
159 ZERO_STRUCT(domain_handle);
160 ZERO_STRUCT(alias_handle);
162 switch (r->in.level) {
163 case 0:
164 info0 = (struct LOCALGROUP_INFO_0 *)r->in.buffer;
165 alias_name = info0->lgrpi0_name;
166 break;
167 case 1:
168 info1 = (struct LOCALGROUP_INFO_1 *)r->in.buffer;
169 alias_name = info1->lgrpi1_name;
170 break;
171 default:
172 werr = WERR_INVALID_LEVEL;
173 goto done;
176 werr = libnetapi_open_pipe(ctx, r->in.server_name,
177 &ndr_table_samr,
178 &pipe_cli);
179 if (!W_ERROR_IS_OK(werr)) {
180 goto done;
183 b = pipe_cli->binding_handle;
185 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
186 SAMR_ACCESS_LOOKUP_DOMAIN |
187 SAMR_ACCESS_ENUM_DOMAINS,
188 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
189 &connect_handle,
190 &builtin_handle);
191 if (!W_ERROR_IS_OK(werr)) {
192 goto done;
195 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
196 &builtin_handle,
197 alias_name,
198 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
199 &alias_handle);
200 if (ctx->disable_policy_handle_cache) {
201 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
204 if (NT_STATUS_IS_OK(status)) {
205 werr = WERR_ALIAS_EXISTS;
206 goto done;
209 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
210 SAMR_ACCESS_ENUM_DOMAINS |
211 SAMR_ACCESS_LOOKUP_DOMAIN,
212 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
213 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
214 &connect_handle,
215 &domain_handle,
216 &domain_sid);
217 if (!W_ERROR_IS_OK(werr)) {
218 goto done;
221 init_lsa_String(&lsa_account_name, alias_name);
223 status = dcerpc_samr_CreateDomAlias(b, talloc_tos(),
224 &domain_handle,
225 &lsa_account_name,
226 SEC_STD_DELETE |
227 SAMR_ALIAS_ACCESS_SET_INFO,
228 &alias_handle,
229 &rid,
230 &result);
231 if (any_nt_status_not_ok(status, result, &status)) {
232 werr = ntstatus_to_werror(status);
233 goto done;
236 if (r->in.level == 1 && info1->lgrpi1_comment) {
238 union samr_AliasInfo alias_info;
240 init_lsa_String(&alias_info.description, info1->lgrpi1_comment);
242 status = dcerpc_samr_SetAliasInfo(b, talloc_tos(),
243 &alias_handle,
244 ALIASINFODESCRIPTION,
245 &alias_info,
246 &result);
247 if (any_nt_status_not_ok(status, result, &status)) {
248 werr = ntstatus_to_werror(status);
249 goto done;
253 werr = WERR_OK;
255 done:
256 if (is_valid_policy_hnd(&alias_handle)) {
257 dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
260 if (ctx->disable_policy_handle_cache) {
261 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
262 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
263 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
266 return werr;
269 /****************************************************************
270 ****************************************************************/
272 WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
273 struct NetLocalGroupAdd *r)
275 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAdd);
278 /****************************************************************
279 ****************************************************************/
282 WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
283 struct NetLocalGroupDel *r)
285 struct rpc_pipe_client *pipe_cli = NULL;
286 NTSTATUS status, result;
287 WERROR werr;
288 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
289 struct dom_sid2 *domain_sid = NULL;
290 struct dcerpc_binding_handle *b = NULL;
292 if (!r->in.group_name) {
293 return WERR_INVALID_PARAMETER;
296 ZERO_STRUCT(connect_handle);
297 ZERO_STRUCT(builtin_handle);
298 ZERO_STRUCT(domain_handle);
299 ZERO_STRUCT(alias_handle);
301 werr = libnetapi_open_pipe(ctx, r->in.server_name,
302 &ndr_table_samr,
303 &pipe_cli);
304 if (!W_ERROR_IS_OK(werr)) {
305 goto done;
308 b = pipe_cli->binding_handle;
310 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
311 SAMR_ACCESS_LOOKUP_DOMAIN |
312 SAMR_ACCESS_ENUM_DOMAINS,
313 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
314 &connect_handle,
315 &builtin_handle);
316 if (!W_ERROR_IS_OK(werr)) {
317 goto done;
320 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
321 &builtin_handle,
322 r->in.group_name,
323 SEC_STD_DELETE,
324 &alias_handle);
326 if (ctx->disable_policy_handle_cache) {
327 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
330 if (NT_STATUS_IS_OK(status)) {
331 goto delete_alias;
334 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
335 SAMR_ACCESS_ENUM_DOMAINS |
336 SAMR_ACCESS_LOOKUP_DOMAIN,
337 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
338 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
339 &connect_handle,
340 &domain_handle,
341 &domain_sid);
342 if (!W_ERROR_IS_OK(werr)) {
343 goto done;
346 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
347 &domain_handle,
348 r->in.group_name,
349 SEC_STD_DELETE,
350 &alias_handle);
352 if (ctx->disable_policy_handle_cache) {
353 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
356 if (!NT_STATUS_IS_OK(status)) {
357 werr = ntstatus_to_werror(status);
358 goto done;
362 delete_alias:
363 status = dcerpc_samr_DeleteDomAlias(b, talloc_tos(),
364 &alias_handle,
365 &result);
366 if (any_nt_status_not_ok(status, result, &status)) {
367 werr = ntstatus_to_werror(status);
368 goto done;
371 ZERO_STRUCT(alias_handle);
373 werr = WERR_OK;
375 done:
376 if (is_valid_policy_hnd(&alias_handle)) {
377 dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
380 if (ctx->disable_policy_handle_cache) {
381 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
382 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
383 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
386 return werr;
389 /****************************************************************
390 ****************************************************************/
392 WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
393 struct NetLocalGroupDel *r)
395 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDel);
398 /****************************************************************
399 ****************************************************************/
401 static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
402 const char *alias_name,
403 struct samr_AliasInfoAll *info,
404 uint32_t level,
405 uint32_t *entries_read,
406 uint8_t **buffer)
408 struct LOCALGROUP_INFO_0 g0;
409 struct LOCALGROUP_INFO_1 g1;
410 struct LOCALGROUP_INFO_1002 g1002;
412 switch (level) {
413 case 0:
414 g0.lgrpi0_name = talloc_strdup(mem_ctx, alias_name);
415 W_ERROR_HAVE_NO_MEMORY(g0.lgrpi0_name);
417 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_0, g0,
418 (struct LOCALGROUP_INFO_0 **)buffer, entries_read);
420 break;
421 case 1:
422 g1.lgrpi1_name = talloc_strdup(mem_ctx, alias_name);
423 g1.lgrpi1_comment = talloc_strdup(mem_ctx, info->description.string);
424 W_ERROR_HAVE_NO_MEMORY(g1.lgrpi1_name);
426 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1, g1,
427 (struct LOCALGROUP_INFO_1 **)buffer, entries_read);
429 break;
430 case 1002:
431 g1002.lgrpi1002_comment = talloc_strdup(mem_ctx, info->description.string);
433 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1002, g1002,
434 (struct LOCALGROUP_INFO_1002 **)buffer, entries_read);
436 break;
437 default:
438 return WERR_INVALID_LEVEL;
441 return WERR_OK;
444 /****************************************************************
445 ****************************************************************/
447 WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
448 struct NetLocalGroupGetInfo *r)
450 struct rpc_pipe_client *pipe_cli = NULL;
451 NTSTATUS status, result;
452 WERROR werr;
453 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
454 struct dom_sid2 *domain_sid = NULL;
455 union samr_AliasInfo *alias_info = NULL;
456 uint32_t entries_read = 0;
457 struct dcerpc_binding_handle *b = NULL;
459 if (!r->in.group_name) {
460 return WERR_INVALID_PARAMETER;
463 switch (r->in.level) {
464 case 0:
465 case 1:
466 case 1002:
467 break;
468 default:
469 return WERR_INVALID_LEVEL;
472 ZERO_STRUCT(connect_handle);
473 ZERO_STRUCT(builtin_handle);
474 ZERO_STRUCT(domain_handle);
475 ZERO_STRUCT(alias_handle);
477 werr = libnetapi_open_pipe(ctx, r->in.server_name,
478 &ndr_table_samr,
479 &pipe_cli);
480 if (!W_ERROR_IS_OK(werr)) {
481 goto done;
484 b = pipe_cli->binding_handle;
486 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
487 SAMR_ACCESS_LOOKUP_DOMAIN |
488 SAMR_ACCESS_ENUM_DOMAINS,
489 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
490 &connect_handle,
491 &builtin_handle);
492 if (!W_ERROR_IS_OK(werr)) {
493 goto done;
496 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
497 &builtin_handle,
498 r->in.group_name,
499 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
500 &alias_handle);
502 if (ctx->disable_policy_handle_cache) {
503 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
506 if (NT_STATUS_IS_OK(status)) {
507 goto query_alias;
510 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
511 SAMR_ACCESS_ENUM_DOMAINS |
512 SAMR_ACCESS_LOOKUP_DOMAIN,
513 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
514 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
515 &connect_handle,
516 &domain_handle,
517 &domain_sid);
518 if (!W_ERROR_IS_OK(werr)) {
519 goto done;
522 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
523 &domain_handle,
524 r->in.group_name,
525 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
526 &alias_handle);
528 if (ctx->disable_policy_handle_cache) {
529 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
532 if (!NT_STATUS_IS_OK(status)) {
533 werr = ntstatus_to_werror(status);
534 goto done;
537 query_alias:
538 status = dcerpc_samr_QueryAliasInfo(b, talloc_tos(),
539 &alias_handle,
540 ALIASINFOALL,
541 &alias_info,
542 &result);
543 if (any_nt_status_not_ok(status, result, &status)) {
544 werr = ntstatus_to_werror(status);
545 goto done;
548 werr = map_alias_info_to_buffer(ctx,
549 r->in.group_name,
550 &alias_info->all,
551 r->in.level, &entries_read,
552 r->out.buffer);
554 done:
555 if (is_valid_policy_hnd(&alias_handle)) {
556 dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
559 if (ctx->disable_policy_handle_cache) {
560 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
561 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
562 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
565 return werr;
568 /****************************************************************
569 ****************************************************************/
571 WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
572 struct NetLocalGroupGetInfo *r)
574 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetInfo);
577 /****************************************************************
578 ****************************************************************/
580 static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
581 uint32_t level,
582 uint8_t *buffer,
583 enum samr_AliasInfoEnum *alias_level,
584 union samr_AliasInfo **alias_info)
586 struct LOCALGROUP_INFO_0 *info0;
587 struct LOCALGROUP_INFO_1 *info1;
588 struct LOCALGROUP_INFO_1002 *info1002;
589 union samr_AliasInfo *info = NULL;
591 info = talloc_zero(mem_ctx, union samr_AliasInfo);
592 W_ERROR_HAVE_NO_MEMORY(info);
594 switch (level) {
595 case 0:
596 info0 = (struct LOCALGROUP_INFO_0 *)buffer;
597 init_lsa_String(&info->name, info0->lgrpi0_name);
598 *alias_level = ALIASINFONAME;
599 break;
600 case 1:
601 info1 = (struct LOCALGROUP_INFO_1 *)buffer;
602 /* group name will be ignored */
603 init_lsa_String(&info->description, info1->lgrpi1_comment);
604 *alias_level = ALIASINFODESCRIPTION;
605 break;
606 case 1002:
607 info1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
608 init_lsa_String(&info->description, info1002->lgrpi1002_comment);
609 *alias_level = ALIASINFODESCRIPTION;
610 break;
613 *alias_info = info;
615 return WERR_OK;
618 /****************************************************************
619 ****************************************************************/
621 WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
622 struct NetLocalGroupSetInfo *r)
624 struct rpc_pipe_client *pipe_cli = NULL;
625 NTSTATUS status, result;
626 WERROR werr;
627 struct lsa_String lsa_account_name;
628 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
629 struct dom_sid2 *domain_sid = NULL;
630 enum samr_AliasInfoEnum alias_level = 0;
631 union samr_AliasInfo *alias_info = NULL;
632 struct dcerpc_binding_handle *b = NULL;
634 if (!r->in.group_name) {
635 return WERR_INVALID_PARAMETER;
638 switch (r->in.level) {
639 case 0:
640 case 1:
641 case 1002:
642 break;
643 default:
644 return WERR_INVALID_LEVEL;
647 ZERO_STRUCT(connect_handle);
648 ZERO_STRUCT(builtin_handle);
649 ZERO_STRUCT(domain_handle);
650 ZERO_STRUCT(alias_handle);
652 werr = libnetapi_open_pipe(ctx, r->in.server_name,
653 &ndr_table_samr,
654 &pipe_cli);
655 if (!W_ERROR_IS_OK(werr)) {
656 goto done;
659 b = pipe_cli->binding_handle;
661 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
662 SAMR_ACCESS_LOOKUP_DOMAIN |
663 SAMR_ACCESS_ENUM_DOMAINS,
664 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
665 &connect_handle,
666 &builtin_handle);
667 if (!W_ERROR_IS_OK(werr)) {
668 goto done;
671 init_lsa_String(&lsa_account_name, r->in.group_name);
673 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
674 &builtin_handle,
675 r->in.group_name,
676 SAMR_ALIAS_ACCESS_SET_INFO,
677 &alias_handle);
679 if (ctx->disable_policy_handle_cache) {
680 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
683 if (NT_STATUS_IS_OK(status)) {
684 goto set_alias;
687 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
688 SAMR_ACCESS_ENUM_DOMAINS |
689 SAMR_ACCESS_LOOKUP_DOMAIN,
690 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
691 &connect_handle,
692 &domain_handle,
693 &domain_sid);
694 if (!W_ERROR_IS_OK(werr)) {
695 goto done;
698 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
699 &domain_handle,
700 r->in.group_name,
701 SAMR_ALIAS_ACCESS_SET_INFO,
702 &alias_handle);
703 if (!NT_STATUS_IS_OK(status)) {
704 werr = ntstatus_to_werror(status);
705 goto done;
708 if (ctx->disable_policy_handle_cache) {
709 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
712 set_alias:
714 werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buffer,
715 &alias_level, &alias_info);
716 if (!W_ERROR_IS_OK(werr)) {
717 goto done;
720 status = dcerpc_samr_SetAliasInfo(b, talloc_tos(),
721 &alias_handle,
722 alias_level,
723 alias_info,
724 &result);
725 if (any_nt_status_not_ok(status, result, &status)) {
726 werr = ntstatus_to_werror(status);
727 goto done;
730 werr = WERR_OK;
732 done:
733 if (is_valid_policy_hnd(&alias_handle)) {
734 dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
737 if (ctx->disable_policy_handle_cache) {
738 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
739 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
740 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
743 return werr;
746 /****************************************************************
747 ****************************************************************/
749 WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
750 struct NetLocalGroupSetInfo *r)
752 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetInfo);
755 /****************************************************************
756 ****************************************************************/
758 WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
759 struct NetLocalGroupEnum *r)
761 struct rpc_pipe_client *pipe_cli = NULL;
762 NTSTATUS status, result;
763 WERROR werr;
764 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
765 struct dom_sid2 *domain_sid = NULL;
766 uint32_t entries_read = 0;
767 union samr_DomainInfo *domain_info = NULL;
768 union samr_DomainInfo *builtin_info = NULL;
769 struct samr_SamArray *domain_sam_array = NULL;
770 struct samr_SamArray *builtin_sam_array = NULL;
771 int i;
772 struct dcerpc_binding_handle *b = NULL;
774 if (!r->out.buffer) {
775 return WERR_INVALID_PARAMETER;
778 switch (r->in.level) {
779 case 0:
780 case 1:
781 break;
782 default:
783 return WERR_INVALID_LEVEL;
786 if (r->out.total_entries) {
787 *r->out.total_entries = 0;
789 if (r->out.entries_read) {
790 *r->out.entries_read = 0;
793 ZERO_STRUCT(connect_handle);
794 ZERO_STRUCT(builtin_handle);
795 ZERO_STRUCT(domain_handle);
796 ZERO_STRUCT(alias_handle);
798 werr = libnetapi_open_pipe(ctx, r->in.server_name,
799 &ndr_table_samr,
800 &pipe_cli);
801 if (!W_ERROR_IS_OK(werr)) {
802 goto done;
805 b = pipe_cli->binding_handle;
807 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
808 SAMR_ACCESS_LOOKUP_DOMAIN |
809 SAMR_ACCESS_ENUM_DOMAINS,
810 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
811 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
812 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
813 &connect_handle,
814 &builtin_handle);
815 if (!W_ERROR_IS_OK(werr)) {
816 goto done;
819 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
820 SAMR_ACCESS_LOOKUP_DOMAIN |
821 SAMR_ACCESS_ENUM_DOMAINS,
822 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
823 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
824 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
825 &connect_handle,
826 &domain_handle,
827 &domain_sid);
828 if (!W_ERROR_IS_OK(werr)) {
829 goto done;
832 status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
833 &builtin_handle,
835 &builtin_info,
836 &result);
837 if (any_nt_status_not_ok(status, result, &status)) {
838 werr = ntstatus_to_werror(status);
839 goto done;
842 if (r->out.total_entries) {
843 *r->out.total_entries += builtin_info->general.num_aliases;
846 status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
847 &domain_handle,
849 &domain_info,
850 &result);
851 if (any_nt_status_not_ok(status, result, &status)) {
852 werr = ntstatus_to_werror(status);
853 goto done;
856 if (r->out.total_entries) {
857 *r->out.total_entries += domain_info->general.num_aliases;
860 status = dcerpc_samr_EnumDomainAliases(b, talloc_tos(),
861 &builtin_handle,
862 r->in.resume_handle,
863 &builtin_sam_array,
864 r->in.prefmaxlen,
865 &entries_read,
866 &result);
867 if (any_nt_status_not_ok(status, result, &status)) {
868 werr = ntstatus_to_werror(status);
869 goto done;
872 for (i=0; i<builtin_sam_array->count; i++) {
873 union samr_AliasInfo *alias_info = NULL;
875 if (r->in.level == 1) {
877 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
878 &builtin_handle,
879 builtin_sam_array->entries[i].idx,
880 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
881 ALIASINFOALL,
882 &alias_info);
883 if (!NT_STATUS_IS_OK(status)) {
884 werr = ntstatus_to_werror(status);
885 goto done;
889 werr = map_alias_info_to_buffer(ctx,
890 builtin_sam_array->entries[i].name.string,
891 alias_info ? &alias_info->all : NULL,
892 r->in.level,
893 r->out.entries_read,
894 r->out.buffer);
897 status = dcerpc_samr_EnumDomainAliases(b, talloc_tos(),
898 &domain_handle,
899 r->in.resume_handle,
900 &domain_sam_array,
901 r->in.prefmaxlen,
902 &entries_read,
903 &result);
904 if (any_nt_status_not_ok(status, result, &status)) {
905 werr = ntstatus_to_werror(status);
906 goto done;
909 for (i=0; i<domain_sam_array->count; i++) {
911 union samr_AliasInfo *alias_info = NULL;
913 if (r->in.level == 1) {
914 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
915 &domain_handle,
916 domain_sam_array->entries[i].idx,
917 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
918 ALIASINFOALL,
919 &alias_info);
920 if (!NT_STATUS_IS_OK(status)) {
921 werr = ntstatus_to_werror(status);
922 goto done;
926 werr = map_alias_info_to_buffer(ctx,
927 domain_sam_array->entries[i].name.string,
928 alias_info ? &alias_info->all : NULL,
929 r->in.level,
930 r->out.entries_read,
931 r->out.buffer);
934 done:
935 if (ctx->disable_policy_handle_cache) {
936 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
937 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
938 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
941 return werr;
944 /****************************************************************
945 ****************************************************************/
947 WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
948 struct NetLocalGroupEnum *r)
950 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupEnum);
953 /****************************************************************
954 ****************************************************************/
956 static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx,
957 struct rpc_pipe_client *lsa_pipe,
958 const char *name,
959 struct dom_sid *sid)
961 NTSTATUS status, result;
962 struct policy_handle lsa_handle;
963 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
965 struct lsa_RefDomainList *domains = NULL;
966 struct lsa_TransSidArray3 sids;
967 uint32_t count = 0;
969 struct lsa_String names;
970 uint32_t num_names = 1;
971 union lsa_revision_info out_revision_info = {
972 .info1 = {
973 .revision = 0,
976 uint32_t out_version = 0;
978 if (!sid || !name) {
979 return NT_STATUS_INVALID_PARAMETER;
982 ZERO_STRUCT(sids);
984 init_lsa_String(&names, name);
986 status = dcerpc_lsa_open_policy_fallback(
988 mem_ctx,
989 lsa_pipe->srv_name_slash,
990 false,
991 SEC_STD_READ_CONTROL |
992 LSA_POLICY_VIEW_LOCAL_INFORMATION |
993 LSA_POLICY_LOOKUP_NAMES,
994 &out_version,
995 &out_revision_info,
996 &lsa_handle,
997 &result);
998 if (any_nt_status_not_ok(status, result, &status)) {
999 return status;
1002 status = dcerpc_lsa_LookupNames3(b, mem_ctx,
1003 &lsa_handle,
1004 num_names,
1005 &names,
1006 &domains,
1007 &sids,
1008 LSA_LOOKUP_NAMES_ALL, /* sure ? */
1009 &count,
1010 0, 0,
1011 &result);
1012 NT_STATUS_NOT_OK_RETURN(status);
1013 NT_STATUS_NOT_OK_RETURN(result);
1015 if (count != 1 || sids.count != 1) {
1016 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1019 sid_copy(sid, sids.sids[0].sid);
1021 return NT_STATUS_OK;
1024 /****************************************************************
1025 ****************************************************************/
1027 static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
1028 struct NetLocalGroupAddMembers *add,
1029 struct NetLocalGroupDelMembers *del,
1030 struct NetLocalGroupSetMembers *set)
1032 struct NetLocalGroupAddMembers *r = NULL;
1034 struct rpc_pipe_client *pipe_cli = NULL;
1035 struct rpc_pipe_client *lsa_pipe = NULL;
1036 NTSTATUS status, result;
1037 WERROR werr;
1038 struct lsa_String lsa_account_name;
1039 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
1040 struct dom_sid2 *domain_sid = NULL;
1041 struct dom_sid *member_sids = NULL;
1042 int i = 0, k = 0;
1044 struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
1045 struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
1047 struct dom_sid *add_sids = NULL;
1048 struct dom_sid *del_sids = NULL;
1049 uint32_t num_add_sids = 0;
1050 uint32_t num_del_sids = 0;
1051 struct dcerpc_binding_handle *b = NULL;
1053 if ((!add && !del && !set) || (add && del && set)) {
1054 return WERR_INVALID_PARAMETER;
1057 if (add) {
1058 r = add;
1061 if (del) {
1062 r = (struct NetLocalGroupAddMembers *)del;
1065 if (set) {
1066 r = (struct NetLocalGroupAddMembers *)set;
1069 if (r==NULL || r->in.group_name == NULL) {
1070 return WERR_INVALID_PARAMETER;
1073 switch (r->in.level) {
1074 case 0:
1075 case 3:
1076 break;
1077 default:
1078 return WERR_INVALID_LEVEL;
1081 if (r->in.total_entries == 0 || !r->in.buffer) {
1082 return WERR_INVALID_PARAMETER;
1085 ZERO_STRUCT(connect_handle);
1086 ZERO_STRUCT(builtin_handle);
1087 ZERO_STRUCT(domain_handle);
1088 ZERO_STRUCT(alias_handle);
1090 member_sids = talloc_zero_array(ctx, struct dom_sid,
1091 r->in.total_entries);
1092 W_ERROR_HAVE_NO_MEMORY(member_sids);
1094 switch (r->in.level) {
1095 case 0:
1096 info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
1097 for (i=0; i < r->in.total_entries; i++) {
1098 sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
1100 break;
1101 case 3:
1102 info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
1103 break;
1104 default:
1105 break;
1108 if (r->in.level == 3) {
1109 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1110 &ndr_table_lsarpc,
1111 &lsa_pipe);
1112 if (!W_ERROR_IS_OK(werr)) {
1113 goto done;
1116 for (i=0; i < r->in.total_entries; i++) {
1117 status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
1118 info3[i].lgrmi3_domainandname,
1119 &member_sids[i]);
1120 if (!NT_STATUS_IS_OK(status)) {
1121 werr = ntstatus_to_werror(status);
1122 goto done;
1125 TALLOC_FREE(lsa_pipe);
1128 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1129 &ndr_table_samr,
1130 &pipe_cli);
1131 if (!W_ERROR_IS_OK(werr)) {
1132 goto done;
1135 b = pipe_cli->binding_handle;
1137 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1138 SAMR_ACCESS_LOOKUP_DOMAIN |
1139 SAMR_ACCESS_ENUM_DOMAINS,
1140 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1141 &connect_handle,
1142 &builtin_handle);
1143 if (!W_ERROR_IS_OK(werr)) {
1144 goto done;
1147 init_lsa_String(&lsa_account_name, r->in.group_name);
1149 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1150 &builtin_handle,
1151 r->in.group_name,
1152 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1153 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1154 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1155 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1156 &alias_handle);
1158 if (ctx->disable_policy_handle_cache) {
1159 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1162 if (NT_STATUS_IS_OK(status)) {
1163 goto modify_membership;
1166 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1167 SAMR_ACCESS_ENUM_DOMAINS |
1168 SAMR_ACCESS_LOOKUP_DOMAIN,
1169 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1170 &connect_handle,
1171 &domain_handle,
1172 &domain_sid);
1173 if (!W_ERROR_IS_OK(werr)) {
1174 goto done;
1177 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1178 &domain_handle,
1179 r->in.group_name,
1180 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1181 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1182 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1183 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1184 &alias_handle);
1185 if (!NT_STATUS_IS_OK(status)) {
1186 werr = ntstatus_to_werror(status);
1187 goto done;
1190 if (ctx->disable_policy_handle_cache) {
1191 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1194 modify_membership:
1196 if (add) {
1197 for (i=0; i < r->in.total_entries; i++) {
1198 status = add_sid_to_array_unique(ctx, &member_sids[i],
1199 &add_sids,
1200 &num_add_sids);
1201 if (!NT_STATUS_IS_OK(status)) {
1202 werr = ntstatus_to_werror(status);
1203 goto done;
1208 if (del) {
1209 for (i=0; i < r->in.total_entries; i++) {
1210 status = add_sid_to_array_unique(ctx, &member_sids[i],
1211 &del_sids,
1212 &num_del_sids);
1213 if (!NT_STATUS_IS_OK(status)) {
1214 werr = ntstatus_to_werror(status);
1215 goto done;
1220 if (set) {
1222 struct lsa_SidArray current_sids;
1224 status = dcerpc_samr_GetMembersInAlias(b, talloc_tos(),
1225 &alias_handle,
1226 &current_sids,
1227 &result);
1228 if (any_nt_status_not_ok(status, result, &status)) {
1229 werr = ntstatus_to_werror(status);
1230 goto done;
1233 /* add list */
1235 for (i=0; i < r->in.total_entries; i++) {
1236 bool already_member = false;
1237 for (k=0; k < current_sids.num_sids; k++) {
1238 if (dom_sid_equal(&member_sids[i],
1239 current_sids.sids[k].sid)) {
1240 already_member = true;
1241 break;
1244 if (!already_member) {
1245 status = add_sid_to_array_unique(ctx,
1246 &member_sids[i],
1247 &add_sids, &num_add_sids);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 werr = ntstatus_to_werror(status);
1250 goto done;
1255 /* del list */
1257 for (k=0; k < current_sids.num_sids; k++) {
1258 bool keep_member = false;
1259 for (i=0; i < r->in.total_entries; i++) {
1260 if (dom_sid_equal(&member_sids[i],
1261 current_sids.sids[k].sid)) {
1262 keep_member = true;
1263 break;
1266 if (!keep_member) {
1267 status = add_sid_to_array_unique(ctx,
1268 current_sids.sids[k].sid,
1269 &del_sids, &num_del_sids);
1270 if (!NT_STATUS_IS_OK(status)) {
1271 werr = ntstatus_to_werror(status);
1272 goto done;
1278 /* add list */
1280 for (i=0; i < num_add_sids; i++) {
1281 status = dcerpc_samr_AddAliasMember(b, talloc_tos(),
1282 &alias_handle,
1283 &add_sids[i],
1284 &result);
1285 if (any_nt_status_not_ok(status, result, &status)) {
1286 werr = ntstatus_to_werror(status);
1287 goto done;
1291 /* del list */
1293 for (i=0; i < num_del_sids; i++) {
1294 status = dcerpc_samr_DeleteAliasMember(b, talloc_tos(),
1295 &alias_handle,
1296 &del_sids[i],
1297 &result);
1298 if (any_nt_status_not_ok(status, result, &status)) {
1299 werr = ntstatus_to_werror(status);
1300 goto done;
1304 werr = WERR_OK;
1306 done:
1307 if (b && is_valid_policy_hnd(&alias_handle)) {
1308 dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
1311 if (ctx->disable_policy_handle_cache) {
1312 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1313 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1314 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1317 return werr;
1320 /****************************************************************
1321 ****************************************************************/
1323 WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
1324 struct NetLocalGroupAddMembers *r)
1326 return NetLocalGroupModifyMembers_r(ctx, r, NULL, NULL);
1329 /****************************************************************
1330 ****************************************************************/
1332 WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
1333 struct NetLocalGroupAddMembers *r)
1335 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAddMembers);
1338 /****************************************************************
1339 ****************************************************************/
1341 WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
1342 struct NetLocalGroupDelMembers *r)
1344 return NetLocalGroupModifyMembers_r(ctx, NULL, r, NULL);
1347 /****************************************************************
1348 ****************************************************************/
1350 WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
1351 struct NetLocalGroupDelMembers *r)
1353 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDelMembers);
1356 /****************************************************************
1357 ****************************************************************/
1359 WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
1360 struct NetLocalGroupGetMembers *r)
1362 return WERR_NOT_SUPPORTED;
1365 /****************************************************************
1366 ****************************************************************/
1368 WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
1369 struct NetLocalGroupGetMembers *r)
1371 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetMembers);
1374 /****************************************************************
1375 ****************************************************************/
1377 WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
1378 struct NetLocalGroupSetMembers *r)
1380 return NetLocalGroupModifyMembers_r(ctx, NULL, NULL, r);
1383 /****************************************************************
1384 ****************************************************************/
1386 WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
1387 struct NetLocalGroupSetMembers *r)
1389 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetMembers);