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