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