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 WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
77 struct NetLocalGroupAdd *r)
79 struct cli_state *cli = NULL;
80 struct rpc_pipe_client *pipe_cli = NULL;
83 struct lsa_String lsa_account_name;
84 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
85 struct dom_sid2 *domain_sid = NULL;
88 struct LOCALGROUP_INFO_0 *info0;
89 struct LOCALGROUP_INFO_1 *info1;
91 const char *alias_name = NULL;
94 return WERR_INVALID_PARAM;
97 switch (r->in.level) {
99 info0 = (struct LOCALGROUP_INFO_0 *)r->in.buf;
100 alias_name = info0->lgrpi0_name;
103 info1 = (struct LOCALGROUP_INFO_1 *)r->in.buf;
104 alias_name = info1->lgrpi1_name;
107 werr = WERR_UNKNOWN_LEVEL;
111 ZERO_STRUCT(connect_handle);
112 ZERO_STRUCT(builtin_handle);
113 ZERO_STRUCT(domain_handle);
114 ZERO_STRUCT(alias_handle);
116 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
117 if (!W_ERROR_IS_OK(werr)) {
121 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
122 if (!W_ERROR_IS_OK(werr)) {
126 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
127 SAMR_ACCESS_OPEN_DOMAIN |
128 SAMR_ACCESS_ENUM_DOMAINS,
129 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
132 if (!W_ERROR_IS_OK(werr)) {
136 init_lsa_String(&lsa_account_name, alias_name);
138 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
141 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
144 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
146 if (W_ERROR_IS_OK(werr)) {
147 werr = WERR_ALIAS_EXISTS;
151 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
152 SAMR_ACCESS_ENUM_DOMAINS |
153 SAMR_ACCESS_OPEN_DOMAIN,
154 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
155 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
159 if (!W_ERROR_IS_OK(werr)) {
163 status = rpccli_samr_CreateDomAlias(pipe_cli, ctx,
167 SAMR_ALIAS_ACCESS_SET_INFO,
170 if (!NT_STATUS_IS_OK(status)) {
171 werr = ntstatus_to_werror(status);
175 if (r->in.level == 1) {
177 union samr_AliasInfo alias_info;
179 init_lsa_String(&alias_info.description, info1->lgrpi1_comment);
181 status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
183 ALIASINFODESCRIPTION,
185 if (!NT_STATUS_IS_OK(status)) {
186 werr = ntstatus_to_werror(status);
198 if (is_valid_policy_hnd(&alias_handle)) {
199 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
201 if (is_valid_policy_hnd(&domain_handle)) {
202 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
204 if (is_valid_policy_hnd(&builtin_handle)) {
205 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
207 if (is_valid_policy_hnd(&connect_handle)) {
208 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
214 /****************************************************************
215 ****************************************************************/
217 WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
218 struct NetLocalGroupAdd *r)
220 return NetLocalGroupAdd_r(ctx, r);
223 /****************************************************************
224 ****************************************************************/
227 WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
228 struct NetLocalGroupDel *r)
230 struct cli_state *cli = NULL;
231 struct rpc_pipe_client *pipe_cli = NULL;
234 struct lsa_String lsa_account_name;
235 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
236 struct dom_sid2 *domain_sid = NULL;
238 if (!r->in.group_name) {
239 return WERR_INVALID_PARAM;
242 ZERO_STRUCT(connect_handle);
243 ZERO_STRUCT(builtin_handle);
244 ZERO_STRUCT(domain_handle);
245 ZERO_STRUCT(alias_handle);
247 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
248 if (!W_ERROR_IS_OK(werr)) {
252 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
253 if (!W_ERROR_IS_OK(werr)) {
257 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
258 SAMR_ACCESS_OPEN_DOMAIN |
259 SAMR_ACCESS_ENUM_DOMAINS,
260 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
263 if (!W_ERROR_IS_OK(werr)) {
267 init_lsa_String(&lsa_account_name, r->in.group_name);
269 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
275 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
277 if (W_ERROR_IS_OK(werr)) {
281 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
282 SAMR_ACCESS_ENUM_DOMAINS |
283 SAMR_ACCESS_OPEN_DOMAIN,
284 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
285 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
289 if (!W_ERROR_IS_OK(werr)) {
293 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
299 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
301 if (!W_ERROR_IS_OK(werr)) {
307 status = rpccli_samr_DeleteDomAlias(pipe_cli, ctx,
309 if (!NT_STATUS_IS_OK(status)) {
310 werr = ntstatus_to_werror(status);
314 ZERO_STRUCT(alias_handle);
323 if (is_valid_policy_hnd(&alias_handle)) {
324 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
326 if (is_valid_policy_hnd(&domain_handle)) {
327 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
329 if (is_valid_policy_hnd(&builtin_handle)) {
330 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
332 if (is_valid_policy_hnd(&connect_handle)) {
333 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
339 /****************************************************************
340 ****************************************************************/
342 WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
343 struct NetLocalGroupDel *r)
345 return NetLocalGroupDel_r(ctx, r);
348 /****************************************************************
349 ****************************************************************/
351 static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
352 struct samr_AliasInfoAll *info,
356 struct LOCALGROUP_INFO_0 g0;
357 struct LOCALGROUP_INFO_1 g1;
358 struct LOCALGROUP_INFO_1002 g1002;
362 g0.lgrpi0_name = info->name.string;
364 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &g0, sizeof(g0));
368 g1.lgrpi1_name = info->name.string;
369 g1.lgrpi1_comment = info->description.string;
371 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &g1, sizeof(g1));
375 g1002.lgrpi1002_comment = info->description.string;
377 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &g1002, sizeof(g1002));
381 return WERR_UNKNOWN_LEVEL;
384 W_ERROR_HAVE_NO_MEMORY(*buffer);
389 /****************************************************************
390 ****************************************************************/
392 WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
393 struct NetLocalGroupGetInfo *r)
395 struct cli_state *cli = NULL;
396 struct rpc_pipe_client *pipe_cli = NULL;
399 struct lsa_String lsa_account_name;
400 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
401 struct dom_sid2 *domain_sid = NULL;
402 union samr_AliasInfo *alias_info = NULL;
404 if (!r->in.group_name) {
405 return WERR_INVALID_PARAM;
408 switch (r->in.level) {
414 return WERR_UNKNOWN_LEVEL;
417 ZERO_STRUCT(connect_handle);
418 ZERO_STRUCT(builtin_handle);
419 ZERO_STRUCT(domain_handle);
420 ZERO_STRUCT(alias_handle);
422 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
423 if (!W_ERROR_IS_OK(werr)) {
427 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
428 if (!W_ERROR_IS_OK(werr)) {
432 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
433 SAMR_ACCESS_OPEN_DOMAIN |
434 SAMR_ACCESS_ENUM_DOMAINS,
435 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
438 if (!W_ERROR_IS_OK(werr)) {
442 init_lsa_String(&lsa_account_name, r->in.group_name);
444 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
447 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
450 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
452 if (W_ERROR_IS_OK(werr)) {
456 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
457 SAMR_ACCESS_ENUM_DOMAINS |
458 SAMR_ACCESS_OPEN_DOMAIN,
459 SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
460 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
464 if (!W_ERROR_IS_OK(werr)) {
468 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
471 SAMR_ALIAS_ACCESS_LOOKUP_INFO,
474 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
476 if (!W_ERROR_IS_OK(werr)) {
481 status = rpccli_samr_QueryAliasInfo(pipe_cli, ctx,
485 if (!NT_STATUS_IS_OK(status)) {
486 werr = ntstatus_to_werror(status);
490 werr = map_alias_info_to_buffer(ctx, &alias_info->all,
491 r->in.level, r->out.buf);
498 if (is_valid_policy_hnd(&alias_handle)) {
499 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
501 if (is_valid_policy_hnd(&domain_handle)) {
502 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
504 if (is_valid_policy_hnd(&builtin_handle)) {
505 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
507 if (is_valid_policy_hnd(&connect_handle)) {
508 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
514 /****************************************************************
515 ****************************************************************/
517 WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
518 struct NetLocalGroupGetInfo *r)
520 return NetLocalGroupGetInfo_r(ctx, r);
523 /****************************************************************
524 ****************************************************************/
526 static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
529 enum samr_AliasInfoEnum *alias_level,
530 union samr_AliasInfo **alias_info)
532 struct LOCALGROUP_INFO_0 *info0;
533 struct LOCALGROUP_INFO_1 *info1;
534 struct LOCALGROUP_INFO_1002 *info1002;
535 union samr_AliasInfo *info = NULL;
537 info = TALLOC_ZERO_P(mem_ctx, union samr_AliasInfo);
538 W_ERROR_HAVE_NO_MEMORY(info);
542 info0 = (struct LOCALGROUP_INFO_0 *)buffer;
543 init_lsa_String(&info->name, info0->lgrpi0_name);
544 *alias_level = ALIASINFONAME;
547 info1 = (struct LOCALGROUP_INFO_1 *)buffer;
548 /* group name will be ignored */
549 init_lsa_String(&info->description, info1->lgrpi1_comment);
550 *alias_level = ALIASINFODESCRIPTION;
553 info1002 = (struct LOCALGROUP_INFO_1002 *)buffer;
554 init_lsa_String(&info->description, info1002->lgrpi1002_comment);
555 *alias_level = ALIASINFODESCRIPTION;
564 /****************************************************************
565 ****************************************************************/
567 WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
568 struct NetLocalGroupSetInfo *r)
570 struct cli_state *cli = NULL;
571 struct rpc_pipe_client *pipe_cli = NULL;
574 struct lsa_String lsa_account_name;
575 struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
576 struct dom_sid2 *domain_sid = NULL;
577 enum samr_AliasInfoEnum alias_level;
578 union samr_AliasInfo *alias_info = NULL;
580 if (!r->in.group_name) {
581 return WERR_INVALID_PARAM;
584 switch (r->in.level) {
590 return WERR_UNKNOWN_LEVEL;
593 ZERO_STRUCT(connect_handle);
594 ZERO_STRUCT(builtin_handle);
595 ZERO_STRUCT(domain_handle);
596 ZERO_STRUCT(alias_handle);
598 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
599 if (!W_ERROR_IS_OK(werr)) {
603 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
604 if (!W_ERROR_IS_OK(werr)) {
608 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
609 SAMR_ACCESS_OPEN_DOMAIN |
610 SAMR_ACCESS_ENUM_DOMAINS,
611 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
614 if (!W_ERROR_IS_OK(werr)) {
618 init_lsa_String(&lsa_account_name, r->in.group_name);
620 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
623 SAMR_ALIAS_ACCESS_SET_INFO,
626 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
628 if (W_ERROR_IS_OK(werr)) {
632 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
633 SAMR_ACCESS_ENUM_DOMAINS |
634 SAMR_ACCESS_OPEN_DOMAIN,
635 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
639 if (!W_ERROR_IS_OK(werr)) {
643 werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
646 SAMR_ALIAS_ACCESS_SET_INFO,
648 if (!W_ERROR_IS_OK(werr)) {
652 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
656 werr = map_buffer_to_alias_info(ctx, r->in.level, r->in.buf,
657 &alias_level, &alias_info);
658 if (!W_ERROR_IS_OK(werr)) {
662 status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
666 if (!NT_STATUS_IS_OK(status)) {
667 werr = ntstatus_to_werror(status);
678 if (is_valid_policy_hnd(&alias_handle)) {
679 rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
681 if (is_valid_policy_hnd(&domain_handle)) {
682 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
684 if (is_valid_policy_hnd(&builtin_handle)) {
685 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
687 if (is_valid_policy_hnd(&connect_handle)) {
688 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
694 /****************************************************************
695 ****************************************************************/
697 WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
698 struct NetLocalGroupSetInfo *r)
700 return NetLocalGroupSetInfo_r(ctx, r);