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/>.
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
27 static WERROR libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
28 struct rpc_pipe_client *pipe_cli,
29 struct policy_handle *domain_handle,
30 struct lsa_String *lsa_account_name,
31 uint32_t access_rights,
32 struct policy_handle *alias_handle)
36 struct samr_Ids user_rids, name_types;
38 status = rpccli_samr_LookupNames(pipe_cli, mem_ctx,
44 if (!NT_STATUS_IS_OK(status)) {
45 werr = ntstatus_to_werror(status);
49 switch (name_types.ids[0]) {
51 case SID_NAME_WKN_GRP:
54 return WERR_INVALID_DATATYPE;
57 status = rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
62 if (NT_STATUS_IS_OK(status)) {
63 werr = ntstatus_to_werror(status);
73 /****************************************************************
74 ****************************************************************/
76 static NTSTATUS libnetapi_samr_open_alias_queryinfo(TALLOC_CTX *mem_ctx,
77 struct rpc_pipe_client *pipe_cli,
78 struct policy_handle *handle,
80 uint32_t access_rights,
81 enum samr_AliasInfoEnum level,
82 union samr_AliasInfo **alias_info)
85 struct policy_handle alias_handle;
86 union samr_AliasInfo *_alias_info = NULL;
88 ZERO_STRUCT(alias_handle);
90 status = rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
95 if (!NT_STATUS_IS_OK(status)) {
99 status = rpccli_samr_QueryAliasInfo(pipe_cli, mem_ctx,
103 if (!NT_STATUS_IS_OK(status)) {
107 *alias_info = _alias_info;
110 if (is_valid_policy_hnd(&alias_handle)) {
111 rpccli_samr_Close(pipe_cli, mem_ctx, &alias_handle);
117 /****************************************************************
118 ****************************************************************/
120 WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
121 struct NetLocalGroupAdd *r)
123 struct cli_state *cli = NULL;
124 struct rpc_pipe_client *pipe_cli = NULL;
127 struct lsa_String lsa_account_name;
128 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
129 struct dom_sid2 *domain_sid = NULL;
132 struct LOCALGROUP_INFO_0 *info0 = NULL;
133 struct LOCALGROUP_INFO_1 *info1 = NULL;
135 const char *alias_name = NULL;
138 return WERR_INVALID_PARAM;
141 switch (r->in.level) {
143 info0 = (struct LOCALGROUP_INFO_0 *)r->in.buf;
144 alias_name = info0->lgrpi0_name;
147 info1 = (struct LOCALGROUP_INFO_1 *)r->in.buf;
148 alias_name = info1->lgrpi1_name;
151 werr = WERR_UNKNOWN_LEVEL;
155 ZERO_STRUCT(connect_handle);
156 ZERO_STRUCT(builtin_handle);
157 ZERO_STRUCT(domain_handle);
158 ZERO_STRUCT(alias_handle);
160 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
161 if (!W_ERROR_IS_OK(werr)) {
165 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
166 if (!W_ERROR_IS_OK(werr)) {
170 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
171 SAMR_ACCESS_OPEN_DOMAIN |
172 SAMR_ACCESS_ENUM_DOMAINS,
173 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
176 if (!W_ERROR_IS_OK(werr)) {
180 init_lsa_String(&lsa_account_name, alias_name);
182 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
185 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
188 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
190 if (W_ERROR_IS_OK(werr)) {
191 werr = WERR_ALIAS_EXISTS;
195 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
196 SAMR_ACCESS_ENUM_DOMAINS |
197 SAMR_ACCESS_OPEN_DOMAIN,
198 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
199 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
203 if (!W_ERROR_IS_OK(werr)) {
207 status = rpccli_samr_CreateDomAlias(pipe_cli, ctx,
211 SAMR_ALIAS_ACCESS_SET_INFO,
214 if (!NT_STATUS_IS_OK(status)) {
215 werr = ntstatus_to_werror(status);
219 if (r->in.level == 1) {
221 union samr_AliasInfo alias_info;
223 init_lsa_String(&alias_info.description, info1->lgrpi1_comment);
225 status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
227 ALIASINFODESCRIPTION,
229 if (!NT_STATUS_IS_OK(status)) {
230 werr = ntstatus_to_werror(status);
242 if (is_valid_policy_hnd(&alias_handle)) {
243 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
245 if (is_valid_policy_hnd(&domain_handle)) {
246 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
248 if (is_valid_policy_hnd(&builtin_handle)) {
249 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
251 if (is_valid_policy_hnd(&connect_handle)) {
252 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
258 /****************************************************************
259 ****************************************************************/
261 WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
262 struct NetLocalGroupAdd *r)
264 return NetLocalGroupAdd_r(ctx, r);
267 /****************************************************************
268 ****************************************************************/
271 WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
272 struct NetLocalGroupDel *r)
274 struct cli_state *cli = NULL;
275 struct rpc_pipe_client *pipe_cli = NULL;
278 struct lsa_String lsa_account_name;
279 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
280 struct dom_sid2 *domain_sid = NULL;
282 if (!r->in.group_name) {
283 return WERR_INVALID_PARAM;
286 ZERO_STRUCT(connect_handle);
287 ZERO_STRUCT(builtin_handle);
288 ZERO_STRUCT(domain_handle);
289 ZERO_STRUCT(alias_handle);
291 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
292 if (!W_ERROR_IS_OK(werr)) {
296 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
297 if (!W_ERROR_IS_OK(werr)) {
301 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
302 SAMR_ACCESS_OPEN_DOMAIN |
303 SAMR_ACCESS_ENUM_DOMAINS,
304 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
307 if (!W_ERROR_IS_OK(werr)) {
311 init_lsa_String(&lsa_account_name, r->in.group_name);
313 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
319 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
321 if (W_ERROR_IS_OK(werr)) {
325 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
326 SAMR_ACCESS_ENUM_DOMAINS |
327 SAMR_ACCESS_OPEN_DOMAIN,
328 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
329 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
333 if (!W_ERROR_IS_OK(werr)) {
337 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
343 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
345 if (!W_ERROR_IS_OK(werr)) {
351 status = rpccli_samr_DeleteDomAlias(pipe_cli, ctx,
353 if (!NT_STATUS_IS_OK(status)) {
354 werr = ntstatus_to_werror(status);
358 ZERO_STRUCT(alias_handle);
367 if (is_valid_policy_hnd(&alias_handle)) {
368 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
370 if (is_valid_policy_hnd(&domain_handle)) {
371 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
373 if (is_valid_policy_hnd(&builtin_handle)) {
374 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
376 if (is_valid_policy_hnd(&connect_handle)) {
377 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
383 /****************************************************************
384 ****************************************************************/
386 WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
387 struct NetLocalGroupDel *r)
389 return NetLocalGroupDel_r(ctx, r);
392 /****************************************************************
393 ****************************************************************/
395 static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
396 const char *alias_name,
397 struct samr_AliasInfoAll *info,
399 uint32_t *entries_read,
402 struct LOCALGROUP_INFO_0 g0;
403 struct LOCALGROUP_INFO_1 g1;
404 struct LOCALGROUP_INFO_1002 g1002;
408 g0.lgrpi0_name = talloc_strdup(mem_ctx, alias_name);
409 W_ERROR_HAVE_NO_MEMORY(g0.lgrpi0_name);
411 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_0, g0,
412 (struct LOCALGROUP_INFO_0 **)buffer, entries_read);
416 g1.lgrpi1_name = talloc_strdup(mem_ctx, alias_name);
417 g1.lgrpi1_comment = talloc_strdup(mem_ctx, info->description.string);
418 W_ERROR_HAVE_NO_MEMORY(g1.lgrpi1_name);
420 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1, g1,
421 (struct LOCALGROUP_INFO_1 **)buffer, entries_read);
425 g1002.lgrpi1002_comment = talloc_strdup(mem_ctx, info->description.string);
427 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_INFO_1002, g1002,
428 (struct LOCALGROUP_INFO_1002 **)buffer, entries_read);
432 return WERR_UNKNOWN_LEVEL;
438 /****************************************************************
439 ****************************************************************/
441 WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
442 struct NetLocalGroupGetInfo *r)
444 struct cli_state *cli = NULL;
445 struct rpc_pipe_client *pipe_cli = NULL;
448 struct lsa_String lsa_account_name;
449 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
450 struct dom_sid2 *domain_sid = NULL;
451 union samr_AliasInfo *alias_info = NULL;
452 uint32_t entries_read = 0;
454 if (!r->in.group_name) {
455 return WERR_INVALID_PARAM;
458 switch (r->in.level) {
464 return WERR_UNKNOWN_LEVEL;
467 ZERO_STRUCT(connect_handle);
468 ZERO_STRUCT(builtin_handle);
469 ZERO_STRUCT(domain_handle);
470 ZERO_STRUCT(alias_handle);
472 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
473 if (!W_ERROR_IS_OK(werr)) {
477 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
478 if (!W_ERROR_IS_OK(werr)) {
482 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
483 SAMR_ACCESS_OPEN_DOMAIN |
484 SAMR_ACCESS_ENUM_DOMAINS,
485 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
488 if (!W_ERROR_IS_OK(werr)) {
492 init_lsa_String(&lsa_account_name, r->in.group_name);
494 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
497 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
500 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
502 if (W_ERROR_IS_OK(werr)) {
506 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
507 SAMR_ACCESS_ENUM_DOMAINS |
508 SAMR_ACCESS_OPEN_DOMAIN,
509 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
510 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
514 if (!W_ERROR_IS_OK(werr)) {
518 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
521 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
524 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
526 if (!W_ERROR_IS_OK(werr)) {
531 status = rpccli_samr_QueryAliasInfo(pipe_cli, ctx,
535 if (!NT_STATUS_IS_OK(status)) {
536 werr = ntstatus_to_werror(status);
540 werr = map_alias_info_to_buffer(ctx,
543 r->in.level, &entries_read,
551 if (is_valid_policy_hnd(&alias_handle)) {
552 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
554 if (is_valid_policy_hnd(&domain_handle)) {
555 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
557 if (is_valid_policy_hnd(&builtin_handle)) {
558 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
560 if (is_valid_policy_hnd(&connect_handle)) {
561 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
567 /****************************************************************
568 ****************************************************************/
570 WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
571 struct NetLocalGroupGetInfo *r)
573 return NetLocalGroupGetInfo_r(ctx, r);
576 /****************************************************************
577 ****************************************************************/
579 static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
582 enum samr_AliasInfoEnum *alias_level,
583 union samr_AliasInfo **alias_info)
585 struct LOCALGROUP_INFO_0 *info0;
586 struct LOCALGROUP_INFO_1 *info1;
587 struct LOCALGROUP_INFO_1002 *info1002;
588 union samr_AliasInfo *info = NULL;
590 info = TALLOC_ZERO_P(mem_ctx, union samr_AliasInfo);
591 W_ERROR_HAVE_NO_MEMORY(info);
595 info0 = (struct LOCALGROUP_INFO_0 *)buffer;
596 init_lsa_String(&info->name, info0->lgrpi0_name);
597 *alias_level = ALIASINFONAME;
600 info1 = (struct LOCALGROUP_INFO_1 *)buffer;
601 /* group name will be ignored */
602 init_lsa_String(&info->description, info1->lgrpi1_comment);
603 *alias_level = ALIASINFODESCRIPTION;
606 info1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
607 init_lsa_String(&info->description, info1002->lgrpi1002_comment);
608 *alias_level = ALIASINFODESCRIPTION;
617 /****************************************************************
618 ****************************************************************/
620 WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
621 struct NetLocalGroupSetInfo *r)
623 struct cli_state *cli = NULL;
624 struct rpc_pipe_client *pipe_cli = NULL;
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;
633 if (!r->in.group_name) {
634 return WERR_INVALID_PARAM;
637 switch (r->in.level) {
643 return WERR_UNKNOWN_LEVEL;
646 ZERO_STRUCT(connect_handle);
647 ZERO_STRUCT(builtin_handle);
648 ZERO_STRUCT(domain_handle);
649 ZERO_STRUCT(alias_handle);
651 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
652 if (!W_ERROR_IS_OK(werr)) {
656 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
657 if (!W_ERROR_IS_OK(werr)) {
661 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
662 SAMR_ACCESS_OPEN_DOMAIN |
663 SAMR_ACCESS_ENUM_DOMAINS,
664 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
667 if (!W_ERROR_IS_OK(werr)) {
671 init_lsa_String(&lsa_account_name, r->in.group_name);
673 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
676 SAMR_ALIAS_ACCESS_SET_INFO,
679 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
681 if (W_ERROR_IS_OK(werr)) {
685 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
686 SAMR_ACCESS_ENUM_DOMAINS |
687 SAMR_ACCESS_OPEN_DOMAIN,
688 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
692 if (!W_ERROR_IS_OK(werr)) {
696 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
699 SAMR_ALIAS_ACCESS_SET_INFO,
701 if (!W_ERROR_IS_OK(werr)) {
705 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
709 werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buf,
710 &alias_level, &alias_info);
711 if (!W_ERROR_IS_OK(werr)) {
715 status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
719 if (!NT_STATUS_IS_OK(status)) {
720 werr = ntstatus_to_werror(status);
731 if (is_valid_policy_hnd(&alias_handle)) {
732 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
734 if (is_valid_policy_hnd(&domain_handle)) {
735 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
737 if (is_valid_policy_hnd(&builtin_handle)) {
738 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
740 if (is_valid_policy_hnd(&connect_handle)) {
741 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
747 /****************************************************************
748 ****************************************************************/
750 WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
751 struct NetLocalGroupSetInfo *r)
753 return NetLocalGroupSetInfo_r(ctx, r);
756 /****************************************************************
757 ****************************************************************/
759 WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
760 struct NetLocalGroupEnum *r)
762 return WERR_NOT_SUPPORTED;
765 /****************************************************************
766 ****************************************************************/
768 WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
769 struct NetLocalGroupEnum *r)
771 return WERR_NOT_SUPPORTED;