Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * Virtual Windows Registry Layer
4 : * Copyright (C) Volker Lendecke 2006
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 : /* Attempt to wrap the existing API in a more winreg.idl-like way */
22 :
23 : /*
24 : * Here is a list of winreg.idl functions and corresponding implementations
25 : * provided here:
26 : *
27 : * 0x00 winreg_OpenHKCR
28 : * 0x01 winreg_OpenHKCU
29 : * 0x02 winreg_OpenHKLM
30 : * 0x03 winreg_OpenHKPD
31 : * 0x04 winreg_OpenHKU
32 : * 0x05 winreg_CloseKey
33 : * 0x06 winreg_CreateKey reg_createkey
34 : * 0x07 winreg_DeleteKey reg_deletekey
35 : * 0x08 winreg_DeleteValue reg_deletevalue
36 : * 0x09 winreg_EnumKey reg_enumkey
37 : * 0x0a winreg_EnumValue reg_enumvalue
38 : * 0x0b winreg_FlushKey
39 : * 0x0c winreg_GetKeySecurity reg_getkeysecurity
40 : * 0x0d winreg_LoadKey
41 : * 0x0e winreg_NotifyChangeKeyValue
42 : * 0x0f winreg_OpenKey reg_openkey
43 : * 0x10 winreg_QueryInfoKey reg_queryinfokey
44 : * 0x11 winreg_QueryValue reg_queryvalue
45 : * 0x12 winreg_ReplaceKey
46 : * 0x13 winreg_RestoreKey reg_restorekey
47 : * 0x14 winreg_SaveKey reg_savekey
48 : * 0x15 winreg_SetKeySecurity reg_setkeysecurity
49 : * 0x16 winreg_SetValue reg_setvalue
50 : * 0x17 winreg_UnLoadKey
51 : * 0x18 winreg_InitiateSystemShutdown
52 : * 0x19 winreg_AbortSystemShutdown
53 : * 0x1a winreg_GetVersion reg_getversion
54 : * 0x1b winreg_OpenHKCC
55 : * 0x1c winreg_OpenHKDD
56 : * 0x1d winreg_QueryMultipleValues reg_querymultiplevalues
57 : * 0x1e winreg_InitiateSystemShutdownEx
58 : * 0x1f winreg_SaveKeyEx
59 : * 0x20 winreg_OpenHKPT
60 : * 0x21 winreg_OpenHKPN
61 : * 0x22 winreg_QueryMultipleValues2 reg_querymultiplevalues
62 : *
63 : */
64 :
65 : #include "includes.h"
66 : #include "registry.h"
67 : #include "reg_api.h"
68 : #include "reg_cachehook.h"
69 : #include "reg_backend_db.h"
70 : #include "reg_dispatcher.h"
71 : #include "reg_objects.h"
72 : #include "../librpc/gen_ndr/ndr_security.h"
73 : #include "reg_parse_internal.h"
74 :
75 : #undef DBGC_CLASS
76 : #define DBGC_CLASS DBGC_REGISTRY
77 :
78 :
79 : /**********************************************************************
80 : * Helper functions
81 : **********************************************************************/
82 :
83 1639 : static WERROR fill_value_cache(struct registry_key *key)
84 : {
85 : WERROR werr;
86 :
87 1639 : if (key->values != NULL) {
88 1276 : if (!reg_values_need_update(key->key, key->values)) {
89 1252 : return WERR_OK;
90 : }
91 : }
92 :
93 387 : TALLOC_FREE(key->values);
94 387 : werr = regval_ctr_init(key, &(key->values));
95 387 : W_ERROR_NOT_OK_RETURN(werr);
96 :
97 387 : if (fetch_reg_values(key->key, key->values) == -1) {
98 0 : TALLOC_FREE(key->values);
99 0 : return WERR_FILE_NOT_FOUND;
100 : }
101 :
102 387 : return WERR_OK;
103 : }
104 :
105 191028 : static WERROR fill_subkey_cache(struct registry_key *key)
106 : {
107 : WERROR werr;
108 :
109 191028 : if (key->subkeys != NULL) {
110 366 : if (!reg_subkeys_need_update(key->key, key->subkeys)) {
111 339 : return WERR_OK;
112 : }
113 : }
114 :
115 190689 : TALLOC_FREE(key->subkeys);
116 190689 : werr = regsubkey_ctr_init(key, &(key->subkeys));
117 190689 : W_ERROR_NOT_OK_RETURN(werr);
118 :
119 190689 : if (fetch_reg_keys(key->key, key->subkeys) == -1) {
120 188020 : TALLOC_FREE(key->subkeys);
121 188020 : return WERR_FILE_NOT_FOUND;
122 : }
123 :
124 2669 : return WERR_OK;
125 : }
126 :
127 190569 : static int regkey_destructor(struct registry_key_handle *key)
128 : {
129 190569 : return regdb_close();
130 : }
131 :
132 190662 : static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx,
133 : struct registry_key *parent,
134 : const char *name,
135 : const struct security_token *token,
136 : uint32_t access_desired,
137 : struct registry_key **pregkey)
138 : {
139 : WERROR result;
140 : struct registry_key *regkey;
141 : struct registry_key_handle *key;
142 :
143 190662 : DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name));
144 :
145 190662 : SMB_ASSERT(strchr(name, '\\') == NULL);
146 :
147 291653 : if (!(regkey = talloc_zero(mem_ctx, struct registry_key)) ||
148 291653 : !(regkey->token = dup_nt_token(regkey, token)) ||
149 190662 : !(regkey->key = talloc_zero(regkey, struct registry_key_handle)))
150 : {
151 0 : result = WERR_NOT_ENOUGH_MEMORY;
152 0 : goto done;
153 : }
154 :
155 190662 : result = regdb_open();
156 190662 : if (!(W_ERROR_IS_OK(result))) {
157 0 : goto done;
158 : }
159 :
160 190662 : key = regkey->key;
161 190662 : talloc_set_destructor(key, regkey_destructor);
162 :
163 : /* initialization */
164 :
165 190662 : key->type = REG_KEY_GENERIC;
166 :
167 190662 : if (name[0] == '\0') {
168 : /*
169 : * Open a copy of the parent key
170 : */
171 0 : if (!parent) {
172 0 : result = WERR_FILE_NOT_FOUND;
173 0 : goto done;
174 : }
175 0 : key->name = talloc_strdup(key, parent->key->name);
176 : }
177 : else {
178 : /*
179 : * Normal subkey open
180 : */
181 381128 : key->name = talloc_asprintf(key, "%s%s%s",
182 190466 : parent ? parent->key->name : "",
183 : parent ? "\\": "",
184 : name);
185 : }
186 :
187 190662 : if (key->name == NULL) {
188 0 : result = WERR_NOT_ENOUGH_MEMORY;
189 0 : goto done;
190 : }
191 :
192 : /* Tag this as a Performance Counter Key */
193 :
194 190662 : if( strncasecmp_m(key->name, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
195 0 : key->type = REG_KEY_HKPD;
196 :
197 : /* Look up the table of registry I/O operations */
198 :
199 190662 : key->ops = reghook_cache_find( key->name );
200 190662 : if (key->ops == NULL) {
201 0 : DEBUG(0,("reg_open_onelevel: Failed to assign "
202 : "registry_ops to [%s]\n", key->name ));
203 0 : result = WERR_FILE_NOT_FOUND;
204 0 : goto done;
205 : }
206 :
207 : /* FIXME: Existence is currently checked by fetching the subkeys */
208 :
209 190662 : result = fill_subkey_cache(regkey);
210 190662 : if (!W_ERROR_IS_OK(result)) {
211 188020 : goto done;
212 : }
213 :
214 2642 : if ( !regkey_access_check( key, access_desired, &key->access_granted,
215 : token ) ) {
216 0 : result = WERR_ACCESS_DENIED;
217 0 : goto done;
218 : }
219 :
220 2642 : *pregkey = regkey;
221 2642 : result = WERR_OK;
222 :
223 190662 : done:
224 190662 : if ( !W_ERROR_IS_OK(result) ) {
225 188020 : TALLOC_FREE(regkey);
226 : }
227 :
228 190662 : return result;
229 : }
230 :
231 196 : WERROR reg_openhive(TALLOC_CTX *mem_ctx, const char *hive,
232 : uint32_t desired_access,
233 : const struct security_token *token,
234 : struct registry_key **pkey)
235 : {
236 : const struct hive_info *hi;
237 196 : SMB_ASSERT(hive != NULL);
238 196 : SMB_ASSERT(strchr(hive, '\\') == NULL);
239 :
240 196 : hi = hive_info(hive);
241 196 : if (hi == NULL) {
242 0 : return WERR_FILE_NOT_FOUND;
243 : }
244 :
245 196 : return regkey_open_onelevel(mem_ctx, NULL, hi->short_name, token,
246 : desired_access, pkey);
247 : }
248 :
249 :
250 : /**********************************************************************
251 : * The API functions
252 : **********************************************************************/
253 :
254 189789 : WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent,
255 : const char *name, uint32_t desired_access,
256 : struct registry_key **pkey)
257 : {
258 189789 : struct registry_key *direct_parent = parent;
259 : WERROR err;
260 : char *p, *path;
261 : size_t len;
262 189789 : TALLOC_CTX *frame = talloc_stackframe();
263 :
264 189789 : path = talloc_strdup(frame, name);
265 189789 : if (path == NULL) {
266 0 : err = WERR_NOT_ENOUGH_MEMORY;
267 0 : goto error;
268 : }
269 :
270 189789 : len = strlen(path);
271 :
272 189789 : if ((len > 0) && (path[len-1] == '\\')) {
273 0 : path[len-1] = '\0';
274 : }
275 :
276 290880 : while ((p = strchr(path, '\\')) != NULL) {
277 : char *name_component;
278 : struct registry_key *tmp;
279 :
280 677 : name_component = talloc_strndup(frame, path, (p - path));
281 677 : if (name_component == NULL) {
282 0 : err = WERR_NOT_ENOUGH_MEMORY;
283 0 : goto error;
284 : }
285 :
286 677 : err = regkey_open_onelevel(frame, direct_parent,
287 677 : name_component, parent->token,
288 : KEY_ENUMERATE_SUB_KEYS, &tmp);
289 :
290 677 : if (!W_ERROR_IS_OK(err)) {
291 0 : goto error;
292 : }
293 :
294 677 : direct_parent = tmp;
295 677 : path = p+1;
296 : }
297 :
298 189789 : err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token,
299 : desired_access, pkey);
300 :
301 189789 : error:
302 189789 : talloc_free(frame);
303 189789 : return err;
304 : }
305 :
306 233 : WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
307 : uint32_t idx, char **name, NTTIME *last_write_time)
308 : {
309 : WERROR err;
310 :
311 233 : if (!(key->key->access_granted & KEY_ENUMERATE_SUB_KEYS)) {
312 0 : return WERR_ACCESS_DENIED;
313 : }
314 :
315 233 : err = fill_subkey_cache(key);
316 233 : if (!W_ERROR_IS_OK(err)) {
317 0 : return err;
318 : }
319 :
320 233 : if (idx >= regsubkey_ctr_numkeys(key->subkeys)) {
321 68 : return WERR_NO_MORE_ITEMS;
322 : }
323 :
324 165 : if (!(*name = talloc_strdup(mem_ctx,
325 165 : regsubkey_ctr_specific_key(key->subkeys, idx))))
326 : {
327 0 : return WERR_NOT_ENOUGH_MEMORY;
328 : }
329 :
330 165 : if (last_write_time) {
331 163 : *last_write_time = 0;
332 : }
333 :
334 165 : return WERR_OK;
335 : }
336 :
337 37 : WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
338 : uint32_t idx, char **pname, struct registry_value **pval)
339 : {
340 : struct registry_value *val;
341 : struct regval_blob *blob;
342 : WERROR err;
343 :
344 37 : if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
345 0 : return WERR_ACCESS_DENIED;
346 : }
347 :
348 37 : err = fill_value_cache(key);
349 37 : if (!(W_ERROR_IS_OK(err))) {
350 0 : return err;
351 : }
352 :
353 37 : if (idx >= regval_ctr_numvals(key->values)) {
354 26 : return WERR_NO_MORE_ITEMS;
355 : }
356 :
357 11 : blob = regval_ctr_specific_value(key->values, idx);
358 :
359 11 : val = talloc_zero(mem_ctx, struct registry_value);
360 11 : if (val == NULL) {
361 0 : return WERR_NOT_ENOUGH_MEMORY;
362 : }
363 :
364 11 : val->type = regval_type(blob);
365 11 : val->data = data_blob_talloc(mem_ctx, regval_data_p(blob), regval_size(blob));
366 :
367 11 : if (pname
368 11 : && !(*pname = talloc_strdup(
369 11 : mem_ctx, regval_name(blob)))) {
370 0 : TALLOC_FREE(val);
371 0 : return WERR_NOT_ENOUGH_MEMORY;
372 : }
373 :
374 11 : *pval = val;
375 11 : return WERR_OK;
376 : }
377 :
378 279 : static WERROR reg_enumvalue_nocachefill(TALLOC_CTX *mem_ctx,
379 : struct registry_key *key,
380 : uint32_t idx, char **pname,
381 : struct registry_value **pval)
382 : {
383 : struct registry_value *val;
384 : struct regval_blob *blob;
385 :
386 279 : if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
387 0 : return WERR_ACCESS_DENIED;
388 : }
389 :
390 279 : if (idx >= regval_ctr_numvals(key->values)) {
391 0 : return WERR_NO_MORE_ITEMS;
392 : }
393 :
394 279 : blob = regval_ctr_specific_value(key->values, idx);
395 :
396 279 : val = talloc_zero(mem_ctx, struct registry_value);
397 279 : if (val == NULL) {
398 0 : return WERR_NOT_ENOUGH_MEMORY;
399 : }
400 :
401 279 : val->type = regval_type(blob);
402 279 : val->data = data_blob_talloc(mem_ctx, regval_data_p(blob), regval_size(blob));
403 :
404 279 : if (pname
405 0 : && !(*pname = talloc_strdup(
406 0 : mem_ctx, regval_name(blob)))) {
407 0 : TALLOC_FREE(val);
408 0 : return WERR_NOT_ENOUGH_MEMORY;
409 : }
410 :
411 279 : *pval = val;
412 279 : return WERR_OK;
413 : }
414 :
415 331 : WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
416 : const char *name, struct registry_value **pval)
417 : {
418 : WERROR err;
419 : uint32_t i;
420 :
421 331 : if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
422 0 : return WERR_ACCESS_DENIED;
423 : }
424 :
425 331 : if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
426 0 : return err;
427 : }
428 :
429 515 : for (i=0; i < regval_ctr_numvals(key->values); i++) {
430 : struct regval_blob *blob;
431 463 : blob = regval_ctr_specific_value(key->values, i);
432 463 : if (strequal(regval_name(blob), name)) {
433 : /*
434 : * don't use reg_enumvalue here:
435 : * re-reading the values from the disk
436 : * would change the indexing and break
437 : * this function.
438 : */
439 279 : return reg_enumvalue_nocachefill(mem_ctx, key, i,
440 : NULL, pval);
441 : }
442 : }
443 :
444 52 : return WERR_FILE_NOT_FOUND;
445 : }
446 :
447 0 : WERROR reg_querymultiplevalues(TALLOC_CTX *mem_ctx,
448 : struct registry_key *key,
449 : uint32_t num_names,
450 : const char **names,
451 : uint32_t *pnum_vals,
452 : struct registry_value **pvals)
453 : {
454 : WERROR err;
455 0 : uint32_t i, n, found = 0;
456 : struct registry_value *vals;
457 :
458 0 : if (num_names == 0) {
459 0 : return WERR_OK;
460 : }
461 :
462 0 : if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
463 0 : return WERR_ACCESS_DENIED;
464 : }
465 :
466 0 : if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
467 0 : return err;
468 : }
469 :
470 0 : vals = talloc_zero_array(mem_ctx, struct registry_value, num_names);
471 0 : if (vals == NULL) {
472 0 : return WERR_NOT_ENOUGH_MEMORY;
473 : }
474 :
475 0 : for (n=0; n < num_names; n++) {
476 0 : for (i=0; i < regval_ctr_numvals(key->values); i++) {
477 : struct regval_blob *blob;
478 0 : blob = regval_ctr_specific_value(key->values, i);
479 0 : if (strequal(regval_name(blob), names[n])) {
480 : struct registry_value *v;
481 0 : err = reg_enumvalue(mem_ctx, key, i, NULL, &v);
482 0 : if (!W_ERROR_IS_OK(err)) {
483 0 : return err;
484 : }
485 0 : vals[n] = *v;
486 0 : found++;
487 : }
488 : }
489 : }
490 :
491 0 : *pvals = vals;
492 0 : *pnum_vals = found;
493 :
494 0 : return WERR_OK;
495 : }
496 :
497 66 : WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
498 : uint32_t *max_subkeylen, uint32_t *max_subkeysize,
499 : uint32_t *num_values, uint32_t *max_valnamelen,
500 : uint32_t *max_valbufsize, uint32_t *secdescsize,
501 : NTTIME *last_changed_time)
502 : {
503 : uint32_t i, max_size;
504 : size_t max_len;
505 : TALLOC_CTX *mem_ctx;
506 : WERROR err;
507 : struct security_descriptor *secdesc;
508 :
509 66 : if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
510 0 : return WERR_ACCESS_DENIED;
511 : }
512 :
513 110 : if (!W_ERROR_IS_OK(fill_subkey_cache(key)) ||
514 66 : !W_ERROR_IS_OK(fill_value_cache(key))) {
515 0 : return WERR_FILE_NOT_FOUND;
516 : }
517 :
518 66 : max_len = 0;
519 229 : for (i=0; i< regsubkey_ctr_numkeys(key->subkeys); i++) {
520 163 : max_len = MAX(max_len,
521 : strlen(regsubkey_ctr_specific_key(key->subkeys, i)));
522 : }
523 :
524 66 : *num_subkeys = regsubkey_ctr_numkeys(key->subkeys);
525 66 : *max_subkeylen = max_len;
526 66 : *max_subkeysize = 0; /* Class length? */
527 :
528 66 : max_len = 0;
529 66 : max_size = 0;
530 120 : for (i=0; i < regval_ctr_numvals(key->values); i++) {
531 : struct regval_blob *blob;
532 54 : blob = regval_ctr_specific_value(key->values, i);
533 54 : max_len = MAX(max_len, strlen(regval_name(blob)));
534 54 : max_size = MAX(max_size, regval_size(blob));
535 : }
536 :
537 66 : *num_values = regval_ctr_numvals(key->values);
538 66 : *max_valnamelen = max_len;
539 66 : *max_valbufsize = max_size;
540 :
541 66 : if (!(mem_ctx = talloc_new(key))) {
542 0 : return WERR_NOT_ENOUGH_MEMORY;
543 : }
544 :
545 66 : err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
546 66 : if (!W_ERROR_IS_OK(err)) {
547 0 : TALLOC_FREE(mem_ctx);
548 0 : return err;
549 : }
550 :
551 66 : *secdescsize = ndr_size_security_descriptor(secdesc, 0);
552 66 : TALLOC_FREE(mem_ctx);
553 :
554 66 : *last_changed_time = 0;
555 :
556 66 : return WERR_OK;
557 : }
558 :
559 1463 : WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
560 : const char *subkeypath, uint32_t desired_access,
561 : struct registry_key **pkey,
562 : enum winreg_CreateAction *paction)
563 : {
564 1463 : struct registry_key *key = parent;
565 : TALLOC_CTX *mem_ctx;
566 : char *path, *end;
567 : WERROR err;
568 : uint32_t access_granted;
569 :
570 1463 : mem_ctx = talloc_new(ctx);
571 1463 : if (mem_ctx == NULL) {
572 0 : return WERR_NOT_ENOUGH_MEMORY;
573 : }
574 :
575 1463 : path = talloc_strdup(mem_ctx, subkeypath);
576 1463 : if (path == NULL) {
577 0 : err = WERR_NOT_ENOUGH_MEMORY;
578 0 : goto done;
579 : }
580 :
581 1463 : err = regdb_transaction_start();
582 1463 : if (!W_ERROR_IS_OK(err)) {
583 0 : DEBUG(0, ("reg_createkey: failed to start transaction: %s\n",
584 : win_errstr(err)));
585 0 : goto done;
586 : }
587 :
588 3495 : while ((end = strchr(path, '\\')) != NULL) {
589 : struct registry_key *tmp;
590 : enum winreg_CreateAction action;
591 :
592 1119 : *end = '\0';
593 :
594 1119 : err = reg_createkey(mem_ctx, key, path,
595 : KEY_ENUMERATE_SUB_KEYS, &tmp, &action);
596 1119 : if (!W_ERROR_IS_OK(err)) {
597 0 : goto trans_done;
598 : }
599 :
600 1119 : if (key != parent) {
601 797 : TALLOC_FREE(key);
602 : }
603 :
604 1119 : key = tmp;
605 1119 : path = end+1;
606 : }
607 :
608 : /*
609 : * At this point, "path" contains the one-element subkey of "key". We
610 : * can try to open it.
611 : */
612 :
613 1463 : err = reg_openkey(ctx, key, path, desired_access, pkey);
614 1463 : if (W_ERROR_IS_OK(err)) {
615 1213 : if (paction != NULL) {
616 1213 : *paction = REG_OPENED_EXISTING_KEY;
617 : }
618 1213 : goto trans_done;
619 : }
620 :
621 250 : if (!W_ERROR_EQUAL(err, WERR_FILE_NOT_FOUND)) {
622 : /*
623 : * Something but "notfound" has happened, so bail out
624 : */
625 0 : goto trans_done;
626 : }
627 :
628 : /*
629 : * We may (e.g. in the iteration) have opened the key with ENUM_SUBKEY.
630 : * Instead of re-opening the key with CREATE_SUB_KEY, we simply
631 : * duplicate the access check here and skip the expensive full open.
632 : */
633 250 : if (!regkey_access_check(key->key, KEY_CREATE_SUB_KEY, &access_granted,
634 250 : key->token))
635 : {
636 0 : err = WERR_ACCESS_DENIED;
637 0 : goto trans_done;
638 : }
639 :
640 : /*
641 : * Actually create the subkey
642 : */
643 :
644 250 : err = create_reg_subkey(key->key, path);
645 250 : if (!W_ERROR_IS_OK(err)) {
646 0 : goto trans_done;
647 : }
648 :
649 : /*
650 : * Now open the newly created key
651 : */
652 :
653 250 : err = reg_openkey(ctx, key, path, desired_access, pkey);
654 423 : if (W_ERROR_IS_OK(err) && (paction != NULL)) {
655 250 : *paction = REG_CREATED_NEW_KEY;
656 : }
657 :
658 913 : trans_done:
659 1463 : if (W_ERROR_IS_OK(err)) {
660 1463 : err = regdb_transaction_commit();
661 1463 : if (!W_ERROR_IS_OK(err)) {
662 0 : DEBUG(0, ("reg_createkey: Error committing transaction: %s\n", win_errstr(err)));
663 : }
664 : } else {
665 0 : WERROR err1 = regdb_transaction_cancel();
666 0 : if (!W_ERROR_IS_OK(err1)) {
667 0 : DEBUG(0, ("reg_createkey: Error cancelling transaction: %s\n", win_errstr(err1)));
668 : }
669 : }
670 :
671 1463 : done:
672 1463 : TALLOC_FREE(mem_ctx);
673 1463 : return err;
674 : }
675 :
676 67 : static WERROR reg_deletekey_internal(TALLOC_CTX *mem_ctx,
677 : struct registry_key *parent,
678 : const char *path, bool lazy)
679 : {
680 : WERROR err;
681 : char *name, *end;
682 : struct registry_key *key;
683 67 : name = talloc_strdup(mem_ctx, path);
684 67 : if (name == NULL) {
685 0 : err = WERR_NOT_ENOUGH_MEMORY;
686 0 : goto done;
687 : }
688 :
689 : /* no subkeys - proceed with delete */
690 67 : end = strrchr(name, '\\');
691 67 : if (end != NULL) {
692 42 : *end = '\0';
693 :
694 42 : err = reg_openkey(mem_ctx, parent, name,
695 : KEY_CREATE_SUB_KEY, &key);
696 42 : W_ERROR_NOT_OK_GOTO_DONE(err);
697 :
698 42 : parent = key;
699 42 : name = end+1;
700 : }
701 :
702 67 : if (name[0] == '\0') {
703 0 : err = WERR_INVALID_PARAMETER;
704 0 : goto done;
705 : }
706 :
707 67 : err = delete_reg_subkey(parent->key, name, lazy);
708 :
709 67 : done:
710 67 : return err;
711 : }
712 :
713 96 : WERROR reg_deletekey(struct registry_key *parent, const char *path)
714 : {
715 : WERROR err;
716 : struct registry_key *key;
717 96 : TALLOC_CTX *mem_ctx = talloc_stackframe();
718 :
719 : /* check if the key has subkeys */
720 96 : err = reg_openkey(mem_ctx, parent, path, REG_KEY_READ, &key);
721 96 : W_ERROR_NOT_OK_GOTO_DONE(err);
722 :
723 66 : err = regdb_transaction_start();
724 66 : if (!W_ERROR_IS_OK(err)) {
725 0 : DEBUG(0, ("reg_deletekey: Error starting transaction: %s\n",
726 : win_errstr(err)));
727 0 : goto done;
728 : }
729 :
730 66 : err = fill_subkey_cache(key);
731 66 : if (!W_ERROR_IS_OK(err)) {
732 0 : goto trans_done;
733 : }
734 :
735 66 : if (regsubkey_ctr_numkeys(key->subkeys) > 0) {
736 0 : err = WERR_ACCESS_DENIED;
737 0 : goto trans_done;
738 : }
739 66 : err = reg_deletekey_internal(mem_ctx, parent, path, false);
740 :
741 66 : trans_done:
742 66 : if (W_ERROR_IS_OK(err)) {
743 66 : err = regdb_transaction_commit();
744 66 : if (!W_ERROR_IS_OK(err)) {
745 0 : DEBUG(0, ("reg_deletekey: Error committing transaction: %s\n", win_errstr(err)));
746 : }
747 : } else {
748 0 : WERROR err1 = regdb_transaction_cancel();
749 0 : if (!W_ERROR_IS_OK(err1)) {
750 0 : DEBUG(0, ("reg_deletekey: Error cancelling transaction: %s\n", win_errstr(err1)));
751 : }
752 : }
753 :
754 96 : done:
755 96 : TALLOC_FREE(mem_ctx);
756 96 : return err;
757 : }
758 :
759 :
760 1151 : WERROR reg_setvalue(struct registry_key *key, const char *name,
761 : const struct registry_value *val)
762 : {
763 : struct regval_blob *existing;
764 : WERROR err;
765 : int res;
766 :
767 1151 : if (!(key->key->access_granted & KEY_SET_VALUE)) {
768 0 : return WERR_ACCESS_DENIED;
769 : }
770 :
771 1151 : err = regdb_transaction_start();
772 1151 : if (!W_ERROR_IS_OK(err)) {
773 0 : DEBUG(0, ("reg_setvalue: Failed to start transaction: %s\n",
774 : win_errstr(err)));
775 0 : return err;
776 : }
777 :
778 1151 : err = fill_value_cache(key);
779 1151 : if (!W_ERROR_IS_OK(err)) {
780 0 : DEBUG(0, ("reg_setvalue: Error filling value cache: %s\n", win_errstr(err)));
781 0 : goto done;
782 : }
783 :
784 1151 : existing = regval_ctr_getvalue(key->values, name);
785 :
786 1346 : if ((existing != NULL) &&
787 518 : (regval_size(existing) == val->data.length) &&
788 323 : (memcmp(regval_data_p(existing), val->data.data,
789 128 : val->data.length) == 0))
790 : {
791 323 : err = WERR_OK;
792 323 : goto done;
793 : }
794 :
795 1334 : res = regval_ctr_addvalue(key->values, name, val->type,
796 828 : val->data.data, val->data.length);
797 :
798 828 : if (res == 0) {
799 0 : TALLOC_FREE(key->values);
800 0 : err = WERR_NOT_ENOUGH_MEMORY;
801 0 : goto done;
802 : }
803 :
804 828 : if (!store_reg_values(key->key, key->values)) {
805 0 : TALLOC_FREE(key->values);
806 0 : DEBUG(0, ("reg_setvalue: store_reg_values failed\n"));
807 0 : err = WERR_REGISTRY_IO_FAILED;
808 0 : goto done;
809 : }
810 :
811 828 : err = WERR_OK;
812 :
813 1151 : done:
814 1151 : if (W_ERROR_IS_OK(err)) {
815 1151 : err = regdb_transaction_commit();
816 1151 : if (!W_ERROR_IS_OK(err)) {
817 0 : DEBUG(0, ("reg_setvalue: Error committing transaction: %s\n", win_errstr(err)));
818 : }
819 : } else {
820 0 : WERROR err1 = regdb_transaction_cancel();
821 0 : if (!W_ERROR_IS_OK(err1)) {
822 0 : DEBUG(0, ("reg_setvalue: Error cancelling transaction: %s\n", win_errstr(err1)));
823 : }
824 : }
825 :
826 1151 : return err;
827 : }
828 :
829 54 : static WERROR reg_value_exists(struct registry_key *key, const char *name)
830 : {
831 : struct regval_blob *blob;
832 :
833 54 : blob = regval_ctr_getvalue(key->values, name);
834 :
835 54 : if (blob == NULL) {
836 0 : return WERR_FILE_NOT_FOUND;
837 : } else {
838 54 : return WERR_OK;
839 : }
840 : }
841 :
842 54 : WERROR reg_deletevalue(struct registry_key *key, const char *name)
843 : {
844 : WERROR err;
845 :
846 54 : if (!(key->key->access_granted & KEY_SET_VALUE)) {
847 0 : return WERR_ACCESS_DENIED;
848 : }
849 :
850 54 : err = regdb_transaction_start();
851 54 : if (!W_ERROR_IS_OK(err)) {
852 0 : DEBUG(0, ("reg_deletevalue: Failed to start transaction: %s\n",
853 : win_errstr(err)));
854 0 : return err;
855 : }
856 :
857 54 : err = fill_value_cache(key);
858 54 : if (!W_ERROR_IS_OK(err)) {
859 0 : DEBUG(0, ("reg_deletevalue; Error filling value cache: %s\n",
860 : win_errstr(err)));
861 0 : goto done;
862 : }
863 :
864 54 : err = reg_value_exists(key, name);
865 54 : if (!W_ERROR_IS_OK(err)) {
866 0 : goto done;
867 : }
868 :
869 54 : regval_ctr_delvalue(key->values, name);
870 :
871 54 : if (!store_reg_values(key->key, key->values)) {
872 0 : TALLOC_FREE(key->values);
873 0 : err = WERR_REGISTRY_IO_FAILED;
874 0 : DEBUG(0, ("reg_deletevalue: store_reg_values failed\n"));
875 0 : goto done;
876 : }
877 :
878 54 : err = WERR_OK;
879 :
880 54 : done:
881 54 : if (W_ERROR_IS_OK(err)) {
882 54 : err = regdb_transaction_commit();
883 54 : if (!W_ERROR_IS_OK(err)) {
884 0 : DEBUG(0, ("reg_deletevalue: Error committing transaction: %s\n", win_errstr(err)));
885 : }
886 : } else {
887 0 : WERROR err1 = regdb_transaction_cancel();
888 0 : if (!W_ERROR_IS_OK(err1)) {
889 0 : DEBUG(0, ("reg_deletevalue: Error cancelling transaction: %s\n", win_errstr(err1)));
890 : }
891 : }
892 :
893 54 : return err;
894 : }
895 :
896 0 : WERROR reg_getkeysecurity(TALLOC_CTX *mem_ctx, struct registry_key *key,
897 : struct security_descriptor **psecdesc)
898 : {
899 0 : return regkey_get_secdesc(mem_ctx, key->key, psecdesc);
900 : }
901 :
902 0 : WERROR reg_setkeysecurity(struct registry_key *key,
903 : struct security_descriptor *psecdesc)
904 : {
905 0 : return regkey_set_secdesc(key->key, psecdesc);
906 : }
907 :
908 12 : WERROR reg_getversion(uint32_t *version)
909 : {
910 12 : if (version == NULL) {
911 0 : return WERR_INVALID_PARAMETER;
912 : }
913 :
914 12 : *version = 0x00000005; /* Windows 2000 registry API version */
915 12 : return WERR_OK;
916 : }
917 :
918 : /**********************************************************************
919 : * Higher level utility functions
920 : **********************************************************************/
921 :
922 0 : WERROR reg_deleteallvalues(struct registry_key *key)
923 : {
924 : WERROR err;
925 : uint32_t i;
926 :
927 0 : if (!(key->key->access_granted & KEY_SET_VALUE)) {
928 0 : return WERR_ACCESS_DENIED;
929 : }
930 :
931 0 : if (!W_ERROR_IS_OK(err = fill_value_cache(key))) {
932 0 : return err;
933 : }
934 :
935 0 : for (i=0; i < regval_ctr_numvals(key->values); i++) {
936 : struct regval_blob *blob;
937 0 : blob = regval_ctr_specific_value(key->values, i);
938 0 : regval_ctr_delvalue(key->values, regval_name(blob));
939 : }
940 :
941 0 : if (!store_reg_values(key->key, key->values)) {
942 0 : TALLOC_FREE(key->values);
943 0 : return WERR_REGISTRY_IO_FAILED;
944 : }
945 :
946 0 : return WERR_OK;
947 : }
948 :
949 : /*
950 : * Utility function to delete a registry key with all its subkeys.
951 : * Note that reg_deletekey returns ACCESS_DENIED when called on a
952 : * key that has subkeys.
953 : */
954 1 : static WERROR reg_deletekey_recursive_internal(struct registry_key *parent,
955 : const char *path,
956 : bool del_key, bool lazy)
957 : {
958 : WERROR werr;
959 : struct registry_key *key;
960 1 : char *subkey_name = NULL;
961 : uint32_t i;
962 1 : TALLOC_CTX *mem_ctx = talloc_stackframe();
963 :
964 1 : DEBUG(5, ("reg_deletekey_recursive_internal: deleting '%s' from '%s'\n",
965 : path, parent->key->name));
966 :
967 : /* recurse through subkeys first */
968 1 : werr = reg_openkey(mem_ctx, parent, path, REG_KEY_ALL, &key);
969 1 : if (!W_ERROR_IS_OK(werr)) {
970 0 : DEBUG(3, ("reg_deletekey_recursive_internal: error opening "
971 : "subkey '%s' of '%s': '%s'\n",
972 : path, parent->key->name, win_errstr(werr)));
973 0 : goto done;
974 : }
975 :
976 1 : werr = fill_subkey_cache(key);
977 1 : W_ERROR_NOT_OK_GOTO_DONE(werr);
978 :
979 : /*
980 : * loop from top to bottom for performance:
981 : * this way, we need to rehash the regsubkey containers less
982 : */
983 1 : for (i = regsubkey_ctr_numkeys(key->subkeys) ; i > 0; i--) {
984 0 : subkey_name = regsubkey_ctr_specific_key(key->subkeys, i-1);
985 0 : werr = reg_deletekey_recursive_internal(key, subkey_name, true, del_key);
986 0 : W_ERROR_NOT_OK_GOTO_DONE(werr);
987 : }
988 :
989 1 : if (del_key) {
990 : /* now delete the actual key */
991 1 : werr = reg_deletekey_internal(mem_ctx, parent, path, lazy);
992 : }
993 :
994 1 : done:
995 :
996 1 : DEBUG(5, ("reg_deletekey_recursive_internal: done deleting '%s' from "
997 : "'%s': %s\n",
998 : path, parent->key->name, win_errstr(werr)));
999 1 : TALLOC_FREE(mem_ctx);
1000 1 : return werr;
1001 : }
1002 :
1003 1 : static WERROR reg_deletekey_recursive_trans(struct registry_key *parent,
1004 : const char *path,
1005 : bool del_key)
1006 : {
1007 : WERROR werr;
1008 :
1009 1 : werr = regdb_transaction_start();
1010 1 : if (!W_ERROR_IS_OK(werr)) {
1011 0 : DEBUG(0, ("reg_deletekey_recursive_trans: "
1012 : "error starting transaction: %s\n",
1013 : win_errstr(werr)));
1014 0 : return werr;
1015 : }
1016 :
1017 1 : werr = reg_deletekey_recursive_internal(parent, path, del_key, false);
1018 :
1019 1 : if (!W_ERROR_IS_OK(werr)) {
1020 : WERROR werr2;
1021 0 : DEBUG(W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND) ? 5 : 1,
1022 : (__location__ ": failed to delete key '%s' from key "
1023 : "'%s': %s\n", path, parent->key->name,
1024 : win_errstr(werr)));
1025 :
1026 0 : werr2 = regdb_transaction_cancel();
1027 0 : if (!W_ERROR_IS_OK(werr2)) {
1028 0 : DEBUG(0, ("reg_deletekey_recursive_trans: "
1029 : "error cancelling transaction: %s\n",
1030 : win_errstr(werr2)));
1031 : /*
1032 : * return the original werr or the
1033 : * error from cancelling the transaction?
1034 : */
1035 : }
1036 : } else {
1037 1 : werr = regdb_transaction_commit();
1038 1 : if (!W_ERROR_IS_OK(werr)) {
1039 0 : DEBUG(0, ("reg_deletekey_recursive_trans: "
1040 : "error committing transaction: %s\n",
1041 : win_errstr(werr)));
1042 : } else {
1043 1 : DEBUG(5, ("reg_deletekey_recursive_trans: deleted key '%s' from '%s'\n",
1044 : path, parent->key->name));
1045 :
1046 : }
1047 : }
1048 :
1049 1 : return werr;
1050 : }
1051 :
1052 1 : WERROR reg_deletekey_recursive(struct registry_key *parent,
1053 : const char *path)
1054 : {
1055 1 : return reg_deletekey_recursive_trans(parent, path, true);
1056 : }
1057 :
1058 0 : WERROR reg_deletesubkeys_recursive(struct registry_key *parent,
1059 : const char *path)
1060 : {
1061 0 : return reg_deletekey_recursive_trans(parent, path, false);
1062 : }
1063 :
|