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