CVE-2013-4408:s3:Ensure LookupNames replies arrays are range checked.
[Samba.git] / source3 / lib / netapi / localgroup.c
blob17cab689b4ea6c68484f719cee9aa33bb4b3acc5
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 (!NT_STATUS_IS_OK(status)) {
56 return status;
58 if (!NT_STATUS_IS_OK(result)) {
59 return result;
61 if (user_rids.count != 1) {
62 return NT_STATUS_INVALID_NETWORK_RESPONSE;
64 if (name_types.count != 1) {
65 return NT_STATUS_INVALID_NETWORK_RESPONSE;
68 switch (name_types.ids[0]) {
69 case SID_NAME_ALIAS:
70 case SID_NAME_WKN_GRP:
71 break;
72 default:
73 return NT_STATUS_INVALID_SID;
76 status = dcerpc_samr_OpenAlias(b, mem_ctx,
77 domain_handle,
78 access_rights,
79 user_rids.ids[0],
80 alias_handle,
81 &result);
82 if (!NT_STATUS_IS_OK(status)) {
83 return status;
86 return result;
89 /****************************************************************
90 ****************************************************************/
92 static NTSTATUS libnetapi_samr_open_alias_queryinfo(TALLOC_CTX *mem_ctx,
93 struct rpc_pipe_client *pipe_cli,
94 struct policy_handle *handle,
95 uint32_t rid,
96 uint32_t access_rights,
97 enum samr_AliasInfoEnum level,
98 union samr_AliasInfo **alias_info)
100 NTSTATUS status, result;
101 struct policy_handle alias_handle;
102 union samr_AliasInfo *_alias_info = NULL;
103 struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
105 ZERO_STRUCT(alias_handle);
107 status = dcerpc_samr_OpenAlias(b, mem_ctx,
108 handle,
109 access_rights,
110 rid,
111 &alias_handle,
112 &result);
113 if (!NT_STATUS_IS_OK(status)) {
114 goto done;
116 if (!NT_STATUS_IS_OK(result)) {
117 status = result;
118 goto done;
121 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
122 &alias_handle,
123 level,
124 &_alias_info,
125 &result);
126 if (!NT_STATUS_IS_OK(status)) {
127 goto done;
129 if (!NT_STATUS_IS_OK(result)) {
130 status = result;
131 goto done;
134 *alias_info = _alias_info;
136 done:
137 if (is_valid_policy_hnd(&alias_handle)) {
138 dcerpc_samr_Close(b, mem_ctx, &alias_handle, &result);
141 return status;
144 /****************************************************************
145 ****************************************************************/
147 WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
148 struct NetLocalGroupAdd *r)
150 struct rpc_pipe_client *pipe_cli = NULL;
151 NTSTATUS status, result;
152 WERROR werr;
153 struct lsa_String lsa_account_name;
154 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
155 struct dom_sid2 *domain_sid = NULL;
156 uint32_t rid;
157 struct dcerpc_binding_handle *b = NULL;
159 struct LOCALGROUP_INFO_0 *info0 = NULL;
160 struct LOCALGROUP_INFO_1 *info1 = NULL;
162 const char *alias_name = NULL;
164 if (!r->in.buffer) {
165 return WERR_INVALID_PARAM;
168 ZERO_STRUCT(connect_handle);
169 ZERO_STRUCT(builtin_handle);
170 ZERO_STRUCT(domain_handle);
171 ZERO_STRUCT(alias_handle);
173 switch (r->in.level) {
174 case 0:
175 info0 = (struct LOCALGROUP_INFO_0 *)r->in.buffer;
176 alias_name = info0->lgrpi0_name;
177 break;
178 case 1:
179 info1 = (struct LOCALGROUP_INFO_1 *)r->in.buffer;
180 alias_name = info1->lgrpi1_name;
181 break;
182 default:
183 werr = WERR_UNKNOWN_LEVEL;
184 goto done;
187 werr = libnetapi_open_pipe(ctx, r->in.server_name,
188 &ndr_table_samr.syntax_id,
189 &pipe_cli);
190 if (!W_ERROR_IS_OK(werr)) {
191 goto done;
194 b = pipe_cli->binding_handle;
196 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
197 SAMR_ACCESS_LOOKUP_DOMAIN |
198 SAMR_ACCESS_ENUM_DOMAINS,
199 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
200 &connect_handle,
201 &builtin_handle);
202 if (!W_ERROR_IS_OK(werr)) {
203 goto done;
206 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
207 &builtin_handle,
208 alias_name,
209 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
210 &alias_handle);
211 if (ctx->disable_policy_handle_cache) {
212 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
215 if (NT_STATUS_IS_OK(status)) {
216 werr = WERR_ALIAS_EXISTS;
217 goto done;
220 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
221 SAMR_ACCESS_ENUM_DOMAINS |
222 SAMR_ACCESS_LOOKUP_DOMAIN,
223 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
224 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
225 &connect_handle,
226 &domain_handle,
227 &domain_sid);
228 if (!W_ERROR_IS_OK(werr)) {
229 goto done;
232 init_lsa_String(&lsa_account_name, alias_name);
234 status = dcerpc_samr_CreateDomAlias(b, talloc_tos(),
235 &domain_handle,
236 &lsa_account_name,
237 SEC_STD_DELETE |
238 SAMR_ALIAS_ACCESS_SET_INFO,
239 &alias_handle,
240 &rid,
241 &result);
242 if (!NT_STATUS_IS_OK(status)) {
243 werr = ntstatus_to_werror(status);
244 goto done;
246 if (!NT_STATUS_IS_OK(result)) {
247 werr = ntstatus_to_werror(result);
248 goto done;
252 if (r->in.level == 1 && info1->lgrpi1_comment) {
254 union samr_AliasInfo alias_info;
256 init_lsa_String(&alias_info.description, info1->lgrpi1_comment);
258 status = dcerpc_samr_SetAliasInfo(b, talloc_tos(),
259 &alias_handle,
260 ALIASINFODESCRIPTION,
261 &alias_info,
262 &result);
263 if (!NT_STATUS_IS_OK(status)) {
264 werr = ntstatus_to_werror(status);
265 goto done;
267 if (!NT_STATUS_IS_OK(result)) {
268 werr = ntstatus_to_werror(result);
269 goto done;
273 werr = WERR_OK;
275 done:
276 if (is_valid_policy_hnd(&alias_handle)) {
277 dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
280 if (ctx->disable_policy_handle_cache) {
281 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
282 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
283 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
286 return werr;
289 /****************************************************************
290 ****************************************************************/
292 WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
293 struct NetLocalGroupAdd *r)
295 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAdd);
298 /****************************************************************
299 ****************************************************************/
302 WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
303 struct NetLocalGroupDel *r)
305 struct rpc_pipe_client *pipe_cli = NULL;
306 NTSTATUS status, result;
307 WERROR werr;
308 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
309 struct dom_sid2 *domain_sid = NULL;
310 struct dcerpc_binding_handle *b = NULL;
312 if (!r->in.group_name) {
313 return WERR_INVALID_PARAM;
316 ZERO_STRUCT(connect_handle);
317 ZERO_STRUCT(builtin_handle);
318 ZERO_STRUCT(domain_handle);
319 ZERO_STRUCT(alias_handle);
321 werr = libnetapi_open_pipe(ctx, r->in.server_name,
322 &ndr_table_samr.syntax_id,
323 &pipe_cli);
324 if (!W_ERROR_IS_OK(werr)) {
325 goto done;
328 b = pipe_cli->binding_handle;
330 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
331 SAMR_ACCESS_LOOKUP_DOMAIN |
332 SAMR_ACCESS_ENUM_DOMAINS,
333 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
334 &connect_handle,
335 &builtin_handle);
336 if (!W_ERROR_IS_OK(werr)) {
337 goto done;
340 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
341 &builtin_handle,
342 r->in.group_name,
343 SEC_STD_DELETE,
344 &alias_handle);
346 if (ctx->disable_policy_handle_cache) {
347 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
350 if (NT_STATUS_IS_OK(status)) {
351 goto delete_alias;
354 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
355 SAMR_ACCESS_ENUM_DOMAINS |
356 SAMR_ACCESS_LOOKUP_DOMAIN,
357 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
358 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
359 &connect_handle,
360 &domain_handle,
361 &domain_sid);
362 if (!W_ERROR_IS_OK(werr)) {
363 goto done;
366 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
367 &domain_handle,
368 r->in.group_name,
369 SEC_STD_DELETE,
370 &alias_handle);
372 if (ctx->disable_policy_handle_cache) {
373 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
376 if (!NT_STATUS_IS_OK(status)) {
377 werr = ntstatus_to_werror(status);
378 goto done;
382 delete_alias:
383 status = dcerpc_samr_DeleteDomAlias(b, talloc_tos(),
384 &alias_handle,
385 &result);
386 if (!NT_STATUS_IS_OK(status)) {
387 werr = ntstatus_to_werror(status);
388 goto done;
390 if (!NT_STATUS_IS_OK(result)) {
391 werr = ntstatus_to_werror(result);
392 goto done;
395 ZERO_STRUCT(alias_handle);
397 werr = WERR_OK;
399 done:
400 if (is_valid_policy_hnd(&alias_handle)) {
401 dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
404 if (ctx->disable_policy_handle_cache) {
405 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
406 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
407 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
410 return werr;
413 /****************************************************************
414 ****************************************************************/
416 WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
417 struct NetLocalGroupDel *r)
419 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDel);
422 /****************************************************************
423 ****************************************************************/
425 static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
426 const char *alias_name,
427 struct samr_AliasInfoAll *info,
428 uint32_t level,
429 uint32_t *entries_read,
430 uint8_t **buffer)
432 struct LOCALGROUP_INFO_0 g0;
433 struct LOCALGROUP_INFO_1 g1;
434 struct LOCALGROUP_INFO_1002 g1002;
436 switch (level) {
437 case 0:
438 g0.lgrpi0_name = talloc_strdup(mem_ctx, alias_name);
439 W_ERROR_HAVE_NO_MEMORY(g0.lgrpi0_name);
441 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_0, g0,
442 (struct LOCALGROUP_INFO_0 **)buffer, entries_read);
444 break;
445 case 1:
446 g1.lgrpi1_name = talloc_strdup(mem_ctx, alias_name);
447 g1.lgrpi1_comment = talloc_strdup(mem_ctx, info->description.string);
448 W_ERROR_HAVE_NO_MEMORY(g1.lgrpi1_name);
450 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1, g1,
451 (struct LOCALGROUP_INFO_1 **)buffer, entries_read);
453 break;
454 case 1002:
455 g1002.lgrpi1002_comment = talloc_strdup(mem_ctx, info->description.string);
457 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1002, g1002,
458 (struct LOCALGROUP_INFO_1002 **)buffer, entries_read);
460 break;
461 default:
462 return WERR_UNKNOWN_LEVEL;
465 return WERR_OK;
468 /****************************************************************
469 ****************************************************************/
471 WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
472 struct NetLocalGroupGetInfo *r)
474 struct rpc_pipe_client *pipe_cli = NULL;
475 NTSTATUS status, result;
476 WERROR werr;
477 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
478 struct dom_sid2 *domain_sid = NULL;
479 union samr_AliasInfo *alias_info = NULL;
480 uint32_t entries_read = 0;
481 struct dcerpc_binding_handle *b = NULL;
483 if (!r->in.group_name) {
484 return WERR_INVALID_PARAM;
487 switch (r->in.level) {
488 case 0:
489 case 1:
490 case 1002:
491 break;
492 default:
493 return WERR_UNKNOWN_LEVEL;
496 ZERO_STRUCT(connect_handle);
497 ZERO_STRUCT(builtin_handle);
498 ZERO_STRUCT(domain_handle);
499 ZERO_STRUCT(alias_handle);
501 werr = libnetapi_open_pipe(ctx, r->in.server_name,
502 &ndr_table_samr.syntax_id,
503 &pipe_cli);
504 if (!W_ERROR_IS_OK(werr)) {
505 goto done;
508 b = pipe_cli->binding_handle;
510 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
511 SAMR_ACCESS_LOOKUP_DOMAIN |
512 SAMR_ACCESS_ENUM_DOMAINS,
513 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
514 &connect_handle,
515 &builtin_handle);
516 if (!W_ERROR_IS_OK(werr)) {
517 goto done;
520 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
521 &builtin_handle,
522 r->in.group_name,
523 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
524 &alias_handle);
526 if (ctx->disable_policy_handle_cache) {
527 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
530 if (NT_STATUS_IS_OK(status)) {
531 goto query_alias;
534 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
535 SAMR_ACCESS_ENUM_DOMAINS |
536 SAMR_ACCESS_LOOKUP_DOMAIN,
537 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
538 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
539 &connect_handle,
540 &domain_handle,
541 &domain_sid);
542 if (!W_ERROR_IS_OK(werr)) {
543 goto done;
546 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
547 &domain_handle,
548 r->in.group_name,
549 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
550 &alias_handle);
552 if (ctx->disable_policy_handle_cache) {
553 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
556 if (!NT_STATUS_IS_OK(status)) {
557 werr = ntstatus_to_werror(status);
558 goto done;
561 query_alias:
562 status = dcerpc_samr_QueryAliasInfo(b, talloc_tos(),
563 &alias_handle,
564 ALIASINFOALL,
565 &alias_info,
566 &result);
567 if (!NT_STATUS_IS_OK(status)) {
568 werr = ntstatus_to_werror(status);
569 goto done;
571 if (!NT_STATUS_IS_OK(result)) {
572 werr = ntstatus_to_werror(result);
573 goto done;
576 werr = map_alias_info_to_buffer(ctx,
577 r->in.group_name,
578 &alias_info->all,
579 r->in.level, &entries_read,
580 r->out.buffer);
582 done:
583 if (is_valid_policy_hnd(&alias_handle)) {
584 dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
587 if (ctx->disable_policy_handle_cache) {
588 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
589 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
590 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
593 return werr;
596 /****************************************************************
597 ****************************************************************/
599 WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
600 struct NetLocalGroupGetInfo *r)
602 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetInfo);
605 /****************************************************************
606 ****************************************************************/
608 static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
609 uint32_t level,
610 uint8_t *buffer,
611 enum samr_AliasInfoEnum *alias_level,
612 union samr_AliasInfo **alias_info)
614 struct LOCALGROUP_INFO_0 *info0;
615 struct LOCALGROUP_INFO_1 *info1;
616 struct LOCALGROUP_INFO_1002 *info1002;
617 union samr_AliasInfo *info = NULL;
619 info = talloc_zero(mem_ctx, union samr_AliasInfo);
620 W_ERROR_HAVE_NO_MEMORY(info);
622 switch (level) {
623 case 0:
624 info0 = (struct LOCALGROUP_INFO_0 *)buffer;
625 init_lsa_String(&info->name, info0->lgrpi0_name);
626 *alias_level = ALIASINFONAME;
627 break;
628 case 1:
629 info1 = (struct LOCALGROUP_INFO_1 *)buffer;
630 /* group name will be ignored */
631 init_lsa_String(&info->description, info1->lgrpi1_comment);
632 *alias_level = ALIASINFODESCRIPTION;
633 break;
634 case 1002:
635 info1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
636 init_lsa_String(&info->description, info1002->lgrpi1002_comment);
637 *alias_level = ALIASINFODESCRIPTION;
638 break;
641 *alias_info = info;
643 return WERR_OK;
646 /****************************************************************
647 ****************************************************************/
649 WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
650 struct NetLocalGroupSetInfo *r)
652 struct rpc_pipe_client *pipe_cli = NULL;
653 NTSTATUS status, result;
654 WERROR werr;
655 struct lsa_String lsa_account_name;
656 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
657 struct dom_sid2 *domain_sid = NULL;
658 enum samr_AliasInfoEnum alias_level = 0;
659 union samr_AliasInfo *alias_info = NULL;
660 struct dcerpc_binding_handle *b = NULL;
662 if (!r->in.group_name) {
663 return WERR_INVALID_PARAM;
666 switch (r->in.level) {
667 case 0:
668 case 1:
669 case 1002:
670 break;
671 default:
672 return WERR_UNKNOWN_LEVEL;
675 ZERO_STRUCT(connect_handle);
676 ZERO_STRUCT(builtin_handle);
677 ZERO_STRUCT(domain_handle);
678 ZERO_STRUCT(alias_handle);
680 werr = libnetapi_open_pipe(ctx, r->in.server_name,
681 &ndr_table_samr.syntax_id,
682 &pipe_cli);
683 if (!W_ERROR_IS_OK(werr)) {
684 goto done;
687 b = pipe_cli->binding_handle;
689 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
690 SAMR_ACCESS_LOOKUP_DOMAIN |
691 SAMR_ACCESS_ENUM_DOMAINS,
692 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
693 &connect_handle,
694 &builtin_handle);
695 if (!W_ERROR_IS_OK(werr)) {
696 goto done;
699 init_lsa_String(&lsa_account_name, r->in.group_name);
701 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
702 &builtin_handle,
703 r->in.group_name,
704 SAMR_ALIAS_ACCESS_SET_INFO,
705 &alias_handle);
707 if (ctx->disable_policy_handle_cache) {
708 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
711 if (NT_STATUS_IS_OK(status)) {
712 goto set_alias;
715 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
716 SAMR_ACCESS_ENUM_DOMAINS |
717 SAMR_ACCESS_LOOKUP_DOMAIN,
718 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
719 &connect_handle,
720 &domain_handle,
721 &domain_sid);
722 if (!W_ERROR_IS_OK(werr)) {
723 goto done;
726 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
727 &domain_handle,
728 r->in.group_name,
729 SAMR_ALIAS_ACCESS_SET_INFO,
730 &alias_handle);
731 if (!NT_STATUS_IS_OK(status)) {
732 werr = ntstatus_to_werror(status);
733 goto done;
736 if (ctx->disable_policy_handle_cache) {
737 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
740 set_alias:
742 werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buffer,
743 &alias_level, &alias_info);
744 if (!W_ERROR_IS_OK(werr)) {
745 goto done;
748 status = dcerpc_samr_SetAliasInfo(b, talloc_tos(),
749 &alias_handle,
750 alias_level,
751 alias_info,
752 &result);
753 if (!NT_STATUS_IS_OK(status)) {
754 werr = ntstatus_to_werror(status);
755 goto done;
757 if (!NT_STATUS_IS_OK(result)) {
758 werr = ntstatus_to_werror(result);
759 goto done;
762 werr = WERR_OK;
764 done:
765 if (is_valid_policy_hnd(&alias_handle)) {
766 dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
769 if (ctx->disable_policy_handle_cache) {
770 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
771 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
772 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
775 return werr;
778 /****************************************************************
779 ****************************************************************/
781 WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
782 struct NetLocalGroupSetInfo *r)
784 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetInfo);
787 /****************************************************************
788 ****************************************************************/
790 WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
791 struct NetLocalGroupEnum *r)
793 struct rpc_pipe_client *pipe_cli = NULL;
794 NTSTATUS status, result;
795 WERROR werr;
796 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
797 struct dom_sid2 *domain_sid = NULL;
798 uint32_t entries_read = 0;
799 union samr_DomainInfo *domain_info = NULL;
800 union samr_DomainInfo *builtin_info = NULL;
801 struct samr_SamArray *domain_sam_array = NULL;
802 struct samr_SamArray *builtin_sam_array = NULL;
803 int i;
804 struct dcerpc_binding_handle *b = NULL;
806 if (!r->out.buffer) {
807 return WERR_INVALID_PARAM;
810 switch (r->in.level) {
811 case 0:
812 case 1:
813 break;
814 default:
815 return WERR_UNKNOWN_LEVEL;
818 if (r->out.total_entries) {
819 *r->out.total_entries = 0;
821 if (r->out.entries_read) {
822 *r->out.entries_read = 0;
825 ZERO_STRUCT(connect_handle);
826 ZERO_STRUCT(builtin_handle);
827 ZERO_STRUCT(domain_handle);
828 ZERO_STRUCT(alias_handle);
830 werr = libnetapi_open_pipe(ctx, r->in.server_name,
831 &ndr_table_samr.syntax_id,
832 &pipe_cli);
833 if (!W_ERROR_IS_OK(werr)) {
834 goto done;
837 b = pipe_cli->binding_handle;
839 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
840 SAMR_ACCESS_LOOKUP_DOMAIN |
841 SAMR_ACCESS_ENUM_DOMAINS,
842 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
843 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
844 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
845 &connect_handle,
846 &builtin_handle);
847 if (!W_ERROR_IS_OK(werr)) {
848 goto done;
851 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
852 SAMR_ACCESS_LOOKUP_DOMAIN |
853 SAMR_ACCESS_ENUM_DOMAINS,
854 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
855 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
856 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
857 &connect_handle,
858 &domain_handle,
859 &domain_sid);
860 if (!W_ERROR_IS_OK(werr)) {
861 goto done;
864 status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
865 &builtin_handle,
867 &builtin_info,
868 &result);
869 if (!NT_STATUS_IS_OK(status)) {
870 werr = ntstatus_to_werror(status);
871 goto done;
873 if (!NT_STATUS_IS_OK(result)) {
874 werr = ntstatus_to_werror(result);
875 goto done;
878 if (r->out.total_entries) {
879 *r->out.total_entries += builtin_info->general.num_aliases;
882 status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
883 &domain_handle,
885 &domain_info,
886 &result);
887 if (!NT_STATUS_IS_OK(status)) {
888 werr = ntstatus_to_werror(status);
889 goto done;
891 if (!NT_STATUS_IS_OK(result)) {
892 werr = ntstatus_to_werror(result);
893 goto done;
896 if (r->out.total_entries) {
897 *r->out.total_entries += domain_info->general.num_aliases;
900 status = dcerpc_samr_EnumDomainAliases(b, talloc_tos(),
901 &builtin_handle,
902 r->in.resume_handle,
903 &builtin_sam_array,
904 r->in.prefmaxlen,
905 &entries_read,
906 &result);
907 if (!NT_STATUS_IS_OK(status)) {
908 werr = ntstatus_to_werror(status);
909 goto done;
911 if (!NT_STATUS_IS_OK(result)) {
912 werr = ntstatus_to_werror(result);
913 goto done;
916 for (i=0; i<builtin_sam_array->count; i++) {
917 union samr_AliasInfo *alias_info = NULL;
919 if (r->in.level == 1) {
921 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
922 &builtin_handle,
923 builtin_sam_array->entries[i].idx,
924 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
925 ALIASINFOALL,
926 &alias_info);
927 if (!NT_STATUS_IS_OK(status)) {
928 werr = ntstatus_to_werror(status);
929 goto done;
933 werr = map_alias_info_to_buffer(ctx,
934 builtin_sam_array->entries[i].name.string,
935 alias_info ? &alias_info->all : NULL,
936 r->in.level,
937 r->out.entries_read,
938 r->out.buffer);
941 status = dcerpc_samr_EnumDomainAliases(b, talloc_tos(),
942 &domain_handle,
943 r->in.resume_handle,
944 &domain_sam_array,
945 r->in.prefmaxlen,
946 &entries_read,
947 &result);
948 if (!NT_STATUS_IS_OK(status)) {
949 werr = ntstatus_to_werror(status);
950 goto done;
952 if (!NT_STATUS_IS_OK(result)) {
953 werr = ntstatus_to_werror(result);
954 goto done;
957 for (i=0; i<domain_sam_array->count; i++) {
959 union samr_AliasInfo *alias_info = NULL;
961 if (r->in.level == 1) {
962 status = libnetapi_samr_open_alias_queryinfo(ctx, pipe_cli,
963 &domain_handle,
964 domain_sam_array->entries[i].idx,
965 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
966 ALIASINFOALL,
967 &alias_info);
968 if (!NT_STATUS_IS_OK(status)) {
969 werr = ntstatus_to_werror(status);
970 goto done;
974 werr = map_alias_info_to_buffer(ctx,
975 domain_sam_array->entries[i].name.string,
976 alias_info ? &alias_info->all : NULL,
977 r->in.level,
978 r->out.entries_read,
979 r->out.buffer);
982 done:
983 if (ctx->disable_policy_handle_cache) {
984 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
985 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
986 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
989 return werr;
992 /****************************************************************
993 ****************************************************************/
995 WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
996 struct NetLocalGroupEnum *r)
998 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupEnum);
1001 /****************************************************************
1002 ****************************************************************/
1004 static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx,
1005 struct rpc_pipe_client *lsa_pipe,
1006 const char *name,
1007 struct dom_sid *sid)
1009 NTSTATUS status, result;
1010 struct policy_handle lsa_handle;
1011 struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
1013 struct lsa_RefDomainList *domains = NULL;
1014 struct lsa_TransSidArray3 sids;
1015 uint32_t count = 0;
1017 struct lsa_String names;
1018 uint32_t num_names = 1;
1020 if (!sid || !name) {
1021 return NT_STATUS_INVALID_PARAMETER;
1024 ZERO_STRUCT(sids);
1026 init_lsa_String(&names, name);
1028 status = rpccli_lsa_open_policy2(lsa_pipe, mem_ctx,
1029 false,
1030 SEC_STD_READ_CONTROL |
1031 LSA_POLICY_VIEW_LOCAL_INFORMATION |
1032 LSA_POLICY_LOOKUP_NAMES,
1033 &lsa_handle);
1034 NT_STATUS_NOT_OK_RETURN(status);
1036 status = dcerpc_lsa_LookupNames3(b, mem_ctx,
1037 &lsa_handle,
1038 num_names,
1039 &names,
1040 &domains,
1041 &sids,
1042 LSA_LOOKUP_NAMES_ALL, /* sure ? */
1043 &count,
1044 0, 0,
1045 &result);
1046 NT_STATUS_NOT_OK_RETURN(status);
1047 NT_STATUS_NOT_OK_RETURN(result);
1049 if (count != 1 || sids.count != 1) {
1050 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1053 sid_copy(sid, sids.sids[0].sid);
1055 return NT_STATUS_OK;
1058 /****************************************************************
1059 ****************************************************************/
1061 static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
1062 struct NetLocalGroupAddMembers *add,
1063 struct NetLocalGroupDelMembers *del,
1064 struct NetLocalGroupSetMembers *set)
1066 struct NetLocalGroupAddMembers *r = NULL;
1068 struct rpc_pipe_client *pipe_cli = NULL;
1069 struct rpc_pipe_client *lsa_pipe = NULL;
1070 NTSTATUS status, result;
1071 WERROR werr;
1072 struct lsa_String lsa_account_name;
1073 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
1074 struct dom_sid2 *domain_sid = NULL;
1075 struct dom_sid *member_sids = NULL;
1076 int i = 0, k = 0;
1078 struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
1079 struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
1081 struct dom_sid *add_sids = NULL;
1082 struct dom_sid *del_sids = NULL;
1083 uint32_t num_add_sids = 0;
1084 uint32_t num_del_sids = 0;
1085 struct dcerpc_binding_handle *b = NULL;
1087 if ((!add && !del && !set) || (add && del && set)) {
1088 return WERR_INVALID_PARAM;
1091 if (add) {
1092 r = add;
1095 if (del) {
1096 r = (struct NetLocalGroupAddMembers *)del;
1099 if (set) {
1100 r = (struct NetLocalGroupAddMembers *)set;
1103 if (!r->in.group_name) {
1104 return WERR_INVALID_PARAM;
1107 switch (r->in.level) {
1108 case 0:
1109 case 3:
1110 break;
1111 default:
1112 return WERR_UNKNOWN_LEVEL;
1115 if (r->in.total_entries == 0 || !r->in.buffer) {
1116 return WERR_INVALID_PARAM;
1119 ZERO_STRUCT(connect_handle);
1120 ZERO_STRUCT(builtin_handle);
1121 ZERO_STRUCT(domain_handle);
1122 ZERO_STRUCT(alias_handle);
1124 member_sids = talloc_zero_array(ctx, struct dom_sid,
1125 r->in.total_entries);
1126 W_ERROR_HAVE_NO_MEMORY(member_sids);
1128 switch (r->in.level) {
1129 case 0:
1130 info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
1131 for (i=0; i < r->in.total_entries; i++) {
1132 sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
1134 break;
1135 case 3:
1136 info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
1137 break;
1138 default:
1139 break;
1142 if (r->in.level == 3) {
1143 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1144 &ndr_table_lsarpc.syntax_id,
1145 &lsa_pipe);
1146 if (!W_ERROR_IS_OK(werr)) {
1147 goto done;
1150 for (i=0; i < r->in.total_entries; i++) {
1151 status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
1152 info3[i].lgrmi3_domainandname,
1153 &member_sids[i]);
1154 if (!NT_STATUS_IS_OK(status)) {
1155 werr = ntstatus_to_werror(status);
1156 goto done;
1159 TALLOC_FREE(lsa_pipe);
1162 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1163 &ndr_table_samr.syntax_id,
1164 &pipe_cli);
1165 if (!W_ERROR_IS_OK(werr)) {
1166 goto done;
1169 b = pipe_cli->binding_handle;
1171 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1172 SAMR_ACCESS_LOOKUP_DOMAIN |
1173 SAMR_ACCESS_ENUM_DOMAINS,
1174 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1175 &connect_handle,
1176 &builtin_handle);
1177 if (!W_ERROR_IS_OK(werr)) {
1178 goto done;
1181 init_lsa_String(&lsa_account_name, r->in.group_name);
1183 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1184 &builtin_handle,
1185 r->in.group_name,
1186 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1187 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1188 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1189 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1190 &alias_handle);
1192 if (ctx->disable_policy_handle_cache) {
1193 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1196 if (NT_STATUS_IS_OK(status)) {
1197 goto modify_membership;
1200 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1201 SAMR_ACCESS_ENUM_DOMAINS |
1202 SAMR_ACCESS_LOOKUP_DOMAIN,
1203 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1204 &connect_handle,
1205 &domain_handle,
1206 &domain_sid);
1207 if (!W_ERROR_IS_OK(werr)) {
1208 goto done;
1211 status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
1212 &domain_handle,
1213 r->in.group_name,
1214 SAMR_ALIAS_ACCESS_ADD_MEMBER |
1215 SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
1216 SAMR_ALIAS_ACCESS_GET_MEMBERS |
1217 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
1218 &alias_handle);
1219 if (!NT_STATUS_IS_OK(status)) {
1220 werr = ntstatus_to_werror(status);
1221 goto done;
1224 if (ctx->disable_policy_handle_cache) {
1225 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1228 modify_membership:
1230 if (add) {
1231 for (i=0; i < r->in.total_entries; i++) {
1232 status = add_sid_to_array_unique(ctx, &member_sids[i],
1233 &add_sids,
1234 &num_add_sids);
1235 if (!NT_STATUS_IS_OK(status)) {
1236 werr = ntstatus_to_werror(status);
1237 goto done;
1242 if (del) {
1243 for (i=0; i < r->in.total_entries; i++) {
1244 status = add_sid_to_array_unique(ctx, &member_sids[i],
1245 &del_sids,
1246 &num_del_sids);
1247 if (!NT_STATUS_IS_OK(status)) {
1248 werr = ntstatus_to_werror(status);
1249 goto done;
1254 if (set) {
1256 struct lsa_SidArray current_sids;
1258 status = dcerpc_samr_GetMembersInAlias(b, talloc_tos(),
1259 &alias_handle,
1260 &current_sids,
1261 &result);
1262 if (!NT_STATUS_IS_OK(status)) {
1263 werr = ntstatus_to_werror(status);
1264 goto done;
1266 if (!NT_STATUS_IS_OK(result)) {
1267 werr = ntstatus_to_werror(result);
1268 goto done;
1271 /* add list */
1273 for (i=0; i < r->in.total_entries; i++) {
1274 bool already_member = false;
1275 for (k=0; k < current_sids.num_sids; k++) {
1276 if (dom_sid_equal(&member_sids[i],
1277 current_sids.sids[k].sid)) {
1278 already_member = true;
1279 break;
1282 if (!already_member) {
1283 status = add_sid_to_array_unique(ctx,
1284 &member_sids[i],
1285 &add_sids, &num_add_sids);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 werr = ntstatus_to_werror(status);
1288 goto done;
1293 /* del list */
1295 for (k=0; k < current_sids.num_sids; k++) {
1296 bool keep_member = false;
1297 for (i=0; i < r->in.total_entries; i++) {
1298 if (dom_sid_equal(&member_sids[i],
1299 current_sids.sids[k].sid)) {
1300 keep_member = true;
1301 break;
1304 if (!keep_member) {
1305 status = add_sid_to_array_unique(ctx,
1306 current_sids.sids[k].sid,
1307 &del_sids, &num_del_sids);
1308 if (!NT_STATUS_IS_OK(status)) {
1309 werr = ntstatus_to_werror(status);
1310 goto done;
1316 /* add list */
1318 for (i=0; i < num_add_sids; i++) {
1319 status = dcerpc_samr_AddAliasMember(b, talloc_tos(),
1320 &alias_handle,
1321 &add_sids[i],
1322 &result);
1323 if (!NT_STATUS_IS_OK(status)) {
1324 werr = ntstatus_to_werror(status);
1325 goto done;
1327 if (!NT_STATUS_IS_OK(result)) {
1328 werr = ntstatus_to_werror(result);
1329 goto done;
1333 /* del list */
1335 for (i=0; i < num_del_sids; i++) {
1336 status = dcerpc_samr_DeleteAliasMember(b, talloc_tos(),
1337 &alias_handle,
1338 &del_sids[i],
1339 &result);
1340 if (!NT_STATUS_IS_OK(status)) {
1341 werr = ntstatus_to_werror(status);
1342 goto done;
1344 if (!NT_STATUS_IS_OK(result)) {
1345 werr = ntstatus_to_werror(result);
1346 goto done;
1350 werr = WERR_OK;
1352 done:
1353 if (b && is_valid_policy_hnd(&alias_handle)) {
1354 dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
1357 if (ctx->disable_policy_handle_cache) {
1358 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1359 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1360 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1363 return werr;
1366 /****************************************************************
1367 ****************************************************************/
1369 WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
1370 struct NetLocalGroupAddMembers *r)
1372 return NetLocalGroupModifyMembers_r(ctx, r, NULL, NULL);
1375 /****************************************************************
1376 ****************************************************************/
1378 WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
1379 struct NetLocalGroupAddMembers *r)
1381 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAddMembers);
1384 /****************************************************************
1385 ****************************************************************/
1387 WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
1388 struct NetLocalGroupDelMembers *r)
1390 return NetLocalGroupModifyMembers_r(ctx, NULL, r, NULL);
1393 /****************************************************************
1394 ****************************************************************/
1396 WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
1397 struct NetLocalGroupDelMembers *r)
1399 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDelMembers);
1402 /****************************************************************
1403 ****************************************************************/
1405 WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
1406 struct NetLocalGroupGetMembers *r)
1408 return WERR_NOT_SUPPORTED;
1411 /****************************************************************
1412 ****************************************************************/
1414 WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
1415 struct NetLocalGroupGetMembers *r)
1417 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetMembers);
1420 /****************************************************************
1421 ****************************************************************/
1423 WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
1424 struct NetLocalGroupSetMembers *r)
1426 return NetLocalGroupModifyMembers_r(ctx, NULL, NULL, r);
1429 /****************************************************************
1430 ****************************************************************/
1432 WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
1433 struct NetLocalGroupSetMembers *r)
1435 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetMembers);