1 /*
2 Unix SMB/CIFS implementation.
3 Transparent registry backend handling
4 Copyright (C) Jelmer Vernooij 2003-2004.
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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "lib/util/dlinklist.h"
23 #include "lib/registry/registry.h"
24 #include "build.h"
25
26 /**
27 * @file
28 * @brief Main registry functions
29 */
30
31 /* List of available backends */
32 static struct reg_init_function_entry *backends = NULL;
33
34 static struct reg_init_function_entry *reg_find_backend_entry(const char *name);
35
36 /** Register a new backend. */
registry_register(const void * _hive_ops)37 _PUBLIC_ NTSTATUS registry_register(const void *_hive_ops)
38 {
39 const struct hive_operations *hive_ops = _hive_ops;
40 struct reg_init_function_entry *entry = backends;
41
42 DEBUG(5,("Attempting to register registry backend %s\n", hive_ops->name));
43
44 /* Check for duplicates */
45 if (reg_find_backend_entry(hive_ops->name)) {
46 DEBUG(0,("There already is a registry backend registered with the name %s!\n", hive_ops->name));
47 return NT_STATUS_OBJECT_NAME_COLLISION;
48 }
49
50 entry = talloc(talloc_autofree_context(), struct reg_init_function_entry);
51 entry->hive_functions = hive_ops;
52
53 DLIST_ADD(backends, entry);
54 DEBUG(5,("Successfully added registry backend '%s'\n", hive_ops->name));
55 return NT_STATUS_OK;
56 }
57
58 /** Find a backend in the list of available backends */
reg_find_backend_entry(const char * name)59 static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
60 {
61 struct reg_init_function_entry *entry;
62
63 entry = backends;
64
65 while(entry) {
66 if (strcmp(entry->hive_functions->name, name) == 0) return entry;
67 entry = entry->next;
68 }
69
70 return NULL;
71 }
72
73 /** Initialize the registry subsystem */
registry_init(void)74 _PUBLIC_ NTSTATUS registry_init(void)
75 {
76 init_module_fn static_init[] = STATIC_registry_MODULES;
77 init_module_fn *shared_init = load_samba_modules(NULL, "registry");
78
79 run_init_functions(static_init);
80 run_init_functions(shared_init);
81
82 talloc_free(shared_init);
83
84 return NT_STATUS_OK;
85 }
86
87 /** Check whether a certain backend is present. */
reg_has_backend(const char * backend)88 _PUBLIC_ BOOL reg_has_backend(const char *backend)
89 {
90 return reg_find_backend_entry(backend) != NULL?True:False;
91 }
92
93 const struct reg_predefined_key reg_predefined_keys[] = {
94 {HKEY_CLASSES_ROOT,"HKEY_CLASSES_ROOT" },
95 {HKEY_CURRENT_USER,"HKEY_CURRENT_USER" },
96 {HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" },
97 {HKEY_PERFORMANCE_DATA, "HKEY_PERFORMANCE_DATA" },
98 {HKEY_USERS, "HKEY_USERS" },
99 {HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG" },
100 {HKEY_DYN_DATA, "HKEY_DYN_DATA" },
101 {HKEY_PERFORMANCE_TEXT, "HKEY_PERFORMANCE_TEXT" },
102 {HKEY_PERFORMANCE_NLSTEXT, "HKEY_PERFORMANCE_NLSTEXT" },
103 { 0, NULL }
104 };
105
106 /** Obtain a list of predefined keys. */
reg_list_predefs(TALLOC_CTX * mem_ctx,char *** predefs,uint32_t ** hkeys)107 _PUBLIC_ int reg_list_predefs(TALLOC_CTX *mem_ctx, char ***predefs, uint32_t **hkeys)
108 {
109 int i;
110 *predefs = talloc_array(mem_ctx, char *, ARRAY_SIZE(reg_predefined_keys));
111 *hkeys = talloc_array(mem_ctx, uint32_t, ARRAY_SIZE(reg_predefined_keys));
112
113 for (i = 0; reg_predefined_keys[i].name; i++) {
114 (*predefs)[i] = talloc_strdup(mem_ctx, reg_predefined_keys[i].name);
115 (*hkeys)[i] = reg_predefined_keys[i].handle;
116 }
117
118 return i;
119 }
120
121 /** Obtain name of specific hkey. */
reg_get_predef_name(uint32_t hkey)122 _PUBLIC_ const char *reg_get_predef_name(uint32_t hkey)
123 {
124 int i;
125 for (i = 0; reg_predefined_keys[i].name; i++) {
126 if (reg_predefined_keys[i].handle == hkey) return reg_predefined_keys[i].name;
127 }
128
129 return NULL;
130 }
131
132 /** Get predefined key by name. */
reg_get_predefined_key_by_name(struct registry_context * ctx,const char * name,struct registry_key ** key)133 _PUBLIC_ WERROR reg_get_predefined_key_by_name(struct registry_context *ctx, const char *name, struct registry_key **key)
134 {
135 int i;
136
137 for (i = 0; reg_predefined_keys[i].name; i++) {
138 if (!strcasecmp(reg_predefined_keys[i].name, name)) return reg_get_predefined_key(ctx, reg_predefined_keys[i].handle, key);
139 }
140
141 DEBUG(1, ("No predefined key with name '%s'\n", name));
142
143 return WERR_BADFILE;
144 }
145
146 /** Get predefined key by id. */
reg_get_predefined_key(struct registry_context * ctx,uint32_t hkey,struct registry_key ** key)147 _PUBLIC_ WERROR reg_get_predefined_key(struct registry_context *ctx, uint32_t hkey, struct registry_key **key)
148 {
149 WERROR ret = ctx->get_predefined_key(ctx, hkey, key);
150
151 if (W_ERROR_IS_OK(ret)) {
152 (*key)->name = talloc_strdup(*key, reg_get_predef_name(hkey));
153 (*key)->path = "";
154 }
155
156 return ret;
157 }
158
159 /** Open a registry file/host/etc */
reg_open_hive(TALLOC_CTX * parent_ctx,const char * backend,const char * location,struct auth_session_info * session_info,struct cli_credentials * credentials,struct registry_key ** root)160 _PUBLIC_ WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *backend, const char *location, struct auth_session_info *session_info, struct cli_credentials *credentials, struct registry_key **root)
161 {
162 struct registry_hive *rethive;
163 struct registry_key *retkey = NULL;
164 struct reg_init_function_entry *entry;
165 WERROR werr;
166
167 entry = reg_find_backend_entry(backend);
168
169 if (!entry) {
170 DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
171 return WERR_GENERAL_FAILURE;
172 }
173
174 if(!entry->hive_functions || !entry->hive_functions->open_hive) {
175 return WERR_NOT_SUPPORTED;
176 }
177
178 rethive = talloc(parent_ctx, struct registry_hive);
179 rethive->location = location?talloc_strdup(rethive, location):NULL;
180 rethive->session_info = talloc_reference(rethive, session_info);
181 rethive->credentials = talloc_reference(rethive, credentials);
182 rethive->functions = entry->hive_functions;
183 rethive->backend_data = NULL;
184
185 werr = entry->hive_functions->open_hive(rethive, &retkey);
186
187 if(!W_ERROR_IS_OK(werr)) {
188 return werr;
189 }
190
191 if(!retkey) {
192 DEBUG(0, ("Backend %s didn't provide root key!\n", backend));
193 return WERR_GENERAL_FAILURE;
194 }
195
196 rethive->root = retkey;
197
198 retkey->hive = rethive;
199 retkey->name = NULL;
200 retkey->path = talloc_strdup(retkey, "");
201
202 *root = retkey;
203
204 return WERR_OK;
205 }
206
207 /**
208 * Open a key
209 * First tries to use the open_key function from the backend
210 * then falls back to get_subkey_by_name and later get_subkey_by_index
211 */
reg_open_key(TALLOC_CTX * mem_ctx,struct registry_key * parent,const char * name,struct registry_key ** result)212 _PUBLIC_ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result)
213 {
214 WERROR error;
215
216 if(!parent) {
217 DEBUG(0, ("Invalid parent key specified for open of '%s'\n", name));
218 return WERR_INVALID_PARAM;
219 }
220
221 if(!parent->hive->functions->open_key &&
222 (parent->hive->functions->get_subkey_by_name ||
223 parent->hive->functions->get_subkey_by_index)) {
224 char *orig = strdup(name),
225 *curbegin = orig,
226 *curend = strchr(orig, '\\');
227 struct registry_key *curkey = parent;
228
229 while(curbegin && *curbegin) {
230 if(curend)*curend = '\0';
231 error = reg_key_get_subkey_by_name(mem_ctx, curkey, curbegin, &curkey);
232 if(!W_ERROR_IS_OK(error)) {
233 SAFE_FREE(orig);
234 return error;
235 }
236 if(!curend) break;
237 curbegin = curend + 1;
238 curend = strchr(curbegin, '\\');
239 }
240 SAFE_FREE(orig);
241
242 *result = curkey;
243
244 return WERR_OK;
245 }
246
247 if(!parent->hive->functions->open_key) {
248 DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n"));
249 return WERR_NOT_SUPPORTED;
250 }
251
252 error = parent->hive->functions->open_key(mem_ctx, parent, name, result);
253
254 if(!W_ERROR_IS_OK(error)) return error;
255
256 (*result)->hive = parent->hive;
257 (*result)->path = ((parent->hive->root == parent)?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name));
258 (*result)->hive = parent->hive;
259
260 return WERR_OK;
261 }
262
263 /**
264 * Get value by index
265 */
reg_key_get_value_by_index(TALLOC_CTX * mem_ctx,const struct registry_key * key,int idx,struct registry_value ** val)266 _PUBLIC_ WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_value **val)
267 {
268 if(!key) return WERR_INVALID_PARAM;
269
270 if(key->hive->functions->get_value_by_index) {
271 WERROR status = key->hive->functions->get_value_by_index(mem_ctx, key, idx, val);
272 if(!W_ERROR_IS_OK(status))
273 return status;
274 } else {
275 return WERR_NOT_SUPPORTED;
276 }
277
278 return WERR_OK;
279 }
280
281 /**
282 * Get the number of subkeys.
283 */
reg_key_num_subkeys(const struct registry_key * key,uint32_t * count)284 _PUBLIC_ WERROR reg_key_num_subkeys(const struct registry_key *key, uint32_t *count)
285 {
286 if(!key) return WERR_INVALID_PARAM;
287
288 if(key->hive->functions->num_subkeys) {
289 return key->hive->functions->num_subkeys(key, count);
290 }
291
292 if(key->hive->functions->get_subkey_by_index) {
293 int i;
294 WERROR error;
295 struct registry_key *dest = NULL;
296 TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
297
298 for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, key, i, &dest)); i++);
299 talloc_free(mem_ctx);
300
301 *count = i;
302 if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
303 return error;
304 }
305
306 return WERR_NOT_SUPPORTED;
307 }
308
309 /**
310 * Get the number of values of a key.
311 */
reg_key_num_values(const struct registry_key * key,uint32_t * count)312 _PUBLIC_ WERROR reg_key_num_values(const struct registry_key *key, uint32_t *count)
313 {
314
315 if(!key) return WERR_INVALID_PARAM;
316
317 if (key->hive->functions->num_values) {
318 return key->hive->functions->num_values(key, count);
319 }
320
321 if(key->hive->functions->get_value_by_index) {
322 int i;
323 WERROR error;
324 struct registry_value *dest;
325 TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
326
327 for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_value_by_index(mem_ctx, key, i, &dest)); i++);
328 talloc_free(mem_ctx);
329
330 *count = i;
331 if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
332 return error;
333 }
334
335 return WERR_NOT_SUPPORTED;
336 }
337
338 /**
339 * Get subkey by index.
340 */
reg_key_get_subkey_by_index(TALLOC_CTX * mem_ctx,const struct registry_key * key,int idx,struct registry_key ** subkey)341 _PUBLIC_ WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_key **subkey)
342 {
343 if(!key) return WERR_INVALID_PARAM;
344
345 if(key->hive->functions->get_subkey_by_index) {
346 WERROR status = key->hive->functions->get_subkey_by_index(mem_ctx, key, idx, subkey);
347 if(!NT_STATUS_IS_OK(status)) return status;
348 } else {
349 return WERR_NOT_SUPPORTED;
350 }
351
352 if(key->hive->root == key)
353 (*subkey)->path = talloc_strdup(mem_ctx, (*subkey)->name);
354 else
355 (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
356
357 (*subkey)->hive = key->hive;
358 return WERR_OK;;
359 }
360
361 /**
362 * Get subkey by name.
363 */
reg_key_get_subkey_by_name(TALLOC_CTX * mem_ctx,const struct registry_key * key,const char * name,struct registry_key ** subkey)364 WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_key **subkey)
365 {
366 int i;
367 WERROR error = WERR_OK;
368
369 if(!key) return WERR_INVALID_PARAM;
370
371 if(key->hive->functions->get_subkey_by_name) {
372 error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey);
373 } else if(key->hive->functions->open_key) {
374 error = key->hive->functions->open_key(mem_ctx, key, name, subkey);
375 } else if(key->hive->functions->get_subkey_by_index) {
376 for(i = 0; W_ERROR_IS_OK(error); i++) {
377 error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey);
378 if(W_ERROR_IS_OK(error) && !strcasecmp((*subkey)->name, name)) {
379 break;
380 }
381 }
382
383 if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
384 error = WERR_DEST_NOT_FOUND;
385 } else {
386 return WERR_NOT_SUPPORTED;
387 }
388
389 if(!W_ERROR_IS_OK(error)) return error;
390
391 (*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
392 (*subkey)->hive = key->hive;
393
394 return WERR_OK;
395 }
396
397 /**
398 * Get value by name.
399 */
reg_key_get_value_by_name(TALLOC_CTX * mem_ctx,const struct registry_key * key,const char * name,struct registry_value ** val)400 _PUBLIC_ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_value **val)
401 {
402 int i;
403 WERROR error = WERR_OK;
404
405 if(!key) return WERR_INVALID_PARAM;
406
407 if(key->hive->functions->get_value_by_name) {
408 error = key->hive->functions->get_value_by_name(mem_ctx, key,name, val);
409 } else {
410 for(i = 0; W_ERROR_IS_OK(error); i++) {
411 error = reg_key_get_value_by_index(mem_ctx, key, i, val);
412 if(W_ERROR_IS_OK(error) && !strcasecmp((*val)->name, name)) {
413 break;
414 }
415 }
416 }
417
418 if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
419 return WERR_DEST_NOT_FOUND;
420
421 return error;
422 }
423
424 /**
425 * Delete a key.
426 */
reg_key_del(struct registry_key * parent,const char * name)427 _PUBLIC_ WERROR reg_key_del(struct registry_key *parent, const char *name)
428 {
429 WERROR error;
430 if(!parent) return WERR_INVALID_PARAM;
431
432
433 if(!parent->hive->functions->del_key)
434 return WERR_NOT_SUPPORTED;
435
436 error = parent->hive->functions->del_key(parent, name);
437 if(!W_ERROR_IS_OK(error)) return error;
438
439 return WERR_OK;
440 }
441
442 /**
443 * Add a key.
444 */
reg_key_add_name(TALLOC_CTX * mem_ctx,const struct registry_key * parent,const char * name,uint32_t access_mask,struct security_descriptor * desc,struct registry_key ** newkey)445 _PUBLIC_ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **newkey)
446 {
447 WERROR error;
448
449 if (!parent) return WERR_INVALID_PARAM;
450
451 if (!parent->hive->functions->add_key) {
452 DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->hive->functions->name));
453 return WERR_NOT_SUPPORTED;
454 }
455
456 error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey);
457
458 if(!W_ERROR_IS_OK(error)) return error;
459
460 if (!*newkey) {
461 DEBUG(0, ("Backend returned WERR_OK, but didn't specify key!\n"));
462 return WERR_GENERAL_FAILURE;
463 }
464
465 (*newkey)->hive = parent->hive;
466
467 return WERR_OK;
468 }
469
470 /**
471 * Set a value.
472 */
reg_val_set(struct registry_key * key,const char * value,uint32_t type,DATA_BLOB data)473 _PUBLIC_ WERROR reg_val_set(struct registry_key *key, const char *value, uint32_t type, DATA_BLOB data)
474 {
475 /* A 'real' set function has preference */
476 if (key->hive->functions->set_value)
477 return key->hive->functions->set_value(key, value, type, data);
478
479 DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name));
480 return WERR_NOT_SUPPORTED;
481 }
482
483 /**
484 * Get the security descriptor on a key.
485 */
reg_get_sec_desc(TALLOC_CTX * ctx,const struct registry_key * key,struct security_descriptor ** secdesc)486 _PUBLIC_ WERROR reg_get_sec_desc(TALLOC_CTX *ctx, const struct registry_key *key, struct security_descriptor **secdesc)
487 {
488 /* A 'real' set function has preference */
489 if (key->hive->functions->key_get_sec_desc)
490 return key->hive->functions->key_get_sec_desc(ctx, key, secdesc);
491
492 DEBUG(1, ("Backend '%s' doesn't support method get_sec_desc\n", key->hive->functions->name));
493 return WERR_NOT_SUPPORTED;
494 }
495
496 /**
497 * Delete a value.
498 */
reg_del_value(const struct registry_key * key,const char * valname)499 _PUBLIC_ WERROR reg_del_value(const struct registry_key *key, const char *valname)
500 {
501 WERROR ret = WERR_OK;
502 if(!key->hive->functions->del_value)
503 return WERR_NOT_SUPPORTED;
504
505 ret = key->hive->functions->del_value(key, valname);
506
507 if(!W_ERROR_IS_OK(ret)) return ret;
508
509 return ret;
510 }
511
512 /**
513 * Flush a key to disk.
514 */
reg_key_flush(const struct registry_key * key)515 _PUBLIC_ WERROR reg_key_flush(const struct registry_key *key)
516 {
517 if (!key) {
518 return WERR_INVALID_PARAM;
519 }
520
521 if (key->hive->functions->flush_key) {
522 return key->hive->functions->flush_key(key);
523 }
524
525 /* No need for flushing, apparently */
526 return WERR_OK;
527 }
528
529 /**
530 * Get the maximum name and data lengths of the subkeys.
531 */
reg_key_subkeysizes(const struct registry_key * key,uint32_t * max_subkeylen,uint32_t * max_subkeysize)532 _PUBLIC_ WERROR reg_key_subkeysizes(const struct registry_key *key, uint32_t *max_subkeylen, uint32_t *max_subkeysize)
533 {
534 int i = 0;
535 struct registry_key *subkey;
536 WERROR error;
537 TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
538
539 *max_subkeylen = *max_subkeysize = 0;
540
541 do {
542 error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey);
543
544 if (W_ERROR_IS_OK(error)) {
545 *max_subkeysize = MAX(*max_subkeysize, 0xFF);
546 *max_subkeylen = MAX(*max_subkeylen, strlen(subkey->name));
547 }
548
549 i++;
550 } while (W_ERROR_IS_OK(error));
551
552 talloc_free(mem_ctx);
553
554 return WERR_OK;
555 }
556
557 /**
558 * Get the maximum name and data lengths of the values.
559 */
reg_key_valuesizes(const struct registry_key * key,uint32_t * max_valnamelen,uint32_t * max_valbufsize)560 _PUBLIC_ WERROR reg_key_valuesizes(const struct registry_key *key, uint32_t *max_valnamelen, uint32_t *max_valbufsize)
561 {
562 int i = 0;
563 struct registry_value *value;
564 WERROR error;
565 TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
566
567 *max_valnamelen = *max_valbufsize = 0;
568
569 do {
570 error = reg_key_get_value_by_index(mem_ctx, key, i, &value);
571
572 if (W_ERROR_IS_OK(error)) {
573 if (value->name) {
574 *max_valnamelen = MAX(*max_valnamelen, strlen(value->name));
575 }
576 *max_valbufsize = MAX(*max_valbufsize, value->data.length);
577 }
578
579 i++;
580 } while (W_ERROR_IS_OK(error));
581
582 talloc_free(mem_ctx);
583
584 return WERR_OK;
585 }
586