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_smbconf_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
);
58 * Open a subkey of KEY_SMBCONF (i.e a service)
60 static WERROR
libnet_smbconf_reg_open_path(TALLOC_CTX
*mem_ctx
,
62 uint32 desired_access
,
63 struct registry_key
**key
)
65 WERROR werr
= WERR_OK
;
69 DEBUG(1, ("Error: NULL path string given\n"));
70 werr
= WERR_INVALID_PARAM
;
74 token
= registry_create_admin_token(mem_ctx
);
76 DEBUG(1, ("Error creating admin token\n"));
77 /* what is the appropriate error code here? */
78 werr
= WERR_CAN_NOT_COMPLETE
;
82 werr
= reg_open_path(mem_ctx
, path
, desired_access
, token
, key
);
84 if (!W_ERROR_IS_OK(werr
)) {
85 DEBUG(1, ("Error opening registry path '%s': %s\n",
86 path
, dos_errstr(werr
)));
94 * Open a subkey of KEY_SMBCONF (i.e a service)
96 static WERROR
libnet_smbconf_reg_open_service_key(TALLOC_CTX
*ctx
,
97 const char *servicename
,
98 uint32 desired_access
,
99 struct registry_key
**key
)
101 WERROR werr
= WERR_OK
;
103 NT_USER_TOKEN
*token
;
105 if (servicename
== NULL
) {
106 DEBUG(3, ("Error: NULL servicename given.\n"));
107 werr
= WERR_INVALID_PARAM
;
111 path
= talloc_asprintf(ctx
, "%s\\%s", KEY_SMBCONF
, servicename
);
113 werr
= libnet_smbconf_reg_open_path(ctx
, path
, desired_access
, key
);
121 * open the base key KEY_SMBCONF
123 static WERROR
libnet_smbconf_reg_open_basekey(TALLOC_CTX
*ctx
,
124 uint32 desired_access
,
125 struct registry_key
**key
)
127 return libnet_smbconf_reg_open_path(ctx
, KEY_SMBCONF
, desired_access
,
131 static bool libnet_smbconf_value_exists(struct registry_key
*key
,
135 WERROR werr
= WERR_OK
;
136 TALLOC_CTX
*ctx
= talloc_stackframe();
137 struct registry_value
*value
= NULL
;
139 werr
= reg_queryvalue(ctx
, key
, param
, &value
);
140 if (W_ERROR_IS_OK(werr
)) {
149 * create a subkey of KEY_SMBCONF
151 static WERROR
libnet_smbconf_reg_createkey_internal(TALLOC_CTX
*ctx
,
152 const char * subkeyname
,
153 struct registry_key
**newkey
)
155 WERROR werr
= WERR_OK
;
156 struct registry_key
*create_parent
= NULL
;
157 TALLOC_CTX
*create_ctx
;
158 enum winreg_CreateAction action
= REG_ACTION_NONE
;
160 /* create a new talloc ctx for creation. it will hold
161 * the intermediate parent key (SMBCONF) for creation
162 * and will be destroyed when leaving this function... */
163 if (!(create_ctx
= talloc_new(ctx
))) {
168 werr
= libnet_smbconf_reg_open_basekey(create_ctx
, REG_KEY_WRITE
,
170 if (!W_ERROR_IS_OK(werr
)) {
174 werr
= reg_createkey(ctx
, create_parent
, subkeyname
,
175 REG_KEY_WRITE
, newkey
, &action
);
176 if (W_ERROR_IS_OK(werr
) && (action
!= REG_CREATED_NEW_KEY
)) {
177 DEBUG(10, ("Key '%s' already exists.\n", subkeyname
));
178 werr
= WERR_ALREADY_EXISTS
;
180 if (!W_ERROR_IS_OK(werr
)) {
181 DEBUG(5, ("Error creating key %s: %s\n",
182 subkeyname
, dos_errstr(werr
)));
186 TALLOC_FREE(create_ctx
);
191 * add a value to a key.
193 static WERROR
libnet_smbconf_reg_setvalue_internal(struct registry_key
*key
,
197 struct registry_value val
;
198 WERROR werr
= WERR_OK
;
200 const char *canon_valname
;
201 const char *canon_valstr
;
203 if (!lp_canonicalize_parameter_with_value(valname
, valstr
,
207 if (canon_valname
== NULL
) {
208 DEBUG(5, ("invalid parameter '%s' given\n",
211 DEBUG(5, ("invalid value '%s' given for "
212 "parameter '%s'\n", valstr
, valname
));
214 werr
= WERR_INVALID_PARAM
;
221 val
.v
.sz
.str
= CONST_DISCARD(char *, canon_valstr
);
222 val
.v
.sz
.len
= strlen(canon_valstr
) + 1;
224 if (registry_smbconf_valname_forbidden(canon_valname
)) {
225 DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
227 werr
= WERR_INVALID_PARAM
;
231 subkeyname
= strrchr_m(key
->key
->name
, '\\');
232 if ((subkeyname
== NULL
) || (*(subkeyname
+1) == '\0')) {
233 DEBUG(5, ("Invalid registry key '%s' given as "
234 "smbconf section.\n", key
->key
->name
));
235 werr
= WERR_INVALID_PARAM
;
239 if (!strequal(subkeyname
, GLOBAL_NAME
) &&
240 lp_parameter_is_global(valname
))
242 DEBUG(5, ("Global paramter '%s' not allowed in "
243 "service definition ('%s').\n", canon_valname
,
245 werr
= WERR_INVALID_PARAM
;
249 werr
= reg_setvalue(key
, canon_valname
, &val
);
250 if (!W_ERROR_IS_OK(werr
)) {
251 DEBUG(5, ("Error adding value '%s' to "
253 canon_valname
, key
->key
->name
, dos_errstr(werr
)));
261 * format a registry_value into a string.
263 * This is intended to be used for smbconf registry values,
264 * which are ar stored as REG_SZ values, so the incomplete
265 * handling should be ok.
267 static char *libnet_smbconf_format_registry_value(TALLOC_CTX
*mem_ctx
,
268 struct registry_value
*value
)
272 /* alternatively, create a new talloc context? */
273 if (mem_ctx
== NULL
) {
277 switch (value
->type
) {
279 result
= talloc_asprintf(mem_ctx
, "%d", value
->v
.dword
);
283 result
= talloc_asprintf(mem_ctx
, "%s", value
->v
.sz
.str
);
287 for (j
= 0; j
< value
->v
.multi_sz
.num_strings
; j
++) {
288 result
= talloc_asprintf(mem_ctx
, "\"%s\" ",
289 value
->v
.multi_sz
.strings
[j
]);
294 result
= talloc_asprintf(mem_ctx
, "binary (%d bytes)",
295 (int)value
->v
.binary
.length
);
298 result
= talloc_asprintf(mem_ctx
, "<unprintable>");
305 * Get the values of a key as a list of value names
306 * and a list of value strings (ordered)
308 static WERROR
libnet_smbconf_reg_get_values(TALLOC_CTX
*mem_ctx
,
309 struct registry_key
*key
,
310 uint32_t *num_values
,
312 char ***value_strings
)
314 TALLOC_CTX
*tmp_ctx
= NULL
;
315 WERROR werr
= WERR_OK
;
317 struct registry_value
*valvalue
= NULL
;
318 char *valname
= NULL
;
319 char **tmp_valnames
= NULL
;
320 char **tmp_valstrings
= NULL
;
322 if ((num_values
== NULL
) || (value_names
== NULL
) ||
323 (value_strings
== NULL
))
325 werr
= WERR_INVALID_PARAM
;
329 tmp_ctx
= talloc_new(mem_ctx
);
330 if (tmp_ctx
== NULL
) {
336 W_ERROR_IS_OK(werr
= reg_enumvalue(tmp_ctx
, key
, count
, &valname
,
342 werr
= libnet_smbconf_add_string_to_array(tmp_ctx
,
345 if (!W_ERROR_IS_OK(werr
)) {
349 valstring
= libnet_smbconf_format_registry_value(tmp_ctx
,
351 werr
= libnet_smbconf_add_string_to_array(tmp_ctx
,
355 if (!W_ERROR_IS_OK(werr
)) {
359 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS
, werr
)) {
367 *value_names
= talloc_move(mem_ctx
, &tmp_valnames
);
368 *value_strings
= talloc_move(mem_ctx
, &tmp_valstrings
);
371 *value_strings
= NULL
;
375 TALLOC_FREE(tmp_ctx
);
379 /**********************************************************************
381 * The actual net conf api functions, that are exported.
383 **********************************************************************/
386 * Drop the whole configuration (restarting empty).
388 WERROR
libnet_smbconf_drop(void)
391 WERROR werr
= WERR_OK
;
392 NT_USER_TOKEN
*token
;
393 struct registry_key
*parent_key
= NULL
;
394 struct registry_key
*new_key
= NULL
;
395 TALLOC_CTX
* mem_ctx
= talloc_stackframe();
396 enum winreg_CreateAction action
;
398 path
= talloc_strdup(mem_ctx
, KEY_SMBCONF
);
403 p
= strrchr(path
, '\\');
405 werr
= libnet_smbconf_reg_open_path(mem_ctx
, path
, REG_KEY_WRITE
,
408 if (!W_ERROR_IS_OK(werr
)) {
412 werr
= reg_deletekey_recursive(mem_ctx
, parent_key
, p
+1);
414 if (!W_ERROR_IS_OK(werr
)) {
418 werr
= reg_createkey(mem_ctx
, parent_key
, p
+1, REG_KEY_WRITE
,
422 TALLOC_FREE(mem_ctx
);
427 * Get the whole configuration as lists of strings with counts:
429 * num_shares : number of shares
430 * share_names : list of length num_shares of share names
431 * num_params : list of length num_shares of parameter counts for each share
432 * param_names : list of lists of parameter names for each share
433 * param_values : list of lists of parameter values for each share
435 WERROR
libnet_smbconf_get_config(TALLOC_CTX
*mem_ctx
, uint32_t *num_shares
,
436 char ***share_names
, uint32_t **num_params
,
437 char ****param_names
, char ****param_values
)
439 WERROR werr
= WERR_OK
;
440 TALLOC_CTX
*tmp_ctx
= NULL
;
441 uint32_t tmp_num_shares
;
442 char **tmp_share_names
;
443 uint32_t *tmp_num_params
;
444 char ***tmp_param_names
;
445 char ***tmp_param_values
;
448 if ((num_shares
== NULL
) || (share_names
== NULL
) ||
449 (num_params
== NULL
) || (param_names
== NULL
) ||
450 (param_values
== NULL
))
452 werr
= WERR_INVALID_PARAM
;
456 tmp_ctx
= talloc_new(mem_ctx
);
457 if (tmp_ctx
== NULL
) {
462 werr
= libnet_smbconf_get_share_names(tmp_ctx
, &tmp_num_shares
,
464 if (!W_ERROR_IS_OK(werr
)) {
468 tmp_num_params
= TALLOC_ARRAY(tmp_ctx
, uint32_t, tmp_num_shares
);
469 tmp_param_names
= TALLOC_ARRAY(tmp_ctx
, char **, tmp_num_shares
);
470 tmp_param_values
= TALLOC_ARRAY(tmp_ctx
, char **, tmp_num_shares
);
472 if ((tmp_num_params
== NULL
) || (tmp_param_names
== NULL
) ||
473 (tmp_param_values
== NULL
))
479 for (count
= 0; count
< tmp_num_shares
; count
++) {
480 werr
= libnet_smbconf_getshare(mem_ctx
, tmp_share_names
[count
],
481 &tmp_num_params
[count
],
482 &tmp_param_names
[count
],
483 &tmp_param_values
[count
]);
484 if (!W_ERROR_IS_OK(werr
)) {
491 *num_shares
= tmp_num_shares
;
492 if (tmp_num_shares
> 0) {
493 *share_names
= talloc_move(mem_ctx
, &tmp_share_names
);
494 *num_params
= talloc_move(mem_ctx
, &tmp_num_params
);
495 *param_names
= talloc_move(mem_ctx
, &tmp_param_names
);
496 *param_values
= talloc_move(mem_ctx
, &tmp_param_values
);
501 *param_values
= NULL
;
505 TALLOC_FREE(tmp_ctx
);
511 * get the list of share names defined in the configuration.
513 WERROR
libnet_smbconf_get_share_names(TALLOC_CTX
*mem_ctx
, uint32_t *num_shares
,
517 uint32_t added_count
= 0;
518 TALLOC_CTX
*tmp_ctx
= NULL
;
519 WERROR werr
= WERR_OK
;
520 struct registry_key
*key
= NULL
;
521 char *subkey_name
= NULL
;
522 char **tmp_share_names
= NULL
;
524 if ((num_shares
== NULL
) || (share_names
== NULL
)) {
525 werr
= WERR_INVALID_PARAM
;
529 tmp_ctx
= talloc_new(mem_ctx
);
530 if (tmp_ctx
== NULL
) {
535 /* make sure "global" is always listed first */
536 if (libnet_smbconf_share_exists(GLOBAL_NAME
)) {
537 werr
= libnet_smbconf_add_string_to_array(tmp_ctx
,
540 if (!W_ERROR_IS_OK(werr
)) {
546 werr
= libnet_smbconf_reg_open_basekey(tmp_ctx
,
547 SEC_RIGHTS_ENUM_SUBKEYS
,
549 if (!W_ERROR_IS_OK(werr
)) {
554 W_ERROR_IS_OK(werr
= reg_enumkey(tmp_ctx
, key
, count
,
555 &subkey_name
, NULL
));
558 if (strequal(subkey_name
, GLOBAL_NAME
)) {
562 werr
= libnet_smbconf_add_string_to_array(tmp_ctx
,
566 if (!W_ERROR_IS_OK(werr
)) {
571 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS
, werr
)) {
576 *num_shares
= added_count
;
577 if (added_count
> 0) {
578 *share_names
= talloc_move(mem_ctx
, &tmp_share_names
);
584 TALLOC_FREE(tmp_ctx
);
589 * check if a share/service of a given name exists
591 bool libnet_smbconf_share_exists(const char *servicename
)
594 WERROR werr
= WERR_OK
;
595 TALLOC_CTX
*mem_ctx
= talloc_stackframe();
596 struct registry_key
*key
= NULL
;
598 werr
= libnet_smbconf_reg_open_service_key(mem_ctx
, servicename
,
600 if (W_ERROR_IS_OK(werr
)) {
604 TALLOC_FREE(mem_ctx
);
609 * get a definition of a share (service) from configuration.
611 WERROR
libnet_smbconf_getshare(TALLOC_CTX
*mem_ctx
, const char *servicename
,
612 uint32_t *num_params
, char ***param_names
,
613 char ***param_values
)
615 WERROR werr
= WERR_OK
;
616 struct registry_key
*key
= NULL
;
618 werr
= libnet_smbconf_reg_open_service_key(mem_ctx
, servicename
,
620 if (!W_ERROR_IS_OK(werr
)) {
624 werr
= libnet_smbconf_reg_get_values(mem_ctx
, key
, num_params
,
625 param_names
, param_values
);
633 * delete a service from configuration
635 WERROR
libnet_smbconf_delshare(const char *servicename
)
637 WERROR werr
= WERR_OK
;
638 struct registry_key
*key
= NULL
;
639 TALLOC_CTX
*ctx
= talloc_stackframe();
641 werr
= libnet_smbconf_reg_open_basekey(ctx
, REG_KEY_WRITE
, &key
);
642 if (!W_ERROR_IS_OK(werr
)) {
646 werr
= reg_deletekey_recursive(key
, key
, servicename
);
654 * set a configuration parameter to the value provided.
656 WERROR
libnet_smbconf_setparm(const char *service
,
661 struct registry_key
*key
= NULL
;
662 TALLOC_CTX
*mem_ctx
= talloc_stackframe();
664 if (!libnet_smbconf_share_exists(service
)) {
665 werr
= libnet_smbconf_reg_createkey_internal(mem_ctx
, service
,
668 werr
= libnet_smbconf_reg_open_service_key(mem_ctx
, service
,
669 REG_KEY_WRITE
, &key
);
671 if (!W_ERROR_IS_OK(werr
)) {
675 werr
= libnet_smbconf_reg_setvalue_internal(key
, param
, valstr
);
678 TALLOC_FREE(mem_ctx
);
683 * get the value of a configuration parameter as a string
685 WERROR
libnet_smbconf_getparm(TALLOC_CTX
*mem_ctx
,
690 WERROR werr
= WERR_OK
;
691 struct registry_key
*key
= NULL
;
692 struct registry_value
*value
= NULL
;
694 if (valstr
== NULL
) {
695 werr
= WERR_INVALID_PARAM
;
699 if (!libnet_smbconf_share_exists(service
)) {
700 werr
= WERR_NO_SUCH_SERVICE
;
704 werr
= libnet_smbconf_reg_open_service_key(mem_ctx
, service
,
706 if (!W_ERROR_IS_OK(werr
)) {
710 if (!libnet_smbconf_value_exists(key
, param
)) {
711 werr
= WERR_INVALID_PARAM
;
715 werr
= reg_queryvalue(mem_ctx
, key
, param
, &value
);
716 if (!W_ERROR_IS_OK(werr
)) {
720 *valstr
= libnet_smbconf_format_registry_value(mem_ctx
, value
);
722 if (*valstr
== NULL
) {
733 * delete a parameter from configuration
735 WERROR
libnet_smbconf_delparm(const char *service
,
738 struct registry_key
*key
= NULL
;
739 WERROR werr
= WERR_OK
;
740 TALLOC_CTX
*mem_ctx
= talloc_stackframe();
742 if (!libnet_smbconf_share_exists(service
)) {
743 return WERR_NO_SUCH_SERVICE
;
746 werr
= libnet_smbconf_reg_open_service_key(mem_ctx
, service
,
748 if (!W_ERROR_IS_OK(werr
)) {
752 if (!libnet_smbconf_value_exists(key
, param
)) {
753 werr
= WERR_INVALID_PARAM
;
757 werr
= reg_deletevalue(key
, param
);
760 TALLOC_FREE(mem_ctx
);
765 /**********************************************************************
767 * Convenience functions that are also exported.
769 **********************************************************************/
771 WERROR
libnet_smbconf_set_global_param(const char *param
,
774 return libnet_smbconf_setparm(GLOBAL_NAME
, param
, val
);