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 311598 : static WERROR fill_value_cache(struct registry_key *key)
84 : {
85 70 : WERROR werr;
86 :
87 311598 : if (key->values != NULL) {
88 259032 : if (!reg_values_need_update(key->key, key->values)) {
89 258407 : return WERR_OK;
90 : }
91 : }
92 :
93 53191 : TALLOC_FREE(key->values);
94 53191 : werr = regval_ctr_init(key, &(key->values));
95 53191 : W_ERROR_NOT_OK_RETURN(werr);
96 :
97 53191 : 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 53191 : return WERR_OK;
103 : }
104 :
105 3630623 : static WERROR fill_subkey_cache(struct registry_key *key)
106 : {
107 263 : WERROR werr;
108 :
109 3630623 : if (key->subkeys != NULL) {
110 311764 : if (!reg_subkeys_need_update(key->key, key->subkeys)) {
111 311663 : return WERR_OK;
112 : }
113 : }
114 :
115 3318960 : TALLOC_FREE(key->subkeys);
116 3318960 : werr = regsubkey_ctr_init(key, &(key->subkeys));
117 3318960 : W_ERROR_NOT_OK_RETURN(werr);
118 :
119 3318960 : if (fetch_reg_keys(key->key, key->subkeys) == -1) {
120 2921015 : TALLOC_FREE(key->subkeys);
121 2921015 : return WERR_FILE_NOT_FOUND;
122 : }
123 :
124 397945 : return WERR_OK;
125 : }
126 :
127 3318413 : static int regkey_destructor(struct registry_key_handle *key)
128 : {
129 3318413 : return regdb_close();
130 : }
131 :
132 3318859 : 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 220 : WERROR result;
140 220 : struct registry_key *regkey;
141 220 : struct registry_key_handle *key;
142 :
143 3318859 : DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name));
144 :
145 3318859 : SMB_ASSERT(strchr(name, '\\') == NULL);
146 :
147 3318859 : if (!(regkey = talloc_zero(mem_ctx, struct registry_key)) ||
148 3318859 : !(regkey->token = security_token_duplicate(regkey, token)) ||
149 3318859 : !(regkey->key = talloc_zero(regkey, struct registry_key_handle)))
150 : {
151 0 : result = WERR_NOT_ENOUGH_MEMORY;
152 0 : goto done;
153 : }
154 :
155 3318859 : result = regdb_open();
156 3318859 : if (!(W_ERROR_IS_OK(result))) {
157 0 : goto done;
158 : }
159 :
160 3318859 : key = regkey->key;
161 3318859 : talloc_set_destructor(key, regkey_destructor);
162 :
163 : /* initialization */
164 :
165 3318859 : key->type = REG_KEY_GENERIC;
166 :
167 3318859 : if (name[0] == '\0') {
168 : /*
169 : * Open a copy of the parent key
170 : */
171 58 : if (!parent) {
172 0 : result = WERR_FILE_NOT_FOUND;
173 0 : goto done;
174 : }
175 58 : key->name = talloc_strdup(key, parent->key->name);
176 : }
177 : else {
178 : /*
179 : * Normal subkey open
180 : */
181 6591657 : key->name = talloc_asprintf(key, "%s%s%s",
182 3272833 : parent ? parent->key->name : "",
183 : parent ? "\\": "",
184 : name);
185 : }
186 :
187 3318859 : 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 3318859 : 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 3318859 : key->ops = reghook_cache_find( key->name );
200 3318859 : 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 3318859 : result = fill_subkey_cache(regkey);
210 3318859 : if (!W_ERROR_IS_OK(result)) {
211 2921015 : goto done;
212 : }
213 :
214 397844 : 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 397844 : *pregkey = regkey;
221 397844 : result = WERR_OK;
222 :
223 3318859 : done:
224 3318859 : if ( !W_ERROR_IS_OK(result) ) {
225 2921015 : TALLOC_FREE(regkey);
226 : }
227 :
228 3318859 : return result;
229 : }
230 :
231 45970 : 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 23 : const struct hive_info *hi;
237 45970 : SMB_ASSERT(hive != NULL);
238 45970 : SMB_ASSERT(strchr(hive, '\\') == NULL);
239 :
240 45970 : hi = hive_info(hive);
241 45970 : if (hi == NULL) {
242 2 : return WERR_FILE_NOT_FOUND;
243 : }
244 :
245 45968 : 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 3012086 : 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 3012086 : struct registry_key *direct_parent = parent;
259 162 : WERROR err;
260 162 : char *p, *path;
261 162 : size_t len;
262 3012086 : TALLOC_CTX *frame = talloc_stackframe();
263 :
264 3012086 : path = talloc_strdup(frame, name);
265 3012086 : if (path == NULL) {
266 0 : err = WERR_NOT_ENOUGH_MEMORY;
267 0 : goto error;
268 : }
269 :
270 3012086 : len = strlen(path);
271 :
272 3012086 : if ((len > 0) && (path[len-1] == '\\')) {
273 0 : path[len-1] = '\0';
274 : }
275 :
276 3272891 : while ((p = strchr(path, '\\')) != NULL) {
277 35 : char *name_component;
278 35 : struct registry_key *tmp;
279 :
280 262645 : name_component = talloc_strndup(frame, path, (p - path));
281 262645 : if (name_component == NULL) {
282 0 : err = WERR_NOT_ENOUGH_MEMORY;
283 0 : goto error;
284 : }
285 :
286 262680 : err = regkey_open_onelevel(frame, direct_parent,
287 262645 : name_component, parent->token,
288 : KEY_ENUMERATE_SUB_KEYS, &tmp);
289 :
290 262645 : if (!W_ERROR_IS_OK(err)) {
291 1840 : goto error;
292 : }
293 :
294 260805 : direct_parent = tmp;
295 260805 : path = p+1;
296 : }
297 :
298 3010246 : err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token,
299 : desired_access, pkey);
300 :
301 3012086 : error:
302 3012086 : talloc_free(frame);
303 3012086 : return err;
304 : }
305 :
306 289763 : WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
307 : uint32_t idx, char **name, NTTIME *last_write_time)
308 : {
309 21 : WERROR err;
310 :
311 289763 : if (!(key->key->access_granted & KEY_ENUMERATE_SUB_KEYS)) {
312 0 : return WERR_ACCESS_DENIED;
313 : }
314 :
315 289763 : err = fill_subkey_cache(key);
316 289763 : if (!W_ERROR_IS_OK(err)) {
317 0 : return err;
318 : }
319 :
320 289763 : if (idx >= regsubkey_ctr_numkeys(key->subkeys)) {
321 1114 : return WERR_NO_MORE_ITEMS;
322 : }
323 :
324 288649 : if (!(*name = talloc_strdup(mem_ctx,
325 288649 : regsubkey_ctr_specific_key(key->subkeys, idx))))
326 : {
327 0 : return WERR_NOT_ENOUGH_MEMORY;
328 : }
329 :
330 288649 : if (last_write_time) {
331 66953 : *last_write_time = 0;
332 : }
333 :
334 288649 : return WERR_OK;
335 : }
336 :
337 216823 : WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
338 : uint32_t idx, char **pname, struct registry_value **pval)
339 : {
340 29 : struct registry_value *val;
341 29 : struct regval_blob *blob;
342 29 : WERROR err;
343 :
344 216823 : if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
345 0 : return WERR_ACCESS_DENIED;
346 : }
347 :
348 216823 : err = fill_value_cache(key);
349 216823 : if (!(W_ERROR_IS_OK(err))) {
350 0 : return err;
351 : }
352 :
353 216823 : if (idx >= regval_ctr_numvals(key->values)) {
354 5474 : return WERR_NO_MORE_ITEMS;
355 : }
356 :
357 211349 : blob = regval_ctr_specific_value(key->values, idx);
358 :
359 211349 : val = talloc_zero(mem_ctx, struct registry_value);
360 211349 : if (val == NULL) {
361 0 : return WERR_NOT_ENOUGH_MEMORY;
362 : }
363 :
364 211349 : val->type = regval_type(blob);
365 211349 : val->data = data_blob_talloc(mem_ctx, regval_data_p(blob), regval_size(blob));
366 :
367 211349 : if (pname
368 211189 : && !(*pname = talloc_strdup(
369 211189 : mem_ctx, regval_name(blob)))) {
370 0 : TALLOC_FREE(val);
371 0 : return WERR_NOT_ENOUGH_MEMORY;
372 : }
373 :
374 211349 : *pval = val;
375 211349 : return WERR_OK;
376 : }
377 :
378 38194 : 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 3 : struct registry_value *val;
384 3 : struct regval_blob *blob;
385 :
386 38194 : if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
387 0 : return WERR_ACCESS_DENIED;
388 : }
389 :
390 38194 : if (idx >= regval_ctr_numvals(key->values)) {
391 0 : return WERR_NO_MORE_ITEMS;
392 : }
393 :
394 38194 : blob = regval_ctr_specific_value(key->values, idx);
395 :
396 38194 : val = talloc_zero(mem_ctx, struct registry_value);
397 38194 : if (val == NULL) {
398 0 : return WERR_NOT_ENOUGH_MEMORY;
399 : }
400 :
401 38194 : val->type = regval_type(blob);
402 38194 : val->data = data_blob_talloc(mem_ctx, regval_data_p(blob), regval_size(blob));
403 :
404 38194 : 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 38194 : *pval = val;
412 38194 : return WERR_OK;
413 : }
414 :
415 50660 : WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key,
416 : const char *name, struct registry_value **pval)
417 : {
418 17 : WERROR err;
419 17 : uint32_t i;
420 :
421 50660 : if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
422 0 : return WERR_ACCESS_DENIED;
423 : }
424 :
425 50660 : if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
426 0 : return err;
427 : }
428 :
429 600273 : for (i=0; i < regval_ctr_numvals(key->values); i++) {
430 36 : struct regval_blob *blob;
431 587807 : blob = regval_ctr_specific_value(key->values, i);
432 587807 : 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 38194 : return reg_enumvalue_nocachefill(mem_ctx, key, i,
440 : NULL, pval);
441 : }
442 : }
443 :
444 12466 : return WERR_FILE_NOT_FOUND;
445 : }
446 :
447 176 : 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 0 : WERROR err;
455 176 : uint32_t i, n, found = 0;
456 0 : struct registry_value *vals;
457 :
458 176 : if (num_names == 0) {
459 72 : return WERR_OK;
460 : }
461 :
462 104 : if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
463 0 : return WERR_ACCESS_DENIED;
464 : }
465 :
466 104 : if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) {
467 0 : return err;
468 : }
469 :
470 104 : vals = talloc_zero_array(mem_ctx, struct registry_value, num_names);
471 104 : if (vals == NULL) {
472 0 : return WERR_NOT_ENOUGH_MEMORY;
473 : }
474 :
475 304 : for (n=0; n < num_names; n++) {
476 600 : for (i=0; i < regval_ctr_numvals(key->values); i++) {
477 0 : struct regval_blob *blob;
478 400 : blob = regval_ctr_specific_value(key->values, i);
479 400 : if (strequal(regval_name(blob), names[n])) {
480 0 : struct registry_value *v;
481 160 : err = reg_enumvalue(mem_ctx, key, i, NULL, &v);
482 160 : if (!W_ERROR_IS_OK(err)) {
483 0 : return err;
484 : }
485 160 : vals[n] = *v;
486 160 : found++;
487 : }
488 : }
489 : }
490 :
491 104 : *pvals = vals;
492 104 : *pnum_vals = found;
493 :
494 104 : return WERR_OK;
495 : }
496 :
497 20362 : 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 0 : uint32_t i, max_size;
504 0 : size_t max_len;
505 0 : TALLOC_CTX *mem_ctx;
506 0 : WERROR err;
507 0 : struct security_descriptor *secdesc;
508 :
509 20362 : if (!(key->key->access_granted & KEY_QUERY_VALUE)) {
510 0 : return WERR_ACCESS_DENIED;
511 : }
512 :
513 20362 : if (!W_ERROR_IS_OK(fill_subkey_cache(key)) ||
514 20362 : !W_ERROR_IS_OK(fill_value_cache(key))) {
515 0 : return WERR_FILE_NOT_FOUND;
516 : }
517 :
518 20362 : max_len = 0;
519 113259 : for (i=0; i< regsubkey_ctr_numkeys(key->subkeys); i++) {
520 92897 : max_len = MAX(max_len,
521 : strlen(regsubkey_ctr_specific_key(key->subkeys, i)));
522 : }
523 :
524 20362 : *num_subkeys = regsubkey_ctr_numkeys(key->subkeys);
525 20362 : *max_subkeylen = max_len;
526 20362 : *max_subkeysize = 0; /* Class length? */
527 :
528 20362 : max_len = 0;
529 20362 : max_size = 0;
530 231948 : for (i=0; i < regval_ctr_numvals(key->values); i++) {
531 0 : struct regval_blob *blob;
532 211586 : blob = regval_ctr_specific_value(key->values, i);
533 211586 : max_len = MAX(max_len, strlen(regval_name(blob)));
534 211586 : max_size = MAX(max_size, regval_size(blob));
535 : }
536 :
537 20362 : *num_values = regval_ctr_numvals(key->values);
538 20362 : *max_valnamelen = max_len;
539 20362 : *max_valbufsize = max_size;
540 :
541 20362 : if (!(mem_ctx = talloc_new(key))) {
542 0 : return WERR_NOT_ENOUGH_MEMORY;
543 : }
544 :
545 20362 : err = regkey_get_secdesc(mem_ctx, key->key, &secdesc);
546 20362 : if (!W_ERROR_IS_OK(err)) {
547 0 : TALLOC_FREE(mem_ctx);
548 0 : return err;
549 : }
550 :
551 20362 : *secdescsize = ndr_size_security_descriptor(secdesc, 0);
552 20362 : TALLOC_FREE(mem_ctx);
553 :
554 20362 : *last_changed_time = 0;
555 :
556 20362 : return WERR_OK;
557 : }
558 :
559 37534 : 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 37534 : struct registry_key *key = parent;
565 25 : TALLOC_CTX *mem_ctx;
566 25 : char *path, *end;
567 25 : WERROR err;
568 25 : uint32_t access_granted;
569 :
570 37534 : mem_ctx = talloc_new(ctx);
571 37534 : if (mem_ctx == NULL) {
572 0 : return WERR_NOT_ENOUGH_MEMORY;
573 : }
574 :
575 37534 : path = talloc_strdup(mem_ctx, subkeypath);
576 37534 : if (path == NULL) {
577 0 : err = WERR_NOT_ENOUGH_MEMORY;
578 0 : goto done;
579 : }
580 :
581 37534 : err = regdb_transaction_start();
582 37534 : 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 67847 : while ((end = strchr(path, '\\')) != NULL) {
589 0 : struct registry_key *tmp;
590 0 : enum winreg_CreateAction action;
591 :
592 30313 : *end = '\0';
593 :
594 30313 : err = reg_createkey(mem_ctx, key, path,
595 : KEY_ENUMERATE_SUB_KEYS, &tmp, &action);
596 30313 : if (!W_ERROR_IS_OK(err)) {
597 0 : goto trans_done;
598 : }
599 :
600 30313 : if (key != parent) {
601 24323 : TALLOC_FREE(key);
602 : }
603 :
604 30313 : key = tmp;
605 30313 : 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 37534 : err = reg_openkey(ctx, key, path, desired_access, pkey);
614 37534 : if (W_ERROR_IS_OK(err)) {
615 35007 : if (paction != NULL) {
616 35007 : *paction = REG_OPENED_EXISTING_KEY;
617 : }
618 35007 : goto trans_done;
619 : }
620 :
621 2527 : 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 2527 : if (!regkey_access_check(key->key, KEY_CREATE_SUB_KEY, &access_granted,
634 2527 : 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 2527 : err = create_reg_subkey(key->key, path);
645 2527 : if (!W_ERROR_IS_OK(err)) {
646 0 : goto trans_done;
647 : }
648 :
649 : /*
650 : * Now open the newly created key
651 : */
652 :
653 2527 : err = reg_openkey(ctx, key, path, desired_access, pkey);
654 2527 : if (W_ERROR_IS_OK(err) && (paction != NULL)) {
655 2527 : *paction = REG_CREATED_NEW_KEY;
656 : }
657 :
658 0 : trans_done:
659 37534 : if (W_ERROR_IS_OK(err)) {
660 37534 : err = regdb_transaction_commit();
661 37534 : 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 37534 : done:
672 37534 : TALLOC_FREE(mem_ctx);
673 37534 : return err;
674 : }
675 :
676 1594 : static WERROR reg_deletekey_internal(TALLOC_CTX *mem_ctx,
677 : struct registry_key *parent,
678 : const char *path, bool lazy)
679 : {
680 11 : WERROR err;
681 11 : char *name, *end;
682 11 : struct registry_key *key;
683 1594 : name = talloc_strdup(mem_ctx, path);
684 1594 : if (name == NULL) {
685 0 : err = WERR_NOT_ENOUGH_MEMORY;
686 0 : goto done;
687 : }
688 :
689 : /* no subkeys - proceed with delete */
690 1594 : end = strrchr(name, '\\');
691 1594 : if (end != NULL) {
692 1056 : *end = '\0';
693 :
694 1056 : err = reg_openkey(mem_ctx, parent, name,
695 : KEY_CREATE_SUB_KEY, &key);
696 1056 : W_ERROR_NOT_OK_GOTO_DONE(err);
697 :
698 1056 : parent = key;
699 1056 : name = end+1;
700 : }
701 :
702 1594 : if (name[0] == '\0') {
703 0 : err = WERR_INVALID_PARAMETER;
704 0 : goto done;
705 : }
706 :
707 1594 : err = delete_reg_subkey(parent->key, name, lazy);
708 :
709 1594 : done:
710 1594 : return err;
711 : }
712 :
713 1212 : WERROR reg_deletekey(struct registry_key *parent, const char *path)
714 : {
715 0 : WERROR err;
716 0 : struct registry_key *key;
717 1212 : TALLOC_CTX *mem_ctx = talloc_stackframe();
718 :
719 : /* check if the key has subkeys */
720 1212 : err = reg_openkey(mem_ctx, parent, path, REG_KEY_READ, &key);
721 1212 : W_ERROR_NOT_OK_GOTO_DONE(err);
722 :
723 1138 : err = regdb_transaction_start();
724 1138 : 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 1138 : err = fill_subkey_cache(key);
731 1138 : if (!W_ERROR_IS_OK(err)) {
732 0 : goto trans_done;
733 : }
734 :
735 1138 : if (regsubkey_ctr_numkeys(key->subkeys) > 0) {
736 4 : err = WERR_ACCESS_DENIED;
737 4 : goto trans_done;
738 : }
739 1134 : err = reg_deletekey_internal(mem_ctx, parent, path, false);
740 :
741 1138 : trans_done:
742 1138 : if (W_ERROR_IS_OK(err)) {
743 1134 : err = regdb_transaction_commit();
744 1134 : if (!W_ERROR_IS_OK(err)) {
745 0 : DEBUG(0, ("reg_deletekey: Error committing transaction: %s\n", win_errstr(err)));
746 : }
747 : } else {
748 4 : WERROR err1 = regdb_transaction_cancel();
749 4 : if (!W_ERROR_IS_OK(err1)) {
750 0 : DEBUG(0, ("reg_deletekey: Error cancelling transaction: %s\n", win_errstr(err1)));
751 : }
752 : }
753 :
754 1212 : done:
755 1212 : TALLOC_FREE(mem_ctx);
756 1212 : return err;
757 : }
758 :
759 :
760 20472 : WERROR reg_setvalue(struct registry_key *key, const char *name,
761 : const struct registry_value *val)
762 : {
763 21 : struct regval_blob *existing;
764 21 : WERROR err;
765 21 : int res;
766 :
767 20472 : if (!(key->key->access_granted & KEY_SET_VALUE)) {
768 0 : return WERR_ACCESS_DENIED;
769 : }
770 :
771 20472 : err = regdb_transaction_start();
772 20472 : 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 20472 : err = fill_value_cache(key);
779 20472 : 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 20472 : existing = regval_ctr_getvalue(key->values, name);
785 :
786 20472 : if ((existing != NULL) &&
787 7899 : (regval_size(existing) == val->data.length) &&
788 7633 : (memcmp(regval_data_p(existing), val->data.data,
789 7633 : val->data.length) == 0))
790 : {
791 3841 : err = WERR_OK;
792 3841 : goto done;
793 : }
794 :
795 16652 : res = regval_ctr_addvalue(key->values, name, val->type,
796 16631 : val->data.data, val->data.length);
797 :
798 16631 : if (res == 0) {
799 0 : TALLOC_FREE(key->values);
800 0 : err = WERR_NOT_ENOUGH_MEMORY;
801 0 : goto done;
802 : }
803 :
804 16631 : if (!store_reg_values(key->key, key->values)) {
805 2 : TALLOC_FREE(key->values);
806 2 : DEBUG(0, ("reg_setvalue: store_reg_values failed\n"));
807 2 : err = WERR_REGISTRY_IO_FAILED;
808 2 : goto done;
809 : }
810 :
811 16608 : err = WERR_OK;
812 :
813 20472 : done:
814 20472 : if (W_ERROR_IS_OK(err)) {
815 20470 : err = regdb_transaction_commit();
816 20470 : if (!W_ERROR_IS_OK(err)) {
817 0 : DEBUG(0, ("reg_setvalue: Error committing transaction: %s\n", win_errstr(err)));
818 : }
819 : } else {
820 2 : WERROR err1 = regdb_transaction_cancel();
821 2 : if (!W_ERROR_IS_OK(err1)) {
822 0 : DEBUG(0, ("reg_setvalue: Error cancelling transaction: %s\n", win_errstr(err1)));
823 : }
824 : }
825 :
826 20472 : return err;
827 : }
828 :
829 3177 : static WERROR reg_value_exists(struct registry_key *key, const char *name)
830 : {
831 3 : struct regval_blob *blob;
832 :
833 3180 : blob = regval_ctr_getvalue(key->values, name);
834 :
835 3177 : if (blob == NULL) {
836 166 : return WERR_FILE_NOT_FOUND;
837 : } else {
838 3011 : return WERR_OK;
839 : }
840 : }
841 :
842 3177 : WERROR reg_deletevalue(struct registry_key *key, const char *name)
843 : {
844 3 : WERROR err;
845 :
846 3177 : if (!(key->key->access_granted & KEY_SET_VALUE)) {
847 0 : return WERR_ACCESS_DENIED;
848 : }
849 :
850 3177 : err = regdb_transaction_start();
851 3177 : 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 3177 : err = fill_value_cache(key);
858 3177 : 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 3177 : err = reg_value_exists(key, name);
865 3177 : if (!W_ERROR_IS_OK(err)) {
866 166 : goto done;
867 : }
868 :
869 3011 : regval_ctr_delvalue(key->values, name);
870 :
871 3011 : 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 3008 : err = WERR_OK;
879 :
880 3177 : done:
881 3177 : if (W_ERROR_IS_OK(err)) {
882 3011 : err = regdb_transaction_commit();
883 3011 : if (!W_ERROR_IS_OK(err)) {
884 0 : DEBUG(0, ("reg_deletevalue: Error committing transaction: %s\n", win_errstr(err)));
885 : }
886 : } else {
887 166 : WERROR err1 = regdb_transaction_cancel();
888 166 : if (!W_ERROR_IS_OK(err1)) {
889 0 : DEBUG(0, ("reg_deletevalue: Error cancelling transaction: %s\n", win_errstr(err1)));
890 : }
891 : }
892 :
893 3177 : return err;
894 : }
895 :
896 2 : WERROR reg_getkeysecurity(TALLOC_CTX *mem_ctx, struct registry_key *key,
897 : struct security_descriptor **psecdesc)
898 : {
899 2 : 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 28 : WERROR reg_getversion(uint32_t *version)
909 : {
910 28 : if (version == NULL) {
911 0 : return WERR_INVALID_PARAMETER;
912 : }
913 :
914 28 : *version = 0x00000005; /* Windows 2000 registry API version */
915 28 : return WERR_OK;
916 : }
917 :
918 : /**********************************************************************
919 : * Higher level utility functions
920 : **********************************************************************/
921 :
922 0 : WERROR reg_deleteallvalues(struct registry_key *key)
923 : {
924 0 : WERROR err;
925 0 : 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 0 : 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 501 : static WERROR reg_deletekey_recursive_internal(struct registry_key *parent,
955 : const char *path,
956 : bool del_key, bool lazy)
957 : {
958 22 : WERROR werr;
959 22 : struct registry_key *key;
960 501 : char *subkey_name = NULL;
961 22 : uint32_t i;
962 501 : TALLOC_CTX *mem_ctx = talloc_stackframe();
963 :
964 501 : DEBUG(5, ("reg_deletekey_recursive_internal: deleting '%s' from '%s'\n",
965 : path, parent->key->name));
966 :
967 : /* recurse through subkeys first */
968 501 : werr = reg_openkey(mem_ctx, parent, path, REG_KEY_ALL, &key);
969 501 : 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 501 : werr = fill_subkey_cache(key);
977 501 : 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 943 : for (i = regsubkey_ctr_numkeys(key->subkeys) ; i > 0; i--) {
984 442 : subkey_name = regsubkey_ctr_specific_key(key->subkeys, i-1);
985 442 : werr = reg_deletekey_recursive_internal(key, subkey_name, true, del_key);
986 442 : W_ERROR_NOT_OK_GOTO_DONE(werr);
987 : }
988 :
989 501 : if (del_key) {
990 : /* now delete the actual key */
991 460 : werr = reg_deletekey_internal(mem_ctx, parent, path, lazy);
992 : }
993 :
994 41 : done:
995 :
996 501 : DEBUG(5, ("reg_deletekey_recursive_internal: done deleting '%s' from "
997 : "'%s': %s\n",
998 : path, parent->key->name, win_errstr(werr)));
999 501 : TALLOC_FREE(mem_ctx);
1000 501 : return werr;
1001 : }
1002 :
1003 59 : static WERROR reg_deletekey_recursive_trans(struct registry_key *parent,
1004 : const char *path,
1005 : bool del_key)
1006 : {
1007 12 : WERROR werr;
1008 :
1009 59 : werr = regdb_transaction_start();
1010 59 : 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 59 : werr = reg_deletekey_recursive_internal(parent, path, del_key, false);
1018 :
1019 59 : if (!W_ERROR_IS_OK(werr)) {
1020 0 : 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 59 : werr = regdb_transaction_commit();
1038 59 : 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 59 : DEBUG(5, ("reg_deletekey_recursive_trans: deleted key '%s' from '%s'\n",
1044 : path, parent->key->name));
1045 :
1046 : }
1047 : }
1048 :
1049 59 : return werr;
1050 : }
1051 :
1052 18 : WERROR reg_deletekey_recursive(struct registry_key *parent,
1053 : const char *path)
1054 : {
1055 18 : return reg_deletekey_recursive_trans(parent, path, true);
1056 : }
1057 :
1058 41 : WERROR reg_deletesubkeys_recursive(struct registry_key *parent,
1059 : const char *path)
1060 : {
1061 41 : return reg_deletekey_recursive_trans(parent, path, false);
1062 : }
1063 :
|