1/* 2 * Unix SMB/CIFS implementation. 3 * Virtual Windows Registry Layer 4 * Copyright (C) Gerald Carter 2002-2005 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21/* Implementation of internal registry database functions. */ 22 23#include "includes.h" 24 25#undef DBGC_CLASS 26#define DBGC_CLASS DBGC_RPC_SRV 27 28static TDB_CONTEXT *tdb_reg; 29static int tdb_refcount; 30 31#define VALUE_PREFIX "SAMBA_REGVAL" 32 33/* List the deepest path into the registry. All part components will be created.*/ 34 35/* If you want to have a part of the path controlled by the tdb and part by 36 a virtual registry db (e.g. printing), then you have to list the deepest path. 37 For example,"HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Print" 38 allows the reg_db backend to handle everything up to 39 "HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion" and then we'll hook 40 the reg_printing backend onto the last component of the path (see 41 KEY_PRINTING_2K in include/rpc_reg.h) --jerry */ 42 43static const char *builtin_registry_paths[] = { 44 KEY_PRINTING_2K, 45 KEY_PRINTING_PORTS, 46 KEY_PRINTING, 47 KEY_SHARES, 48 KEY_EVENTLOG, 49 "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib", 50 "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009", 51 "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors", 52 "HKLM\\SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 53 "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\DefaultUserConfiguration", 54 "HKLM\\SYSTEM\\CurrentControlSet\\Services\\TcpIp\\Parameters", 55 "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Netlogon\\Parameters", 56 "HKU", 57 "HKCR", 58 "HKPD", 59 "HKPT", 60 NULL }; 61 62struct builtin_regkey_value { 63 const char *path; 64 const char *valuename; 65 uint32 type; 66 union { 67 const char *string; 68 uint32 dw_value; 69 } data; 70}; 71 72static struct builtin_regkey_value builtin_registry_values[] = { 73 { KEY_PRINTING_PORTS, 74 SAMBA_PRINTER_PORT_NAME, REG_SZ, { "" } }, 75 { KEY_PRINTING_2K, 76 "DefaultSpoolDirectory", REG_SZ, { "C:\\Windows\\System32\\Spool\\Printers" } }, 77 { KEY_EVENTLOG, 78 "DisplayName", REG_SZ, { "Event Log" } }, 79 { KEY_EVENTLOG, 80 "ErrorControl", REG_DWORD, { (char*)0x00000001 } }, 81 { NULL, NULL, 0, { NULL } } 82}; 83 84#define REGVER_V1 1 /* first db version with write support */ 85 86/*********************************************************************** 87 Open the registry data in the tdb 88 ***********************************************************************/ 89 90static BOOL init_registry_data( void ) 91{ 92 pstring path, base, remaining; 93 fstring keyname, subkeyname; 94 REGSUBKEY_CTR *subkeys; 95 REGVAL_CTR *values; 96 int i; 97 const char *p, *p2; 98 UNISTR2 data; 99 100 /* 101 * There are potentially quite a few store operations which are all 102 * indiviually wrapped in tdb transactions. Wrapping them in a single 103 * transaction gives just a single transaction_commit() to actually do 104 * its fsync()s. See tdb/common/transaction.c for info about nested 105 * transaction behaviour. 106 */ 107 108 if ( tdb_transaction_start( tdb_reg ) == -1 ) { 109 DEBUG(0, ("init_registry_data: tdb_transaction_start " 110 "failed\n")); 111 return False; 112 } 113 114 /* loop over all of the predefined paths and add each component */ 115 116 for ( i=0; builtin_registry_paths[i] != NULL; i++ ) { 117 118 DEBUG(6,("init_registry_data: Adding [%s]\n", builtin_registry_paths[i])); 119 120 pstrcpy( path, builtin_registry_paths[i] ); 121 pstrcpy( base, "" ); 122 p = path; 123 124 while ( next_token(&p, keyname, "\\", sizeof(keyname)) ) { 125 126 /* build up the registry path from the components */ 127 128 if ( *base ) 129 pstrcat( base, "\\" ); 130 pstrcat( base, keyname ); 131 132 /* get the immediate subkeyname (if we have one ) */ 133 134 *subkeyname = '\0'; 135 if ( *p ) { 136 pstrcpy( remaining, p ); 137 p2 = remaining; 138 139 if ( !next_token(&p2, subkeyname, "\\", sizeof(subkeyname)) ) 140 fstrcpy( subkeyname, p2 ); 141 } 142 143 DEBUG(10,("init_registry_data: Storing key [%s] with subkey [%s]\n", 144 base, *subkeyname ? subkeyname : "NULL")); 145 146 /* we don't really care if the lookup succeeds or not since 147 we are about to update the record. We just want any 148 subkeys already present */ 149 150 if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) { 151 DEBUG(0,("talloc() failure!\n")); 152 goto fail; 153 } 154 155 regdb_fetch_keys( base, subkeys ); 156 if ( *subkeyname ) 157 regsubkey_ctr_addkey( subkeys, subkeyname ); 158 if ( !regdb_store_keys( base, subkeys )) 159 goto fail; 160 161 TALLOC_FREE( subkeys ); 162 } 163 } 164 165 /* loop over all of the predefined values and add each component */ 166 167 for ( i=0; builtin_registry_values[i].path != NULL; i++ ) { 168 if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) { 169 DEBUG(0,("talloc() failure!\n")); 170 goto fail; 171 } 172 173 regdb_fetch_values( builtin_registry_values[i].path, values ); 174 175 /* preserve existing values across restarts. Only add new ones */ 176 177 if ( !regval_ctr_key_exists( values, builtin_registry_values[i].valuename ) ) 178 { 179 switch( builtin_registry_values[i].type ) { 180 case REG_DWORD: 181 regval_ctr_addvalue( values, 182 builtin_registry_values[i].valuename, 183 REG_DWORD, 184 (char*)&builtin_registry_values[i].data.dw_value, 185 sizeof(uint32) ); 186 break; 187 188 case REG_SZ: 189 init_unistr2( &data, builtin_registry_values[i].data.string, UNI_STR_TERMINATE); 190 regval_ctr_addvalue( values, 191 builtin_registry_values[i].valuename, 192 REG_SZ, 193 (char*)data.buffer, 194 data.uni_str_len*sizeof(uint16) ); 195 break; 196 197 default: 198 DEBUG(0,("init_registry_data: invalid value type in builtin_registry_values [%d]\n", 199 builtin_registry_values[i].type)); 200 } 201 regdb_store_values( builtin_registry_values[i].path, values ); 202 } 203 204 TALLOC_FREE( values ); 205 } 206 207 if (tdb_transaction_commit( tdb_reg ) == -1) { 208 DEBUG(0, ("init_registry_data: Could not commit " 209 "transaction\n")); 210 return False; 211 } 212 213 return True; 214 215 fail: 216 217 if (tdb_transaction_cancel( tdb_reg ) == -1) { 218 smb_panic("init_registry_data: tdb_transaction_cancel " 219 "failed\n"); 220 } 221 222 return False; 223} 224 225/*********************************************************************** 226 Open the registry database 227 ***********************************************************************/ 228 229BOOL regdb_init( void ) 230{ 231 const char *vstring = "INFO/version"; 232 uint32 vers_id; 233 234 if ( tdb_reg ) 235 return True; 236 237 if ( !(tdb_reg = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600)) ) 238 { 239 tdb_reg = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); 240 if ( !tdb_reg ) { 241 DEBUG(0,("regdb_init: Failed to open registry %s (%s)\n", 242 lock_path("registry.tdb"), strerror(errno) )); 243 return False; 244 } 245 246 DEBUG(10,("regdb_init: Successfully created registry tdb\n")); 247 } 248 249 tdb_refcount = 1; 250 251 252 vers_id = tdb_fetch_int32(tdb_reg, vstring); 253 254 if ( vers_id != REGVER_V1 ) { 255 /* any upgrade code here if needed */ 256 } 257 258 /* always setup the necessary keys and values */ 259 260 if ( !init_registry_data() ) { 261 DEBUG(0,("init_registry: Failed to initialize data in registry!\n")); 262 return False; 263 } 264 265 return True; 266} 267 268/*********************************************************************** 269 Open the registry. Must already have been initialized by regdb_init() 270 ***********************************************************************/ 271 272WERROR regdb_open( void ) 273{ 274 WERROR result = WERR_OK; 275 276 if ( tdb_reg ) { 277 DEBUG(10,("regdb_open: incrementing refcount (%d)\n", tdb_refcount)); 278 tdb_refcount++; 279 return WERR_OK; 280 } 281 282 become_root(); 283 284 tdb_reg = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600); 285 if ( !tdb_reg ) { 286 result = ntstatus_to_werror( map_nt_error_from_unix( errno ) ); 287 DEBUG(0,("regdb_open: Failed to open %s! (%s)\n", 288 lock_path("registry.tdb"), strerror(errno) )); 289 } 290 291 unbecome_root(); 292 293 tdb_refcount = 1; 294 DEBUG(10,("regdb_open: refcount reset (%d)\n", tdb_refcount)); 295 296 return result; 297} 298 299/*********************************************************************** 300 ***********************************************************************/ 301 302int regdb_close( void ) 303{ 304 int ret; 305 306 tdb_refcount--; 307 308 DEBUG(10,("regdb_close: decrementing refcount (%d)\n", tdb_refcount)); 309 310 if ( tdb_refcount > 0 ) 311 return 0; 312 313 SMB_ASSERT( tdb_refcount >= 0 ); 314 315 ret = tdb_close( tdb_reg ); 316 tdb_reg = NULL; 317 318 return ret; 319} 320 321/*********************************************************************** 322 Add subkey strings to the registry tdb under a defined key 323 fmt is the same format as tdb_pack except this function only supports 324 fstrings 325 ***********************************************************************/ 326 327static BOOL regdb_store_keys_internal( const char *key, REGSUBKEY_CTR *ctr ) 328{ 329 TDB_DATA kbuf, dbuf; 330 char *buffer; 331 int i = 0; 332 uint32 len, buflen; 333 BOOL ret = True; 334 uint32 num_subkeys = regsubkey_ctr_numkeys( ctr ); 335 pstring keyname; 336 337 if ( !key ) 338 return False; 339 340 pstrcpy( keyname, key ); 341 normalize_reg_path( keyname ); 342 343 /* allocate some initial memory */ 344 345 if (!(buffer = (char *)SMB_MALLOC(sizeof(pstring)))) { 346 return False; 347 } 348 buflen = sizeof(pstring); 349 len = 0; 350 351 /* store the number of subkeys */ 352 353 len += tdb_pack(buffer+len, buflen-len, "d", num_subkeys ); 354 355 /* pack all the strings */ 356 357 for (i=0; i<num_subkeys; i++) { 358 len += tdb_pack( buffer+len, buflen-len, "f", regsubkey_ctr_specific_key(ctr, i) ); 359 if ( len > buflen ) { 360 /* allocate some extra space */ 361 if ((buffer = (char *)SMB_REALLOC( buffer, len*2 )) == NULL) { 362 DEBUG(0,("regdb_store_keys: Failed to realloc memory of size [%d]\n", len*2)); 363 ret = False; 364 goto done; 365 } 366 buflen = len*2; 367 368 len = tdb_pack( buffer+len, buflen-len, "f", regsubkey_ctr_specific_key(ctr, i) ); 369 } 370 } 371 372 /* finally write out the data */ 373 374 kbuf.dptr = keyname; 375 kbuf.dsize = strlen(keyname)+1; 376 dbuf.dptr = buffer; 377 dbuf.dsize = len; 378 if ( tdb_store( tdb_reg, kbuf, dbuf, TDB_REPLACE ) == -1) { 379 ret = False; 380 goto done; 381 } 382 383done: 384 SAFE_FREE( buffer ); 385 386 return ret; 387} 388 389/*********************************************************************** 390 Store the new subkey record and create any child key records that 391 do not currently exist 392 ***********************************************************************/ 393 394BOOL regdb_store_keys( const char *key, REGSUBKEY_CTR *ctr ) 395{ 396 int num_subkeys, i; 397 pstring path; 398 REGSUBKEY_CTR *subkeys, *old_subkeys; 399 char *oldkeyname; 400 401 /* fetch a list of the old subkeys so we can determine if any were deleted */ 402 403 if ( !(old_subkeys = TALLOC_ZERO_P( ctr, REGSUBKEY_CTR )) ) { 404 DEBUG(0,("regdb_store_keys: talloc() failure!\n")); 405 return False; 406 } 407 408 regdb_fetch_keys( key, old_subkeys ); 409 410 /* store the subkey list for the parent */ 411 412 if ( !regdb_store_keys_internal( key, ctr ) ) { 413 DEBUG(0,("regdb_store_keys: Failed to store new subkey list for parent [%s}\n", key )); 414 return False; 415 } 416 417 /* now delete removed keys */ 418 419 num_subkeys = regsubkey_ctr_numkeys( old_subkeys ); 420 for ( i=0; i<num_subkeys; i++ ) { 421 oldkeyname = regsubkey_ctr_specific_key( old_subkeys, i ); 422 if ( !regsubkey_ctr_key_exists( ctr, oldkeyname ) ) { 423 pstr_sprintf( path, "%s%c%s", key, '/', oldkeyname ); 424 normalize_reg_path( path ); 425 tdb_delete_bystring( tdb_reg, path ); 426 } 427 } 428 429 TALLOC_FREE( old_subkeys ); 430 431 /* now create records for any subkeys that don't already exist */ 432 433 num_subkeys = regsubkey_ctr_numkeys( ctr ); 434 for ( i=0; i<num_subkeys; i++ ) { 435 pstr_sprintf( path, "%s%c%s", key, '/', regsubkey_ctr_specific_key( ctr, i ) ); 436 437 if ( !(subkeys = TALLOC_ZERO_P( ctr, REGSUBKEY_CTR )) ) { 438 DEBUG(0,("regdb_store_keys: talloc() failure!\n")); 439 return False; 440 } 441 442 if ( regdb_fetch_keys( path, subkeys ) == -1 ) { 443 /* create a record with 0 subkeys */ 444 if ( !regdb_store_keys_internal( path, subkeys ) ) { 445 DEBUG(0,("regdb_store_keys: Failed to store new record for key [%s}\n", path )); 446 TALLOC_FREE( subkeys ); 447 return False; 448 } 449 } 450 451 TALLOC_FREE( subkeys ); 452 } 453 454 return True; 455} 456 457 458/*********************************************************************** 459 Retrieve an array of strings containing subkeys. Memory should be 460 released by the caller. 461 ***********************************************************************/ 462 463int regdb_fetch_keys( const char* key, REGSUBKEY_CTR *ctr ) 464{ 465 pstring path; 466 uint32 num_items; 467 TDB_DATA dbuf; 468 char *buf; 469 uint32 buflen, len; 470 int i; 471 fstring subkeyname; 472 473 DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL")); 474 475 pstrcpy( path, key ); 476 477 /* convert to key format */ 478 pstring_sub( path, "\\", "/" ); 479 strupper_m( path ); 480 481 dbuf = tdb_fetch_bystring( tdb_reg, path ); 482 483 buf = dbuf.dptr; 484 buflen = dbuf.dsize; 485 486 if ( !buf ) { 487 DEBUG(5,("regdb_fetch_keys: tdb lookup failed to locate key [%s]\n", key)); 488 return -1; 489 } 490 491 len = tdb_unpack( buf, buflen, "d", &num_items); 492 493 for (i=0; i<num_items; i++) { 494 len += tdb_unpack( buf+len, buflen-len, "f", subkeyname ); 495 regsubkey_ctr_addkey( ctr, subkeyname ); 496 } 497 498 SAFE_FREE( dbuf.dptr ); 499 500 DEBUG(11,("regdb_fetch_keys: Exit [%d] items\n", num_items)); 501 502 return num_items; 503} 504 505/**************************************************************************** 506 Unpack a list of registry values frem the TDB 507 ***************************************************************************/ 508 509static int regdb_unpack_values(REGVAL_CTR *values, char *buf, int buflen) 510{ 511 int len = 0; 512 uint32 type; 513 pstring valuename; 514 uint32 size; 515 uint8 *data_p; 516 uint32 num_values = 0; 517 int i; 518 519 520 521 /* loop and unpack the rest of the registry values */ 522 523 len += tdb_unpack(buf+len, buflen-len, "d", &num_values); 524 525 for ( i=0; i<num_values; i++ ) { 526 /* unpack the next regval */ 527 528 type = REG_NONE; 529 size = 0; 530 data_p = NULL; 531 len += tdb_unpack(buf+len, buflen-len, "fdB", 532 valuename, 533 &type, 534 &size, 535 &data_p); 536 537 /* add the new value. Paranoid protective code -- make sure data_p is valid */ 538 539 if ( size && data_p ) { 540 regval_ctr_addvalue( values, valuename, type, (const char *)data_p, size ); 541 SAFE_FREE(data_p); /* 'B' option to tdb_unpack does a malloc() */ 542 } 543 544 DEBUG(8,("specific: [%s], len: %d\n", valuename, size)); 545 } 546 547 return len; 548} 549 550/**************************************************************************** 551 Pack all values in all printer keys 552 ***************************************************************************/ 553 554static int regdb_pack_values(REGVAL_CTR *values, char *buf, int buflen) 555{ 556 int len = 0; 557 int i; 558 REGISTRY_VALUE *val; 559 int num_values; 560 561 if ( !values ) 562 return 0; 563 564 num_values = regval_ctr_numvals( values ); 565 566 /* pack the number of values first */ 567 568 len += tdb_pack( buf+len, buflen-len, "d", num_values ); 569 570 /* loop over all values */ 571 572 for ( i=0; i<num_values; i++ ) { 573 val = regval_ctr_specific_value( values, i ); 574 len += tdb_pack(buf+len, buflen-len, "fdB", 575 regval_name(val), 576 regval_type(val), 577 regval_size(val), 578 regval_data_p(val) ); 579 } 580 581 return len; 582} 583 584/*********************************************************************** 585 Retrieve an array of strings containing subkeys. Memory should be 586 released by the caller. 587 ***********************************************************************/ 588 589int regdb_fetch_values( const char* key, REGVAL_CTR *values ) 590{ 591 TDB_DATA data; 592 pstring keystr; 593 594 DEBUG(10,("regdb_fetch_values: Looking for value of key [%s] \n", key)); 595 596 pstr_sprintf( keystr, "%s/%s", VALUE_PREFIX, key ); 597 normalize_reg_path( keystr ); 598 599 data = tdb_fetch_bystring( tdb_reg, keystr ); 600 601 if ( !data.dptr ) { 602 /* all keys have zero values by default */ 603 return 0; 604 } 605 606 regdb_unpack_values( values, data.dptr, data.dsize ); 607 608 SAFE_FREE( data.dptr ); 609 610 return regval_ctr_numvals(values); 611} 612 613/*********************************************************************** 614 Stub function since we do not currently support storing registry 615 values in the registry.tdb 616 ***********************************************************************/ 617 618BOOL regdb_store_values( const char *key, REGVAL_CTR *values ) 619{ 620 TDB_DATA data; 621 pstring keystr; 622 int len, ret; 623 624 DEBUG(10,("regdb_store_values: Looking for value of key [%s] \n", key)); 625 626 ZERO_STRUCT( data ); 627 628 len = regdb_pack_values( values, data.dptr, data.dsize ); 629 if ( len <= 0 ) { 630 DEBUG(0,("regdb_store_values: unable to pack values. len <= 0\n")); 631 return False; 632 } 633 634 data.dptr = SMB_MALLOC_ARRAY( char, len ); 635 data.dsize = len; 636 637 len = regdb_pack_values( values, data.dptr, data.dsize ); 638 639 SMB_ASSERT( len == data.dsize ); 640 641 pstr_sprintf( keystr, "%s/%s", VALUE_PREFIX, key ); 642 normalize_reg_path( keystr ); 643 644 ret = tdb_store_bystring(tdb_reg, keystr, data, TDB_REPLACE); 645 646 SAFE_FREE( data.dptr ); 647 648 return ret != -1 ; 649} 650 651 652/* 653 * Table of function pointers for default access 654 */ 655 656REGISTRY_OPS regdb_ops = { 657 regdb_fetch_keys, 658 regdb_fetch_values, 659 regdb_store_keys, 660 regdb_store_values, 661 NULL 662}; 663 664 665