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