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