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 **********************************************************************/
33 static struct reg_private_data *rpd(struct smbconf_ctx *ctx)
35 return (struct reg_private_data *)(ctx->data);
39 * Open a registry key specified by "path"
41 static WERROR smbconf_reg_open_path(TALLOC_CTX *mem_ctx,
42 struct smbconf_ctx *ctx,
44 uint32 desired_access,
45 struct registry_key **key)
47 WERROR werr = WERR_OK;
50 DEBUG(1, ("Error: configuration is not open!\n"));
51 werr = WERR_INVALID_PARAM;
55 if (rpd(ctx)->token == NULL) {
56 DEBUG(1, ("Error: token missing from smbconf_ctx. "
57 "was smbconf_init() called?\n"));
58 werr = WERR_INVALID_PARAM;
63 DEBUG(1, ("Error: NULL path string given\n"));
64 werr = WERR_INVALID_PARAM;
68 werr = reg_open_path(mem_ctx, path, desired_access, rpd(ctx)->token,
71 if (!W_ERROR_IS_OK(werr)) {
72 DEBUG(1, ("Error opening registry path '%s': %s\n",
73 path, dos_errstr(werr)));
81 * Open a subkey of the base key (i.e a service)
83 static WERROR smbconf_reg_open_service_key(TALLOC_CTX *mem_ctx,
84 struct smbconf_ctx *ctx,
85 const char *servicename,
86 uint32 desired_access,
87 struct registry_key **key)
89 WERROR werr = WERR_OK;
92 if (servicename == NULL) {
93 DEBUG(3, ("Error: NULL servicename given.\n"));
94 werr = WERR_INVALID_PARAM;
98 path = talloc_asprintf(mem_ctx, "%s\\%s", ctx->path, servicename);
104 werr = smbconf_reg_open_path(mem_ctx, ctx, path, desired_access, key);
114 static WERROR smbconf_reg_open_base_key(TALLOC_CTX *mem_ctx,
115 struct smbconf_ctx *ctx,
116 uint32 desired_access,
117 struct registry_key **key)
119 return smbconf_reg_open_path(mem_ctx, ctx, ctx->path, desired_access,
124 * check if a value exists in a given registry key
126 static bool smbconf_value_exists(struct registry_key *key, const char *param)
129 WERROR werr = WERR_OK;
130 TALLOC_CTX *ctx = talloc_stackframe();
131 struct registry_value *value = NULL;
133 werr = reg_queryvalue(ctx, key, param, &value);
134 if (W_ERROR_IS_OK(werr)) {
143 * create a subkey of the base key (i.e. a service...)
145 static WERROR smbconf_reg_create_service_key(TALLOC_CTX *mem_ctx,
146 struct smbconf_ctx *ctx,
147 const char * subkeyname,
148 struct registry_key **newkey)
150 WERROR werr = WERR_OK;
151 struct registry_key *create_parent = NULL;
152 TALLOC_CTX *create_ctx;
153 enum winreg_CreateAction action = REG_ACTION_NONE;
155 /* create a new talloc ctx for creation. it will hold
156 * the intermediate parent key (SMBCONF) for creation
157 * and will be destroyed when leaving this function... */
158 if (!(create_ctx = talloc_stackframe())) {
163 werr = smbconf_reg_open_base_key(create_ctx, ctx, REG_KEY_WRITE,
165 if (!W_ERROR_IS_OK(werr)) {
169 werr = reg_createkey(mem_ctx, create_parent, subkeyname,
170 REG_KEY_WRITE, newkey, &action);
171 if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
172 DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
173 werr = WERR_ALREADY_EXISTS;
175 if (!W_ERROR_IS_OK(werr)) {
176 DEBUG(5, ("Error creating key %s: %s\n",
177 subkeyname, dos_errstr(werr)));
181 TALLOC_FREE(create_ctx);
186 * add a value to a key.
188 static WERROR smbconf_reg_set_value(struct registry_key *key,
192 struct registry_value val;
193 WERROR werr = WERR_OK;
195 const char *canon_valname;
196 const char *canon_valstr;
198 if (!lp_canonicalize_parameter_with_value(valname, valstr,
202 if (canon_valname == NULL) {
203 DEBUG(5, ("invalid parameter '%s' given\n",
206 DEBUG(5, ("invalid value '%s' given for "
207 "parameter '%s'\n", valstr, valname));
209 werr = WERR_INVALID_PARAM;
216 val.v.sz.str = CONST_DISCARD(char *, canon_valstr);
217 val.v.sz.len = strlen(canon_valstr) + 1;
219 if (registry_smbconf_valname_forbidden(canon_valname)) {
220 DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
222 werr = WERR_INVALID_PARAM;
226 subkeyname = strrchr_m(key->key->name, '\\');
227 if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
228 DEBUG(5, ("Invalid registry key '%s' given as "
229 "smbconf section.\n", key->key->name));
230 werr = WERR_INVALID_PARAM;
234 if (!strequal(subkeyname, GLOBAL_NAME) &&
235 lp_parameter_is_global(valname))
237 DEBUG(5, ("Global paramter '%s' not allowed in "
238 "service definition ('%s').\n", canon_valname,
240 werr = WERR_INVALID_PARAM;
244 werr = reg_setvalue(key, canon_valname, &val);
245 if (!W_ERROR_IS_OK(werr)) {
246 DEBUG(5, ("Error adding value '%s' to "
248 canon_valname, key->key->name, dos_errstr(werr)));
256 * format a registry_value into a string.
258 * This is intended to be used for smbconf registry values,
259 * which are ar stored as REG_SZ values, so the incomplete
260 * handling should be ok.
262 static char *smbconf_format_registry_value(TALLOC_CTX *mem_ctx,
263 struct registry_value *value)
267 /* alternatively, create a new talloc context? */
268 if (mem_ctx == NULL) {
272 switch (value->type) {
274 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
278 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
282 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
283 result = talloc_asprintf(mem_ctx, "%s \"%s\" ",
285 value->v.multi_sz.strings[j]);
286 if (result == NULL) {
293 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
294 (int)value->v.binary.length);
297 result = talloc_asprintf(mem_ctx, "<unprintable>");
304 * Get the values of a key as a list of value names
305 * and a list of value strings (ordered)
307 static WERROR smbconf_reg_get_values(TALLOC_CTX *mem_ctx,
308 struct registry_key *key,
309 uint32_t *num_values,
311 char ***value_strings)
313 TALLOC_CTX *tmp_ctx = NULL;
314 WERROR werr = WERR_OK;
316 struct registry_value *valvalue = NULL;
317 char *valname = NULL;
318 char **tmp_valnames = NULL;
319 char **tmp_valstrings = NULL;
321 if ((num_values == NULL) || (value_names == NULL) ||
322 (value_strings == NULL))
324 werr = WERR_INVALID_PARAM;
328 tmp_ctx = talloc_stackframe();
329 if (tmp_ctx == NULL) {
335 W_ERROR_IS_OK(werr = reg_enumvalue(tmp_ctx, key, count, &valname,
341 werr = smbconf_add_string_to_array(tmp_ctx,
344 if (!W_ERROR_IS_OK(werr)) {
348 valstring = smbconf_format_registry_value(tmp_ctx, valvalue);
349 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
351 if (!W_ERROR_IS_OK(werr)) {
355 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
363 *value_names = talloc_move(mem_ctx, &tmp_valnames);
364 *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
367 *value_strings = NULL;
371 TALLOC_FREE(tmp_ctx);
375 /**********************************************************************
377 * smbconf operations: registry implementations
379 **********************************************************************/
382 * initialize the registry smbconf backend
384 static WERROR smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
386 WERROR werr = WERR_OK;
391 ctx->path = talloc_strdup(ctx, path);
392 if (ctx->path == NULL) {
397 ctx->data = TALLOC_ZERO_P(ctx, struct reg_private_data);
399 werr = ntstatus_to_werror(registry_create_admin_token(ctx,
400 &(rpd(ctx)->token)));
401 if (!W_ERROR_IS_OK(werr)) {
402 DEBUG(1, ("Error creating admin token\n"));
406 if (!registry_init_smbconf()) {
407 werr = WERR_REG_IO_FAILURE;
416 static int smbconf_reg_shutdown(struct smbconf_ctx *ctx)
418 return regdb_close();
421 static WERROR smbconf_reg_open(struct smbconf_ctx *ctx)
426 static int smbconf_reg_close(struct smbconf_ctx *ctx)
428 return regdb_close();
432 * Get the change sequence number of the given service/parameter.
433 * service and parameter strings may be NULL.
435 static void smbconf_reg_get_csn(struct smbconf_ctx *ctx,
436 struct smbconf_csn *csn,
437 const char *service, const char *param)
442 csn->csn = (uint64_t)regdb_get_seqnum();
446 * Drop the whole configuration (restarting empty) - registry version
448 static WERROR smbconf_reg_drop(struct smbconf_ctx *ctx)
451 WERROR werr = WERR_OK;
452 struct registry_key *parent_key = NULL;
453 struct registry_key *new_key = NULL;
454 TALLOC_CTX* mem_ctx = talloc_stackframe();
455 enum winreg_CreateAction action;
457 path = talloc_strdup(mem_ctx, ctx->path);
462 p = strrchr(path, '\\');
464 werr = smbconf_reg_open_path(mem_ctx, ctx, path, REG_KEY_WRITE,
467 if (!W_ERROR_IS_OK(werr)) {
471 werr = reg_deletekey_recursive(mem_ctx, parent_key, p+1);
473 if (!W_ERROR_IS_OK(werr)) {
477 werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
481 TALLOC_FREE(mem_ctx);
486 * get the list of share names defined in the configuration.
489 static WERROR smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
491 uint32_t *num_shares,
495 uint32_t added_count = 0;
496 TALLOC_CTX *tmp_ctx = NULL;
497 WERROR werr = WERR_OK;
498 struct registry_key *key = NULL;
499 char *subkey_name = NULL;
500 char **tmp_share_names = NULL;
502 if ((num_shares == NULL) || (share_names == NULL)) {
503 werr = WERR_INVALID_PARAM;
507 tmp_ctx = talloc_stackframe();
508 if (tmp_ctx == NULL) {
513 /* make sure "global" is always listed first */
514 if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
515 werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
517 if (!W_ERROR_IS_OK(werr)) {
523 werr = smbconf_reg_open_base_key(tmp_ctx, ctx,
524 SEC_RIGHTS_ENUM_SUBKEYS, &key);
525 if (!W_ERROR_IS_OK(werr)) {
530 W_ERROR_IS_OK(werr = reg_enumkey(tmp_ctx, key, count,
531 &subkey_name, NULL));
534 if (strequal(subkey_name, GLOBAL_NAME)) {
538 werr = smbconf_add_string_to_array(tmp_ctx,
542 if (!W_ERROR_IS_OK(werr)) {
547 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
552 *num_shares = added_count;
553 if (added_count > 0) {
554 *share_names = talloc_move(mem_ctx, &tmp_share_names);
560 TALLOC_FREE(tmp_ctx);
565 * check if a share/service of a given name exists - registry version
567 static bool smbconf_reg_share_exists(struct smbconf_ctx *ctx,
568 const char *servicename)
571 WERROR werr = WERR_OK;
572 TALLOC_CTX *mem_ctx = talloc_stackframe();
573 struct registry_key *key = NULL;
575 werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
577 if (W_ERROR_IS_OK(werr)) {
581 TALLOC_FREE(mem_ctx);
586 * Add a service if it does not already exist - registry version
588 static WERROR smbconf_reg_create_share(struct smbconf_ctx *ctx,
589 const char *servicename)
592 TALLOC_CTX *mem_ctx = talloc_stackframe();
593 struct registry_key *key = NULL;
595 werr = smbconf_reg_create_service_key(mem_ctx, ctx, servicename, &key);
597 TALLOC_FREE(mem_ctx);
602 * get a definition of a share (service) from configuration.
604 static WERROR smbconf_reg_get_share(struct smbconf_ctx *ctx,
606 const char *servicename,
607 uint32_t *num_params,
608 char ***param_names, char ***param_values)
610 WERROR werr = WERR_OK;
611 struct registry_key *key = NULL;
613 werr = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
615 if (!W_ERROR_IS_OK(werr)) {
619 werr = smbconf_reg_get_values(mem_ctx, key, num_params,
620 param_names, param_values);
628 * delete a service from configuration
630 static WERROR smbconf_reg_delete_share(struct smbconf_ctx *ctx,
631 const char *servicename)
633 WERROR werr = WERR_OK;
634 struct registry_key *key = NULL;
635 TALLOC_CTX *mem_ctx = talloc_stackframe();
637 werr = smbconf_reg_open_base_key(mem_ctx, ctx, REG_KEY_WRITE, &key);
638 if (!W_ERROR_IS_OK(werr)) {
642 werr = reg_deletekey_recursive(key, key, servicename);
645 TALLOC_FREE(mem_ctx);
650 * set a configuration parameter to the value provided.
652 static WERROR smbconf_reg_set_parameter(struct smbconf_ctx *ctx,
658 struct registry_key *key = NULL;
659 TALLOC_CTX *mem_ctx = talloc_stackframe();
661 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
662 REG_KEY_WRITE, &key);
663 if (!W_ERROR_IS_OK(werr)) {
667 werr = smbconf_reg_set_value(key, param, valstr);
670 TALLOC_FREE(mem_ctx);
675 * get the value of a configuration parameter as a string
677 static WERROR smbconf_reg_get_parameter(struct smbconf_ctx *ctx,
683 WERROR werr = WERR_OK;
684 struct registry_key *key = NULL;
685 struct registry_value *value = NULL;
687 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
689 if (!W_ERROR_IS_OK(werr)) {
693 if (!smbconf_value_exists(key, param)) {
694 werr = WERR_INVALID_PARAM;
698 werr = reg_queryvalue(mem_ctx, key, param, &value);
699 if (!W_ERROR_IS_OK(werr)) {
703 *valstr = smbconf_format_registry_value(mem_ctx, value);
705 if (*valstr == NULL) {
716 * delete a parameter from configuration
718 static WERROR smbconf_reg_delete_parameter(struct smbconf_ctx *ctx,
722 struct registry_key *key = NULL;
723 WERROR werr = WERR_OK;
724 TALLOC_CTX *mem_ctx = talloc_stackframe();
726 werr = smbconf_reg_open_service_key(mem_ctx, ctx, service,
728 if (!W_ERROR_IS_OK(werr)) {
732 if (!smbconf_value_exists(key, param)) {
733 werr = WERR_INVALID_PARAM;
737 werr = reg_deletevalue(key, param);
740 TALLOC_FREE(mem_ctx);
744 struct smbconf_ops smbconf_ops_reg = {
745 .init = smbconf_reg_init,
746 .shutdown = smbconf_reg_shutdown,
747 .open_conf = smbconf_reg_open,
748 .close_conf = smbconf_reg_close,
749 .get_csn = smbconf_reg_get_csn,
750 .drop = smbconf_reg_drop,
751 .get_share_names = smbconf_reg_get_share_names,
752 .share_exists = smbconf_reg_share_exists,
753 .create_share = smbconf_reg_create_share,
754 .get_share = smbconf_reg_get_share,
755 .delete_share = smbconf_reg_delete_share,
756 .set_parameter = smbconf_reg_set_parameter,
757 .get_parameter = smbconf_reg_get_parameter,
758 .delete_parameter = smbconf_reg_delete_parameter
763 * initialize the smbconf registry backend
764 * the only function that is exported from this module
766 WERROR smbconf_init_reg(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
769 return smbconf_init(mem_ctx, conf_ctx, path, &smbconf_ops_reg);