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