Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * libsmbconf - Samba configuration library, registry backend
4 : * Copyright (C) Michael Adam 2008
5 : *
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.
10 : *
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.
15 : *
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/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "lib/smbconf/smbconf_private.h"
22 : #include "registry.h"
23 : #include "registry/reg_api.h"
24 : #include "registry/reg_backend_db.h"
25 : #include "registry/reg_util_token.h"
26 : #include "registry/reg_api_util.h"
27 : #include "registry/reg_init_smbconf.h"
28 : #include "lib/smbconf/smbconf_init.h"
29 : #include "lib/smbconf/smbconf_reg.h"
30 : #include "../libcli/registry/util_reg.h"
31 :
32 : #define INCLUDES_VALNAME "includes"
33 :
34 : struct reg_private_data {
35 : struct registry_key *base_key;
36 : bool open; /* did _we_ open the registry? */
37 : };
38 :
39 : /**********************************************************************
40 : *
41 : * helper functions
42 : *
43 : **********************************************************************/
44 :
45 : /**
46 : * a convenience helper to cast the private data structure
47 : */
48 3153776 : static struct reg_private_data *rpd(struct smbconf_ctx *ctx)
49 : {
50 3153776 : return (struct reg_private_data *)(ctx->data);
51 : }
52 :
53 : /**
54 : * Check whether a given parameter name is valid in the
55 : * smbconf registry backend.
56 : */
57 20547 : bool smbconf_reg_parameter_is_valid(const char *param_name)
58 : {
59 : /* hard code the list of forbidden names here for now */
60 20547 : const char *forbidden_names[] = {
61 : "state directory",
62 : "lock directory",
63 : "lock dir",
64 : "config backend",
65 : "include",
66 : /*
67 : * "includes" has a special meaning internally.
68 : * It is currently not necessary to list it here since it is
69 : * not a valid parameter. But for clarity and safety, we keep
70 : * it for now.
71 : */
72 : INCLUDES_VALNAME,
73 : NULL
74 : };
75 20547 : const char **forbidden = NULL;
76 :
77 20547 : if (!lp_parameter_is_valid(param_name)) {
78 2 : return false;
79 : }
80 :
81 143735 : for (forbidden = forbidden_names; *forbidden != NULL; forbidden++) {
82 123210 : if (strwicmp(param_name, *forbidden) == 0) {
83 20 : return false;
84 : }
85 : }
86 :
87 20481 : return true;
88 : }
89 :
90 : /**
91 : * Open a subkey of the base key (i.e a service)
92 : */
93 2924652 : static sbcErr smbconf_reg_open_service_key(TALLOC_CTX *mem_ctx,
94 : struct smbconf_ctx *ctx,
95 : const char *servicename,
96 : uint32_t desired_access,
97 : struct registry_key **key)
98 : {
99 78 : WERROR werr;
100 :
101 2924652 : if (servicename == NULL) {
102 0 : *key = rpd(ctx)->base_key;
103 0 : return SBC_ERR_OK;
104 : }
105 2924652 : werr = reg_openkey(mem_ctx, rpd(ctx)->base_key, servicename,
106 : desired_access, key);
107 2924652 : if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
108 2916015 : return SBC_ERR_NO_SUCH_SERVICE;
109 : }
110 8610 : if (!W_ERROR_IS_OK(werr)) {
111 0 : return SBC_ERR_NOMEM;
112 : }
113 :
114 8559 : return SBC_ERR_OK;
115 : }
116 :
117 : /**
118 : * check if a value exists in a given registry key
119 : */
120 4769 : static bool smbconf_value_exists(struct registry_key *key, const char *param)
121 : {
122 4769 : bool ret = false;
123 17 : WERROR werr;
124 4769 : TALLOC_CTX *ctx = talloc_stackframe();
125 4769 : struct registry_value *value = NULL;
126 :
127 4769 : werr = reg_queryvalue(ctx, key, param, &value);
128 4769 : if (W_ERROR_IS_OK(werr)) {
129 21 : ret = true;
130 : }
131 :
132 4769 : talloc_free(ctx);
133 4769 : return ret;
134 : }
135 :
136 : /**
137 : * create a subkey of the base key (i.e. a service...)
138 : */
139 667 : static sbcErr smbconf_reg_create_service_key(TALLOC_CTX *mem_ctx,
140 : struct smbconf_ctx *ctx,
141 : const char * subkeyname,
142 : struct registry_key **newkey)
143 : {
144 14 : WERROR werr;
145 667 : sbcErr err = SBC_ERR_OK;
146 14 : TALLOC_CTX *create_ctx;
147 667 : enum winreg_CreateAction action = REG_ACTION_NONE;
148 :
149 : /* create a new talloc ctx for creation. it will hold
150 : * the intermediate parent key (SMBCONF) for creation
151 : * and will be destroyed when leaving this function... */
152 667 : create_ctx = talloc_stackframe();
153 :
154 667 : werr = reg_createkey(mem_ctx, rpd(ctx)->base_key, subkeyname,
155 : REG_KEY_WRITE, newkey, &action);
156 667 : if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
157 0 : DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
158 0 : err = SBC_ERR_FILE_EXISTS;
159 : }
160 667 : if (!W_ERROR_IS_OK(werr)) {
161 0 : DEBUG(5, ("Error creating key %s: %s\n",
162 : subkeyname, win_errstr(werr)));
163 0 : err = SBC_ERR_UNKNOWN_FAILURE;
164 : }
165 :
166 667 : talloc_free(create_ctx);
167 667 : return err;
168 : }
169 :
170 : /**
171 : * add a value to a key.
172 : */
173 2918 : static sbcErr smbconf_reg_set_value(struct registry_key *key,
174 : const char *valname,
175 : const char *valstr)
176 : {
177 21 : struct registry_value val;
178 21 : WERROR werr;
179 21 : sbcErr err;
180 21 : char *subkeyname;
181 21 : const char *canon_valname;
182 21 : const char *canon_valstr;
183 2918 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
184 :
185 2918 : if (!lp_parameter_is_valid(valname)) {
186 0 : DEBUG(5, ("Invalid parameter '%s' given.\n", valname));
187 0 : err = SBC_ERR_INVALID_PARAM;
188 0 : goto done;
189 : }
190 :
191 2918 : if (!smbconf_reg_parameter_is_valid(valname)) {
192 0 : DEBUG(5, ("Parameter '%s' not allowed in registry.\n",
193 : valname));
194 0 : err = SBC_ERR_INVALID_PARAM;
195 0 : goto done;
196 : }
197 :
198 2918 : subkeyname = strrchr_m(key->key->name, '\\');
199 2918 : if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
200 0 : DEBUG(5, ("Invalid registry key '%s' given as "
201 : "smbconf section.\n", key->key->name));
202 0 : err = SBC_ERR_INVALID_PARAM;
203 0 : goto done;
204 : }
205 2918 : subkeyname++;
206 5594 : if (!strequal(subkeyname, GLOBAL_NAME) &&
207 2676 : lp_parameter_is_global(valname))
208 : {
209 0 : DEBUG(5, ("Global parameter '%s' not allowed in "
210 : "service definition ('%s').\n", valname,
211 : subkeyname));
212 0 : err = SBC_ERR_INVALID_PARAM;
213 0 : goto done;
214 : }
215 :
216 2918 : if (!lp_canonicalize_parameter_with_value(valname, valstr,
217 : &canon_valname,
218 : &canon_valstr))
219 : {
220 : /*
221 : * We already know the parameter name is valid.
222 : * So the value must be invalid.
223 : */
224 0 : DEBUG(5, ("invalid value '%s' given for parameter '%s'\n",
225 : valstr, valname));
226 0 : err = SBC_ERR_INVALID_PARAM;
227 0 : goto done;
228 : }
229 :
230 2918 : ZERO_STRUCT(val);
231 :
232 2918 : val.type = REG_SZ;
233 2918 : if (!push_reg_sz(tmp_ctx, &val.data, canon_valstr)) {
234 0 : err = SBC_ERR_NOMEM;
235 0 : goto done;
236 : }
237 :
238 2918 : werr = reg_setvalue(key, canon_valname, &val);
239 2918 : if (!W_ERROR_IS_OK(werr)) {
240 0 : DEBUG(5, ("Error adding value '%s' to "
241 : "key '%s': %s\n",
242 : canon_valname, key->key->name, win_errstr(werr)));
243 0 : err = SBC_ERR_NOMEM;
244 0 : goto done;
245 : }
246 :
247 2897 : err = SBC_ERR_OK;
248 2918 : done:
249 2918 : talloc_free(tmp_ctx);
250 2918 : return err;
251 : }
252 :
253 6 : static sbcErr smbconf_reg_set_multi_sz_value(struct registry_key *key,
254 : const char *valname,
255 : const uint32_t num_strings,
256 : const char **strings)
257 : {
258 0 : WERROR werr;
259 6 : sbcErr err = SBC_ERR_OK;
260 0 : struct registry_value *value;
261 0 : uint32_t count;
262 6 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
263 0 : const char **array;
264 :
265 6 : if (strings == NULL) {
266 0 : err = SBC_ERR_INVALID_PARAM;
267 0 : goto done;
268 : }
269 :
270 6 : array = talloc_zero_array(tmp_ctx, const char *, num_strings + 1);
271 6 : if (array == NULL) {
272 0 : err = SBC_ERR_NOMEM;
273 0 : goto done;
274 : }
275 :
276 6 : value = talloc_zero(tmp_ctx, struct registry_value);
277 6 : if (value == NULL) {
278 0 : err = SBC_ERR_NOMEM;
279 0 : goto done;
280 : }
281 :
282 6 : value->type = REG_MULTI_SZ;
283 :
284 18 : for (count = 0; count < num_strings; count++) {
285 12 : array[count] = talloc_strdup(value, strings[count]);
286 12 : if (array[count] == NULL) {
287 0 : err = SBC_ERR_NOMEM;
288 0 : goto done;
289 : }
290 : }
291 :
292 6 : if (!push_reg_multi_sz(value, &value->data, array)) {
293 0 : err = SBC_ERR_NOMEM;
294 0 : goto done;
295 : }
296 :
297 6 : werr = reg_setvalue(key, valname, value);
298 6 : if (!W_ERROR_IS_OK(werr)) {
299 0 : DEBUG(5, ("Error adding value '%s' to key '%s': %s\n",
300 : valname, key->key->name, win_errstr(werr)));
301 0 : err = SBC_ERR_ACCESS_DENIED;
302 : }
303 :
304 6 : done:
305 6 : talloc_free(tmp_ctx);
306 6 : return err;
307 : }
308 :
309 : /**
310 : * format a registry_value into a string.
311 : *
312 : * This is intended to be used for smbconf registry values,
313 : * which are ar stored as REG_SZ values, so the incomplete
314 : * handling should be ok.
315 : */
316 17567 : static char *smbconf_format_registry_value(TALLOC_CTX *mem_ctx,
317 : struct registry_value *value)
318 : {
319 17567 : char *result = NULL;
320 :
321 : /* alternatively, create a new talloc context? */
322 17567 : if (mem_ctx == NULL) {
323 0 : return result;
324 : }
325 :
326 17567 : switch (value->type) {
327 0 : case REG_DWORD:
328 0 : if (value->data.length >= 4) {
329 0 : uint32_t v = IVAL(value->data.data, 0);
330 0 : result = talloc_asprintf(mem_ctx, "%d", v);
331 : }
332 0 : break;
333 17567 : case REG_SZ:
334 : case REG_EXPAND_SZ: {
335 20 : const char *s;
336 17567 : if (!pull_reg_sz(mem_ctx, &value->data, &s)) {
337 0 : break;
338 : }
339 17567 : result = talloc_strdup(mem_ctx, s);
340 17567 : break;
341 : }
342 0 : case REG_MULTI_SZ: {
343 0 : uint32_t j;
344 0 : const char **a = NULL;
345 0 : if (!pull_reg_multi_sz(mem_ctx, &value->data, &a)) {
346 0 : break;
347 : }
348 0 : for (j = 0; a[j] != NULL; j++) {
349 0 : result = talloc_asprintf(mem_ctx, "%s\"%s\" ",
350 : result ? result : "" ,
351 0 : a[j]);
352 0 : if (result == NULL) {
353 0 : break;
354 : }
355 : }
356 0 : break;
357 : }
358 0 : case REG_BINARY:
359 0 : result = talloc_asprintf(mem_ctx, "binary (%d bytes)",
360 0 : (int)value->data.length);
361 0 : break;
362 0 : default:
363 0 : result = talloc_asprintf(mem_ctx, "<unprintable>");
364 0 : break;
365 : }
366 17547 : return result;
367 : }
368 :
369 4313 : static sbcErr smbconf_reg_get_includes_internal(TALLOC_CTX *mem_ctx,
370 : struct registry_key *key,
371 : uint32_t *num_includes,
372 : char ***includes)
373 : {
374 9 : WERROR werr;
375 9 : sbcErr err;
376 9 : uint32_t count;
377 4313 : struct registry_value *value = NULL;
378 4313 : char **tmp_includes = NULL;
379 4313 : const char **array = NULL;
380 4313 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
381 :
382 4313 : if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
383 : /* no includes */
384 4307 : *num_includes = 0;
385 4307 : *includes = NULL;
386 4307 : err = SBC_ERR_OK;
387 4307 : goto done;
388 : }
389 :
390 6 : werr = reg_queryvalue(tmp_ctx, key, INCLUDES_VALNAME, &value);
391 6 : if (!W_ERROR_IS_OK(werr)) {
392 0 : err = SBC_ERR_ACCESS_DENIED;
393 0 : goto done;
394 : }
395 :
396 6 : if (value->type != REG_MULTI_SZ) {
397 : /* wrong type -- ignore */
398 0 : err = SBC_ERR_OK;
399 0 : goto done;
400 : }
401 :
402 6 : if (!pull_reg_multi_sz(tmp_ctx, &value->data, &array)) {
403 0 : err = SBC_ERR_NOMEM;
404 0 : goto done;
405 : }
406 :
407 22 : for (count = 0; array[count] != NULL; count++) {
408 16 : err = smbconf_add_string_to_array(tmp_ctx,
409 : &tmp_includes,
410 : count,
411 16 : array[count]);
412 16 : if (!SBC_ERROR_IS_OK(err)) {
413 0 : goto done;
414 : }
415 : }
416 :
417 6 : if (count > 0) {
418 6 : *includes = talloc_move(mem_ctx, &tmp_includes);
419 6 : if (*includes == NULL) {
420 0 : err = SBC_ERR_NOMEM;
421 0 : goto done;
422 : }
423 6 : *num_includes = count;
424 : } else {
425 0 : *num_includes = 0;
426 0 : *includes = NULL;
427 : }
428 :
429 6 : err = SBC_ERR_OK;
430 4313 : done:
431 4313 : talloc_free(tmp_ctx);
432 4313 : return err;
433 : }
434 :
435 : /**
436 : * Get the values of a key as a list of value names
437 : * and a list of value strings (ordered)
438 : */
439 4305 : static sbcErr smbconf_reg_get_values(TALLOC_CTX *mem_ctx,
440 : struct registry_key *key,
441 : uint32_t *num_values,
442 : char ***value_names,
443 : char ***value_strings)
444 : {
445 4305 : TALLOC_CTX *tmp_ctx = NULL;
446 9 : WERROR werr;
447 9 : sbcErr err;
448 9 : uint32_t count;
449 4305 : struct registry_value *valvalue = NULL;
450 4305 : char *valname = NULL;
451 4305 : uint32_t tmp_num_values = 0;
452 4305 : char **tmp_valnames = NULL;
453 4305 : char **tmp_valstrings = NULL;
454 4305 : uint32_t num_includes = 0;
455 4305 : char **includes = NULL;
456 :
457 4305 : if ((num_values == NULL) || (value_names == NULL) ||
458 : (value_strings == NULL))
459 : {
460 0 : err = SBC_ERR_INVALID_PARAM;
461 0 : goto done;
462 : }
463 :
464 4305 : tmp_ctx = talloc_stackframe();
465 :
466 4305 : for (count = 0;
467 21868 : werr = reg_enumvalue(tmp_ctx, key, count, &valname, &valvalue),
468 21839 : W_ERROR_IS_OK(werr);
469 17563 : count++)
470 : {
471 20 : char *valstring;
472 :
473 17563 : if (!smbconf_reg_parameter_is_valid(valname)) {
474 2 : continue;
475 : }
476 :
477 17561 : err = smbconf_add_string_to_array(tmp_ctx,
478 : &tmp_valnames,
479 : tmp_num_values, valname);
480 17561 : if (!SBC_ERROR_IS_OK(err)) {
481 0 : goto done;
482 : }
483 :
484 17561 : valstring = smbconf_format_registry_value(tmp_ctx, valvalue);
485 17561 : err = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
486 : tmp_num_values, valstring);
487 17561 : if (!SBC_ERROR_IS_OK(err)) {
488 0 : goto done;
489 : }
490 17561 : tmp_num_values++;
491 : }
492 4305 : if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
493 0 : err = SBC_ERR_NOMEM;
494 0 : goto done;
495 : }
496 :
497 : /* now add the includes at the end */
498 4305 : err = smbconf_reg_get_includes_internal(tmp_ctx, key, &num_includes,
499 : &includes);
500 4305 : if (!SBC_ERROR_IS_OK(err)) {
501 0 : goto done;
502 : }
503 :
504 4311 : for (count = 0; count < num_includes; count++) {
505 6 : err = smbconf_add_string_to_array(tmp_ctx, &tmp_valnames,
506 : tmp_num_values, "include");
507 6 : if (!SBC_ERROR_IS_OK(err)) {
508 0 : goto done;
509 : }
510 :
511 6 : err = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings,
512 : tmp_num_values,
513 6 : includes[count]);
514 6 : if (!SBC_ERROR_IS_OK(err)) {
515 0 : goto done;
516 : }
517 :
518 6 : tmp_num_values++;
519 : }
520 :
521 4305 : *num_values = tmp_num_values;
522 4305 : if (tmp_num_values > 0) {
523 4293 : *value_names = talloc_move(mem_ctx, &tmp_valnames);
524 4293 : *value_strings = talloc_move(mem_ctx, &tmp_valstrings);
525 : } else {
526 12 : *value_names = NULL;
527 12 : *value_strings = NULL;
528 : }
529 :
530 4305 : done:
531 4305 : talloc_free(tmp_ctx);
532 4305 : return err;
533 : }
534 :
535 : /**
536 : * delete all values from a key
537 : */
538 0 : static sbcErr smbconf_reg_delete_values(struct registry_key *key)
539 : {
540 0 : WERROR werr;
541 0 : sbcErr err;
542 0 : char *valname;
543 0 : struct registry_value *valvalue;
544 0 : uint32_t count;
545 0 : TALLOC_CTX *mem_ctx = talloc_stackframe();
546 :
547 0 : for (count = 0;
548 0 : werr = reg_enumvalue(mem_ctx, key, count, &valname, &valvalue),
549 0 : W_ERROR_IS_OK(werr);
550 0 : count++)
551 : {
552 0 : werr = reg_deletevalue(key, valname);
553 0 : if (!W_ERROR_IS_OK(werr)) {
554 0 : err = SBC_ERR_ACCESS_DENIED;
555 0 : goto done;
556 : }
557 : }
558 0 : if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
559 0 : DEBUG(1, ("smbconf_reg_delete_values: "
560 : "Error enumerating values of %s: %s\n",
561 : key->key->name,
562 : win_errstr(werr)));
563 0 : err = SBC_ERR_ACCESS_DENIED;
564 0 : goto done;
565 : }
566 :
567 0 : err = SBC_ERR_OK;
568 :
569 0 : done:
570 0 : talloc_free(mem_ctx);
571 0 : return err;
572 : }
573 :
574 : /**********************************************************************
575 : *
576 : * smbconf operations: registry implementations
577 : *
578 : **********************************************************************/
579 :
580 : /**
581 : * initialize the registry smbconf backend
582 : */
583 1051 : static sbcErr smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
584 : {
585 12 : WERROR werr;
586 12 : sbcErr err;
587 12 : struct security_token *token;
588 :
589 1051 : if (path == NULL) {
590 1051 : path = KEY_SMBCONF;
591 : }
592 1051 : ctx->path = talloc_strdup(ctx, path);
593 1051 : if (ctx->path == NULL) {
594 0 : err = SBC_ERR_NOMEM;
595 0 : goto done;
596 : }
597 :
598 1051 : ctx->data = talloc_zero(ctx, struct reg_private_data);
599 :
600 1051 : werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
601 1051 : if (!W_ERROR_IS_OK(werr)) {
602 0 : DEBUG(1, ("Error creating admin token\n"));
603 0 : err = SBC_ERR_UNKNOWN_FAILURE;
604 0 : goto done;
605 : }
606 1051 : rpd(ctx)->open = false;
607 :
608 1051 : werr = registry_init_smbconf(path);
609 1051 : if (!W_ERROR_IS_OK(werr)) {
610 0 : err = SBC_ERR_BADFILE;
611 0 : goto done;
612 : }
613 :
614 1051 : err = ctx->ops->open_conf(ctx);
615 1051 : if (!SBC_ERROR_IS_OK(err)) {
616 0 : DEBUG(1, ("Error opening the registry.\n"));
617 0 : goto done;
618 : }
619 :
620 1063 : werr = reg_open_path(ctx, ctx->path,
621 : KEY_ENUMERATE_SUB_KEYS | REG_KEY_WRITE,
622 1051 : token, &rpd(ctx)->base_key);
623 1051 : if (!W_ERROR_IS_OK(werr)) {
624 0 : err = SBC_ERR_UNKNOWN_FAILURE;
625 0 : goto done;
626 : }
627 :
628 1051 : done:
629 1051 : return err;
630 : }
631 :
632 607 : static int smbconf_reg_shutdown(struct smbconf_ctx *ctx)
633 : {
634 607 : return ctx->ops->close_conf(ctx);
635 : }
636 :
637 0 : static bool smbconf_reg_requires_messaging(struct smbconf_ctx *ctx)
638 : {
639 0 : if (lp_clustering() && lp_parm_bool(-1, "ctdb", "registry.tdb", true)) {
640 0 : return true;
641 : }
642 :
643 0 : return false;
644 : }
645 :
646 2 : static bool smbconf_reg_is_writeable(struct smbconf_ctx *ctx)
647 : {
648 : /*
649 : * The backend has write support.
650 : *
651 : * TODO: add access checks whether the concrete
652 : * config source is really writeable by the calling user.
653 : */
654 2 : return true;
655 : }
656 :
657 2111 : static sbcErr smbconf_reg_open(struct smbconf_ctx *ctx)
658 : {
659 12 : WERROR werr;
660 :
661 2111 : if (rpd(ctx)->open) {
662 1060 : return SBC_ERR_OK;
663 : }
664 :
665 1051 : werr = regdb_open();
666 1051 : if (!W_ERROR_IS_OK(werr)) {
667 0 : return SBC_ERR_BADFILE;
668 : }
669 :
670 1051 : rpd(ctx)->open = true;
671 1051 : return SBC_ERR_OK;
672 : }
673 :
674 607 : static int smbconf_reg_close(struct smbconf_ctx *ctx)
675 : {
676 12 : int ret;
677 :
678 607 : if (!rpd(ctx)->open) {
679 0 : return 0;
680 : }
681 :
682 607 : ret = regdb_close();
683 607 : if (ret == 0) {
684 607 : rpd(ctx)->open = false;
685 : }
686 595 : return ret;
687 : }
688 :
689 : /**
690 : * Get the change sequence number of the given service/parameter.
691 : * service and parameter strings may be NULL.
692 : */
693 1060 : static void smbconf_reg_get_csn(struct smbconf_ctx *ctx,
694 : struct smbconf_csn *csn,
695 : const char *service, const char *param)
696 : {
697 1060 : if (csn == NULL) {
698 0 : return;
699 : }
700 :
701 1060 : if (!SBC_ERROR_IS_OK(ctx->ops->open_conf(ctx))) {
702 0 : return;
703 : }
704 :
705 1060 : csn->csn = (uint64_t)regdb_get_seqnum();
706 : }
707 :
708 : /**
709 : * Drop the whole configuration (restarting empty) - registry version
710 : */
711 41 : static sbcErr smbconf_reg_drop(struct smbconf_ctx *ctx)
712 : {
713 11 : char *path, *p;
714 11 : WERROR werr;
715 41 : sbcErr err = SBC_ERR_OK;
716 41 : struct registry_key *parent_key = NULL;
717 41 : struct registry_key *new_key = NULL;
718 41 : TALLOC_CTX* mem_ctx = talloc_stackframe();
719 11 : enum winreg_CreateAction action;
720 11 : struct security_token *token;
721 :
722 41 : werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
723 41 : if (!W_ERROR_IS_OK(werr)) {
724 0 : DEBUG(1, ("Error creating admin token\n"));
725 0 : err = SBC_ERR_UNKNOWN_FAILURE;
726 0 : goto done;
727 : }
728 :
729 41 : path = talloc_strdup(mem_ctx, ctx->path);
730 41 : if (path == NULL) {
731 0 : err = SBC_ERR_NOMEM;
732 0 : goto done;
733 : }
734 41 : p = strrchr(path, '\\');
735 41 : if (p == NULL) {
736 0 : err = SBC_ERR_INVALID_PARAM;
737 0 : goto done;
738 : }
739 41 : *p = '\0';
740 41 : werr = reg_open_path(mem_ctx, path, REG_KEY_WRITE, token,
741 : &parent_key);
742 41 : if (!W_ERROR_IS_OK(werr)) {
743 0 : err = SBC_ERR_IO_FAILURE;
744 0 : goto done;
745 : }
746 :
747 41 : werr = reg_deletesubkeys_recursive(parent_key, p+1);
748 41 : if (!W_ERROR_IS_OK(werr)) {
749 0 : err = SBC_ERR_IO_FAILURE;
750 0 : goto done;
751 : }
752 :
753 41 : werr = reg_createkey(mem_ctx, parent_key, p+1, REG_KEY_WRITE,
754 : &new_key, &action);
755 41 : if (!W_ERROR_IS_OK(werr)) {
756 0 : err = SBC_ERR_IO_FAILURE;
757 0 : goto done;
758 : }
759 :
760 41 : done:
761 41 : talloc_free(mem_ctx);
762 41 : return err;
763 : }
764 :
765 : /**
766 : * get the list of share names defined in the configuration.
767 : * registry version.
768 : */
769 265 : static sbcErr smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
770 : TALLOC_CTX *mem_ctx,
771 : uint32_t *num_shares,
772 : char ***share_names)
773 : {
774 5 : uint32_t count;
775 265 : uint32_t added_count = 0;
776 265 : TALLOC_CTX *tmp_ctx = NULL;
777 5 : WERROR werr;
778 265 : sbcErr err = SBC_ERR_OK;
779 265 : char *subkey_name = NULL;
780 265 : char **tmp_share_names = NULL;
781 :
782 265 : if ((num_shares == NULL) || (share_names == NULL)) {
783 0 : return SBC_ERR_INVALID_PARAM;
784 : }
785 :
786 265 : tmp_ctx = talloc_stackframe();
787 :
788 : /* make sure "global" is always listed first */
789 265 : if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
790 16 : err = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
791 : added_count, GLOBAL_NAME);
792 16 : if (!SBC_ERROR_IS_OK(err)) {
793 0 : goto done;
794 : }
795 16 : added_count++;
796 : }
797 :
798 260 : for (count = 0;
799 3930 : werr = reg_enumkey(tmp_ctx, rpd(ctx)->base_key, count,
800 : &subkey_name, NULL),
801 3918 : W_ERROR_IS_OK(werr);
802 3665 : count++)
803 : {
804 3665 : if (strequal(subkey_name, GLOBAL_NAME)) {
805 16 : continue;
806 : }
807 :
808 3649 : err = smbconf_add_string_to_array(tmp_ctx,
809 : &tmp_share_names,
810 : added_count,
811 : subkey_name);
812 3649 : if (!SBC_ERROR_IS_OK(err)) {
813 0 : goto done;
814 : }
815 3649 : added_count++;
816 : }
817 265 : if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
818 0 : err = SBC_ERR_NO_MORE_ITEMS;
819 0 : goto done;
820 : }
821 265 : err = SBC_ERR_OK;
822 :
823 265 : *num_shares = added_count;
824 265 : if (added_count > 0) {
825 64 : *share_names = talloc_move(mem_ctx, &tmp_share_names);
826 : } else {
827 201 : *share_names = NULL;
828 : }
829 :
830 265 : done:
831 265 : talloc_free(tmp_ctx);
832 265 : return err;
833 : }
834 :
835 : /**
836 : * check if a share/service of a given name exists - registry version
837 : */
838 2916955 : static bool smbconf_reg_share_exists(struct smbconf_ctx *ctx,
839 : const char *servicename)
840 : {
841 2916955 : bool ret = false;
842 40 : sbcErr err;
843 2916955 : TALLOC_CTX *mem_ctx = talloc_stackframe();
844 2916955 : struct registry_key *key = NULL;
845 :
846 2916955 : err = smbconf_reg_open_service_key(mem_ctx, ctx, servicename,
847 : REG_KEY_READ, &key);
848 2916955 : if (SBC_ERROR_IS_OK(err)) {
849 917 : ret = true;
850 : }
851 :
852 2916955 : talloc_free(mem_ctx);
853 2916955 : return ret;
854 : }
855 :
856 : /**
857 : * Add a service if it does not already exist - registry version
858 : */
859 667 : static sbcErr smbconf_reg_create_share(struct smbconf_ctx *ctx,
860 : const char *servicename)
861 : {
862 14 : sbcErr err;
863 667 : struct registry_key *key = NULL;
864 667 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
865 :
866 667 : if (servicename == NULL) {
867 0 : return SBC_ERR_OK;
868 : }
869 :
870 667 : err = smbconf_reg_create_service_key(tmp_ctx, ctx,
871 : servicename, &key);
872 :
873 667 : talloc_free(tmp_ctx);
874 667 : return err;
875 : }
876 :
877 : /**
878 : * get a definition of a share (service) from configuration.
879 : */
880 4305 : static sbcErr smbconf_reg_get_share(struct smbconf_ctx *ctx,
881 : TALLOC_CTX *mem_ctx,
882 : const char *servicename,
883 : struct smbconf_service **service)
884 : {
885 9 : sbcErr err;
886 4305 : struct registry_key *key = NULL;
887 4305 : struct smbconf_service *tmp_service = NULL;
888 4305 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
889 :
890 4305 : err = smbconf_reg_open_service_key(tmp_ctx, ctx, servicename,
891 : REG_KEY_READ, &key);
892 4305 : if (!SBC_ERROR_IS_OK(err)) {
893 0 : goto done;
894 : }
895 :
896 4305 : tmp_service = talloc_zero(tmp_ctx, struct smbconf_service);
897 4305 : if (tmp_service == NULL) {
898 0 : err = SBC_ERR_NOMEM;
899 0 : goto done;
900 : }
901 :
902 4305 : if (servicename != NULL) {
903 9 : WERROR werr;
904 4305 : uint32_t count = 0;
905 4305 : char *name = NULL;
906 :
907 : /*
908 : * Determine correct upper/lowercase.
909 : */
910 4305 : for (count = 0;
911 218031 : werr = reg_enumkey(tmp_ctx, rpd(ctx)->base_key, count,
912 : &name, NULL),
913 218031 : W_ERROR_IS_OK(werr);
914 213726 : count++) {
915 218031 : if (!strequal(name, servicename)) {
916 213726 : continue;
917 : }
918 :
919 4305 : tmp_service->name = talloc_strdup(tmp_service, name);
920 4305 : if (tmp_service->name == NULL) {
921 0 : err = SBC_ERR_NOMEM;
922 0 : goto done;
923 : }
924 4296 : break;
925 : }
926 : }
927 :
928 4314 : err = smbconf_reg_get_values(tmp_service, key,
929 4296 : &(tmp_service->num_params),
930 4296 : &(tmp_service->param_names),
931 4305 : &(tmp_service->param_values));
932 4305 : if (SBC_ERROR_IS_OK(err)) {
933 4305 : *service = talloc_move(mem_ctx, &tmp_service);
934 : }
935 :
936 0 : done:
937 4305 : talloc_free(tmp_ctx);
938 4305 : return err;
939 : }
940 :
941 : /**
942 : * delete a service from configuration
943 : */
944 18 : static sbcErr smbconf_reg_delete_share(struct smbconf_ctx *ctx,
945 : const char *servicename)
946 : {
947 1 : WERROR werr;
948 18 : sbcErr err = SBC_ERR_OK;
949 18 : TALLOC_CTX *mem_ctx = talloc_stackframe();
950 :
951 18 : if (servicename != NULL) {
952 18 : werr = reg_deletekey_recursive(rpd(ctx)->base_key, servicename);
953 18 : if (!W_ERROR_IS_OK(werr)) {
954 0 : err = SBC_ERR_ACCESS_DENIED;
955 : }
956 : } else {
957 0 : err = smbconf_reg_delete_values(rpd(ctx)->base_key);
958 : }
959 :
960 18 : talloc_free(mem_ctx);
961 18 : return err;
962 : }
963 :
964 : /**
965 : * set a configuration parameter to the value provided.
966 : */
967 2918 : static sbcErr smbconf_reg_set_parameter(struct smbconf_ctx *ctx,
968 : const char *service,
969 : const char *param,
970 : const char *valstr)
971 : {
972 21 : sbcErr err;
973 2918 : struct registry_key *key = NULL;
974 2918 : TALLOC_CTX *mem_ctx = talloc_stackframe();
975 :
976 2918 : err = smbconf_reg_open_service_key(mem_ctx, ctx, service,
977 : REG_KEY_WRITE, &key);
978 2918 : if (!SBC_ERROR_IS_OK(err)) {
979 0 : goto done;
980 : }
981 :
982 2918 : err = smbconf_reg_set_value(key, param, valstr);
983 :
984 2918 : done:
985 2918 : talloc_free(mem_ctx);
986 2918 : return err;
987 : }
988 :
989 : /**
990 : * get the value of a configuration parameter as a string
991 : */
992 6 : static sbcErr smbconf_reg_get_parameter(struct smbconf_ctx *ctx,
993 : TALLOC_CTX *mem_ctx,
994 : const char *service,
995 : const char *param,
996 : char **valstr)
997 : {
998 0 : WERROR werr;
999 0 : sbcErr err;
1000 6 : struct registry_key *key = NULL;
1001 6 : struct registry_value *value = NULL;
1002 :
1003 6 : err = smbconf_reg_open_service_key(mem_ctx, ctx, service,
1004 : REG_KEY_READ, &key);
1005 6 : if (!SBC_ERROR_IS_OK(err)) {
1006 0 : goto done;
1007 : }
1008 :
1009 6 : if (!smbconf_reg_parameter_is_valid(param)) {
1010 0 : err = SBC_ERR_INVALID_PARAM;
1011 0 : goto done;
1012 : }
1013 :
1014 6 : if (!smbconf_value_exists(key, param)) {
1015 0 : err = SBC_ERR_INVALID_PARAM;
1016 0 : goto done;
1017 : }
1018 :
1019 6 : werr = reg_queryvalue(mem_ctx, key, param, &value);
1020 6 : if (!W_ERROR_IS_OK(werr)) {
1021 0 : err = SBC_ERR_NOMEM;
1022 0 : goto done;
1023 : }
1024 :
1025 6 : *valstr = smbconf_format_registry_value(mem_ctx, value);
1026 6 : if (*valstr == NULL) {
1027 0 : err = SBC_ERR_NOMEM;
1028 : }
1029 :
1030 6 : done:
1031 6 : talloc_free(key);
1032 6 : talloc_free(value);
1033 6 : return err;
1034 : }
1035 :
1036 : /**
1037 : * delete a parameter from configuration
1038 : */
1039 7 : static sbcErr smbconf_reg_delete_parameter(struct smbconf_ctx *ctx,
1040 : const char *service,
1041 : const char *param)
1042 : {
1043 7 : struct registry_key *key = NULL;
1044 3 : WERROR werr;
1045 3 : sbcErr err;
1046 7 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1047 :
1048 7 : err = smbconf_reg_open_service_key(mem_ctx, ctx, service,
1049 : REG_KEY_ALL, &key);
1050 7 : if (!SBC_ERROR_IS_OK(err)) {
1051 2 : goto done;
1052 : }
1053 :
1054 5 : if (!smbconf_reg_parameter_is_valid(param)) {
1055 0 : err = SBC_ERR_INVALID_PARAM;
1056 0 : goto done;
1057 : }
1058 :
1059 5 : if (!smbconf_value_exists(key, param)) {
1060 0 : err = SBC_ERR_OK;
1061 0 : goto done;
1062 : }
1063 :
1064 5 : werr = reg_deletevalue(key, param);
1065 5 : if (!W_ERROR_IS_OK(werr)) {
1066 0 : err = SBC_ERR_ACCESS_DENIED;
1067 : }
1068 :
1069 5 : done:
1070 7 : talloc_free(mem_ctx);
1071 7 : return err;
1072 : }
1073 :
1074 8 : static sbcErr smbconf_reg_get_includes(struct smbconf_ctx *ctx,
1075 : TALLOC_CTX *mem_ctx,
1076 : const char *service,
1077 : uint32_t *num_includes,
1078 : char ***includes)
1079 : {
1080 0 : sbcErr err;
1081 8 : struct registry_key *key = NULL;
1082 8 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1083 :
1084 8 : err = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1085 : REG_KEY_READ, &key);
1086 8 : if (!SBC_ERROR_IS_OK(err)) {
1087 0 : goto done;
1088 : }
1089 :
1090 8 : err = smbconf_reg_get_includes_internal(mem_ctx, key, num_includes,
1091 : includes);
1092 8 : if (!SBC_ERROR_IS_OK(err)) {
1093 0 : goto done;
1094 : }
1095 :
1096 8 : done:
1097 8 : talloc_free(tmp_ctx);
1098 8 : return err;
1099 : }
1100 :
1101 443 : static sbcErr smbconf_reg_set_includes(struct smbconf_ctx *ctx,
1102 : const char *service,
1103 : uint32_t num_includes,
1104 : const char **includes)
1105 : {
1106 5 : sbcErr err;
1107 443 : struct registry_key *key = NULL;
1108 443 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1109 :
1110 443 : err = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1111 : REG_KEY_ALL, &key);
1112 443 : if (!SBC_ERROR_IS_OK(err)) {
1113 0 : goto done;
1114 : }
1115 :
1116 443 : if (num_includes == 0) {
1117 5 : WERROR werr;
1118 437 : if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
1119 437 : err = SBC_ERR_OK;
1120 437 : goto done;
1121 : }
1122 0 : werr = reg_deletevalue(key, INCLUDES_VALNAME);
1123 0 : if (!W_ERROR_IS_OK(werr)) {
1124 0 : err = SBC_ERR_ACCESS_DENIED;
1125 0 : goto done;
1126 : }
1127 : } else {
1128 6 : err = smbconf_reg_set_multi_sz_value(key, INCLUDES_VALNAME,
1129 : num_includes, includes);
1130 : }
1131 :
1132 443 : done:
1133 443 : talloc_free(tmp_ctx);
1134 443 : return err;
1135 : }
1136 :
1137 10 : static sbcErr smbconf_reg_delete_includes(struct smbconf_ctx *ctx,
1138 : const char *service)
1139 : {
1140 0 : WERROR werr;
1141 0 : sbcErr err;
1142 10 : struct registry_key *key = NULL;
1143 10 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1144 :
1145 10 : err = smbconf_reg_open_service_key(tmp_ctx, ctx, service,
1146 : REG_KEY_ALL, &key);
1147 10 : if (!SBC_ERROR_IS_OK(err)) {
1148 2 : goto done;
1149 : }
1150 :
1151 8 : if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
1152 4 : err = SBC_ERR_OK;
1153 4 : goto done;
1154 : }
1155 :
1156 4 : werr = reg_deletevalue(key, INCLUDES_VALNAME);
1157 4 : if (!W_ERROR_IS_OK(werr)) {
1158 0 : err = SBC_ERR_ACCESS_DENIED;
1159 0 : goto done;
1160 : }
1161 :
1162 4 : err = SBC_ERR_OK;
1163 10 : done:
1164 10 : talloc_free(tmp_ctx);
1165 10 : return err;
1166 : }
1167 :
1168 717 : static sbcErr smbconf_reg_transaction_start(struct smbconf_ctx *ctx)
1169 : {
1170 9 : WERROR werr;
1171 :
1172 717 : werr = regdb_transaction_start();
1173 717 : if (!W_ERROR_IS_OK(werr)) {
1174 0 : return SBC_ERR_IO_FAILURE;
1175 : }
1176 :
1177 708 : return SBC_ERR_OK;
1178 : }
1179 :
1180 715 : static sbcErr smbconf_reg_transaction_commit(struct smbconf_ctx *ctx)
1181 : {
1182 7 : WERROR werr;
1183 :
1184 715 : werr = regdb_transaction_commit();
1185 715 : if (!W_ERROR_IS_OK(werr)) {
1186 0 : return SBC_ERR_IO_FAILURE;
1187 : }
1188 :
1189 708 : return SBC_ERR_OK;
1190 : }
1191 :
1192 2 : static sbcErr smbconf_reg_transaction_cancel(struct smbconf_ctx *ctx)
1193 : {
1194 2 : WERROR werr;
1195 :
1196 2 : werr = regdb_transaction_cancel();
1197 2 : if (!W_ERROR_IS_OK(werr)) {
1198 0 : return SBC_ERR_IO_FAILURE;
1199 : }
1200 :
1201 0 : return SBC_ERR_OK;
1202 : }
1203 :
1204 : struct smbconf_ops smbconf_ops_reg = {
1205 : .init = smbconf_reg_init,
1206 : .shutdown = smbconf_reg_shutdown,
1207 : .requires_messaging = smbconf_reg_requires_messaging,
1208 : .is_writeable = smbconf_reg_is_writeable,
1209 : .open_conf = smbconf_reg_open,
1210 : .close_conf = smbconf_reg_close,
1211 : .get_csn = smbconf_reg_get_csn,
1212 : .drop = smbconf_reg_drop,
1213 : .get_share_names = smbconf_reg_get_share_names,
1214 : .share_exists = smbconf_reg_share_exists,
1215 : .create_share = smbconf_reg_create_share,
1216 : .get_share = smbconf_reg_get_share,
1217 : .delete_share = smbconf_reg_delete_share,
1218 : .set_parameter = smbconf_reg_set_parameter,
1219 : .get_parameter = smbconf_reg_get_parameter,
1220 : .delete_parameter = smbconf_reg_delete_parameter,
1221 : .get_includes = smbconf_reg_get_includes,
1222 : .set_includes = smbconf_reg_set_includes,
1223 : .delete_includes = smbconf_reg_delete_includes,
1224 : .transaction_start = smbconf_reg_transaction_start,
1225 : .transaction_commit = smbconf_reg_transaction_commit,
1226 : .transaction_cancel = smbconf_reg_transaction_cancel,
1227 : };
1228 :
1229 :
1230 : /**
1231 : * initialize the smbconf registry backend
1232 : * the only function that is exported from this module
1233 : */
1234 1051 : sbcErr smbconf_init_reg(TALLOC_CTX *mem_ctx, struct smbconf_ctx **conf_ctx,
1235 : const char *path)
1236 : {
1237 : /*
1238 : * this tmp_ctx stackframe is required to initialize the registry backend.
1239 : * Without it, the calls panics due to the use of talloc_tos in the
1240 : * source3/registry code.
1241 : */
1242 1051 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1243 1051 : sbcErr err = smbconf_init_internal(mem_ctx, conf_ctx, path, &smbconf_ops_reg);
1244 1051 : talloc_free(tmp_ctx);
1245 1051 : return err;
1246 : }
|