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 {
27 /**********************************************************************
31 **********************************************************************/
34 * a convenience helper to cast the private data structure
36 static struct reg_private_data *rpd(struct smbconf_ctx *ctx)
38 return (struct reg_private_data *)(ctx->data);
42 * Open a registry key specified by "path"
44 static WERROR smbconf_reg_open_path(TALLOC_CTX *mem_ctx,
45 struct smbconf_ctx *ctx,
47 uint32 desired_access,
48 struct registry_key **key)
50 WERROR werr = WERR_OK;
53 DEBUG(1, ("Error: configuration is not open!\n"));
54 werr = WERR_INVALID_PARAM;
58 if (rpd(ctx)->token == NULL) {
59 DEBUG(1, ("Error: token missing from smbconf_ctx. "
60 "was smbconf_init() called?\n"));
61 werr = WERR_INVALID_PARAM;
66 DEBUG(1, ("Error: NULL path string given\n"));
67 werr = WERR_INVALID_PARAM;
71 werr = reg_open_path(mem_ctx, path, desired_access, rpd(ctx)->token,
74 if (!W_ERROR_IS_OK(werr)) {
75 DEBUG(1, ("Error opening registry path '%s': %s\n",
76 path, dos_errstr(werr)));
84 * Open a subkey of the base key (i.e a service)
86 static WERROR smbconf_reg_open_service_key(TALLOC_CTX *mem_ctx,
87 struct smbconf_ctx *ctx,
88 const char *servicename,
89 uint32 desired_access,
90 struct registry_key **key)
92 WERROR werr = WERR_OK;
95 if (servicename == NULL) {
96 DEBUG(3, ("Error: NULL servicename given.\n"));
97 werr = WERR_INVALID_PARAM;
101 path = talloc_asprintf(mem_ctx, "%s\\%s", ctx->path, servicename);
107 werr = smbconf_reg_open_path(mem_ctx, ctx, path, desired_access, key);
117 static WERROR smbconf_reg_open_base_key(TALLOC_CTX *mem_ctx,
118 struct smbconf_ctx *ctx,
119 uint32 desired_access,
120 struct registry_key **key)
122 return smbconf_reg_open_path(mem_ctx, ctx, ctx->path, desired_access,
127 * check if a value exists in a given registry key
129 static bool smbconf_value_exists(struct registry_key *key, const char *param)
132 WERROR werr = WERR_OK;
133 TALLOC_CTX *ctx = talloc_stackframe();
134 struct registry_value *value = NULL;
136 werr = reg_queryvalue(ctx, key, param, &value);
137 if (W_ERROR_IS_OK(werr)) {
146 * create a subkey of the base key (i.e. a service...)
148 static WERROR smbconf_reg_create_service_key(TALLOC_CTX *mem_ctx,
149 struct smbconf_ctx *ctx,
150 const char * subkeyname,
151 struct registry_key **newkey)
153 WERROR werr = WERR_OK;
154 struct registry_key *create_parent = NULL;
155 TALLOC_CTX *create_ctx;
156 enum winreg_CreateAction action = REG_ACTION_NONE;
158 /* create a new talloc ctx for creation. it will hold
159 * the intermediate parent key (SMBCONF) for creation
160 * and will be destroyed when leaving this function... */
161 if (!(create_ctx = talloc_stackframe())) {
166 werr = smbconf_reg_open_base_key(create_ctx, ctx, REG_KEY_WRITE,
168 if (!W_ERROR_IS_OK(werr)) {
172 werr = reg_createkey(mem_ctx, create_parent, subkeyname,
173 REG_KEY_WRITE, newkey, &action);
174 if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
175 DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
176 werr = WERR_ALREADY_EXISTS;
178 if (!W_ERROR_IS_OK(werr)) {
179 DEBUG(5, ("Error creating key %s: %s\n",
180 subkeyname, dos_errstr(werr)));
184 TALLOC_FREE(create_ctx);
189 * add a value to a key.
191 static WERROR smbconf_reg_set_value(struct registry_key *key,
195 struct registry_value val;
196 WERROR werr = WERR_OK;
198 const char *canon_valname;
199 const char *canon_valstr;
201 if (!lp_canonicalize_parameter_with_value(valname, valstr,
205 if (canon_valname == NULL) {
206 DEBUG(5, ("invalid parameter '%s' given\n",
209 DEBUG(5, ("invalid value '%s' given for "
210 "parameter '%s'\n", valstr, valname));
212 werr = WERR_INVALID_PARAM;
219 val.v.sz.str = CONST_DISCARD(char *, canon_valstr);
220 val.v.sz.len = strlen(canon_valstr) + 1;
222 if (registry_smbconf_valname_forbidden(canon_valname)) {
223 DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
225 werr = WERR_INVALID_PARAM;
229 subkeyname = strrchr_m(key->key->name, '\\');
230 if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
231 DEBUG(5, ("Invalid registry key '%s' given as "
232 "smbconf section.\n", key->key->name));
233 werr = WERR_INVALID_PARAM;
237 if (!strequal(subkeyname, GLOBAL_NAME) &&
238 lp_parameter_is_global(valname))
240 DEBUG(5, ("Global paramter '%s' not allowed in "
241 "service definition ('%s').\n", canon_valname,
243 werr = WERR_INVALID_PARAM;
247 werr = reg_setvalue(key, canon_valname, &val);
248 if (!W_ERROR_IS_OK(werr)) {
249 DEBUG(5, ("Error adding value '%s' to "
251 canon_valname, key->key->name, dos_errstr(werr)));
259 * format a registry_value into a string.
261 * This is intended to be used for smbconf registry values,
262 * which are ar stored as REG_SZ values, so the incomplete
263 * handling should be ok.
265 static char *smbconf_format_registry_value(TALLOC_CTX *mem_ctx,
266 struct registry_value *value)
270 /* alternatively, create a new talloc context? */
271 if (mem_ctx == NULL) {
275 switch (value->type) {
277 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
281 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
285 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
286 result = talloc_asprintf(mem_ctx, "%s \"%s\" ",
288 value->v.multi_sz.strings[j]);
289 if (result == NULL) {
296 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
297 (int)value->v.binary.length);
300 result = talloc_asprintf(mem_ctx, "<unprintable>");
307 * Get the values of a key as a list of value names
308 * and a list of value strings (ordered)
310 static WERROR smbconf_reg_get_values(TALLOC_CTX *mem_ctx,
311 struct registry_key *key,
312 uint32_t *num_values,
314 char ***value_strings)
316 TALLOC_CTX *tmp_ctx = NULL;
317 WERROR werr = WERR_OK;
319 struct registry_value *valvalue = NULL;
320 char *valname = NULL;
321 char **tmp_valnames = NULL;
322 char **tmp_valstrings = NULL;
324 if ((num_values == NULL) || (value_names == NULL) ||
325 (value_strings == NULL))
327 werr = WERR_INVALID_PARAM;
331 tmp_ctx = talloc_stackframe();
332 if (tmp_ctx == NULL) {
338 W_ERROR_IS_OK(werr = reg_enumvalue(tmp_ctx, key, count, &valname,
344 werr = smbconf_add_string_to_array(tmp_ctx,
347 if (!W_ERROR_IS_OK(werr)) {
351 valstring = smbconf_format_registry_value(tmp_ctx, valvalue);
352 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
354 if (!W_ERROR_IS_OK(werr)) {
358 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
366 *value_names = talloc_move(mem_ctx, &tmp_valnames);
367 *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
370 *value_strings = NULL;
374 TALLOC_FREE(tmp_ctx);
378 /**********************************************************************
380 * smbconf operations: registry implementations
382 **********************************************************************/
385 * initialize the registry smbconf backend
387 static WERROR smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
389 WERROR werr = WERR_OK;
394 ctx->path = talloc_strdup(ctx, path);
395 if (ctx->path == NULL) {
400 ctx->data = TALLOC_ZERO_P(ctx, struct reg_private_data);
402 werr = ntstatus_to_werror(registry_create_admin_token(ctx,
403 &(rpd(ctx)->token)));
404 if (!W_ERROR_IS_OK(werr)) {
405 DEBUG(1, ("Error creating admin token\n"));
409 if (!registry_init_smbconf()) {
410 werr = WERR_REG_IO_FAILURE;
419 static int smbconf_reg_shutdown(struct smbconf_ctx *ctx)
421 return regdb_close();
424 static WERROR smbconf_reg_open(struct smbconf_ctx *ctx)
429 static int smbconf_reg_close(struct smbconf_ctx *ctx)
431 return regdb_close();
435 * Get the change sequence number of the given service/parameter.
436 * service and parameter strings may be NULL.
438 static void smbconf_reg_get_csn(struct smbconf_ctx *ctx,
439 struct smbconf_csn *csn,
440 const char *service, const char *param)
445 csn->csn = (uint64_t)regdb_get_seqnum();
449 * Drop the whole configuration (restarting empty) - registry version
451 static WERROR smbconf_reg_drop(struct smbconf_ctx *ctx)
454 WERROR werr = WERR_OK;
455 struct registry_key *parent_key = NULL;
456 struct registry_key *new_key = NULL;
457 TALLOC_CTX* mem_ctx = talloc_stackframe();
458 enum winreg_CreateAction action;
460 path = talloc_strdup(mem_ctx, ctx->path);
465 p = strrchr(path, '\\');
467 werr = smbconf_reg_open_path(mem_ctx, ctx, path, REG_KEY_WRITE,
470 if (!W_ERROR_IS_OK(werr)) {
474 werr = reg_deletekey_recursive(mem_ctx, parent_key, p+1);
476 if (!W_ERROR_IS_OK(werr)) {
480 werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
484 TALLOC_FREE(mem_ctx);
489 * get the list of share names defined in the configuration.
492 static WERROR smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
494 uint32_t *num_shares,
498 uint32_t added_count = 0;
499 TALLOC_CTX *tmp_ctx = NULL;
500 WERROR werr = WERR_OK;
501 struct registry_key *key = NULL;
502 char *subkey_name = NULL;
503 char **tmp_share_names = NULL;
505 if ((num_shares == NULL) || (share_names == NULL)) {
506 werr = WERR_INVALID_PARAM;
510 tmp_ctx = talloc_stackframe();
511 if (tmp_ctx == NULL) {
516 /* make sure "global" is always listed first */
517 if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
518 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
520 if (!W_ERROR_IS_OK(werr)) {
526 werr = smbconf_reg_open_base_key(tmp_ctx, ctx,
527 SEC_RIGHTS_ENUM_SUBKEYS, &key);
528 if (!W_ERROR_IS_OK(werr)) {
533 W_ERROR_IS_OK(werr = reg_enumkey(tmp_ctx, key, count,
534 &subkey_name, NULL));
537 if (strequal(subkey_name, GLOBAL_NAME)) {
541 werr = smbconf_add_string_to_array(tmp_ctx,
545 if (!W_ERROR_IS_OK(werr)) {
550 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
555 *num_shares = added_count;
556 if (added_count > 0) {
557 *share_names = talloc_move(mem_ctx, &tmp_share_names);
563 TALLOC_FREE(tmp_ctx);
568 * check if a share/service of a given name exists - registry version
570 static bool smbconf_reg_share_exists(struct smbconf_ctx *ctx,
571 const char *servicename)
574 WERROR werr = WERR_OK;
575 TALLOC_CTX *mem_ctx = talloc_stackframe();
576 struct registry_key *key = NULL;
578 werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
580 if (W_ERROR_IS_OK(werr)) {
584 TALLOC_FREE(mem_ctx);
589 * Add a service if it does not already exist - registry version
591 static WERROR smbconf_reg_create_share(struct smbconf_ctx *ctx,
592 const char *servicename)
595 TALLOC_CTX *mem_ctx = talloc_stackframe();
596 struct registry_key *key = NULL;
598 werr = smbconf_reg_create_service_key(mem_ctx, ctx, servicename, &key);
600 TALLOC_FREE(mem_ctx);
605 * get a definition of a share (service) from configuration.
607 static WERROR smbconf_reg_get_share(struct smbconf_ctx *ctx,
609 const char *servicename,
610 uint32_t *num_params,
611 char ***param_names, char ***param_values)
613 WERROR werr = WERR_OK;
614 struct registry_key *key = NULL;
616 werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
618 if (!W_ERROR_IS_OK(werr)) {
622 werr = smbconf_reg_get_values(mem_ctx, key, num_params,
623 param_names, param_values);
631 * delete a service from configuration
633 static WERROR smbconf_reg_delete_share(struct smbconf_ctx *ctx,
634 const char *servicename)
636 WERROR werr = WERR_OK;
637 struct registry_key *key = NULL;
638 TALLOC_CTX *mem_ctx = talloc_stackframe();
640 werr = smbconf_reg_open_base_key(mem_ctx, ctx, REG_KEY_WRITE, &key);
641 if (!W_ERROR_IS_OK(werr)) {
645 werr = reg_deletekey_recursive(key, key, servicename);
648 TALLOC_FREE(mem_ctx);
653 * set a configuration parameter to the value provided.
655 static WERROR smbconf_reg_set_parameter(struct smbconf_ctx *ctx,
661 struct registry_key *key = NULL;
662 TALLOC_CTX *mem_ctx = talloc_stackframe();
664 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
665 REG_KEY_WRITE, &key);
666 if (!W_ERROR_IS_OK(werr)) {
670 werr = smbconf_reg_set_value(key, param, valstr);
673 TALLOC_FREE(mem_ctx);
678 * get the value of a configuration parameter as a string
680 static WERROR smbconf_reg_get_parameter(struct smbconf_ctx *ctx,
686 WERROR werr = WERR_OK;
687 struct registry_key *key = NULL;
688 struct registry_value *value = NULL;
690 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
692 if (!W_ERROR_IS_OK(werr)) {
696 if (!smbconf_value_exists(key, param)) {
697 werr = WERR_INVALID_PARAM;
701 werr = reg_queryvalue(mem_ctx, key, param, &value);
702 if (!W_ERROR_IS_OK(werr)) {
706 *valstr = smbconf_format_registry_value(mem_ctx, value);
708 if (*valstr == NULL) {
719 * delete a parameter from configuration
721 static WERROR smbconf_reg_delete_parameter(struct smbconf_ctx *ctx,
725 struct registry_key *key = NULL;
726 WERROR werr = WERR_OK;
727 TALLOC_CTX *mem_ctx = talloc_stackframe();
729 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
731 if (!W_ERROR_IS_OK(werr)) {
735 if (!smbconf_value_exists(key, param)) {
736 werr = WERR_INVALID_PARAM;
740 werr = reg_deletevalue(key, param);
743 TALLOC_FREE(mem_ctx);
747 struct smbconf_ops smbconf_ops_reg = {
748 .init = smbconf_reg_init,
749 .shutdown = smbconf_reg_shutdown,
750 .open_conf = smbconf_reg_open,
751 .close_conf = smbconf_reg_close,
752 .get_csn = smbconf_reg_get_csn,
753 .drop = smbconf_reg_drop,
754 .get_share_names = smbconf_reg_get_share_names,
755 .share_exists = smbconf_reg_share_exists,
756 .create_share = smbconf_reg_create_share,
757 .get_share = smbconf_reg_get_share,
758 .delete_share = smbconf_reg_delete_share,
759 .set_parameter = smbconf_reg_set_parameter,
760 .get_parameter = smbconf_reg_get_parameter,
761 .delete_parameter = smbconf_reg_delete_parameter
766 * initialize the smbconf registry backend
767 * the only function that is exported from this module
769 WERROR smbconf_init_reg(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
772 return smbconf_init(mem_ctx, conf_ctx, path, &smbconf_ops_reg);