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