1/* 2 Unix SMB/CIFS implementation. 3 4 local testing of registry library - hives 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 "system/filesys.h" 28#include "param/param.h" 29#include "libcli/security/security.h" 30 31static bool test_del_nonexistant_key(struct torture_context *tctx, 32 const void *test_data) 33{ 34 const struct hive_key *root = (const struct hive_key *)test_data; 35 WERROR error = hive_key_del(root, "bla"); 36 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 37 "invalid return code"); 38 39 return true; 40} 41 42static bool test_keyinfo_root(struct torture_context *tctx, 43 const void *test_data) 44{ 45 uint32_t num_subkeys, num_values; 46 const struct hive_key *root = (const struct hive_key *)test_data; 47 WERROR error; 48 49 /* This is a new backend. There should be no subkeys and no 50 * values */ 51 error = hive_key_get_info(tctx, root, NULL, &num_subkeys, &num_values, 52 NULL, NULL, NULL, NULL); 53 torture_assert_werr_ok(tctx, error, "reg_key_num_subkeys()"); 54 55 torture_assert_int_equal(tctx, num_subkeys, 0, 56 "New key has non-zero subkey count"); 57 58 torture_assert_werr_ok(tctx, error, "reg_key_num_values"); 59 60 torture_assert_int_equal(tctx, num_values, 0, 61 "New key has non-zero value count"); 62 63 return true; 64} 65 66static bool test_keyinfo_nums(struct torture_context *tctx, void *test_data) 67{ 68 uint32_t num_subkeys, num_values; 69 struct hive_key *root = (struct hive_key *)test_data; 70 WERROR error; 71 struct hive_key *subkey; 72 char data[4]; 73 SIVAL(data, 0, 42); 74 75 error = hive_key_add_name(tctx, root, "Nested Keyll", NULL, 76 NULL, &subkey); 77 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 78 79 error = hive_key_set_value(root, "Answer", REG_DWORD, 80 data_blob_talloc(tctx, data, sizeof(data))); 81 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 82 83 /* This is a new backend. There should be no subkeys and no 84 * values */ 85 error = hive_key_get_info(tctx, root, NULL, &num_subkeys, &num_values, 86 NULL, NULL, NULL, NULL); 87 torture_assert_werr_ok(tctx, error, "reg_key_num_subkeys()"); 88 89 torture_assert_int_equal(tctx, num_subkeys, 1, "subkey count"); 90 91 torture_assert_werr_ok(tctx, error, "reg_key_num_values"); 92 93 torture_assert_int_equal(tctx, num_values, 1, "value count"); 94 95 return true; 96} 97 98static bool test_add_subkey(struct torture_context *tctx, 99 const void *test_data) 100{ 101 WERROR error; 102 struct hive_key *subkey; 103 const struct hive_key *root = (const struct hive_key *)test_data; 104 TALLOC_CTX *mem_ctx = tctx; 105 106 error = hive_key_add_name(mem_ctx, root, "Nested Key", NULL, 107 NULL, &subkey); 108 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 109 110 error = hive_key_del(root, "Nested Key"); 111 torture_assert_werr_ok(tctx, error, "reg_key_del"); 112 113 return true; 114} 115 116static bool test_del_recursive(struct torture_context *tctx, 117 const void *test_data) 118{ 119 WERROR error; 120 struct hive_key *subkey; 121 struct hive_key *subkey2; 122 const struct hive_key *root = (const struct hive_key *)test_data; 123 TALLOC_CTX *mem_ctx = tctx; 124 char data[4]; 125 SIVAL(data, 0, 42); 126 127 /* Create a new key under the root */ 128 error = hive_key_add_name(mem_ctx, root, "Parent Key", NULL, 129 NULL, &subkey); 130 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 131 132 /* Create a new key under "Parent Key" */ 133 error = hive_key_add_name(mem_ctx, subkey, "Child Key", NULL, 134 NULL, &subkey2); 135 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 136 137 /* Create a new value under "Child Key" */ 138 error = hive_key_set_value(subkey2, "Answer Recursive", REG_DWORD, 139 data_blob_talloc(mem_ctx, data, sizeof(data))); 140 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 141 142 /* Deleting "Parent Key" will also delete "Child Key" and the value. */ 143 error = hive_key_del(root, "Parent Key"); 144 torture_assert_werr_ok(tctx, error, "hive_key_del"); 145 146 return true; 147} 148 149static bool test_flush_key(struct torture_context *tctx, void *test_data) 150{ 151 struct hive_key *root = (struct hive_key *)test_data; 152 153 torture_assert_werr_ok(tctx, hive_key_flush(root), "flush key"); 154 155 return true; 156} 157 158static bool test_del_key(struct torture_context *tctx, const void *test_data) 159{ 160 WERROR error; 161 struct hive_key *subkey; 162 const struct hive_key *root = (const struct hive_key *)test_data; 163 TALLOC_CTX *mem_ctx = tctx; 164 165 error = hive_key_add_name(mem_ctx, root, "Nested Key", NULL, 166 NULL, &subkey); 167 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 168 169 error = hive_key_del(root, "Nested Key"); 170 torture_assert_werr_ok(tctx, error, "reg_key_del"); 171 172 error = hive_key_del(root, "Nested Key"); 173 torture_assert_werr_equal(tctx, error, WERR_BADFILE, "reg_key_del"); 174 175 return true; 176} 177 178static bool test_set_value(struct torture_context *tctx, 179 const void *test_data) 180{ 181 WERROR error; 182 struct hive_key *subkey; 183 const struct hive_key *root = (const struct hive_key *)test_data; 184 TALLOC_CTX *mem_ctx = tctx; 185 char data[4]; 186 SIVAL(data, 0, 42); 187 188 error = hive_key_add_name(mem_ctx, root, "YA Nested Key", NULL, 189 NULL, &subkey); 190 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 191 192 error = hive_key_set_value(subkey, "Answer", REG_DWORD, 193 data_blob_talloc(mem_ctx, data, sizeof(data))); 194 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 195 196 return true; 197} 198 199static bool test_get_value(struct torture_context *tctx, const void *test_data) 200{ 201 WERROR error; 202 struct hive_key *subkey; 203 const struct hive_key *root = (const struct hive_key *)test_data; 204 TALLOC_CTX *mem_ctx = tctx; 205 char data[4]; 206 uint32_t type; 207 DATA_BLOB value; 208 209 SIVAL(data, 0, 42); 210 211 error = hive_key_add_name(mem_ctx, root, "EYA Nested Key", NULL, 212 NULL, &subkey); 213 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 214 215 error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value); 216 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 217 "getting missing value"); 218 219 error = hive_key_set_value(subkey, "Answer", REG_DWORD, 220 data_blob_talloc(mem_ctx, data, sizeof(data))); 221 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 222 223 error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value); 224 torture_assert_werr_ok(tctx, error, "getting value"); 225 226 torture_assert_int_equal(tctx, value.length, 4, "value length"); 227 torture_assert_int_equal(tctx, type, REG_DWORD, "value type"); 228 229 torture_assert_mem_equal(tctx, &data, value.data, sizeof(uint32_t), 230 "value data"); 231 232 return true; 233} 234 235static bool test_del_value(struct torture_context *tctx, const void *test_data) 236{ 237 WERROR error; 238 struct hive_key *subkey; 239 const struct hive_key *root = (const struct hive_key *)test_data; 240 TALLOC_CTX *mem_ctx = tctx; 241 char data[4]; 242 uint32_t type; 243 DATA_BLOB value; 244 245 SIVAL(data, 0, 42); 246 247 error = hive_key_add_name(mem_ctx, root, "EEYA Nested Key", NULL, 248 NULL, &subkey); 249 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 250 251 error = hive_key_set_value(subkey, "Answer", REG_DWORD, 252 data_blob_talloc(mem_ctx, data, sizeof(data))); 253 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 254 255 error = hive_key_del_value(subkey, "Answer"); 256 torture_assert_werr_ok(tctx, error, "deleting value"); 257 258 error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value); 259 torture_assert_werr_equal(tctx, error, WERR_BADFILE, "getting value"); 260 261 error = hive_key_del_value(subkey, "Answer"); 262 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 263 "deleting value"); 264 265 return true; 266} 267 268static bool test_list_values(struct torture_context *tctx, 269 const void *test_data) 270{ 271 WERROR error; 272 struct hive_key *subkey; 273 const struct hive_key *root = (const struct hive_key *)test_data; 274 TALLOC_CTX *mem_ctx = tctx; 275 char data[4]; 276 uint32_t type; 277 DATA_BLOB value; 278 const char *name; 279 int data_val = 42; 280 SIVAL(data, 0, data_val); 281 282 error = hive_key_add_name(mem_ctx, root, "AYAYA Nested Key", NULL, 283 NULL, &subkey); 284 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 285 286 error = hive_key_set_value(subkey, "Answer", REG_DWORD, 287 data_blob_talloc(mem_ctx, data, sizeof(data))); 288 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 289 290 error = hive_get_value_by_index(mem_ctx, subkey, 0, &name, 291 &type, &value); 292 torture_assert_werr_ok(tctx, error, "getting value"); 293 294 torture_assert_str_equal(tctx, name, "Answer", "value name"); 295 296 torture_assert_int_equal(tctx, value.length, 4, "value length"); 297 torture_assert_int_equal(tctx, type, REG_DWORD, "value type"); 298 299 300 torture_assert_int_equal(tctx, data_val, IVAL(value.data, 0), "value data"); 301 302 error = hive_get_value_by_index(mem_ctx, subkey, 1, &name, 303 &type, &value); 304 torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS, 305 "getting missing value"); 306 307 return true; 308} 309 310static bool test_hive_security(struct torture_context *tctx, const void *_data) 311{ 312 struct hive_key *subkey = NULL; 313 const struct hive_key *root = _data; 314 WERROR error; 315 struct security_descriptor *osd, *nsd; 316 317 osd = security_descriptor_dacl_create(tctx, 318 0, 319 NULL, NULL, 320 SID_NT_AUTHENTICATED_USERS, 321 SEC_ACE_TYPE_ACCESS_ALLOWED, 322 SEC_GENERIC_ALL, 323 SEC_ACE_FLAG_OBJECT_INHERIT, 324 NULL); 325 326 327 error = hive_key_add_name(tctx, root, "SecurityKey", NULL, 328 osd, &subkey); 329 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 330 331 error = hive_get_sec_desc(tctx, subkey, &nsd); 332 torture_assert_werr_ok (tctx, error, "getting security descriptor"); 333 334 torture_assert(tctx, security_descriptor_equal(osd, nsd), 335 "security descriptor changed!"); 336 337 /* Create a fresh security descriptor */ 338 talloc_free(osd); 339 osd = security_descriptor_dacl_create(tctx, 340 0, 341 NULL, NULL, 342 SID_NT_AUTHENTICATED_USERS, 343 SEC_ACE_TYPE_ACCESS_ALLOWED, 344 SEC_GENERIC_ALL, 345 SEC_ACE_FLAG_OBJECT_INHERIT, 346 NULL); 347 348 error = hive_set_sec_desc(subkey, osd); 349 torture_assert_werr_ok(tctx, error, "setting security descriptor"); 350 351 error = hive_get_sec_desc(tctx, subkey, &nsd); 352 torture_assert_werr_ok (tctx, error, "getting security descriptor"); 353 354 torture_assert(tctx, security_descriptor_equal(osd, nsd), 355 "security descriptor changed!"); 356 357 return true; 358} 359 360static void tcase_add_tests(struct torture_tcase *tcase) 361{ 362 torture_tcase_add_simple_test_const(tcase, "del_nonexistant_key", 363 test_del_nonexistant_key); 364 torture_tcase_add_simple_test_const(tcase, "add_subkey", 365 test_add_subkey); 366 torture_tcase_add_simple_test(tcase, "flush_key", 367 test_flush_key); 368 /* test_del_recursive() test must run before test_keyinfo_root(). 369 test_keyinfo_root() checks the number of subkeys, which verifies 370 the recursive delete worked properly. */ 371 torture_tcase_add_simple_test_const(tcase, "del_recursive", 372 test_del_recursive); 373 torture_tcase_add_simple_test_const(tcase, "get_info", 374 test_keyinfo_root); 375 torture_tcase_add_simple_test(tcase, "get_info_nums", 376 test_keyinfo_nums); 377 torture_tcase_add_simple_test_const(tcase, "set_value", 378 test_set_value); 379 torture_tcase_add_simple_test_const(tcase, "get_value", 380 test_get_value); 381 torture_tcase_add_simple_test_const(tcase, "list_values", 382 test_list_values); 383 torture_tcase_add_simple_test_const(tcase, "del_key", 384 test_del_key); 385 torture_tcase_add_simple_test_const(tcase, "del_value", 386 test_del_value); 387 torture_tcase_add_simple_test_const(tcase, "check hive security", 388 test_hive_security); 389} 390 391static bool hive_setup_dir(struct torture_context *tctx, void **data) 392{ 393 struct hive_key *key; 394 WERROR error; 395 char *dirname; 396 NTSTATUS status; 397 398 status = torture_temp_dir(tctx, "hive-dir", &dirname); 399 if (!NT_STATUS_IS_OK(status)) 400 return false; 401 402 rmdir(dirname); 403 404 error = reg_create_directory(tctx, dirname, &key); 405 if (!W_ERROR_IS_OK(error)) { 406 fprintf(stderr, "Unable to initialize dir hive\n"); 407 return false; 408 } 409 410 *data = key; 411 412 return true; 413} 414 415static bool hive_setup_ldb(struct torture_context *tctx, void **data) 416{ 417 struct hive_key *key; 418 WERROR error; 419 char *dirname; 420 NTSTATUS status; 421 422 status = torture_temp_dir(tctx, "hive-ldb", &dirname); 423 if (!NT_STATUS_IS_OK(status)) 424 return false; 425 426 rmdir(dirname); 427 428 error = reg_open_ldb_file(tctx, dirname, NULL, NULL, tctx->ev, tctx->lp_ctx, &key); 429 if (!W_ERROR_IS_OK(error)) { 430 fprintf(stderr, "Unable to initialize ldb hive\n"); 431 return false; 432 } 433 434 *data = key; 435 436 return true; 437} 438 439static bool hive_setup_regf(struct torture_context *tctx, void **data) 440{ 441 struct hive_key *key; 442 WERROR error; 443 char *dirname; 444 NTSTATUS status; 445 446 status = torture_temp_dir(tctx, "hive-regf", &dirname); 447 if (!NT_STATUS_IS_OK(status)) 448 return false; 449 450 rmdir(dirname); 451 452 error = reg_create_regf_file(tctx, lp_iconv_convenience(tctx->lp_ctx), 453 dirname, 5, &key); 454 if (!W_ERROR_IS_OK(error)) { 455 fprintf(stderr, "Unable to create new regf file\n"); 456 return false; 457 } 458 459 *data = key; 460 461 return true; 462} 463 464static bool test_dir_refuses_null_location(struct torture_context *tctx) 465{ 466 torture_assert_werr_equal(tctx, WERR_INVALID_PARAM, 467 reg_open_directory(NULL, NULL, NULL), 468 "reg_open_directory accepts NULL location"); 469 return true; 470} 471 472struct torture_suite *torture_registry_hive(TALLOC_CTX *mem_ctx) 473{ 474 struct torture_tcase *tcase; 475 struct torture_suite *suite = torture_suite_create(mem_ctx, "HIVE"); 476 477 torture_suite_add_simple_test(suite, "dir-refuses-null-location", 478 test_dir_refuses_null_location); 479 480 tcase = torture_suite_add_tcase(suite, "dir"); 481 torture_tcase_set_fixture(tcase, hive_setup_dir, NULL); 482 tcase_add_tests(tcase); 483 484 tcase = torture_suite_add_tcase(suite, "ldb"); 485 torture_tcase_set_fixture(tcase, hive_setup_ldb, NULL); 486 tcase_add_tests(tcase); 487 488 tcase = torture_suite_add_tcase(suite, "regf"); 489 torture_tcase_set_fixture(tcase, hive_setup_regf, NULL); 490 tcase_add_tests(tcase); 491 492 return suite; 493} 494