1/* 2 Unix SMB/CIFS implementation. 3 4 local testing of registry library - registry backend 5 6 Copyright (C) Jelmer Vernooij 2005-2007 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21*/ 22 23#include "includes.h" 24#include "lib/registry/registry.h" 25#include "torture/torture.h" 26#include "librpc/gen_ndr/winreg.h" 27#include "libcli/security/security.h" 28#include "system/filesys.h" 29 30/** 31 * Test obtaining a predefined key. 32 */ 33static bool test_get_predefined(struct torture_context *tctx, void *_data) 34{ 35 struct registry_context *rctx = (struct registry_context *)_data; 36 struct registry_key *root; 37 WERROR error; 38 39 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root); 40 torture_assert_werr_ok(tctx, error, 41 "getting predefined key failed"); 42 return true; 43} 44 45/** 46 * Test obtaining a predefined key. 47 */ 48static bool test_get_predefined_unknown(struct torture_context *tctx, 49 void *_data) 50{ 51 struct registry_context *rctx = _data; 52 struct registry_key *root; 53 WERROR error; 54 55 error = reg_get_predefined_key(rctx, 1337, &root); 56 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 57 "getting predefined key failed"); 58 return true; 59} 60 61static bool test_predef_key_by_name(struct torture_context *tctx, void *_data) 62{ 63 struct registry_context *rctx = (struct registry_context *)_data; 64 struct registry_key *root; 65 WERROR error; 66 67 error = reg_get_predefined_key_by_name(rctx, "HKEY_CLASSES_ROOT", 68 &root); 69 torture_assert_werr_ok(tctx, error, 70 "getting predefined key failed"); 71 72 error = reg_get_predefined_key_by_name(rctx, "HKEY_classes_ROOT", 73 &root); 74 torture_assert_werr_ok(tctx, error, 75 "getting predefined key case insensitively failed"); 76 77 return true; 78} 79 80static bool test_predef_key_by_name_invalid(struct torture_context *tctx, 81 void *_data) 82{ 83 struct registry_context *rctx = (struct registry_context *)_data; 84 struct registry_key *root; 85 WERROR error; 86 87 error = reg_get_predefined_key_by_name(rctx, "BLA", &root); 88 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 89 "getting predefined key failed"); 90 return true; 91} 92 93/** 94 * Test creating a new subkey 95 */ 96static bool test_create_subkey(struct torture_context *tctx, void *_data) 97{ 98 struct registry_context *rctx = (struct registry_context *)_data; 99 struct registry_key *root, *newkey; 100 WERROR error; 101 102 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root); 103 torture_assert_werr_ok(tctx, error, 104 "getting predefined key failed"); 105 106 error = reg_key_add_name(rctx, root, "Bad Bentheim", NULL, NULL, 107 &newkey); 108 torture_assert_werr_ok(tctx, error, "Creating key return code"); 109 torture_assert(tctx, newkey != NULL, "Creating new key"); 110 111 return true; 112} 113 114/** 115 * Test creating a new nested subkey 116 */ 117static bool test_create_nested_subkey(struct torture_context *tctx, void *_data) 118{ 119 struct registry_context *rctx = (struct registry_context *)_data; 120 struct registry_key *root, *newkey1, *newkey2; 121 WERROR error; 122 123 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root); 124 torture_assert_werr_ok(tctx, error, 125 "getting predefined key failed"); 126 127 error = reg_key_add_name(rctx, root, "Hamburg", NULL, NULL, 128 &newkey1); 129 torture_assert_werr_ok(tctx, error, "Creating key return code"); 130 torture_assert(tctx, newkey1 != NULL, "Creating new key"); 131 132 error = reg_key_add_name(rctx, root, "Hamburg\\Hamburg", NULL, NULL, 133 &newkey2); 134 torture_assert_werr_ok(tctx, error, "Creating key return code"); 135 torture_assert(tctx, newkey2 != NULL, "Creating new key"); 136 137 return true; 138} 139 140/** 141 * Test creating a new subkey 142 */ 143static bool test_key_add_abs_top(struct torture_context *tctx, void *_data) 144{ 145 struct registry_context *rctx = (struct registry_context *)_data; 146 struct registry_key *root; 147 WERROR error; 148 149 error = reg_key_add_abs(tctx, rctx, "HKEY_CLASSES_ROOT", 0, NULL, 150 &root); 151 torture_assert_werr_equal(tctx, error, WERR_ALREADY_EXISTS, 152 "create top level"); 153 154 return true; 155} 156 157/** 158 * Test creating a new subkey 159 */ 160static bool test_key_add_abs(struct torture_context *tctx, void *_data) 161{ 162 WERROR error; 163 struct registry_context *rctx = (struct registry_context *)_data; 164 struct registry_key *root, *result1, *result2; 165 166 error = reg_key_add_abs(tctx, rctx, "HKEY_CLASSES_ROOT\\bloe", 0, NULL, 167 &result1); 168 torture_assert_werr_ok(tctx, error, "create lowest"); 169 170 error = reg_key_add_abs(tctx, rctx, "HKEY_CLASSES_ROOT\\bloe\\bla", 0, 171 NULL, &result1); 172 torture_assert_werr_ok(tctx, error, "create nested"); 173 174 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root); 175 torture_assert_werr_ok(tctx, error, 176 "getting predefined key failed"); 177 178 error = reg_open_key(tctx, root, "bloe", &result2); 179 torture_assert_werr_ok(tctx, error, "opening key"); 180 181 error = reg_open_key(tctx, root, "bloe\\bla", &result2); 182 torture_assert_werr_ok(tctx, error, "opening key"); 183 184 return true; 185} 186 187 188static bool test_del_key(struct torture_context *tctx, void *_data) 189{ 190 struct registry_context *rctx = (struct registry_context *)_data; 191 struct registry_key *root, *newkey; 192 WERROR error; 193 194 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, &root); 195 torture_assert_werr_ok(tctx, error, 196 "getting predefined key failed"); 197 198 error = reg_key_add_name(rctx, root, "Polen", NULL, NULL, &newkey); 199 200 torture_assert_werr_ok(tctx, error, "Creating key return code"); 201 torture_assert(tctx, newkey != NULL, "Creating new key"); 202 203 error = reg_key_del(root, "Polen"); 204 torture_assert_werr_ok(tctx, error, "Delete key"); 205 206 error = reg_key_del(root, "Polen"); 207 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 208 "Delete missing key"); 209 210 return true; 211} 212 213/** 214 * Convenience function for opening the HKEY_CLASSES_ROOT hive and 215 * creating a single key for testing purposes. 216 */ 217static bool create_test_key(struct torture_context *tctx, 218 struct registry_context *rctx, 219 const char *name, 220 struct registry_key **root, 221 struct registry_key **subkey) 222{ 223 WERROR error; 224 225 error = reg_get_predefined_key(rctx, HKEY_CLASSES_ROOT, root); 226 torture_assert_werr_ok(tctx, error, 227 "getting predefined key failed"); 228 229 error = reg_key_add_name(rctx, *root, name, NULL, NULL, subkey); 230 torture_assert_werr_ok(tctx, error, "Creating key return code"); 231 232 return true; 233} 234 235 236static bool test_flush_key(struct torture_context *tctx, void *_data) 237{ 238 struct registry_context *rctx = (struct registry_context *)_data; 239 struct registry_key *root, *subkey; 240 WERROR error; 241 242 if (!create_test_key(tctx, rctx, "Bremen", &root, &subkey)) 243 return false; 244 245 error = reg_key_flush(subkey); 246 torture_assert_werr_ok(tctx, error, "flush key"); 247 248 torture_assert_werr_equal(tctx, reg_key_flush(NULL), 249 WERR_INVALID_PARAM, "flush key"); 250 251 return true; 252} 253 254static bool test_query_key(struct torture_context *tctx, void *_data) 255{ 256 struct registry_context *rctx = (struct registry_context *)_data; 257 struct registry_key *root, *subkey; 258 WERROR error; 259 NTTIME last_changed_time; 260 uint32_t num_subkeys, num_values; 261 const char *classname; 262 263 if (!create_test_key(tctx, rctx, "Munchen", &root, &subkey)) 264 return false; 265 266 error = reg_key_get_info(tctx, subkey, &classname, 267 &num_subkeys, &num_values, 268 &last_changed_time, NULL, NULL, NULL); 269 270 torture_assert_werr_ok(tctx, error, "get info key"); 271 torture_assert(tctx, classname == NULL, "classname"); 272 torture_assert_int_equal(tctx, num_subkeys, 0, "num subkeys"); 273 torture_assert_int_equal(tctx, num_values, 0, "num values"); 274 275 return true; 276} 277 278static bool test_query_key_nums(struct torture_context *tctx, void *_data) 279{ 280 struct registry_context *rctx = (struct registry_context *)_data; 281 struct registry_key *root, *subkey1, *subkey2; 282 WERROR error; 283 uint32_t num_subkeys, num_values; 284 char data[4]; 285 SIVAL(data, 0, 42); 286 287 if (!create_test_key(tctx, rctx, "Berlin", &root, &subkey1)) 288 return false; 289 290 error = reg_key_add_name(rctx, subkey1, "Bentheim", NULL, NULL, 291 &subkey2); 292 torture_assert_werr_ok(tctx, error, "Creating key return code"); 293 294 error = reg_val_set(subkey1, "Answer", REG_DWORD, 295 data_blob_talloc(tctx, &data, sizeof(data))); 296 torture_assert_werr_ok(tctx, error, "set value"); 297 298 error = reg_key_get_info(tctx, subkey1, NULL, &num_subkeys, 299 &num_values, NULL, NULL, NULL, NULL); 300 301 torture_assert_werr_ok(tctx, error, "get info key"); 302 torture_assert_int_equal(tctx, num_subkeys, 1, "num subkeys"); 303 torture_assert_int_equal(tctx, num_values, 1, "num values"); 304 305 return true; 306} 307 308/** 309 * Test that the subkeys of a key can be enumerated, that 310 * the returned parameters for get_subkey_by_index are optional and 311 * that enumerating the parents of a non-top-level node works. 312 */ 313static bool test_list_subkeys(struct torture_context *tctx, void *_data) 314{ 315 struct registry_context *rctx = (struct registry_context *)_data; 316 struct registry_key *subkey = NULL, *root; 317 WERROR error; 318 NTTIME last_mod_time; 319 const char *classname, *name; 320 321 if (!create_test_key(tctx, rctx, "Goettingen", &root, &subkey)) 322 return false; 323 324 error = reg_key_get_subkey_by_index(tctx, root, 0, &name, &classname, 325 &last_mod_time); 326 327 torture_assert_werr_ok(tctx, error, "Enum keys return code"); 328 torture_assert_str_equal(tctx, name, "Goettingen", "Enum keys data"); 329 330 331 error = reg_key_get_subkey_by_index(tctx, root, 0, NULL, NULL, NULL); 332 333 torture_assert_werr_ok(tctx, error, 334 "Enum keys with NULL arguments return code"); 335 336 error = reg_key_get_subkey_by_index(tctx, root, 1, NULL, NULL, NULL); 337 338 torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS, 339 "Invalid error for no more items"); 340 341 error = reg_key_get_subkey_by_index(tctx, subkey, 0, NULL, NULL, NULL); 342 343 torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS, 344 "Invalid error for no more items"); 345 346 return true; 347} 348 349/** 350 * Test setting a value 351 */ 352static bool test_set_value(struct torture_context *tctx, void *_data) 353{ 354 struct registry_context *rctx = (struct registry_context *)_data; 355 struct registry_key *subkey = NULL, *root; 356 WERROR error; 357 char data[4]; 358 359 SIVAL(data, 0, 42); 360 361 if (!create_test_key(tctx, rctx, "Dusseldorf", &root, &subkey)) 362 return false; 363 364 error = reg_val_set(subkey, "Answer", REG_DWORD, 365 data_blob_talloc(tctx, data, sizeof(data))); 366 torture_assert_werr_ok (tctx, error, "setting value"); 367 368 return true; 369} 370 371/** 372 * Test getting/setting security descriptors 373 */ 374static bool test_security(struct torture_context *tctx, void *_data) 375{ 376 struct registry_context *rctx = (struct registry_context *)_data; 377 struct registry_key *subkey = NULL, *root; 378 WERROR error; 379 struct security_descriptor *osd, *nsd; 380 381 if (!create_test_key(tctx, rctx, "Düsseldorf", &root, &subkey)) 382 return false; 383 384 osd = security_descriptor_dacl_create(tctx, 385 0, 386 NULL, NULL, 387 SID_NT_AUTHENTICATED_USERS, 388 SEC_ACE_TYPE_ACCESS_ALLOWED, 389 SEC_GENERIC_ALL, 390 SEC_ACE_FLAG_OBJECT_INHERIT, 391 NULL); 392 393 error = reg_set_sec_desc(subkey, osd); 394 torture_assert_werr_ok(tctx, error, "setting security descriptor"); 395 396 error = reg_get_sec_desc(tctx, subkey, &nsd); 397 torture_assert_werr_ok (tctx, error, "getting security descriptor"); 398 399 torture_assert(tctx, security_descriptor_equal(osd, nsd), 400 "security descriptor changed!"); 401 402 return true; 403} 404 405/** 406 * Test getting a value 407 */ 408static bool test_get_value(struct torture_context *tctx, void *_data) 409{ 410 struct registry_context *rctx = (struct registry_context *)_data; 411 struct registry_key *subkey = NULL, *root; 412 WERROR error; 413 DATA_BLOB data; 414 char value[4]; 415 uint32_t type; 416 SIVAL(value, 0, 42); 417 418 if (!create_test_key(tctx, rctx, "Duisburg", &root, &subkey)) 419 return false; 420 421 error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type, 422 &data); 423 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 424 "getting missing value"); 425 426 error = reg_val_set(subkey, __FUNCTION__, REG_DWORD, 427 data_blob_talloc(tctx, value, sizeof(value))); 428 torture_assert_werr_ok(tctx, error, "setting value"); 429 430 error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type, 431 &data); 432 torture_assert_werr_ok(tctx, error, "getting value"); 433 434 torture_assert_int_equal(tctx, sizeof(value), data.length, "value length ok"); 435 torture_assert_mem_equal(tctx, data.data, value, sizeof(value), 436 "value content ok"); 437 torture_assert_int_equal(tctx, REG_DWORD, type, "value type"); 438 439 return true; 440} 441 442/** 443 * Test unsetting a value 444 */ 445static bool test_del_value(struct torture_context *tctx, void *_data) 446{ 447 struct registry_context *rctx =(struct registry_context *)_data; 448 struct registry_key *subkey = NULL, *root; 449 WERROR error; 450 DATA_BLOB data; 451 uint32_t type; 452 char value[4]; 453 SIVAL(value, 0, 42); 454 455 if (!create_test_key(tctx, rctx, "Warschau", &root, &subkey)) 456 return false; 457 458 error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, &type, 459 &data); 460 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 461 "getting missing value"); 462 463 error = reg_val_set(subkey, __FUNCTION__, REG_DWORD, 464 data_blob_talloc(tctx, value, sizeof(value))); 465 torture_assert_werr_ok (tctx, error, "setting value"); 466 467 error = reg_del_value(subkey, __FUNCTION__); 468 torture_assert_werr_ok (tctx, error, "unsetting value"); 469 470 error = reg_key_get_value_by_name(tctx, subkey, __FUNCTION__, 471 &type, &data); 472 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 473 "getting missing value"); 474 475 return true; 476} 477 478/** 479 * Test listing values 480 */ 481static bool test_list_values(struct torture_context *tctx, void *_data) 482{ 483 struct registry_context *rctx = (struct registry_context *)_data; 484 struct registry_key *subkey = NULL, *root; 485 WERROR error; 486 DATA_BLOB data; 487 uint32_t type; 488 const char *name; 489 char value[4]; 490 SIVAL(value, 0, 42); 491 492 if (!create_test_key(tctx, rctx, "Bonn", &root, &subkey)) 493 return false; 494 495 error = reg_val_set(subkey, "bar", REG_DWORD, 496 data_blob_talloc(tctx, value, sizeof(value))); 497 torture_assert_werr_ok (tctx, error, "setting value"); 498 499 error = reg_key_get_value_by_index(tctx, subkey, 0, &name, 500 &type, &data); 501 torture_assert_werr_ok(tctx, error, "getting value"); 502 503 torture_assert_str_equal(tctx, name, "bar", "value name"); 504 torture_assert_int_equal(tctx, sizeof(value), data.length, "value length"); 505 torture_assert_mem_equal(tctx, data.data, value, sizeof(value), 506 "value content"); 507 torture_assert_int_equal(tctx, REG_DWORD, type, "value type"); 508 509 error = reg_key_get_value_by_index(tctx, subkey, 1, &name, 510 &type, &data); 511 torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS, 512 "getting missing value"); 513 514 return true; 515} 516 517static bool setup_local_registry(struct torture_context *tctx, void **data) 518{ 519 struct registry_context *rctx; 520 WERROR error; 521 char *tempdir; 522 NTSTATUS status; 523 struct hive_key *hive_key; 524 const char *filename; 525 526 error = reg_open_local(tctx, &rctx); 527 torture_assert_werr_ok(tctx, error, "Opening local registry failed"); 528 529 status = torture_temp_dir(tctx, "registry-local", &tempdir); 530 torture_assert_ntstatus_ok(tctx, status, "Creating temp dir failed"); 531 532 filename = talloc_asprintf(tctx, "%s/classes_root.ldb", tempdir); 533 error = reg_open_ldb_file(tctx, filename, NULL, NULL, tctx->ev, tctx->lp_ctx, &hive_key); 534 torture_assert_werr_ok(tctx, error, "Opening classes_root file failed"); 535 536 error = reg_mount_hive(rctx, hive_key, HKEY_CLASSES_ROOT, NULL); 537 torture_assert_werr_ok(tctx, error, "Mounting hive failed"); 538 539 *data = rctx; 540 541 return true; 542} 543 544static void tcase_add_tests(struct torture_tcase *tcase) 545{ 546 torture_tcase_add_simple_test(tcase, "list_subkeys", 547 test_list_subkeys); 548 torture_tcase_add_simple_test(tcase, "get_predefined_key", 549 test_get_predefined); 550 torture_tcase_add_simple_test(tcase, "get_predefined_key", 551 test_get_predefined_unknown); 552 torture_tcase_add_simple_test(tcase, "create_key", 553 test_create_subkey); 554 torture_tcase_add_simple_test(tcase, "create_key", 555 test_create_nested_subkey); 556 torture_tcase_add_simple_test(tcase, "key_add_abs", 557 test_key_add_abs); 558 torture_tcase_add_simple_test(tcase, "key_add_abs_top", 559 test_key_add_abs_top); 560 torture_tcase_add_simple_test(tcase, "set_value", 561 test_set_value); 562 torture_tcase_add_simple_test(tcase, "get_value", 563 test_get_value); 564 torture_tcase_add_simple_test(tcase, "list_values", 565 test_list_values); 566 torture_tcase_add_simple_test(tcase, "del_key", 567 test_del_key); 568 torture_tcase_add_simple_test(tcase, "del_value", 569 test_del_value); 570 torture_tcase_add_simple_test(tcase, "flush_key", 571 test_flush_key); 572 torture_tcase_add_simple_test(tcase, "query_key", 573 test_query_key); 574 torture_tcase_add_simple_test(tcase, "query_key_nums", 575 test_query_key_nums); 576 torture_tcase_add_simple_test(tcase, "test_predef_key_by_name", 577 test_predef_key_by_name); 578 torture_tcase_add_simple_test(tcase, "security", 579 test_security); 580 torture_tcase_add_simple_test(tcase,"test_predef_key_by_name_invalid", 581 test_predef_key_by_name_invalid); 582} 583 584struct torture_suite *torture_registry_registry(TALLOC_CTX *mem_ctx) 585{ 586 struct torture_tcase *tcase; 587 struct torture_suite *suite = torture_suite_create(mem_ctx, "REGISTRY"); 588 589 tcase = torture_suite_add_tcase(suite, "local"); 590 torture_tcase_set_fixture(tcase, setup_local_registry, NULL); 591 tcase_add_tests(tcase); 592 593 return suite; 594} 595