s3:g_lock: reorder the logic in g_lock_lock_simple_fn()
[Samba.git] / source3 / lib / netapi / localgroup.c
blob5d6ad174fb1d3a3904239156fa605945f8a7fa4d
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;
972 if (!sid || !name) {
973 return NT_STATUS_INVALID_PARAMETER;
976 ZERO_STRUCT(sids);
978 init_lsa_String(&names, name);
980 status = rpccli_lsa_open_policy2(lsa_pipe, mem_ctx,
981 false,
982 SEC_STD_READ_CONTROL |
983 LSA_POLICY_VIEW_LOCAL_INFORMATION |
984 LSA_POLICY_LOOKUP_NAMES,
985 &lsa_handle);
986 NT_STATUS_NOT_OK_RETURN(status);
988 status = dcerpc_lsa_LookupNames3(b, mem_ctx,
989 &lsa_handle,
990 num_names,
991 &names,
992 &domains,
993 &sids,
994 LSA_LOOKUP_NAMES_ALL, /* sure ? */
995 &count,
996 0, 0,
997 &result);
998 NT_STATUS_NOT_OK_RETURN(status);
999 NT_STATUS_NOT_OK_RETURN(result);
1001 if (count != 1 || sids.count != 1) {
1002 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1005 sid_copy(sid, sids.sids[0].sid);
1007 return NT_STATUS_OK;
1010 /****************************************************************
1011 ****************************************************************/
1013 static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
1014 struct NetLocalGroupAddMembers *add,
1015 struct NetLocalGroupDelMembers *del,
1016 struct NetLocalGroupSetMembers *set)
1018 struct NetLocalGroupAddMembers *r = NULL;
1020 struct rpc_pipe_client *pipe_cli = NULL;
1021 struct rpc_pipe_client *lsa_pipe = NULL;
1022 NTSTATUS status, result;
1023 WERROR werr;
1024 struct lsa_String lsa_account_name;
1025 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
1026 struct dom_sid2 *domain_sid = NULL;
1027 struct dom_sid *member_sids = NULL;
1028 int i = 0, k = 0;
1030 struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
1031 struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
1033 struct dom_sid *add_sids = NULL;
1034 struct dom_sid *del_sids = NULL;
1035 uint32_t num_add_sids = 0;
1036 uint32_t num_del_sids = 0;
1037 struct dcerpc_binding_handle *b = NULL;
1039 if ((!add && !del && !set) || (add && del && set)) {
1040 return WERR_INVALID_PARAMETER;
1043 if (add) {
1044 r = add;
1047 if (del) {
1048 r = (struct NetLocalGroupAddMembers *)del;
1051 if (set) {
1052 r = (struct NetLocalGroupAddMembers *)set;
1055 if (r==NULL || r->in.group_name == NULL) {
1056 return WERR_INVALID_PARAMETER;
1059 switch (r->in.level) {
1060 case 0:
1061 case 3:
1062 break;
1063 default:
1064 return WERR_INVALID_LEVEL;
1067 if (r->in.total_entries == 0 || !r->in.buffer) {
1068 return WERR_INVALID_PARAMETER;
1071 ZERO_STRUCT(connect_handle);
1072 ZERO_STRUCT(builtin_handle);
1073 ZERO_STRUCT(domain_handle);
1074 ZERO_STRUCT(alias_handle);
1076 member_sids = talloc_zero_array(ctx, struct dom_sid,
1077 r->in.total_entries);
1078 W_ERROR_HAVE_NO_MEMORY(member_sids);
1080 switch (r->in.level) {
1081 case 0:
1082 info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
1083 for (i=0; i < r->in.total_entries; i++) {
1084 sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
1086 break;
1087 case 3:
1088 info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
1089 break;
1090 default:
1091 break;
1094 if (r->in.level == 3) {
1095 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1096 &ndr_table_lsarpc,
1097 &lsa_pipe);
1098 if (!W_ERROR_IS_OK(werr)) {
1099 goto done;
1102 for (i=0; i < r->in.total_entries; i++) {
1103 status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
1104 info3[i].lgrmi3_domainandname,
1105 &member_sids[i]);
1106 if (!NT_STATUS_IS_OK(status)) {
1107 werr = ntstatus_to_werror(status);
1108 goto done;
1111 TALLOC_FREE(lsa_pipe);
1114 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1115 &ndr_table_samr,
1116 &pipe_cli);
1117 if (!W_ERROR_IS_OK(werr)) {
1118 goto done;
1121 b = pipe_cli->binding_handle;
1123 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1124 SAMR_ACCESS_LOOKUP_DOMAIN |
1125 SAMR_ACCESS_ENUM_DOMAINS,
1126 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1127 &connect_handle,
1128 &builtin_handle);
1129 if (!W_ERROR_IS_OK(werr)) {
1130 goto done;
1133 init_lsa_String(&lsa_account_name, r->in.group_name);
1135 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1136 &builtin_handle,
1137 r->in.group_name,
1138 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1139 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1140 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1141 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1142 &alias_handle);
1144 if (ctx->disable_policy_handle_cache) {
1145 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1148 if (NT_STATUS_IS_OK(status)) {
1149 goto modify_membership;
1152 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1153 SAMR_ACCESS_ENUM_DOMAINS |
1154 SAMR_ACCESS_LOOKUP_DOMAIN,
1155 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1156 &connect_handle,
1157 &domain_handle,
1158 &domain_sid);
1159 if (!W_ERROR_IS_OK(werr)) {
1160 goto done;
1163 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1164 &domain_handle,
1165 r->in.group_name,
1166 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1167 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1168 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1169 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1170 &alias_handle);
1171 if (!NT_STATUS_IS_OK(status)) {
1172 werr = ntstatus_to_werror(status);
1173 goto done;
1176 if (ctx->disable_policy_handle_cache) {
1177 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1180 modify_membership:
1182 if (add) {
1183 for (i=0; i < r->in.total_entries; i++) {
1184 status = add_sid_to_array_unique(ctx, &member_sids[i],
1185 &add_sids,
1186 &num_add_sids);
1187 if (!NT_STATUS_IS_OK(status)) {
1188 werr = ntstatus_to_werror(status);
1189 goto done;
1194 if (del) {
1195 for (i=0; i < r->in.total_entries; i++) {
1196 status = add_sid_to_array_unique(ctx, &member_sids[i],
1197 &del_sids,
1198 &num_del_sids);
1199 if (!NT_STATUS_IS_OK(status)) {
1200 werr = ntstatus_to_werror(status);
1201 goto done;
1206 if (set) {
1208 struct lsa_SidArray current_sids;
1210 status = dcerpc_samr_GetMembersInAlias(b, talloc_tos(),
1211 &alias_handle,
1212 &current_sids,
1213 &result);
1214 if (any_nt_status_not_ok(status, result, &status)) {
1215 werr = ntstatus_to_werror(status);
1216 goto done;
1219 /* add list */
1221 for (i=0; i < r->in.total_entries; i++) {
1222 bool already_member = false;
1223 for (k=0; k < current_sids.num_sids; k++) {
1224 if (dom_sid_equal(&member_sids[i],
1225 current_sids.sids[k].sid)) {
1226 already_member = true;
1227 break;
1230 if (!already_member) {
1231 status = add_sid_to_array_unique(ctx,
1232 &member_sids[i],
1233 &add_sids, &num_add_sids);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 werr = ntstatus_to_werror(status);
1236 goto done;
1241 /* del list */
1243 for (k=0; k < current_sids.num_sids; k++) {
1244 bool keep_member = false;
1245 for (i=0; i < r->in.total_entries; i++) {
1246 if (dom_sid_equal(&member_sids[i],
1247 current_sids.sids[k].sid)) {
1248 keep_member = true;
1249 break;
1252 if (!keep_member) {
1253 status = add_sid_to_array_unique(ctx,
1254 current_sids.sids[k].sid,
1255 &del_sids, &num_del_sids);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 werr = ntstatus_to_werror(status);
1258 goto done;
1264 /* add list */
1266 for (i=0; i < num_add_sids; i++) {
1267 status = dcerpc_samr_AddAliasMember(b, talloc_tos(),
1268 &alias_handle,
1269 &add_sids[i],
1270 &result);
1271 if (any_nt_status_not_ok(status, result, &status)) {
1272 werr = ntstatus_to_werror(status);
1273 goto done;
1277 /* del list */
1279 for (i=0; i < num_del_sids; i++) {
1280 status = dcerpc_samr_DeleteAliasMember(b, talloc_tos(),
1281 &alias_handle,
1282 &del_sids[i],
1283 &result);
1284 if (any_nt_status_not_ok(status, result, &status)) {
1285 werr = ntstatus_to_werror(status);
1286 goto done;
1290 werr = WERR_OK;
1292 done:
1293 if (b && is_valid_policy_hnd(&alias_handle)) {
1294 dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
1297 if (ctx->disable_policy_handle_cache) {
1298 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1299 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1300 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1303 return werr;
1306 /****************************************************************
1307 ****************************************************************/
1309 WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
1310 struct NetLocalGroupAddMembers *r)
1312 return NetLocalGroupModifyMembers_r(ctx, r, NULL, NULL);
1315 /****************************************************************
1316 ****************************************************************/
1318 WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
1319 struct NetLocalGroupAddMembers *r)
1321 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAddMembers);
1324 /****************************************************************
1325 ****************************************************************/
1327 WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
1328 struct NetLocalGroupDelMembers *r)
1330 return NetLocalGroupModifyMembers_r(ctx, NULL, r, NULL);
1333 /****************************************************************
1334 ****************************************************************/
1336 WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
1337 struct NetLocalGroupDelMembers *r)
1339 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDelMembers);
1342 /****************************************************************
1343 ****************************************************************/
1345 WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
1346 struct NetLocalGroupGetMembers *r)
1348 return WERR_NOT_SUPPORTED;
1351 /****************************************************************
1352 ****************************************************************/
1354 WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
1355 struct NetLocalGroupGetMembers *r)
1357 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetMembers);
1360 /****************************************************************
1361 ****************************************************************/
1363 WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
1364 struct NetLocalGroupSetMembers *r)
1366 return NetLocalGroupModifyMembers_r(ctx, NULL, NULL, r);
1369 /****************************************************************
1370 ****************************************************************/
1372 WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
1373 struct NetLocalGroupSetMembers *r)
1375 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetMembers);