1 /*
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer
4  *  Copyright (C) Gerald Carter                     2002-2005
5  *  Copyright (C) Michael Adam                      2007-2010
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 /* Implementation of registry frontend view functions. */
22 
23 #include "includes.h"
24 #include "registry.h"
25 #include "reg_objects.h"
26 #include "util_tdb.h"
27 #include "dbwrap/dbwrap.h"
28 #include "dbwrap/dbwrap_rbt.h"
29 #include "../libcli/registry/util_reg.h"
30 
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_REGISTRY
33 
34 /* low level structure to contain registry values */
35 
36 struct regval_blob {
37 	fstring		valuename;
38 	uint32_t	type;
39 	/* this should be encapsulated in an RPC_DATA_BLOB */
40 	uint32_t	size;	/* in bytes */
41 	uint8_t		*data_p;
42 };
43 
44 /* container for registry values */
45 
46 struct regval_ctr {
47 	uint32_t num_values;
48 	struct regval_blob **values;
49 	int seqnum;
50 };
51 
52 struct regsubkey_ctr {
53 	uint32_t        num_subkeys;
54 	char            **subkeys;
55 	struct db_context *subkeys_hash;
56 	int seqnum;
57 };
58 
59 /**********************************************************************
60 
61  Note that the struct regsubkey_ctr and struct regval_ctr objects *must* be
62  talloc()'d since the methods use the object pointer as the talloc
63  context for internal private data.
64 
65  There is no longer a regval_ctr_intit() and regval_ctr_destroy()
66  pair of functions.  Simply talloc_zero() and TALLOC_FREE() the
67  object.
68 
69  **********************************************************************/
70 
regsubkey_ctr_init(TALLOC_CTX * mem_ctx,struct regsubkey_ctr ** ctr)71 WERROR regsubkey_ctr_init(TALLOC_CTX *mem_ctx, struct regsubkey_ctr **ctr)
72 {
73 	if (ctr == NULL) {
74 		return WERR_INVALID_PARAMETER;
75 	}
76 
77 	*ctr = talloc_zero(mem_ctx, struct regsubkey_ctr);
78 	if (*ctr == NULL) {
79 		return WERR_NOT_ENOUGH_MEMORY;
80 	}
81 
82 	(*ctr)->subkeys_hash = db_open_rbt(*ctr);
83 	if ((*ctr)->subkeys_hash == NULL) {
84 		talloc_free(*ctr);
85 		return WERR_NOT_ENOUGH_MEMORY;
86 	}
87 
88 	return WERR_OK;
89 }
90 
91 /**
92  * re-initialize the list of subkeys (to the empty list)
93  * in an already allocated regsubkey_ctr
94  */
95 
regsubkey_ctr_reinit(struct regsubkey_ctr * ctr)96 WERROR regsubkey_ctr_reinit(struct regsubkey_ctr *ctr)
97 {
98 	if (ctr == NULL) {
99 		return WERR_INVALID_PARAMETER;
100 	}
101 
102 	talloc_free(ctr->subkeys_hash);
103 	ctr->subkeys_hash = db_open_rbt(ctr);
104 	W_ERROR_HAVE_NO_MEMORY(ctr->subkeys_hash);
105 
106 	TALLOC_FREE(ctr->subkeys);
107 
108 	ctr->num_subkeys = 0;
109 	ctr->seqnum = 0;
110 
111 	return WERR_OK;
112 }
113 
regsubkey_ctr_set_seqnum(struct regsubkey_ctr * ctr,int seqnum)114 WERROR regsubkey_ctr_set_seqnum(struct regsubkey_ctr *ctr, int seqnum)
115 {
116 	if (ctr == NULL) {
117 		return WERR_INVALID_PARAMETER;
118 	}
119 
120 	ctr->seqnum = seqnum;
121 
122 	return WERR_OK;
123 }
124 
regsubkey_ctr_get_seqnum(struct regsubkey_ctr * ctr)125 int regsubkey_ctr_get_seqnum(struct regsubkey_ctr *ctr)
126 {
127 	if (ctr == NULL) {
128 		return -1;
129 	}
130 
131 	return ctr->seqnum;
132 }
133 
regsubkey_ctr_hash_keyname(struct regsubkey_ctr * ctr,const char * keyname,uint32_t idx)134 static WERROR regsubkey_ctr_hash_keyname(struct regsubkey_ctr *ctr,
135 					 const char *keyname,
136 					 uint32_t idx)
137 {
138 	WERROR werr;
139 
140 	werr = ntstatus_to_werror(dbwrap_store_bystring_upper(ctr->subkeys_hash,
141 						keyname,
142 						make_tdb_data((uint8_t *)&idx,
143 							      sizeof(idx)),
144 						TDB_REPLACE));
145 	if (!W_ERROR_IS_OK(werr)) {
146 		DEBUG(1, ("error hashing new key '%s' in container: %s\n",
147 			  keyname, win_errstr(werr)));
148 	}
149 
150 	return werr;
151 }
152 
regsubkey_ctr_unhash_keyname(struct regsubkey_ctr * ctr,const char * keyname)153 static WERROR regsubkey_ctr_unhash_keyname(struct regsubkey_ctr *ctr,
154 					   const char *keyname)
155 {
156 	WERROR werr;
157 
158 	werr = ntstatus_to_werror(dbwrap_delete_bystring_upper(ctr->subkeys_hash,
159 				  keyname));
160 	if (!W_ERROR_IS_OK(werr)) {
161 		DEBUG(1, ("error unhashing key '%s' in container: %s\n",
162 			  keyname, win_errstr(werr)));
163 	}
164 
165 	return werr;
166 }
167 
regsubkey_ctr_index_for_keyname(struct regsubkey_ctr * ctr,const char * keyname,uint32_t * idx)168 static WERROR regsubkey_ctr_index_for_keyname(struct regsubkey_ctr *ctr,
169 					      const char *keyname,
170 					      uint32_t *idx)
171 {
172 	TDB_DATA data;
173 	NTSTATUS status;
174 
175 	if ((ctr == NULL) || (keyname == NULL)) {
176 		return WERR_INVALID_PARAMETER;
177 	}
178 
179 	status = dbwrap_fetch_bystring_upper(ctr->subkeys_hash, ctr, keyname,
180 					     &data);
181 	if (!NT_STATUS_IS_OK(status)) {
182 		return WERR_NOT_FOUND;
183 	}
184 
185 	if (data.dsize != sizeof(*idx)) {
186 		talloc_free(data.dptr);
187 		return WERR_INVALID_DATATYPE;
188 	}
189 
190 	if (idx != NULL) {
191 		memcpy(idx, data.dptr, sizeof(*idx));
192 	}
193 
194 	talloc_free(data.dptr);
195 	return WERR_OK;
196 }
197 
198 /***********************************************************************
199  Add a new key to the array
200  **********************************************************************/
201 
regsubkey_ctr_addkey(struct regsubkey_ctr * ctr,const char * keyname)202 WERROR regsubkey_ctr_addkey( struct regsubkey_ctr *ctr, const char *keyname )
203 {
204 	char **newkeys;
205 	WERROR werr;
206 
207 	if ( !keyname ) {
208 		return WERR_OK;
209 	}
210 
211 	/* make sure the keyname is not already there */
212 
213 	if ( regsubkey_ctr_key_exists( ctr, keyname ) ) {
214 		return WERR_OK;
215 	}
216 
217 	if (!(newkeys = talloc_realloc(ctr, ctr->subkeys, char *,
218 					     ctr->num_subkeys+1))) {
219 		return WERR_NOT_ENOUGH_MEMORY;
220 	}
221 
222 	ctr->subkeys = newkeys;
223 
224 	if (!(ctr->subkeys[ctr->num_subkeys] = talloc_strdup(ctr->subkeys,
225 							     keyname ))) {
226 		/*
227 		 * Don't shrink the new array again, this wastes a pointer
228 		 */
229 		return WERR_NOT_ENOUGH_MEMORY;
230 	}
231 
232 	werr = regsubkey_ctr_hash_keyname(ctr, keyname, ctr->num_subkeys);
233 	W_ERROR_NOT_OK_RETURN(werr);
234 
235 	ctr->num_subkeys++;
236 
237 	return WERR_OK;
238 }
239 
240  /***********************************************************************
241  Delete a key from the array
242  **********************************************************************/
243 
regsubkey_ctr_delkey(struct regsubkey_ctr * ctr,const char * keyname)244 WERROR regsubkey_ctr_delkey( struct regsubkey_ctr *ctr, const char *keyname )
245 {
246 	WERROR werr;
247 	uint32_t idx, j;
248 
249 	if (keyname == NULL) {
250 		return WERR_INVALID_PARAMETER;
251 	}
252 
253 	/* make sure the keyname is actually already there */
254 
255 	werr = regsubkey_ctr_index_for_keyname(ctr, keyname, &idx);
256 	W_ERROR_NOT_OK_RETURN(werr);
257 
258 	werr = regsubkey_ctr_unhash_keyname(ctr, keyname);
259 	W_ERROR_NOT_OK_RETURN(werr);
260 
261 	/* update if we have any keys left */
262 	ctr->num_subkeys--;
263 	if (idx < ctr->num_subkeys) {
264 		memmove(&ctr->subkeys[idx], &ctr->subkeys[idx+1],
265 			sizeof(char *) * (ctr->num_subkeys - idx));
266 
267 		/* we have to re-hash rest of the array...  :-( */
268 		for (j = idx; j < ctr->num_subkeys; j++) {
269 			werr = regsubkey_ctr_hash_keyname(ctr, ctr->subkeys[j], j);
270 			W_ERROR_NOT_OK_RETURN(werr);
271 		}
272 	}
273 
274 	return WERR_OK;
275 }
276 
277 /***********************************************************************
278  Check for the existence of a key
279  **********************************************************************/
280 
regsubkey_ctr_key_exists(struct regsubkey_ctr * ctr,const char * keyname)281 bool regsubkey_ctr_key_exists( struct regsubkey_ctr *ctr, const char *keyname )
282 {
283 	WERROR werr;
284 
285 	if (!ctr->subkeys) {
286 		return False;
287 	}
288 
289 	werr = regsubkey_ctr_index_for_keyname(ctr, keyname, NULL);
290 	if (!W_ERROR_IS_OK(werr)) {
291 		return false;
292 	}
293 
294 	return true;
295 }
296 
297 /***********************************************************************
298  How many keys does the container hold ?
299  **********************************************************************/
300 
regsubkey_ctr_numkeys(struct regsubkey_ctr * ctr)301 int regsubkey_ctr_numkeys( struct regsubkey_ctr *ctr )
302 {
303 	return ctr->num_subkeys;
304 }
305 
306 /***********************************************************************
307  Retrieve a specific key string
308  **********************************************************************/
309 
regsubkey_ctr_specific_key(struct regsubkey_ctr * ctr,uint32_t key_index)310 char* regsubkey_ctr_specific_key( struct regsubkey_ctr *ctr, uint32_t key_index )
311 {
312 	if ( ! (key_index < ctr->num_subkeys) )
313 		return NULL;
314 
315 	return ctr->subkeys[key_index];
316 }
317 
318 /*
319  * Utility functions for struct regval_ctr
320  */
321 
322 /**
323  * allocate a regval_ctr structure.
324  */
regval_ctr_init(TALLOC_CTX * mem_ctx,struct regval_ctr ** ctr)325 WERROR regval_ctr_init(TALLOC_CTX *mem_ctx, struct regval_ctr **ctr)
326 {
327 	if (ctr == NULL) {
328 		return WERR_INVALID_PARAMETER;
329 	}
330 
331 	*ctr = talloc_zero(mem_ctx, struct regval_ctr);
332 	if (*ctr == NULL) {
333 		return WERR_NOT_ENOUGH_MEMORY;
334 	}
335 
336 	return WERR_OK;
337 }
338 
339 /***********************************************************************
340  How many keys does the container hold ?
341  **********************************************************************/
342 
regval_ctr_numvals(struct regval_ctr * ctr)343 int regval_ctr_numvals(struct regval_ctr *ctr)
344 {
345 	return ctr->num_values;
346 }
347 
348 /**********************************************************************
349  *********************************************************************/
350 
regval_data_p(struct regval_blob * val)351 uint8_t* regval_data_p(struct regval_blob *val)
352 {
353 	return val->data_p;
354 }
355 
356 /**********************************************************************
357  *********************************************************************/
358 
regval_size(struct regval_blob * val)359 uint32_t regval_size(struct regval_blob *val)
360 {
361 	return val->size;
362 }
363 
364 /**********************************************************************
365  *********************************************************************/
366 
regval_name(struct regval_blob * val)367 char* regval_name(struct regval_blob *val)
368 {
369 	return val->valuename;
370 }
371 
372 /**********************************************************************
373  *********************************************************************/
374 
regval_type(struct regval_blob * val)375 uint32_t regval_type(struct regval_blob *val)
376 {
377 	return val->type;
378 }
379 
380 /***********************************************************************
381  Retrieve a pointer to a specific value.  Caller shoud dup the structure
382  since this memory will go away when the ctr is free()'d
383  **********************************************************************/
384 
regval_ctr_specific_value(struct regval_ctr * ctr,uint32_t idx)385 struct regval_blob *regval_ctr_specific_value(struct regval_ctr *ctr,
386 					      uint32_t idx)
387 {
388 	if ( !(idx < ctr->num_values) )
389 		return NULL;
390 
391 	return ctr->values[idx];
392 }
393 
394 /***********************************************************************
395  Check for the existence of a value
396  **********************************************************************/
397 
regval_ctr_value_exists(struct regval_ctr * ctr,const char * value)398 bool regval_ctr_value_exists(struct regval_ctr *ctr, const char *value)
399 {
400 	int 	i;
401 
402 	for ( i=0; i<ctr->num_values; i++ ) {
403 		if ( strequal( ctr->values[i]->valuename, value) )
404 			return True;
405 	}
406 
407 	return False;
408 }
409 
410 /**
411  * Get a value by its name
412  */
regval_ctr_value_byname(struct regval_ctr * ctr,const char * value)413 struct regval_blob *regval_ctr_value_byname(struct regval_ctr *ctr,
414 					    const char *value)
415 {
416 	int i;
417 
418 	for (i = 0; i < ctr->num_values; i++) {
419 		if (strequal(ctr->values[i]->valuename, value)) {
420 			return ctr->values[i];
421 		}
422 	}
423 
424 	return NULL;
425 }
426 
427 
428 /***********************************************************************
429  * compose a struct regval_blob from input data
430  **********************************************************************/
431 
regval_compose(TALLOC_CTX * ctx,const char * name,uint32_t type,const uint8_t * data_p,size_t size)432 struct regval_blob *regval_compose(TALLOC_CTX *ctx, const char *name,
433 				   uint32_t type,
434 				   const uint8_t *data_p, size_t size)
435 {
436 	struct regval_blob *regval = talloc(ctx, struct regval_blob);
437 
438 	if (regval == NULL) {
439 		return NULL;
440 	}
441 
442 	fstrcpy(regval->valuename, name);
443 	regval->type = type;
444 	if (size) {
445 		regval->data_p = (uint8_t *)talloc_memdup(regval, data_p, size);
446 		if (!regval->data_p) {
447 			TALLOC_FREE(regval);
448 			return NULL;
449 		}
450 	} else {
451 		regval->data_p = NULL;
452 	}
453 	regval->size = size;
454 
455 	return regval;
456 }
457 
458 /***********************************************************************
459  Add a new registry value to the array
460  **********************************************************************/
461 
regval_ctr_addvalue(struct regval_ctr * ctr,const char * name,uint32_t type,const uint8_t * data_p,size_t size)462 int regval_ctr_addvalue(struct regval_ctr *ctr, const char *name, uint32_t type,
463                         const uint8_t *data_p, size_t size)
464 {
465 	if ( !name )
466 		return ctr->num_values;
467 
468 	/* Delete the current value (if it exists) and add the new one */
469 
470 	regval_ctr_delvalue( ctr, name );
471 
472 	/* allocate a slot in the array of pointers */
473 
474 	if (  ctr->num_values == 0 ) {
475 		ctr->values = talloc( ctr, struct regval_blob *);
476 	} else {
477 		ctr->values = talloc_realloc(ctr, ctr->values,
478 						   struct regval_blob *,
479 						   ctr->num_values+1);
480 	}
481 
482 	if (!ctr->values) {
483 		ctr->num_values = 0;
484 		return 0;
485 	}
486 
487 	/* allocate a new value and store the pointer in the array */
488 
489 	ctr->values[ctr->num_values] = regval_compose(ctr, name, type, data_p,
490 						      size);
491 	if (ctr->values[ctr->num_values] == NULL) {
492 		ctr->num_values = 0;
493 		return 0;
494 	}
495 	ctr->num_values++;
496 
497 	return ctr->num_values;
498 }
499 
500 /***********************************************************************
501  Add a new registry SZ value to the array
502  **********************************************************************/
503 
regval_ctr_addvalue_sz(struct regval_ctr * ctr,const char * name,const char * data)504 int regval_ctr_addvalue_sz(struct regval_ctr *ctr, const char *name, const char *data)
505 {
506 	DATA_BLOB blob;
507 
508 	if (!push_reg_sz(ctr, &blob, data)) {
509 		return -1;
510 	}
511 
512 	return regval_ctr_addvalue(ctr, name, REG_SZ,
513 				   (const uint8_t *)blob.data,
514 				   blob.length);
515 }
516 
517 /***********************************************************************
518  Add a new registry MULTI_SZ value to the array
519  **********************************************************************/
520 
regval_ctr_addvalue_multi_sz(struct regval_ctr * ctr,const char * name,const char ** data)521 int regval_ctr_addvalue_multi_sz(struct regval_ctr *ctr, const char *name, const char **data)
522 {
523 	DATA_BLOB blob;
524 
525 	if (!push_reg_multi_sz(ctr, &blob, data)) {
526 		return -1;
527 	}
528 
529 	return regval_ctr_addvalue(ctr, name, REG_MULTI_SZ,
530 				   (const uint8_t *)blob.data,
531 				   blob.length);
532 }
533 
534 /***********************************************************************
535  Add a new registry value to the array
536  **********************************************************************/
537 
regval_ctr_copyvalue(struct regval_ctr * ctr,struct regval_blob * val)538 int regval_ctr_copyvalue(struct regval_ctr *ctr, struct regval_blob *val)
539 {
540 	if ( val ) {
541 		regval_ctr_addvalue(ctr, val->valuename, val->type,
542 				    (uint8_t *)val->data_p, val->size);
543 	}
544 
545 	return ctr->num_values;
546 }
547 
548 /***********************************************************************
549  Delete a single value from the registry container.
550  No need to free memory since it is talloc'd.
551  **********************************************************************/
552 
regval_ctr_delvalue(struct regval_ctr * ctr,const char * name)553 int regval_ctr_delvalue(struct regval_ctr *ctr, const char *name)
554 {
555 	int 	i;
556 
557 	for ( i=0; i<ctr->num_values; i++ ) {
558 		if ( strequal( ctr->values[i]->valuename, name ) )
559 			break;
560 	}
561 
562 	/* just return if we don't find it */
563 
564 	if ( i == ctr->num_values )
565 		return ctr->num_values;
566 
567 	/* If 'i' was not the last element, just shift everything down one */
568 	ctr->num_values--;
569 	if ( i < ctr->num_values )
570 		memmove(&ctr->values[i], &ctr->values[i+1],
571 			sizeof(struct regval_blob*)*(ctr->num_values-i));
572 
573 	return ctr->num_values;
574 }
575 
576 /***********************************************************************
577  Retrieve single value from the registry container.
578  No need to free memory since it is talloc'd.
579  **********************************************************************/
580 
regval_ctr_getvalue(struct regval_ctr * ctr,const char * name)581 struct regval_blob* regval_ctr_getvalue(struct regval_ctr *ctr,
582 					const char *name)
583 {
584 	int 	i;
585 
586 	/* search for the value */
587 
588 	for ( i=0; i<ctr->num_values; i++ ) {
589 		if ( strequal( ctr->values[i]->valuename, name ) )
590 			return ctr->values[i];
591 	}
592 
593 	return NULL;
594 }
595 
regval_ctr_get_seqnum(struct regval_ctr * ctr)596 int regval_ctr_get_seqnum(struct regval_ctr *ctr)
597 {
598 	if (ctr == NULL) {
599 		return -1;
600 	}
601 
602 	return ctr->seqnum;
603 }
604 
regval_ctr_set_seqnum(struct regval_ctr * ctr,int seqnum)605 WERROR regval_ctr_set_seqnum(struct regval_ctr *ctr, int seqnum)
606 {
607 	if (ctr == NULL) {
608 		return WERR_INVALID_PARAMETER;
609 	}
610 
611 	ctr->seqnum = seqnum;
612 
613 	return WERR_OK;
614 }
615