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