2 * Unix SMB/CIFS implementation.
3 * libnet smbconf registry Support
4 * Copyright (C) Michael Adam 2007-2008
5 * Copyright (C) Guenther Deschner 2007
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "libnet/libnet.h"
24 /**********************************************************************
26 * Helper functions (mostly registry related)
27 * TODO: These should be eventually static.
29 **********************************************************************/
32 * add a string to a talloced array of strings.
34 static WERROR libnet_conf_add_string_to_array(TALLOC_CTX *mem_ctx,
39 char **new_array = NULL;
41 if ((array == NULL) || (string == NULL)) {
42 return WERR_INVALID_PARAM;
45 new_array = TALLOC_REALLOC_ARRAY(mem_ctx, *array, char *, count + 1);
46 if (new_array == NULL) {
50 new_array[count] = talloc_strdup(new_array, string);
51 if (new_array[count] == NULL) {
52 TALLOC_FREE(new_array);
61 static WERROR libnet_conf_reg_initialize(struct libnet_conf_ctx *ctx)
63 WERROR werr = WERR_OK;
65 if (!registry_init_regdb()) {
66 werr = WERR_REG_IO_FAILURE;
70 werr = ntstatus_to_werror(registry_create_admin_token(ctx,
72 if (!W_ERROR_IS_OK(werr)) {
73 DEBUG(1, ("Error creating admin token\n"));
82 * Open a registry key specified by "path"
84 static WERROR libnet_conf_reg_open_path(TALLOC_CTX *mem_ctx,
85 struct libnet_conf_ctx *ctx,
87 uint32 desired_access,
88 struct registry_key **key)
90 WERROR werr = WERR_OK;
93 DEBUG(1, ("Error: configuration is not open!\n"));
94 werr = WERR_INVALID_PARAM;
98 if (ctx->token == NULL) {
99 DEBUG(1, ("Error: token missing from libnet_conf_ctx. "
100 "was libnet_conf_open() called?\n"));
101 werr = WERR_INVALID_PARAM;
106 DEBUG(1, ("Error: NULL path string given\n"));
107 werr = WERR_INVALID_PARAM;
111 werr = reg_open_path(mem_ctx, path, desired_access, ctx->token, key);
113 if (!W_ERROR_IS_OK(werr)) {
114 DEBUG(1, ("Error opening registry path '%s': %s\n",
115 path, dos_errstr(werr)));
123 * Open a subkey of KEY_SMBCONF (i.e a service)
125 static WERROR libnet_conf_reg_open_service_key(TALLOC_CTX *mem_ctx,
126 struct libnet_conf_ctx *ctx,
127 const char *servicename,
128 uint32 desired_access,
129 struct registry_key **key)
131 WERROR werr = WERR_OK;
134 if (servicename == NULL) {
135 DEBUG(3, ("Error: NULL servicename given.\n"));
136 werr = WERR_INVALID_PARAM;
140 path = talloc_asprintf(mem_ctx, "%s\\%s", KEY_SMBCONF, servicename);
146 werr = libnet_conf_reg_open_path(mem_ctx, ctx, path, desired_access,
155 * open the base key KEY_SMBCONF
157 static WERROR libnet_conf_reg_open_base_key(TALLOC_CTX *mem_ctx,
158 struct libnet_conf_ctx *ctx,
159 uint32 desired_access,
160 struct registry_key **key)
162 return libnet_conf_reg_open_path(mem_ctx, ctx, KEY_SMBCONF,
163 desired_access, key);
167 * check if a value exists in a given registry key
169 static bool libnet_conf_value_exists(struct registry_key *key,
173 WERROR werr = WERR_OK;
174 TALLOC_CTX *ctx = talloc_stackframe();
175 struct registry_value *value = NULL;
177 werr = reg_queryvalue(ctx, key, param, &value);
178 if (W_ERROR_IS_OK(werr)) {
187 * create a subkey of KEY_SMBCONF
189 static WERROR libnet_conf_reg_create_service_key(TALLOC_CTX *mem_ctx,
190 struct libnet_conf_ctx *ctx,
191 const char * subkeyname,
192 struct registry_key **newkey)
194 WERROR werr = WERR_OK;
195 struct registry_key *create_parent = NULL;
196 TALLOC_CTX *create_ctx;
197 enum winreg_CreateAction action = REG_ACTION_NONE;
199 /* create a new talloc ctx for creation. it will hold
200 * the intermediate parent key (SMBCONF) for creation
201 * and will be destroyed when leaving this function... */
202 if (!(create_ctx = talloc_stackframe())) {
207 werr = libnet_conf_reg_open_base_key(create_ctx, ctx, REG_KEY_WRITE,
209 if (!W_ERROR_IS_OK(werr)) {
213 werr = reg_createkey(mem_ctx, create_parent, subkeyname,
214 REG_KEY_WRITE, newkey, &action);
215 if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
216 DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
217 werr = WERR_ALREADY_EXISTS;
219 if (!W_ERROR_IS_OK(werr)) {
220 DEBUG(5, ("Error creating key %s: %s\n",
221 subkeyname, dos_errstr(werr)));
225 TALLOC_FREE(create_ctx);
230 * add a value to a key.
232 static WERROR libnet_conf_reg_set_value(struct registry_key *key,
236 struct registry_value val;
237 WERROR werr = WERR_OK;
239 const char *canon_valname;
240 const char *canon_valstr;
242 if (!lp_canonicalize_parameter_with_value(valname, valstr,
246 if (canon_valname == NULL) {
247 DEBUG(5, ("invalid parameter '%s' given\n",
250 DEBUG(5, ("invalid value '%s' given for "
251 "parameter '%s'\n", valstr, valname));
253 werr = WERR_INVALID_PARAM;
260 val.v.sz.str = CONST_DISCARD(char *, canon_valstr);
261 val.v.sz.len = strlen(canon_valstr) + 1;
263 if (registry_smbconf_valname_forbidden(canon_valname)) {
264 DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
266 werr = WERR_INVALID_PARAM;
270 subkeyname = strrchr_m(key->key->name, '\\');
271 if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
272 DEBUG(5, ("Invalid registry key '%s' given as "
273 "smbconf section.\n", key->key->name));
274 werr = WERR_INVALID_PARAM;
278 if (!strequal(subkeyname, GLOBAL_NAME) &&
279 lp_parameter_is_global(valname))
281 DEBUG(5, ("Global paramter '%s' not allowed in "
282 "service definition ('%s').\n", canon_valname,
284 werr = WERR_INVALID_PARAM;
288 werr = reg_setvalue(key, canon_valname, &val);
289 if (!W_ERROR_IS_OK(werr)) {
290 DEBUG(5, ("Error adding value '%s' to "
292 canon_valname, key->key->name, dos_errstr(werr)));
300 * format a registry_value into a string.
302 * This is intended to be used for smbconf registry values,
303 * which are ar stored as REG_SZ values, so the incomplete
304 * handling should be ok.
306 static char *libnet_conf_format_registry_value(TALLOC_CTX *mem_ctx,
307 struct registry_value *value)
311 /* alternatively, create a new talloc context? */
312 if (mem_ctx == NULL) {
316 switch (value->type) {
318 result = talloc_asprintf(mem_ctx, "%d", value->v.dword);
322 result = talloc_asprintf(mem_ctx, "%s", value->v.sz.str);
326 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
327 result = talloc_asprintf(mem_ctx, "%s \"%s\" ",
329 value->v.multi_sz.strings[j]);
330 if (result == NULL) {
337 result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
338 (int)value->v.binary.length);
341 result = talloc_asprintf(mem_ctx, "<unprintable>");
348 * Get the values of a key as a list of value names
349 * and a list of value strings (ordered)
351 static WERROR libnet_conf_reg_get_values(TALLOC_CTX *mem_ctx,
352 struct registry_key *key,
353 uint32_t *num_values,
355 char ***value_strings)
357 TALLOC_CTX *tmp_ctx = NULL;
358 WERROR werr = WERR_OK;
360 struct registry_value *valvalue = NULL;
361 char *valname = NULL;
362 char **tmp_valnames = NULL;
363 char **tmp_valstrings = NULL;
365 if ((num_values == NULL) || (value_names == NULL) ||
366 (value_strings == NULL))
368 werr = WERR_INVALID_PARAM;
372 tmp_ctx = talloc_stackframe();
373 if (tmp_ctx == NULL) {
379 W_ERROR_IS_OK(werr = reg_enumvalue(tmp_ctx, key, count, &valname,
385 werr = libnet_conf_add_string_to_array(tmp_ctx,
388 if (!W_ERROR_IS_OK(werr)) {
392 valstring = libnet_conf_format_registry_value(tmp_ctx,
394 werr = libnet_conf_add_string_to_array(tmp_ctx,
398 if (!W_ERROR_IS_OK(werr)) {
402 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
410 *value_names = talloc_move(mem_ctx, &tmp_valnames);
411 *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
414 *value_strings = NULL;
418 TALLOC_FREE(tmp_ctx);
422 static int libnet_conf_destroy_ctx(struct libnet_conf_ctx *ctx)
424 return regdb_close();
427 /**********************************************************************
429 * The actual net conf api functions, that are exported.
431 **********************************************************************/
434 * Open the configuration.
436 * This should be the first function in a sequence of calls to libnet_conf
439 * Upon success, this creates and returns the conf context
440 * that should be passed around in subsequent calls to the other
441 * libnet_conf functions.
443 * After the work with the configuration is completed, libnet_conf_close()
446 WERROR libnet_conf_open(TALLOC_CTX *mem_ctx, struct libnet_conf_ctx **conf_ctx)
448 WERROR werr = WERR_OK;
449 struct libnet_conf_ctx *ctx;
451 if (conf_ctx == NULL) {
452 return WERR_INVALID_PARAM;
455 ctx = TALLOC_ZERO_P(mem_ctx, struct libnet_conf_ctx);
460 werr = libnet_conf_reg_initialize(ctx);
461 if (!W_ERROR_IS_OK(werr)) {
465 talloc_set_destructor(ctx, libnet_conf_destroy_ctx);
476 * Close the configuration.
478 void libnet_conf_close(struct libnet_conf_ctx *ctx)
480 /* this also closes the registry (by destructor): */
485 * Drop the whole configuration (restarting empty).
487 WERROR libnet_conf_drop(struct libnet_conf_ctx *ctx)
490 WERROR werr = WERR_OK;
491 struct registry_key *parent_key = NULL;
492 struct registry_key *new_key = NULL;
493 TALLOC_CTX* mem_ctx = talloc_stackframe();
494 enum winreg_CreateAction action;
496 path = talloc_strdup(mem_ctx, KEY_SMBCONF);
501 p = strrchr(path, '\\');
503 werr = libnet_conf_reg_open_path(mem_ctx, ctx, path, REG_KEY_WRITE,
506 if (!W_ERROR_IS_OK(werr)) {
510 werr = reg_deletekey_recursive(mem_ctx, parent_key, p+1);
512 if (!W_ERROR_IS_OK(werr)) {
516 werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
520 TALLOC_FREE(mem_ctx);
525 * Get the whole configuration as lists of strings with counts:
527 * num_shares : number of shares
528 * share_names : list of length num_shares of share names
529 * num_params : list of length num_shares of parameter counts for each share
530 * param_names : list of lists of parameter names for each share
531 * param_values : list of lists of parameter values for each share
533 WERROR libnet_conf_get_config(TALLOC_CTX *mem_ctx,
534 struct libnet_conf_ctx *ctx, uint32_t *num_shares,
535 char ***share_names, uint32_t **num_params,
536 char ****param_names, char ****param_values)
538 WERROR werr = WERR_OK;
539 TALLOC_CTX *tmp_ctx = NULL;
540 uint32_t tmp_num_shares;
541 char **tmp_share_names;
542 uint32_t *tmp_num_params;
543 char ***tmp_param_names;
544 char ***tmp_param_values;
547 if ((num_shares == NULL) || (share_names == NULL) ||
548 (num_params == NULL) || (param_names == NULL) ||
549 (param_values == NULL))
551 werr = WERR_INVALID_PARAM;
555 tmp_ctx = talloc_stackframe();
556 if (tmp_ctx == NULL) {
561 werr = libnet_conf_get_share_names(tmp_ctx, ctx, &tmp_num_shares,
563 if (!W_ERROR_IS_OK(werr)) {
567 tmp_num_params = TALLOC_ARRAY(tmp_ctx, uint32_t, tmp_num_shares);
568 tmp_param_names = TALLOC_ARRAY(tmp_ctx, char **, tmp_num_shares);
569 tmp_param_values = TALLOC_ARRAY(tmp_ctx, char **, tmp_num_shares);
571 if ((tmp_num_params == NULL) || (tmp_param_names == NULL) ||
572 (tmp_param_values == NULL))
578 for (count = 0; count < tmp_num_shares; count++) {
579 werr = libnet_conf_get_share(mem_ctx, ctx,
580 tmp_share_names[count],
581 &tmp_num_params[count],
582 &tmp_param_names[count],
583 &tmp_param_values[count]);
584 if (!W_ERROR_IS_OK(werr)) {
591 *num_shares = tmp_num_shares;
592 if (tmp_num_shares > 0) {
593 *share_names = talloc_move(mem_ctx, &tmp_share_names);
594 *num_params = talloc_move(mem_ctx, &tmp_num_params);
595 *param_names = talloc_move(mem_ctx, &tmp_param_names);
596 *param_values = talloc_move(mem_ctx, &tmp_param_values);
601 *param_values = NULL;
605 TALLOC_FREE(tmp_ctx);
610 * get the list of share names defined in the configuration.
612 WERROR libnet_conf_get_share_names(TALLOC_CTX *mem_ctx,
613 struct libnet_conf_ctx *ctx,
614 uint32_t *num_shares,
618 uint32_t added_count = 0;
619 TALLOC_CTX *tmp_ctx = NULL;
620 WERROR werr = WERR_OK;
621 struct registry_key *key = NULL;
622 char *subkey_name = NULL;
623 char **tmp_share_names = NULL;
625 if ((num_shares == NULL) || (share_names == NULL)) {
626 werr = WERR_INVALID_PARAM;
630 tmp_ctx = talloc_stackframe();
631 if (tmp_ctx == NULL) {
636 /* make sure "global" is always listed first */
637 if (libnet_conf_share_exists(ctx, GLOBAL_NAME)) {
638 werr = libnet_conf_add_string_to_array(tmp_ctx,
641 if (!W_ERROR_IS_OK(werr)) {
647 werr = libnet_conf_reg_open_base_key(tmp_ctx, ctx,
648 SEC_RIGHTS_ENUM_SUBKEYS, &key);
649 if (!W_ERROR_IS_OK(werr)) {
654 W_ERROR_IS_OK(werr = reg_enumkey(tmp_ctx, key, count,
655 &subkey_name, NULL));
658 if (strequal(subkey_name, GLOBAL_NAME)) {
662 werr = libnet_conf_add_string_to_array(tmp_ctx,
666 if (!W_ERROR_IS_OK(werr)) {
671 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
676 *num_shares = added_count;
677 if (added_count > 0) {
678 *share_names = talloc_move(mem_ctx, &tmp_share_names);
684 TALLOC_FREE(tmp_ctx);
689 * check if a share/service of a given name exists
691 bool libnet_conf_share_exists(struct libnet_conf_ctx *ctx,
692 const char *servicename)
695 WERROR werr = WERR_OK;
696 TALLOC_CTX *mem_ctx = talloc_stackframe();
697 struct registry_key *key = NULL;
699 werr = libnet_conf_reg_open_service_key(mem_ctx, ctx, servicename,
701 if (W_ERROR_IS_OK(werr)) {
705 TALLOC_FREE(mem_ctx);
710 * Add a service if it does not already exist.
712 WERROR libnet_conf_create_share(struct libnet_conf_ctx *ctx,
713 const char *servicename)
716 TALLOC_CTX *mem_ctx = talloc_stackframe();
717 struct registry_key *key = NULL;
719 if (libnet_conf_share_exists(ctx, servicename)) {
720 werr = WERR_ALREADY_EXISTS;
724 werr = libnet_conf_reg_create_service_key(mem_ctx, ctx, servicename,
728 TALLOC_FREE(mem_ctx);
733 * get a definition of a share (service) from configuration.
735 WERROR libnet_conf_get_share(TALLOC_CTX *mem_ctx, struct libnet_conf_ctx *ctx,
736 const char *servicename, uint32_t *num_params,
737 char ***param_names, char ***param_values)
739 WERROR werr = WERR_OK;
740 struct registry_key *key = NULL;
742 werr = libnet_conf_reg_open_service_key(mem_ctx, ctx, servicename,
744 if (!W_ERROR_IS_OK(werr)) {
748 werr = libnet_conf_reg_get_values(mem_ctx, key, num_params,
749 param_names, param_values);
757 * delete a service from configuration
759 WERROR libnet_conf_delete_share(struct libnet_conf_ctx *ctx,
760 const char *servicename)
762 WERROR werr = WERR_OK;
763 struct registry_key *key = NULL;
764 TALLOC_CTX *mem_ctx = talloc_stackframe();
766 werr = libnet_conf_reg_open_base_key(mem_ctx, ctx, REG_KEY_WRITE, &key);
767 if (!W_ERROR_IS_OK(werr)) {
771 werr = reg_deletekey_recursive(key, key, servicename);
774 TALLOC_FREE(mem_ctx);
779 * set a configuration parameter to the value provided.
781 WERROR libnet_conf_set_parameter(struct libnet_conf_ctx *ctx,
787 struct registry_key *key = NULL;
788 TALLOC_CTX *mem_ctx = talloc_stackframe();
790 if (!libnet_conf_share_exists(ctx, service)) {
791 werr = WERR_NO_SUCH_SERVICE;
795 werr = libnet_conf_reg_open_service_key(mem_ctx, ctx, service,
796 REG_KEY_WRITE, &key);
797 if (!W_ERROR_IS_OK(werr)) {
801 werr = libnet_conf_reg_set_value(key, param, valstr);
804 TALLOC_FREE(mem_ctx);
809 * Set a global parameter
810 * (i.e. a parameter in the [global] service).
812 * This also creates [global] when it does not exist.
814 WERROR libnet_conf_set_global_parameter(struct libnet_conf_ctx *ctx,
815 const char *param, const char *val)
819 if (!libnet_conf_share_exists(ctx, GLOBAL_NAME)) {
820 werr = libnet_conf_create_share(ctx, GLOBAL_NAME);
821 if (!W_ERROR_IS_OK(werr)) {
825 werr = libnet_conf_set_parameter(ctx, GLOBAL_NAME, param, val);
832 * get the value of a configuration parameter as a string
834 WERROR libnet_conf_get_parameter(TALLOC_CTX *mem_ctx,
835 struct libnet_conf_ctx *ctx,
840 WERROR werr = WERR_OK;
841 struct registry_key *key = NULL;
842 struct registry_value *value = NULL;
844 if (valstr == NULL) {
845 werr = WERR_INVALID_PARAM;
849 if (!libnet_conf_share_exists(ctx, service)) {
850 werr = WERR_NO_SUCH_SERVICE;
854 werr = libnet_conf_reg_open_service_key(mem_ctx, ctx, service,
856 if (!W_ERROR_IS_OK(werr)) {
860 if (!libnet_conf_value_exists(key, param)) {
861 werr = WERR_INVALID_PARAM;
865 werr = reg_queryvalue(mem_ctx, key, param, &value);
866 if (!W_ERROR_IS_OK(werr)) {
870 *valstr = libnet_conf_format_registry_value(mem_ctx, value);
872 if (*valstr == NULL) {
883 * Get the value of a global parameter.
885 * Create [global] if it does not exist.
887 WERROR libnet_conf_get_global_parameter(TALLOC_CTX *mem_ctx,
888 struct libnet_conf_ctx *ctx,
894 if (!libnet_conf_share_exists(ctx, GLOBAL_NAME)) {
895 werr = libnet_conf_create_share(ctx, GLOBAL_NAME);
896 if (!W_ERROR_IS_OK(werr)) {
900 werr = libnet_conf_get_parameter(mem_ctx, ctx, GLOBAL_NAME, param,
908 * delete a parameter from configuration
910 WERROR libnet_conf_delete_parameter(struct libnet_conf_ctx *ctx,
911 const char *service, const char *param)
913 struct registry_key *key = NULL;
914 WERROR werr = WERR_OK;
915 TALLOC_CTX *mem_ctx = talloc_stackframe();
917 if (!libnet_conf_share_exists(ctx, service)) {
918 return WERR_NO_SUCH_SERVICE;
921 werr = libnet_conf_reg_open_service_key(mem_ctx, ctx, service,
924 if (!W_ERROR_IS_OK(werr)) {
928 if (!libnet_conf_value_exists(key, param)) {
929 werr = WERR_INVALID_PARAM;
933 werr = reg_deletevalue(key, param);
936 TALLOC_FREE(mem_ctx);
941 * Delete a global parameter.
943 * Create [global] if it does not exist.
945 WERROR libnet_conf_delete_global_parameter(struct libnet_conf_ctx *ctx,
950 if (!libnet_conf_share_exists(ctx, GLOBAL_NAME)) {
951 werr = libnet_conf_create_share(ctx, GLOBAL_NAME);
952 if (!W_ERROR_IS_OK(werr)) {
956 werr = libnet_conf_delete_parameter(ctx, GLOBAL_NAME, param);