1/* 2 * Unix SMB/CIFS implementation. 3 * Virtual Windows Registry Layer 4 * Copyright (C) Volker Lendecke 2006 5 * Copyright (C) Michael Adam 2007-2008 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 57 * 0x1e winreg_InitiateSystemShutdownEx 58 * 0x1f winreg_SaveKeyEx 59 * 0x20 winreg_OpenHKPT 60 * 0x21 winreg_OpenHKPN 61 * 0x22 winreg_QueryMultipleValues2 62 * 63 */ 64 65#include "includes.h" 66#include "regfio.h" 67 68#undef DBGC_CLASS 69#define DBGC_CLASS DBGC_REGISTRY 70 71 72/********************************************************************** 73 * Helper functions 74 **********************************************************************/ 75 76static WERROR fill_value_cache(struct registry_key *key) 77{ 78 if (key->values != NULL) { 79 if (!reg_values_need_update(key->key, key->values)) { 80 return WERR_OK; 81 } 82 } 83 84 if (!(key->values = TALLOC_ZERO_P(key, struct regval_ctr))) { 85 return WERR_NOMEM; 86 } 87 if (fetch_reg_values(key->key, key->values) == -1) { 88 TALLOC_FREE(key->values); 89 return WERR_BADFILE; 90 } 91 92 return WERR_OK; 93} 94 95static WERROR fill_subkey_cache(struct registry_key *key) 96{ 97 WERROR werr; 98 99 if (key->subkeys != NULL) { 100 if (!reg_subkeys_need_update(key->key, key->subkeys)) { 101 return WERR_OK; 102 } 103 } 104 105 werr = regsubkey_ctr_init(key, &(key->subkeys)); 106 W_ERROR_NOT_OK_RETURN(werr); 107 108 if (fetch_reg_keys(key->key, key->subkeys) == -1) { 109 TALLOC_FREE(key->subkeys); 110 return WERR_NO_MORE_ITEMS; 111 } 112 113 return WERR_OK; 114} 115 116static int regkey_destructor(struct registry_key_handle *key) 117{ 118 return regdb_close(); 119} 120 121static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx, 122 struct registry_key *parent, 123 const char *name, 124 const struct nt_user_token *token, 125 uint32 access_desired, 126 struct registry_key **pregkey) 127{ 128 WERROR result = WERR_OK; 129 struct registry_key *regkey; 130 struct registry_key_handle *key; 131 struct regsubkey_ctr *subkeys = NULL; 132 133 DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name)); 134 135 SMB_ASSERT(strchr(name, '\\') == NULL); 136 137 if (!(regkey = TALLOC_ZERO_P(mem_ctx, struct registry_key)) || 138 !(regkey->token = dup_nt_token(regkey, token)) || 139 !(regkey->key = TALLOC_ZERO_P(regkey, struct registry_key_handle))) 140 { 141 result = WERR_NOMEM; 142 goto done; 143 } 144 145 if ( !(W_ERROR_IS_OK(result = regdb_open())) ) { 146 goto done; 147 } 148 149 key = regkey->key; 150 talloc_set_destructor(key, regkey_destructor); 151 152 /* initialization */ 153 154 key->type = REG_KEY_GENERIC; 155 156 if (name[0] == '\0') { 157 /* 158 * Open a copy of the parent key 159 */ 160 if (!parent) { 161 result = WERR_BADFILE; 162 goto done; 163 } 164 key->name = talloc_strdup(key, parent->key->name); 165 } 166 else { 167 /* 168 * Normal subkey open 169 */ 170 key->name = talloc_asprintf(key, "%s%s%s", 171 parent ? parent->key->name : "", 172 parent ? "\\": "", 173 name); 174 } 175 176 if (key->name == NULL) { 177 result = WERR_NOMEM; 178 goto done; 179 } 180 181 /* Tag this as a Performance Counter Key */ 182 183 if( StrnCaseCmp(key->name, KEY_HKPD, strlen(KEY_HKPD)) == 0 ) 184 key->type = REG_KEY_HKPD; 185 186 /* Look up the table of registry I/O operations */ 187 188 if ( !(key->ops = reghook_cache_find( key->name )) ) { 189 DEBUG(0,("reg_open_onelevel: Failed to assign " 190 "registry_ops to [%s]\n", key->name )); 191 result = WERR_BADFILE; 192 goto done; 193 } 194 195 /* check if the path really exists; failed is indicated by -1 */ 196 /* if the subkey count failed, bail out */ 197 198 result = regsubkey_ctr_init(key, &subkeys); 199 if (!W_ERROR_IS_OK(result)) { 200 goto done; 201 } 202 203 if ( fetch_reg_keys( key, subkeys ) == -1 ) { 204 result = WERR_BADFILE; 205 goto done; 206 } 207 208 TALLOC_FREE( subkeys ); 209 210 if ( !regkey_access_check( key, access_desired, &key->access_granted, 211 token ) ) { 212 result = WERR_ACCESS_DENIED; 213 goto done; 214 } 215 216 *pregkey = regkey; 217 result = WERR_OK; 218 219done: 220 if ( !W_ERROR_IS_OK(result) ) { 221 TALLOC_FREE(regkey); 222 } 223 224 return result; 225} 226 227WERROR reg_openhive(TALLOC_CTX *mem_ctx, const char *hive, 228 uint32 desired_access, 229 const struct nt_user_token *token, 230 struct registry_key **pkey) 231{ 232 SMB_ASSERT(hive != NULL); 233 SMB_ASSERT(hive[0] != '\0'); 234 SMB_ASSERT(strchr(hive, '\\') == NULL); 235 236 return regkey_open_onelevel(mem_ctx, NULL, hive, token, desired_access, 237 pkey); 238} 239 240 241/********************************************************************** 242 * The API functions 243 **********************************************************************/ 244 245WERROR reg_openkey(TALLOC_CTX *mem_ctx, struct registry_key *parent, 246 const char *name, uint32 desired_access, 247 struct registry_key **pkey) 248{ 249 struct registry_key *direct_parent = parent; 250 WERROR err; 251 char *p, *path, *to_free; 252 size_t len; 253 254 if (!(path = SMB_STRDUP(name))) { 255 return WERR_NOMEM; 256 } 257 to_free = path; 258 259 len = strlen(path); 260 261 if ((len > 0) && (path[len-1] == '\\')) { 262 path[len-1] = '\0'; 263 } 264 265 while ((p = strchr(path, '\\')) != NULL) { 266 char *name_component; 267 struct registry_key *tmp; 268 269 if (!(name_component = SMB_STRNDUP(path, (p - path)))) { 270 err = WERR_NOMEM; 271 goto error; 272 } 273 274 err = regkey_open_onelevel(mem_ctx, direct_parent, 275 name_component, parent->token, 276 KEY_ENUMERATE_SUB_KEYS, &tmp); 277 SAFE_FREE(name_component); 278 279 if (!W_ERROR_IS_OK(err)) { 280 goto error; 281 } 282 if (direct_parent != parent) { 283 TALLOC_FREE(direct_parent); 284 } 285 286 direct_parent = tmp; 287 path = p+1; 288 } 289 290 err = regkey_open_onelevel(mem_ctx, direct_parent, path, parent->token, 291 desired_access, pkey); 292 error: 293 if (direct_parent != parent) { 294 TALLOC_FREE(direct_parent); 295 } 296 SAFE_FREE(to_free); 297 return err; 298} 299 300WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key, 301 uint32 idx, char **name, NTTIME *last_write_time) 302{ 303 WERROR err; 304 305 if (!(key->key->access_granted & KEY_ENUMERATE_SUB_KEYS)) { 306 return WERR_ACCESS_DENIED; 307 } 308 309 if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) { 310 return err; 311 } 312 313 if (idx >= regsubkey_ctr_numkeys(key->subkeys)) { 314 return WERR_NO_MORE_ITEMS; 315 } 316 317 if (!(*name = talloc_strdup(mem_ctx, 318 regsubkey_ctr_specific_key(key->subkeys, idx)))) 319 { 320 return WERR_NOMEM; 321 } 322 323 if (last_write_time) { 324 *last_write_time = 0; 325 } 326 327 return WERR_OK; 328} 329 330WERROR reg_enumvalue(TALLOC_CTX *mem_ctx, struct registry_key *key, 331 uint32 idx, char **pname, struct registry_value **pval) 332{ 333 struct registry_value *val; 334 WERROR err; 335 336 if (!(key->key->access_granted & KEY_QUERY_VALUE)) { 337 return WERR_ACCESS_DENIED; 338 } 339 340 if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) { 341 return err; 342 } 343 344 if (idx >= key->values->num_values) { 345 return WERR_NO_MORE_ITEMS; 346 } 347 348 err = registry_pull_value(mem_ctx, &val, 349 key->values->values[idx]->type, 350 key->values->values[idx]->data_p, 351 key->values->values[idx]->size, 352 key->values->values[idx]->size); 353 if (!W_ERROR_IS_OK(err)) { 354 return err; 355 } 356 357 if (pname 358 && !(*pname = talloc_strdup( 359 mem_ctx, key->values->values[idx]->valuename))) { 360 SAFE_FREE(val); 361 return WERR_NOMEM; 362 } 363 364 *pval = val; 365 return WERR_OK; 366} 367 368WERROR reg_queryvalue(TALLOC_CTX *mem_ctx, struct registry_key *key, 369 const char *name, struct registry_value **pval) 370{ 371 WERROR err; 372 uint32 i; 373 374 if (!(key->key->access_granted & KEY_QUERY_VALUE)) { 375 return WERR_ACCESS_DENIED; 376 } 377 378 if (!(W_ERROR_IS_OK(err = fill_value_cache(key)))) { 379 return err; 380 } 381 382 for (i=0; i<key->values->num_values; i++) { 383 if (strequal(key->values->values[i]->valuename, name)) { 384 return reg_enumvalue(mem_ctx, key, i, NULL, pval); 385 } 386 } 387 388 return WERR_BADFILE; 389} 390 391WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys, 392 uint32_t *max_subkeylen, uint32_t *max_subkeysize, 393 uint32_t *num_values, uint32_t *max_valnamelen, 394 uint32_t *max_valbufsize, uint32_t *secdescsize, 395 NTTIME *last_changed_time) 396{ 397 uint32 i, max_size; 398 size_t max_len; 399 TALLOC_CTX *mem_ctx; 400 WERROR err; 401 struct security_descriptor *secdesc; 402 403 if (!(key->key->access_granted & KEY_QUERY_VALUE)) { 404 return WERR_ACCESS_DENIED; 405 } 406 407 if (!W_ERROR_IS_OK(fill_subkey_cache(key)) || 408 !W_ERROR_IS_OK(fill_value_cache(key))) { 409 return WERR_BADFILE; 410 } 411 412 max_len = 0; 413 for (i=0; i< regsubkey_ctr_numkeys(key->subkeys); i++) { 414 max_len = MAX(max_len, 415 strlen(regsubkey_ctr_specific_key(key->subkeys, i))); 416 } 417 418 *num_subkeys = regsubkey_ctr_numkeys(key->subkeys); 419 *max_subkeylen = max_len; 420 *max_subkeysize = 0; /* Class length? */ 421 422 max_len = 0; 423 max_size = 0; 424 for (i=0; i<key->values->num_values; i++) { 425 max_len = MAX(max_len, 426 strlen(key->values->values[i]->valuename)); 427 max_size = MAX(max_size, key->values->values[i]->size); 428 } 429 430 *num_values = key->values->num_values; 431 *max_valnamelen = max_len; 432 *max_valbufsize = max_size; 433 434 if (!(mem_ctx = talloc_new(key))) { 435 return WERR_NOMEM; 436 } 437 438 err = regkey_get_secdesc(mem_ctx, key->key, &secdesc); 439 if (!W_ERROR_IS_OK(err)) { 440 TALLOC_FREE(mem_ctx); 441 return err; 442 } 443 444 *secdescsize = ndr_size_security_descriptor(secdesc, NULL, 0); 445 TALLOC_FREE(mem_ctx); 446 447 *last_changed_time = 0; 448 449 return WERR_OK; 450} 451 452WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent, 453 const char *subkeypath, uint32 desired_access, 454 struct registry_key **pkey, 455 enum winreg_CreateAction *paction) 456{ 457 struct registry_key *key = parent; 458 struct registry_key *create_parent; 459 TALLOC_CTX *mem_ctx; 460 char *path, *end; 461 WERROR err; 462 463 /* 464 * We must refuse to handle subkey-paths containing 465 * a '/' character because at a lower level, after 466 * normalization, '/' is treated as a key separator 467 * just like '\\'. 468 */ 469 if (strchr(subkeypath, '/') != NULL) { 470 return WERR_INVALID_PARAM; 471 } 472 473 if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM; 474 475 if (!(path = talloc_strdup(mem_ctx, subkeypath))) { 476 err = WERR_NOMEM; 477 goto done; 478 } 479 480 while ((end = strchr(path, '\\')) != NULL) { 481 struct registry_key *tmp; 482 enum winreg_CreateAction action; 483 484 *end = '\0'; 485 486 err = reg_createkey(mem_ctx, key, path, 487 KEY_ENUMERATE_SUB_KEYS, &tmp, &action); 488 if (!W_ERROR_IS_OK(err)) { 489 goto done; 490 } 491 492 if (key != parent) { 493 TALLOC_FREE(key); 494 } 495 496 key = tmp; 497 path = end+1; 498 } 499 500 /* 501 * At this point, "path" contains the one-element subkey of "key". We 502 * can try to open it. 503 */ 504 505 err = reg_openkey(ctx, key, path, desired_access, pkey); 506 if (W_ERROR_IS_OK(err)) { 507 if (paction != NULL) { 508 *paction = REG_OPENED_EXISTING_KEY; 509 } 510 goto done; 511 } 512 513 if (!W_ERROR_EQUAL(err, WERR_BADFILE)) { 514 /* 515 * Something but "notfound" has happened, so bail out 516 */ 517 goto done; 518 } 519 520 /* 521 * We have to make a copy of the current key, as we opened it only 522 * with ENUM_SUBKEY access. 523 */ 524 525 err = reg_openkey(mem_ctx, key, "", KEY_CREATE_SUB_KEY, 526 &create_parent); 527 if (!W_ERROR_IS_OK(err)) { 528 goto done; 529 } 530 531 /* 532 * Actually create the subkey 533 */ 534 535 err = fill_subkey_cache(create_parent); 536 if (!W_ERROR_IS_OK(err)) goto done; 537 538 err = create_reg_subkey(key->key, path); 539 W_ERROR_NOT_OK_GOTO_DONE(err); 540 541 /* 542 * Now open the newly created key 543 */ 544 545 err = reg_openkey(ctx, create_parent, path, desired_access, pkey); 546 if (W_ERROR_IS_OK(err) && (paction != NULL)) { 547 *paction = REG_CREATED_NEW_KEY; 548 } 549 550 done: 551 TALLOC_FREE(mem_ctx); 552 return err; 553} 554 555WERROR reg_deletekey(struct registry_key *parent, const char *path) 556{ 557 WERROR err; 558 char *name, *end; 559 struct registry_key *tmp_key, *key; 560 TALLOC_CTX *mem_ctx = talloc_stackframe(); 561 562 name = talloc_strdup(mem_ctx, path); 563 if (name == NULL) { 564 err = WERR_NOMEM; 565 goto done; 566 } 567 568 /* check if the key has subkeys */ 569 err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &key); 570 W_ERROR_NOT_OK_GOTO_DONE(err); 571 572 err = fill_subkey_cache(key); 573 W_ERROR_NOT_OK_GOTO_DONE(err); 574 575 if (regsubkey_ctr_numkeys(key->subkeys) > 0) { 576 err = WERR_ACCESS_DENIED; 577 goto done; 578 } 579 580 /* no subkeys - proceed with delete */ 581 end = strrchr(name, '\\'); 582 if (end != NULL) { 583 *end = '\0'; 584 585 err = reg_openkey(mem_ctx, parent, name, 586 KEY_CREATE_SUB_KEY, &tmp_key); 587 W_ERROR_NOT_OK_GOTO_DONE(err); 588 589 parent = tmp_key; 590 name = end+1; 591 } 592 593 if (name[0] == '\0') { 594 err = WERR_INVALID_PARAM; 595 goto done; 596 } 597 598 err = delete_reg_subkey(parent->key, name); 599 600done: 601 TALLOC_FREE(mem_ctx); 602 return err; 603} 604 605WERROR reg_setvalue(struct registry_key *key, const char *name, 606 const struct registry_value *val) 607{ 608 WERROR err; 609 DATA_BLOB value_data; 610 int res; 611 612 if (!(key->key->access_granted & KEY_SET_VALUE)) { 613 return WERR_ACCESS_DENIED; 614 } 615 616 if (!W_ERROR_IS_OK(err = fill_value_cache(key))) { 617 return err; 618 } 619 620 err = registry_push_value(key, val, &value_data); 621 if (!W_ERROR_IS_OK(err)) { 622 return err; 623 } 624 625 res = regval_ctr_addvalue(key->values, name, val->type, 626 (char *)value_data.data, value_data.length); 627 TALLOC_FREE(value_data.data); 628 629 if (res == 0) { 630 TALLOC_FREE(key->values); 631 return WERR_NOMEM; 632 } 633 634 if (!store_reg_values(key->key, key->values)) { 635 TALLOC_FREE(key->values); 636 return WERR_REG_IO_FAILURE; 637 } 638 639 return WERR_OK; 640} 641 642static WERROR reg_value_exists(struct registry_key *key, const char *name) 643{ 644 int i; 645 646 for (i=0; i<key->values->num_values; i++) { 647 if (strequal(key->values->values[i]->valuename, name)) { 648 return WERR_OK; 649 } 650 } 651 652 return WERR_BADFILE; 653} 654 655WERROR reg_deletevalue(struct registry_key *key, const char *name) 656{ 657 WERROR err; 658 659 if (!(key->key->access_granted & KEY_SET_VALUE)) { 660 return WERR_ACCESS_DENIED; 661 } 662 663 if (!W_ERROR_IS_OK(err = fill_value_cache(key))) { 664 return err; 665 } 666 667 err = reg_value_exists(key, name); 668 if (!W_ERROR_IS_OK(err)) { 669 return err; 670 } 671 672 regval_ctr_delvalue(key->values, name); 673 674 if (!store_reg_values(key->key, key->values)) { 675 TALLOC_FREE(key->values); 676 return WERR_REG_IO_FAILURE; 677 } 678 679 return WERR_OK; 680} 681 682WERROR reg_getkeysecurity(TALLOC_CTX *mem_ctx, struct registry_key *key, 683 struct security_descriptor **psecdesc) 684{ 685 return regkey_get_secdesc(mem_ctx, key->key, psecdesc); 686} 687 688WERROR reg_setkeysecurity(struct registry_key *key, 689 struct security_descriptor *psecdesc) 690{ 691 return regkey_set_secdesc(key->key, psecdesc); 692} 693 694WERROR reg_getversion(uint32_t *version) 695{ 696 if (version == NULL) { 697 return WERR_INVALID_PARAM; 698 } 699 700 *version = 0x00000005; /* Windows 2000 registry API version */ 701 return WERR_OK; 702} 703 704/******************************************************************* 705 Note: topkeypat is the *full* path that this *key will be 706 loaded into (including the name of the key) 707 ********************************************************************/ 708 709static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath, 710 REGF_NK_REC *key) 711{ 712 REGF_NK_REC *subkey; 713 struct registry_key_handle registry_key; 714 struct regval_ctr *values; 715 struct regsubkey_ctr *subkeys; 716 int i; 717 char *path = NULL; 718 WERROR result = WERR_OK; 719 720 /* initialize the struct registry_key_handle structure */ 721 722 registry_key.ops = reghook_cache_find(topkeypath); 723 if (!registry_key.ops) { 724 DEBUG(0, ("reg_load_tree: Failed to assign registry_ops " 725 "to [%s]\n", topkeypath)); 726 return WERR_BADFILE; 727 } 728 729 registry_key.name = talloc_strdup(regfile->mem_ctx, topkeypath); 730 if (!registry_key.name) { 731 DEBUG(0, ("reg_load_tree: Talloc failed for reg_key.name!\n")); 732 return WERR_NOMEM; 733 } 734 735 /* now start parsing the values and subkeys */ 736 737 result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys); 738 W_ERROR_NOT_OK_RETURN(result); 739 740 values = TALLOC_ZERO_P(subkeys, struct regval_ctr); 741 if (values == NULL) { 742 return WERR_NOMEM; 743 } 744 745 /* copy values into the struct regval_ctr */ 746 747 for (i=0; i<key->num_values; i++) { 748 regval_ctr_addvalue(values, key->values[i].valuename, 749 key->values[i].type, 750 (char*)key->values[i].data, 751 (key->values[i].data_size & ~VK_DATA_IN_OFFSET)); 752 } 753 754 /* copy subkeys into the struct regsubkey_ctr */ 755 756 key->subkey_index = 0; 757 while ((subkey = regfio_fetch_subkey( regfile, key ))) { 758 result = regsubkey_ctr_addkey(subkeys, subkey->keyname); 759 if (!W_ERROR_IS_OK(result)) { 760 TALLOC_FREE(subkeys); 761 return result; 762 } 763 } 764 765 /* write this key and values out */ 766 767 if (!store_reg_values(®istry_key, values) 768 || !store_reg_keys(®istry_key, subkeys)) 769 { 770 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath)); 771 result = WERR_REG_IO_FAILURE; 772 } 773 774 TALLOC_FREE(subkeys); 775 776 if (!W_ERROR_IS_OK(result)) { 777 return result; 778 } 779 780 /* now continue to load each subkey registry tree */ 781 782 key->subkey_index = 0; 783 while ((subkey = regfio_fetch_subkey(regfile, key))) { 784 path = talloc_asprintf(regfile->mem_ctx, 785 "%s\\%s", 786 topkeypath, 787 subkey->keyname); 788 if (path == NULL) { 789 return WERR_NOMEM; 790 } 791 result = reg_load_tree(regfile, path, subkey); 792 if (!W_ERROR_IS_OK(result)) { 793 break; 794 } 795 } 796 797 return result; 798} 799 800/******************************************************************* 801 ********************************************************************/ 802 803static WERROR restore_registry_key(struct registry_key_handle *krecord, 804 const char *fname) 805{ 806 REGF_FILE *regfile; 807 REGF_NK_REC *rootkey; 808 WERROR result; 809 810 /* open the registry file....fail if the file already exists */ 811 812 regfile = regfio_open(fname, (O_RDONLY), 0); 813 if (regfile == NULL) { 814 DEBUG(0, ("restore_registry_key: failed to open \"%s\" (%s)\n", 815 fname, strerror(errno))); 816 return ntstatus_to_werror(map_nt_error_from_unix(errno)); 817 } 818 819 /* get the rootkey from the regf file and then load the tree 820 via recursive calls */ 821 822 if (!(rootkey = regfio_rootkey(regfile))) { 823 regfio_close(regfile); 824 return WERR_REG_FILE_INVALID; 825 } 826 827 result = reg_load_tree(regfile, krecord->name, rootkey); 828 829 /* cleanup */ 830 831 regfio_close(regfile); 832 833 return result; 834} 835 836WERROR reg_restorekey(struct registry_key *key, const char *fname) 837{ 838 return restore_registry_key(key->key, fname); 839} 840 841/******************************************************************** 842********************************************************************/ 843 844static WERROR reg_write_tree(REGF_FILE *regfile, const char *keypath, 845 REGF_NK_REC *parent) 846{ 847 REGF_NK_REC *key; 848 struct regval_ctr *values; 849 struct regsubkey_ctr *subkeys; 850 int i, num_subkeys; 851 char *key_tmp = NULL; 852 char *keyname, *parentpath; 853 char *subkeypath = NULL; 854 char *subkeyname; 855 struct registry_key_handle registry_key; 856 WERROR result = WERR_OK; 857 SEC_DESC *sec_desc = NULL; 858 859 if (!regfile) { 860 return WERR_GENERAL_FAILURE; 861 } 862 863 if (!keypath) { 864 return WERR_OBJECT_PATH_INVALID; 865 } 866 867 /* split up the registry key path */ 868 869 key_tmp = talloc_strdup(regfile->mem_ctx, keypath); 870 if (!key_tmp) { 871 return WERR_NOMEM; 872 } 873 if (!reg_split_key(key_tmp, &parentpath, &keyname)) { 874 return WERR_OBJECT_PATH_INVALID; 875 } 876 877 if (!keyname) { 878 keyname = parentpath; 879 } 880 881 /* we need a registry_key_handle object here to enumerate subkeys and values */ 882 883 ZERO_STRUCT(registry_key); 884 885 registry_key.name = talloc_strdup(regfile->mem_ctx, keypath); 886 if (registry_key.name == NULL) { 887 return WERR_NOMEM; 888 } 889 890 registry_key.ops = reghook_cache_find(registry_key.name); 891 if (registry_key.ops == NULL) { 892 return WERR_BADFILE; 893 } 894 895 /* lookup the values and subkeys */ 896 897 result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys); 898 W_ERROR_NOT_OK_RETURN(result); 899 900 values = TALLOC_ZERO_P(subkeys, struct regval_ctr); 901 if (values == NULL) { 902 return WERR_NOMEM; 903 } 904 905 fetch_reg_keys(®istry_key, subkeys); 906 fetch_reg_values(®istry_key, values); 907 908 result = regkey_get_secdesc(regfile->mem_ctx, ®istry_key, &sec_desc); 909 if (!W_ERROR_IS_OK(result)) { 910 goto done; 911 } 912 913 /* write out this key */ 914 915 key = regfio_write_key(regfile, keyname, values, subkeys, sec_desc, 916 parent); 917 if (key == NULL) { 918 result = WERR_CAN_NOT_COMPLETE; 919 goto done; 920 } 921 922 /* write each one of the subkeys out */ 923 924 num_subkeys = regsubkey_ctr_numkeys(subkeys); 925 for (i=0; i<num_subkeys; i++) { 926 subkeyname = regsubkey_ctr_specific_key(subkeys, i); 927 subkeypath = talloc_asprintf(regfile->mem_ctx, "%s\\%s", 928 keypath, subkeyname); 929 if (subkeypath == NULL) { 930 result = WERR_NOMEM; 931 goto done; 932 } 933 result = reg_write_tree(regfile, subkeypath, key); 934 if (!W_ERROR_IS_OK(result)) 935 goto done; 936 } 937 938 DEBUG(6, ("reg_write_tree: wrote key [%s]\n", keypath)); 939 940done: 941 TALLOC_FREE(subkeys); 942 TALLOC_FREE(registry_key.name); 943 944 return result; 945} 946 947static WERROR backup_registry_key(struct registry_key_handle *krecord, 948 const char *fname) 949{ 950 REGF_FILE *regfile; 951 WERROR result; 952 953 /* open the registry file....fail if the file already exists */ 954 955 regfile = regfio_open(fname, (O_RDWR|O_CREAT|O_EXCL), 956 (S_IRUSR|S_IWUSR)); 957 if (regfile == NULL) { 958 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n", 959 fname, strerror(errno) )); 960 return ntstatus_to_werror(map_nt_error_from_unix(errno)); 961 } 962 963 /* write the registry tree to the file */ 964 965 result = reg_write_tree(regfile, krecord->name, NULL); 966 967 /* cleanup */ 968 969 regfio_close(regfile); 970 971 return result; 972} 973 974WERROR reg_savekey(struct registry_key *key, const char *fname) 975{ 976 return backup_registry_key(key->key, fname); 977} 978 979/********************************************************************** 980 * Higher level utility functions 981 **********************************************************************/ 982 983WERROR reg_deleteallvalues(struct registry_key *key) 984{ 985 WERROR err; 986 int i; 987 988 if (!(key->key->access_granted & KEY_SET_VALUE)) { 989 return WERR_ACCESS_DENIED; 990 } 991 992 if (!W_ERROR_IS_OK(err = fill_value_cache(key))) { 993 return err; 994 } 995 996 for (i=0; i<key->values->num_values; i++) { 997 regval_ctr_delvalue(key->values, key->values->values[i]->valuename); 998 } 999 1000 if (!store_reg_values(key->key, key->values)) { 1001 TALLOC_FREE(key->values); 1002 return WERR_REG_IO_FAILURE; 1003 } 1004 1005 return WERR_OK; 1006} 1007 1008/* 1009 * Utility function to open a complete registry path including the hive prefix. 1010 */ 1011 1012WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path, 1013 uint32 desired_access, const struct nt_user_token *token, 1014 struct registry_key **pkey) 1015{ 1016 struct registry_key *hive, *key; 1017 char *path, *p; 1018 WERROR err; 1019 1020 if (!(path = SMB_STRDUP(orig_path))) { 1021 return WERR_NOMEM; 1022 } 1023 1024 p = strchr(path, '\\'); 1025 1026 if ((p == NULL) || (p[1] == '\0')) { 1027 /* 1028 * No key behind the hive, just return the hive 1029 */ 1030 1031 err = reg_openhive(mem_ctx, path, desired_access, token, 1032 &hive); 1033 if (!W_ERROR_IS_OK(err)) { 1034 SAFE_FREE(path); 1035 return err; 1036 } 1037 SAFE_FREE(path); 1038 *pkey = hive; 1039 return WERR_OK; 1040 } 1041 1042 *p = '\0'; 1043 1044 err = reg_openhive(mem_ctx, path, KEY_ENUMERATE_SUB_KEYS, token, 1045 &hive); 1046 if (!W_ERROR_IS_OK(err)) { 1047 SAFE_FREE(path); 1048 return err; 1049 } 1050 1051 err = reg_openkey(mem_ctx, hive, p+1, desired_access, &key); 1052 1053 TALLOC_FREE(hive); 1054 SAFE_FREE(path); 1055 1056 if (!W_ERROR_IS_OK(err)) { 1057 return err; 1058 } 1059 1060 *pkey = key; 1061 return WERR_OK; 1062} 1063 1064/* 1065 * Utility function to delete a registry key with all its subkeys. 1066 * Note that reg_deletekey returns ACCESS_DENIED when called on a 1067 * key that has subkeys. 1068 */ 1069static WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx, 1070 struct registry_key *parent, 1071 const char *path, 1072 bool del_key) 1073{ 1074 TALLOC_CTX *mem_ctx = NULL; 1075 WERROR werr = WERR_OK; 1076 struct registry_key *key; 1077 char *subkey_name = NULL; 1078 uint32 i; 1079 1080 mem_ctx = talloc_new(ctx); 1081 if (mem_ctx == NULL) { 1082 werr = WERR_NOMEM; 1083 goto done; 1084 } 1085 1086 /* recurse through subkeys first */ 1087 werr = reg_openkey(mem_ctx, parent, path, REG_KEY_ALL, &key); 1088 if (!W_ERROR_IS_OK(werr)) { 1089 goto done; 1090 } 1091 1092 werr = fill_subkey_cache(key); 1093 W_ERROR_NOT_OK_GOTO_DONE(werr); 1094 1095 /* 1096 * loop from top to bottom for perfomance: 1097 * this way, we need to rehash the regsubkey containers less 1098 */ 1099 for (i = regsubkey_ctr_numkeys(key->subkeys) ; i > 0; i--) { 1100 subkey_name = regsubkey_ctr_specific_key(key->subkeys, i-1); 1101 werr = reg_deletekey_recursive_internal(mem_ctx, key, 1102 subkey_name, 1103 true); 1104 W_ERROR_NOT_OK_GOTO_DONE(werr); 1105 } 1106 1107 if (del_key) { 1108 /* now delete the actual key */ 1109 werr = reg_deletekey(parent, path); 1110 } 1111 1112done: 1113 TALLOC_FREE(mem_ctx); 1114 return werr; 1115} 1116 1117static WERROR reg_deletekey_recursive_trans(TALLOC_CTX *ctx, 1118 struct registry_key *parent, 1119 const char *path, 1120 bool del_key) 1121{ 1122 WERROR werr; 1123 1124 werr = regdb_transaction_start(); 1125 if (!W_ERROR_IS_OK(werr)) { 1126 DEBUG(0, ("reg_deletekey_recursive_trans: " 1127 "error starting transaction: %s\n", 1128 win_errstr(werr))); 1129 return werr; 1130 } 1131 1132 werr = reg_deletekey_recursive_internal(ctx, parent, path, del_key); 1133 1134 if (!W_ERROR_IS_OK(werr)) { 1135 DEBUG(1, (__location__ " failed to delete key '%s' from key " 1136 "'%s': %s\n", path, parent->key->name, 1137 win_errstr(werr))); 1138 werr = regdb_transaction_cancel(); 1139 if (!W_ERROR_IS_OK(werr)) { 1140 DEBUG(0, ("reg_deletekey_recursive_trans: " 1141 "error cancelling transaction: %s\n", 1142 win_errstr(werr))); 1143 } 1144 } else { 1145 werr = regdb_transaction_commit(); 1146 if (!W_ERROR_IS_OK(werr)) { 1147 DEBUG(0, ("reg_deletekey_recursive_trans: " 1148 "error committing transaction: %s\n", 1149 win_errstr(werr))); 1150 } 1151 } 1152 1153 return werr; 1154} 1155 1156WERROR reg_deletekey_recursive(TALLOC_CTX *ctx, 1157 struct registry_key *parent, 1158 const char *path) 1159{ 1160 return reg_deletekey_recursive_trans(ctx, parent, path, true); 1161} 1162 1163WERROR reg_deletesubkeys_recursive(TALLOC_CTX *ctx, 1164 struct registry_key *parent, 1165 const char *path) 1166{ 1167 return reg_deletekey_recursive_trans(ctx, parent, path, false); 1168} 1169 1170#if 0 1171/* these two functions are unused. */ 1172 1173/** 1174 * Utility function to create a registry key without opening the hive 1175 * before. Assumes the hive already exists. 1176 */ 1177 1178WERROR reg_create_path(TALLOC_CTX *mem_ctx, const char *orig_path, 1179 uint32 desired_access, 1180 const struct nt_user_token *token, 1181 enum winreg_CreateAction *paction, 1182 struct registry_key **pkey) 1183{ 1184 struct registry_key *hive; 1185 char *path, *p; 1186 WERROR err; 1187 1188 if (!(path = SMB_STRDUP(orig_path))) { 1189 return WERR_NOMEM; 1190 } 1191 1192 p = strchr(path, '\\'); 1193 1194 if ((p == NULL) || (p[1] == '\0')) { 1195 /* 1196 * No key behind the hive, just return the hive 1197 */ 1198 1199 err = reg_openhive(mem_ctx, path, desired_access, token, 1200 &hive); 1201 if (!W_ERROR_IS_OK(err)) { 1202 SAFE_FREE(path); 1203 return err; 1204 } 1205 SAFE_FREE(path); 1206 *pkey = hive; 1207 *paction = REG_OPENED_EXISTING_KEY; 1208 return WERR_OK; 1209 } 1210 1211 *p = '\0'; 1212 1213 err = reg_openhive(mem_ctx, path, 1214 (strchr(p+1, '\\') != NULL) ? 1215 KEY_ENUMERATE_SUB_KEYS : KEY_CREATE_SUB_KEY, 1216 token, &hive); 1217 if (!W_ERROR_IS_OK(err)) { 1218 SAFE_FREE(path); 1219 return err; 1220 } 1221 1222 err = reg_createkey(mem_ctx, hive, p+1, desired_access, pkey, paction); 1223 SAFE_FREE(path); 1224 TALLOC_FREE(hive); 1225 return err; 1226} 1227 1228/* 1229 * Utility function to create a registry key without opening the hive 1230 * before. Will not delete a hive. 1231 */ 1232 1233WERROR reg_delete_path(const struct nt_user_token *token, 1234 const char *orig_path) 1235{ 1236 struct registry_key *hive; 1237 char *path, *p; 1238 WERROR err; 1239 1240 if (!(path = SMB_STRDUP(orig_path))) { 1241 return WERR_NOMEM; 1242 } 1243 1244 p = strchr(path, '\\'); 1245 1246 if ((p == NULL) || (p[1] == '\0')) { 1247 SAFE_FREE(path); 1248 return WERR_INVALID_PARAM; 1249 } 1250 1251 *p = '\0'; 1252 1253 err = reg_openhive(NULL, path, 1254 (strchr(p+1, '\\') != NULL) ? 1255 KEY_ENUMERATE_SUB_KEYS : KEY_CREATE_SUB_KEY, 1256 token, &hive); 1257 if (!W_ERROR_IS_OK(err)) { 1258 SAFE_FREE(path); 1259 return err; 1260 } 1261 1262 err = reg_deletekey(hive, p+1); 1263 SAFE_FREE(path); 1264 TALLOC_FREE(hive); 1265 return err; 1266} 1267#endif /* #if 0 */ 1268