Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into registry
[ira/wip.git] / source4 / lib / registry / tests / registry.c
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  */
33 static 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  */
48 static 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
61 static 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
80 static 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  */
96 static 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  */
117 static 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  */
143 static 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  */
160 static 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
188 static 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  */
217 static 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
236 static 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
254 static 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
278 static 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  */
313 static 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  */
352 static 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  */
374 static 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  */
408 static 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  */
445 static 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  */
481 static 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
517 static 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
544 static 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
584 struct 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 }