2 * Unix SMB/CIFS implementation.
3 * libsmbconf - Samba configuration library, registry backend
4 * Copyright (C) Michael Adam 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/>.
21 #include "smbconf_private.h"
23 struct reg_private_data {
25 bool open; /* did _we_ open the registry? */
28 /**********************************************************************
32 **********************************************************************/
35 * a convenience helper to cast the private data structure
37 static struct reg_private_data *rpd(struct smbconf_ctx *ctx)
39 return (struct reg_private_data *)(ctx->data);
43 * Open a registry key specified by "path"
45 static WERROR smbconf_reg_open_path(TALLOC_CTX *mem_ctx,
46 struct smbconf_ctx *ctx,
48 uint32 desired_access,
49 struct registry_key **key)
51 WERROR werr = WERR_OK;
54 DEBUG(1, ("Error: configuration is not open!\n"));
55 werr = WERR_INVALID_PARAM;
59 if (rpd(ctx)->token == NULL) {
60 DEBUG(1, ("Error: token missing from smbconf_ctx. "
61 "was smbconf_init() called?\n"));
62 werr = WERR_INVALID_PARAM;
66 werr = ctx->ops->open_conf(ctx);
67 if (!W_ERROR_IS_OK(werr)) {
68 DEBUG(1, ("Error opening the registry.\n"));
73 DEBUG(1, ("Error: NULL path string given\n"));
74 werr = WERR_INVALID_PARAM;
78 werr = reg_open_path(mem_ctx, path, desired_access, rpd(ctx)->token,
81 if (!W_ERROR_IS_OK(werr)) {
82 DEBUG(1, ("Error opening registry path '%s': %s\n",
83 path, dos_errstr(werr)));
91 * Open a subkey of the base key (i.e a service)
93 static WERROR smbconf_reg_open_service_key(TALLOC_CTX *mem_ctx,
94 struct smbconf_ctx *ctx,
95 const char *servicename,
96 uint32 desired_access,
97 struct registry_key **key)
99 WERROR werr = WERR_OK;
102 if (servicename == NULL) {
103 DEBUG(3, ("Error: NULL servicename given.\n"));
104 werr = WERR_INVALID_PARAM;
108 path = talloc_asprintf(mem_ctx, "%s\\%s", ctx->path, servicename);
114 werr = smbconf_reg_open_path(mem_ctx, ctx, path, desired_access, key);
124 static WERROR smbconf_reg_open_base_key(TALLOC_CTX *mem_ctx,
125 struct smbconf_ctx *ctx,
126 uint32 desired_access,
127 struct registry_key **key)
129 return smbconf_reg_open_path(mem_ctx, ctx, ctx->path, desired_access,
134 * check if a value exists in a given registry key
136 static bool smbconf_value_exists(struct registry_key *key, const char *param)
139 WERROR werr = WERR_OK;
140 TALLOC_CTX *ctx = talloc_stackframe();
141 struct registry_value *value = NULL;
143 werr = reg_queryvalue(ctx, key, param, &value);
144 if (W_ERROR_IS_OK(werr)) {
153 * create a subkey of the base key (i.e. a service...)
155 static WERROR smbconf_reg_create_service_key(TALLOC_CTX *mem_ctx,
156 struct smbconf_ctx *ctx,
157 const char * subkeyname,
158 struct registry_key **newkey)
160 WERROR werr = WERR_OK;
161 struct registry_key *create_parent = NULL;
162 TALLOC_CTX *create_ctx;
163 enum winreg_CreateAction action = REG_ACTION_NONE;
165 /* create a new talloc ctx for creation. it will hold
166 * the intermediate parent key (SMBCONF) for creation
167 * and will be destroyed when leaving this function... */
168 if (!(create_ctx = talloc_stackframe())) {
173 werr = smbconf_reg_open_base_key(create_ctx, ctx, REG_KEY_WRITE,
175 if (!W_ERROR_IS_OK(werr)) {
179 werr = reg_createkey(mem_ctx, create_parent, subkeyname,
180 REG_KEY_WRITE, newkey, &action);
181 if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
182 DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
183 werr = WERR_ALREADY_EXISTS;
185 if (!W_ERROR_IS_OK(werr)) {
186 DEBUG(5, ("Error creating key %s: %s\n",
187 subkeyname, dos_errstr(werr)));
191 TALLOC_FREE(create_ctx);
196 * add a value to a key.
198 static WERROR smbconf_reg_set_value(struct registry_key *key,
202 struct registry_value val;
203 WERROR werr = WERR_OK;
205 const char *canon_valname;
206 const char *canon_valstr;
208 if (!lp_canonicalize_parameter_with_value(valname, valstr,
212 if (canon_valname == NULL) {
213 DEBUG(5, ("invalid parameter '%s' given\n",
216 DEBUG(5, ("invalid value '%s' given for "
217 "parameter '%s'\n", valstr, valname));
219 werr = WERR_INVALID_PARAM;
223 if (registry_smbconf_valname_forbidden(canon_valname)) {
224 DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
226 werr = WERR_INVALID_PARAM;
230 subkeyname = strrchr_m(key->key->name, '\\');
231 if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
232 DEBUG(5, ("Invalid registry key '%s' given as "
233 "smbconf section.\n", key->key->name));
234 werr = WERR_INVALID_PARAM;
238 if (!strequal(subkeyname, GLOBAL_NAME) &&
239 lp_parameter_is_global(valname))
241 DEBUG(5, ("Global paramter '%s' not allowed in "
242 "service definition ('%s').\n", canon_valname,
244 werr = WERR_INVALID_PARAM;
251 val.v.sz.str = CONST_DISCARD(char *, canon_valstr);
252 val.v.sz.len = strlen(canon_valstr) + 1;
254 werr = reg_setvalue(key, canon_valname, &val);
255 if (!W_ERROR_IS_OK(werr)) {
256 DEBUG(5, ("Error adding value '%s' to "
258 canon_valname, key->key->name, dos_errstr(werr)));
266 * format a registry_value into a string.
268 * This is intended to be used for smbconf registry values,
269 * which are ar stored as REG_SZ values, so the incomplete
270 * handling should be ok.
272 static char *smbconf_format_registry_value(TALLOC_CTX *mem_ctx,
273 struct registry_value *value)
277 /* alternatively, create a new talloc context? */
278 if (mem_ctx == NULL) {
282 switch (value->type) {
284 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
288 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
292 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
293 result = talloc_asprintf(mem_ctx, "%s \"%s\" ",
295 value->v.multi_sz.strings[j]);
296 if (result == NULL) {
303 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
304 (int)value->v.binary.length);
307 result = talloc_asprintf(mem_ctx, "<unprintable>");
314 * Get the values of a key as a list of value names
315 * and a list of value strings (ordered)
317 static WERROR smbconf_reg_get_values(TALLOC_CTX *mem_ctx,
318 struct registry_key *key,
319 uint32_t *num_values,
321 char ***value_strings)
323 TALLOC_CTX *tmp_ctx = NULL;
324 WERROR werr = WERR_OK;
326 struct registry_value *valvalue = NULL;
327 char *valname = NULL;
328 char **tmp_valnames = NULL;
329 char **tmp_valstrings = NULL;
331 if ((num_values == NULL) || (value_names == NULL) ||
332 (value_strings == NULL))
334 werr = WERR_INVALID_PARAM;
338 tmp_ctx = talloc_stackframe();
339 if (tmp_ctx == NULL) {
345 werr = reg_enumvalue(tmp_ctx, key, count, &valname, &valvalue),
351 werr = smbconf_add_string_to_array(tmp_ctx,
354 if (!W_ERROR_IS_OK(werr)) {
358 valstring = smbconf_format_registry_value(tmp_ctx, valvalue);
359 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
361 if (!W_ERROR_IS_OK(werr)) {
365 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
373 *value_names = talloc_move(mem_ctx, &tmp_valnames);
374 *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
377 *value_strings = NULL;
381 TALLOC_FREE(tmp_ctx);
385 /**********************************************************************
387 * smbconf operations: registry implementations
389 **********************************************************************/
392 * initialize the registry smbconf backend
394 static WERROR smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
396 WERROR werr = WERR_OK;
401 ctx->path = talloc_strdup(ctx, path);
402 if (ctx->path == NULL) {
407 ctx->data = TALLOC_ZERO_P(ctx, struct reg_private_data);
409 werr = ntstatus_to_werror(registry_create_admin_token(ctx,
410 &(rpd(ctx)->token)));
411 if (!W_ERROR_IS_OK(werr)) {
412 DEBUG(1, ("Error creating admin token\n"));
415 rpd(ctx)->open = false;
417 if (!registry_init_smbconf()) {
418 werr = WERR_REG_IO_FAILURE;
426 static int smbconf_reg_shutdown(struct smbconf_ctx *ctx)
428 return ctx->ops->close_conf(ctx);
431 static WERROR smbconf_reg_open(struct smbconf_ctx *ctx)
435 if (rpd(ctx)->open) {
440 if (W_ERROR_IS_OK(werr)) {
441 rpd(ctx)->open = true;
446 static int smbconf_reg_close(struct smbconf_ctx *ctx)
450 if (!rpd(ctx)->open) {
456 rpd(ctx)->open = false;
462 * Get the change sequence number of the given service/parameter.
463 * service and parameter strings may be NULL.
465 static void smbconf_reg_get_csn(struct smbconf_ctx *ctx,
466 struct smbconf_csn *csn,
467 const char *service, const char *param)
473 if (!W_ERROR_IS_OK(ctx->ops->open_conf(ctx))) {
477 csn->csn = (uint64_t)regdb_get_seqnum();
481 * Drop the whole configuration (restarting empty) - registry version
483 static WERROR smbconf_reg_drop(struct smbconf_ctx *ctx)
486 WERROR werr = WERR_OK;
487 struct registry_key *parent_key = NULL;
488 struct registry_key *new_key = NULL;
489 TALLOC_CTX* mem_ctx = talloc_stackframe();
490 enum winreg_CreateAction action;
492 path = talloc_strdup(mem_ctx, ctx->path);
497 p = strrchr(path, '\\');
499 werr = smbconf_reg_open_path(mem_ctx, ctx, path, REG_KEY_WRITE,
502 if (!W_ERROR_IS_OK(werr)) {
506 werr = reg_deletekey_recursive(mem_ctx, parent_key, p+1);
508 if (!W_ERROR_IS_OK(werr)) {
512 werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
516 TALLOC_FREE(mem_ctx);
521 * get the list of share names defined in the configuration.
524 static WERROR smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
526 uint32_t *num_shares,
530 uint32_t added_count = 0;
531 TALLOC_CTX *tmp_ctx = NULL;
532 WERROR werr = WERR_OK;
533 struct registry_key *key = NULL;
534 char *subkey_name = NULL;
535 char **tmp_share_names = NULL;
537 if ((num_shares == NULL) || (share_names == NULL)) {
538 werr = WERR_INVALID_PARAM;
542 tmp_ctx = talloc_stackframe();
543 if (tmp_ctx == NULL) {
548 /* make sure "global" is always listed first */
549 if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
550 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
552 if (!W_ERROR_IS_OK(werr)) {
558 werr = smbconf_reg_open_base_key(tmp_ctx, ctx,
559 SEC_RIGHTS_ENUM_SUBKEYS, &key);
560 if (!W_ERROR_IS_OK(werr)) {
565 werr = reg_enumkey(tmp_ctx, key, count, &subkey_name, NULL),
569 if (strequal(subkey_name, GLOBAL_NAME)) {
573 werr = smbconf_add_string_to_array(tmp_ctx,
577 if (!W_ERROR_IS_OK(werr)) {
582 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
587 *num_shares = added_count;
588 if (added_count > 0) {
589 *share_names = talloc_move(mem_ctx, &tmp_share_names);
595 TALLOC_FREE(tmp_ctx);
600 * check if a share/service of a given name exists - registry version
602 static bool smbconf_reg_share_exists(struct smbconf_ctx *ctx,
603 const char *servicename)
606 WERROR werr = WERR_OK;
607 TALLOC_CTX *mem_ctx = talloc_stackframe();
608 struct registry_key *key = NULL;
610 werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
612 if (W_ERROR_IS_OK(werr)) {
616 TALLOC_FREE(mem_ctx);
621 * Add a service if it does not already exist - registry version
623 static WERROR smbconf_reg_create_share(struct smbconf_ctx *ctx,
624 const char *servicename)
627 TALLOC_CTX *mem_ctx = talloc_stackframe();
628 struct registry_key *key = NULL;
630 werr = smbconf_reg_create_service_key(mem_ctx, ctx, servicename, &key);
632 TALLOC_FREE(mem_ctx);
637 * get a definition of a share (service) from configuration.
639 static WERROR smbconf_reg_get_share(struct smbconf_ctx *ctx,
641 const char *servicename,
642 uint32_t *num_params,
643 char ***param_names, char ***param_values)
645 WERROR werr = WERR_OK;
646 struct registry_key *key = NULL;
648 werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
650 if (!W_ERROR_IS_OK(werr)) {
654 werr = smbconf_reg_get_values(mem_ctx, key, num_params,
655 param_names, param_values);
663 * delete a service from configuration
665 static WERROR smbconf_reg_delete_share(struct smbconf_ctx *ctx,
666 const char *servicename)
668 WERROR werr = WERR_OK;
669 struct registry_key *key = NULL;
670 TALLOC_CTX *mem_ctx = talloc_stackframe();
672 werr = smbconf_reg_open_base_key(mem_ctx, ctx, REG_KEY_WRITE, &key);
673 if (!W_ERROR_IS_OK(werr)) {
677 werr = reg_deletekey_recursive(key, key, servicename);
680 TALLOC_FREE(mem_ctx);
685 * set a configuration parameter to the value provided.
687 static WERROR smbconf_reg_set_parameter(struct smbconf_ctx *ctx,
693 struct registry_key *key = NULL;
694 TALLOC_CTX *mem_ctx = talloc_stackframe();
696 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
697 REG_KEY_WRITE, &key);
698 if (!W_ERROR_IS_OK(werr)) {
702 werr = smbconf_reg_set_value(key, param, valstr);
705 TALLOC_FREE(mem_ctx);
710 * get the value of a configuration parameter as a string
712 static WERROR smbconf_reg_get_parameter(struct smbconf_ctx *ctx,
718 WERROR werr = WERR_OK;
719 struct registry_key *key = NULL;
720 struct registry_value *value = NULL;
722 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
724 if (!W_ERROR_IS_OK(werr)) {
728 if (!smbconf_value_exists(key, param)) {
729 werr = WERR_INVALID_PARAM;
733 werr = reg_queryvalue(mem_ctx, key, param, &value);
734 if (!W_ERROR_IS_OK(werr)) {
738 *valstr = smbconf_format_registry_value(mem_ctx, value);
740 if (*valstr == NULL) {
751 * delete a parameter from configuration
753 static WERROR smbconf_reg_delete_parameter(struct smbconf_ctx *ctx,
757 struct registry_key *key = NULL;
758 WERROR werr = WERR_OK;
759 TALLOC_CTX *mem_ctx = talloc_stackframe();
761 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
763 if (!W_ERROR_IS_OK(werr)) {
767 if (!smbconf_value_exists(key, param)) {
768 werr = WERR_INVALID_PARAM;
772 werr = reg_deletevalue(key, param);
775 TALLOC_FREE(mem_ctx);
779 struct smbconf_ops smbconf_ops_reg = {
780 .init = smbconf_reg_init,
781 .shutdown = smbconf_reg_shutdown,
782 .open_conf = smbconf_reg_open,
783 .close_conf = smbconf_reg_close,
784 .get_csn = smbconf_reg_get_csn,
785 .drop = smbconf_reg_drop,
786 .get_share_names = smbconf_reg_get_share_names,
787 .share_exists = smbconf_reg_share_exists,
788 .create_share = smbconf_reg_create_share,
789 .get_share = smbconf_reg_get_share,
790 .delete_share = smbconf_reg_delete_share,
791 .set_parameter = smbconf_reg_set_parameter,
792 .get_parameter = smbconf_reg_get_parameter,
793 .delete_parameter = smbconf_reg_delete_parameter
798 * initialize the smbconf registry backend
799 * the only function that is exported from this module
801 WERROR smbconf_init_reg(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
804 return smbconf_init(mem_ctx, conf_ctx, path, &smbconf_ops_reg);