r25810: Add test for blocking security descriptor inheritance in winreg.
[samba.git] / source4 / torture / rpc / winreg.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for winreg rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Jelmer Vernooij 2004-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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "torture/torture.h"
24 #include "librpc/gen_ndr/ndr_winreg_c.h"
25 #include "librpc/gen_ndr/ndr_security.h"
26 #include "libcli/security/security.h"
27 #include "torture/rpc/rpc.h"
28
29 #define TEST_KEY_BASE "smbtorture test"
30 #define TEST_KEY1 TEST_KEY_BASE "\\spottyfoot"
31 #define TEST_KEY2 TEST_KEY_BASE "\\with a SD (#1)"
32 #define TEST_KEY3 TEST_KEY_BASE "\\with a subkey"
33 #define TEST_KEY4 TEST_KEY_BASE "\\sd_tests"
34 #define TEST_SUBKEY TEST_KEY3 "\\subkey"
35 #define TEST_SUBKEY_SD  TEST_KEY4 "\\subkey_sd"
36 #define TEST_SUBSUBKEY_SD TEST_KEY4 "\\subkey_sd\\subsubkey_sd"
37
38 #define TEST_SID "S-1-5-21-1234567890-1234567890-1234567890-500"
39
40 static void init_initshutdown_String(TALLOC_CTX *mem_ctx,
41                                      struct initshutdown_String *name,
42                                      const char *s)
43 {
44         name->name = talloc(mem_ctx, struct initshutdown_String_sub);
45         name->name->name = s;
46 }
47
48 static void init_winreg_String(struct winreg_String *name, const char *s)
49 {
50         name->name = s;
51         if (s) {
52                 name->name_len = 2 * (strlen_m(s) + 1);
53                 name->name_size = name->name_len;
54         } else {
55                 name->name_len = 0;
56                 name->name_size = 0;
57         }
58 }
59
60 static bool test_GetVersion(struct dcerpc_pipe *p,
61                             struct torture_context *tctx,
62                             struct policy_handle *handle)
63 {
64         struct winreg_GetVersion r;
65         uint32_t v;
66
67         ZERO_STRUCT(r);
68         r.in.handle = handle;
69         r.out.version = &v;
70
71         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_GetVersion(p, tctx, &r),
72                                    "GetVersion failed");
73
74         torture_assert_werr_ok(tctx, r.out.result, "GetVersion failed");
75
76         return true;
77 }
78
79 static bool test_NotifyChangeKeyValue(struct dcerpc_pipe *p,
80                                       struct torture_context *tctx,
81                                       struct policy_handle *handle)
82 {
83         struct winreg_NotifyChangeKeyValue r;
84
85         r.in.handle = handle;
86         r.in.watch_subtree = true;
87         r.in.notify_filter = 0;
88         r.in.unknown = r.in.unknown2 = 0;
89         init_winreg_String(&r.in.string1, NULL);
90         init_winreg_String(&r.in.string2, NULL);
91
92         torture_assert_ntstatus_ok(tctx,
93                                    dcerpc_winreg_NotifyChangeKeyValue(p, tctx, &r),
94                                    "NotifyChangeKeyValue failed");
95
96         if (!W_ERROR_IS_OK(r.out.result)) {
97                 torture_comment(tctx,
98                                 "NotifyChangeKeyValue failed - %s - not considering\n",
99                                 win_errstr(r.out.result));
100                 return true;
101         }
102
103         return true;
104 }
105
106 static bool test_CreateKey(struct dcerpc_pipe *p, struct torture_context *tctx,
107                            struct policy_handle *handle, const char *name,
108                            const char *class)
109 {
110         struct winreg_CreateKey r;
111         struct policy_handle newhandle;
112         enum winreg_CreateAction action_taken = 0;
113
114         r.in.handle = handle;
115         r.out.new_handle = &newhandle;
116         init_winreg_String(&r.in.name, name);
117         init_winreg_String(&r.in.keyclass, class);
118         r.in.options = 0x0;
119         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
120         r.in.action_taken = r.out.action_taken = &action_taken;
121         r.in.secdesc = NULL;
122
123         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CreateKey(p, tctx, &r),
124                                    "CreateKey failed");
125
126         torture_assert_werr_ok(tctx,  r.out.result, "CreateKey failed");
127
128         return true;
129 }
130
131
132 /*
133   createkey testing with a SD
134 */
135 static bool test_CreateKey_sd(struct dcerpc_pipe *p,
136                               struct torture_context *tctx,
137                               struct policy_handle *handle, const char *name,
138                               const char *class,
139                               struct policy_handle *newhandle)
140 {
141         struct winreg_CreateKey r;
142         enum winreg_CreateAction action_taken = 0;
143         struct security_descriptor *sd;
144         DATA_BLOB sdblob;
145         struct winreg_SecBuf secbuf;
146
147         sd = security_descriptor_dacl_create(tctx,
148                                         0,
149                                         NULL, NULL,
150                                         SID_NT_AUTHENTICATED_USERS,
151                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
152                                         SEC_GENERIC_ALL,
153                                         SEC_ACE_FLAG_OBJECT_INHERIT |
154                                         SEC_ACE_FLAG_CONTAINER_INHERIT,
155                                         NULL);
156
157         torture_assert_ntstatus_ok(tctx,
158                 ndr_push_struct_blob(&sdblob, tctx, sd,
159                                      (ndr_push_flags_fn_t)ndr_push_security_descriptor),
160                                      "Failed to push security_descriptor ?!\n");
161
162         secbuf.sd.data = sdblob.data;
163         secbuf.sd.len = sdblob.length;
164         secbuf.sd.size = sdblob.length;
165         secbuf.length = sdblob.length-10;
166         secbuf.inherit = 0;
167
168         r.in.handle = handle;
169         r.out.new_handle = newhandle;
170         init_winreg_String(&r.in.name, name);
171         init_winreg_String(&r.in.keyclass, class);
172         r.in.options = 0x0;
173         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
174         r.in.action_taken = r.out.action_taken = &action_taken;
175         r.in.secdesc = &secbuf;
176
177         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CreateKey(p, tctx, &r),
178                                    "CreateKey with sd failed");
179
180         torture_assert_werr_ok(tctx, r.out.result, "CreateKey with sd failed");
181
182         return true;
183 }
184
185 static bool _test_GetKeySecurity(struct dcerpc_pipe *p,
186                                  struct torture_context *tctx,
187                                  struct policy_handle *handle,
188                                  uint32_t *sec_info_ptr,
189                                  WERROR get_werr,
190                                  struct security_descriptor **sd_out)
191 {
192         struct winreg_GetKeySecurity r;
193         struct security_descriptor *sd = NULL;
194         uint32_t sec_info;
195         DATA_BLOB sdblob;
196
197         if (sec_info_ptr) {
198                 sec_info = *sec_info_ptr;
199         } else {
200                 sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
201         }
202
203         ZERO_STRUCT(r);
204
205         r.in.handle = handle;
206         r.in.sec_info = sec_info;
207         r.in.sd = r.out.sd = talloc_zero(tctx, struct KeySecurityData);
208         r.in.sd->size = 0x1000;
209
210         torture_assert_ntstatus_ok(tctx,
211                                    dcerpc_winreg_GetKeySecurity(p, tctx, &r),
212                                    "GetKeySecurity failed");
213
214         torture_assert_werr_equal(tctx, r.out.result, get_werr,
215                                   "GetKeySecurity failed");
216
217         sdblob.data = r.out.sd->data;
218         sdblob.length = r.out.sd->len;
219
220         sd = talloc_zero(tctx, struct security_descriptor);
221
222         torture_assert_ntstatus_ok(tctx,
223                 ndr_pull_struct_blob(&sdblob, tctx, sd,
224                                      (ndr_pull_flags_fn_t)ndr_pull_security_descriptor),
225                                      "pull_security_descriptor failed");
226
227         if (p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
228                 NDR_PRINT_DEBUG(security_descriptor, sd);
229         }
230
231         if (sd_out) {
232                 *sd_out = sd;
233         } else {
234                 talloc_free(sd);
235         }
236
237         return true;
238 }
239
240 static bool test_GetKeySecurity(struct dcerpc_pipe *p,
241                                 struct torture_context *tctx,
242                                 struct policy_handle *handle,
243                                 struct security_descriptor **sd_out)
244 {
245         return _test_GetKeySecurity(p, tctx, handle, NULL, WERR_OK, sd_out);
246 }
247
248 static bool _test_SetKeySecurity(struct dcerpc_pipe *p,
249                                  struct torture_context *tctx,
250                                  struct policy_handle *handle,
251                                  uint32_t *sec_info_ptr,
252                                  struct security_descriptor *sd,
253                                  WERROR werr)
254 {
255         struct winreg_SetKeySecurity r;
256         struct KeySecurityData *sdata = NULL;
257         DATA_BLOB sdblob;
258         uint32_t sec_info;
259
260         ZERO_STRUCT(r);
261
262         if (sd && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) {
263                 NDR_PRINT_DEBUG(security_descriptor, sd);
264         }
265
266         torture_assert_ntstatus_ok(tctx,
267                 ndr_push_struct_blob(&sdblob, tctx, sd,
268                                      (ndr_push_flags_fn_t)ndr_push_security_descriptor),
269                                      "push_security_descriptor failed");
270
271         sdata = talloc_zero(tctx, struct KeySecurityData);
272         sdata->data = sdblob.data;
273         sdata->size = sdblob.length;
274         sdata->len = sdblob.length;
275
276         if (sec_info_ptr) {
277                 sec_info = *sec_info_ptr;
278         } else {
279                 sec_info = SECINFO_UNPROTECTED_SACL |
280                            SECINFO_UNPROTECTED_DACL;
281                 if (sd->owner_sid) {
282                         sec_info |= SECINFO_OWNER;
283                 }
284                 if (sd->group_sid) {
285                         sec_info |= SECINFO_GROUP;
286                 }
287                 if (sd->sacl) {
288                         sec_info |= SECINFO_SACL;
289                 }
290                 if (sd->dacl) {
291                         sec_info |= SECINFO_DACL;
292                 }
293         }
294
295         r.in.handle = handle;
296         r.in.sec_info = sec_info;
297         r.in.sd = sdata;
298
299         torture_assert_ntstatus_ok(tctx,
300                                    dcerpc_winreg_SetKeySecurity(p, tctx, &r),
301                                    "SetKeySecurity failed");
302
303         torture_assert_werr_equal(tctx, r.out.result, werr,
304                                   "SetKeySecurity failed");
305
306         return true;
307 }
308
309 static bool test_SetKeySecurity(struct dcerpc_pipe *p,
310                                 struct torture_context *tctx,
311                                 struct policy_handle *handle,
312                                 struct security_descriptor *sd)
313 {
314         return _test_SetKeySecurity(p, tctx, handle, NULL, sd, WERR_OK);
315 }
316
317 static bool test_CloseKey(struct dcerpc_pipe *p, struct torture_context *tctx,
318                           struct policy_handle *handle)
319 {
320         struct winreg_CloseKey r;
321
322         r.in.handle = r.out.handle = handle;
323
324         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey(p, tctx, &r),
325                                    "CloseKey failed");
326
327         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
328
329         return true;
330 }
331
332 static bool test_FlushKey(struct dcerpc_pipe *p, struct torture_context *tctx,
333                           struct policy_handle *handle)
334 {
335         struct winreg_FlushKey r;
336
337         r.in.handle = handle;
338
339         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_FlushKey(p, tctx, &r),
340                                    "FlushKey failed");
341
342         torture_assert_werr_ok(tctx, r.out.result, "FlushKey failed");
343
344         return true;
345 }
346
347 static bool test_OpenKey(struct dcerpc_pipe *p, struct torture_context *tctx,
348                          struct policy_handle *hive_handle,
349                          const char *keyname, struct policy_handle *key_handle)
350 {
351         struct winreg_OpenKey r;
352
353         r.in.parent_handle = hive_handle;
354         init_winreg_String(&r.in.keyname, keyname);
355         r.in.unknown = 0x00000000;
356         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
357         r.out.handle = key_handle;
358
359         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey(p, tctx, &r),
360                                    "OpenKey failed");
361
362         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
363
364         return true;
365 }
366
367 static bool test_Cleanup(struct dcerpc_pipe *p, struct torture_context *tctx,
368                          struct policy_handle *handle, const char *key)
369 {
370         struct winreg_DeleteKey r;
371
372         r.in.handle = handle;
373
374         init_winreg_String(&r.in.key, key);
375         dcerpc_winreg_DeleteKey(p, tctx, &r);
376
377         return true;
378 }
379
380 static bool _test_GetSetSecurityDescriptor(struct dcerpc_pipe *p,
381                                            struct torture_context *tctx,
382                                            struct policy_handle *handle,
383                                            WERROR get_werr,
384                                            WERROR set_werr)
385 {
386         struct security_descriptor *sd = NULL;
387
388         if (!_test_GetKeySecurity(p, tctx, handle, NULL, get_werr, &sd)) {
389                 return false;
390         }
391
392         if (!_test_SetKeySecurity(p, tctx, handle, NULL, sd, set_werr)) {
393                 return false;
394         }
395
396         return true;
397 }
398
399 static bool test_SecurityDescriptor(struct dcerpc_pipe *p,
400                                     struct torture_context *tctx,
401                                     struct policy_handle *handle,
402                                     const char *key)
403 {
404         struct policy_handle new_handle;
405         bool ret = true;
406
407         torture_comment(tctx, "SecurityDescriptor get & set\n");
408
409         if (!test_OpenKey(p, tctx, handle, key, &new_handle)) {
410                 return false;
411         }
412
413         if (!_test_GetSetSecurityDescriptor(p, tctx, &new_handle,
414                                             WERR_OK, WERR_OK)) {
415                 ret = false;
416         }
417
418         if (!test_CloseKey(p, tctx, &new_handle)) {
419                 return false;
420         }
421
422         return ret;
423 }
424
425 static bool test_dacl_trustee_present(struct dcerpc_pipe *p,
426                                       struct torture_context *tctx,
427                                       struct policy_handle *handle,
428                                       const struct dom_sid *sid)
429 {
430         struct security_descriptor *sd = NULL;
431         int i;
432
433         if (!test_GetKeySecurity(p, tctx, handle, &sd)) {
434                 return false;
435         }
436
437         if (!sd || !sd->dacl) {
438                 return false;
439         }
440
441         for (i = 0; i < sd->dacl->num_aces; i++) {
442                 if (dom_sid_equal(&sd->dacl->aces[i].trustee, sid)) {
443                         return true;
444                 }
445         }
446
447         return false;
448 }
449
450 static bool test_dacl_trustee_flags_present(struct dcerpc_pipe *p,
451                                             struct torture_context *tctx,
452                                             struct policy_handle *handle,
453                                             const struct dom_sid *sid,
454                                             uint8_t flags)
455 {
456         struct security_descriptor *sd = NULL;
457         int i;
458
459         if (!test_GetKeySecurity(p, tctx, handle, &sd)) {
460                 return false;
461         }
462
463         if (!sd || !sd->dacl) {
464                 return false;
465         }
466
467         for (i = 0; i < sd->dacl->num_aces; i++) {
468                 if ((dom_sid_equal(&sd->dacl->aces[i].trustee, sid)) &&
469                     (sd->dacl->aces[i].flags == flags)) {
470                         return true;
471                 }
472         }
473
474         return false;
475 }
476
477 static bool test_dacl_ace_present(struct dcerpc_pipe *p,
478                                   struct torture_context *tctx,
479                                   struct policy_handle *handle,
480                                   const struct security_ace *ace)
481 {
482         struct security_descriptor *sd = NULL;
483         int i;
484
485         if (!test_GetKeySecurity(p, tctx, handle, &sd)) {
486                 return false;
487         }
488
489         if (!sd || !sd->dacl) {
490                 return false;
491         }
492
493         for (i = 0; i < sd->dacl->num_aces; i++) {
494                 if (security_ace_equal(&sd->dacl->aces[i], ace)) {
495                         return true;
496                 }
497         }
498
499         return false;
500 }
501
502 static bool test_RestoreSecurity(struct dcerpc_pipe *p,
503                                  struct torture_context *tctx,
504                                  struct policy_handle *handle,
505                                  const char *key,
506                                  struct security_descriptor *sd)
507 {
508         struct policy_handle new_handle;
509         bool ret = true;
510
511         if (!test_OpenKey(p, tctx, handle, key, &new_handle)) {
512                 return false;
513         }
514
515         if (!test_SetKeySecurity(p, tctx, &new_handle, sd)) {
516                 ret = false;
517         }
518
519         if (!test_CloseKey(p, tctx, &new_handle)) {
520                 ret = false;
521         }
522
523         return ret;
524 }
525
526 static bool test_SecurityDescriptorInheritance(struct dcerpc_pipe *p,
527                                                struct torture_context *tctx,
528                                                struct policy_handle *handle,
529                                                const char *key)
530 {
531         /* get sd
532            add ace SEC_ACE_FLAG_CONTAINER_INHERIT
533            set sd
534            get sd
535            check ace
536            add subkey
537            get sd
538            check ace
539            add subsubkey
540            get sd
541            check ace
542            del subsubkey
543            del subkey
544            reset sd
545         */
546
547         struct security_descriptor *sd = NULL;
548         struct security_descriptor *sd_orig = NULL;
549         struct security_ace *ace = NULL;
550         struct policy_handle new_handle;
551         NTSTATUS status;
552         bool ret = true;
553
554         torture_comment(tctx, "SecurityDescriptor inheritance\n");
555
556         if (!test_OpenKey(p, tctx, handle, key, &new_handle)) {
557                 return false;
558         }
559
560         if (!_test_GetKeySecurity(p, tctx, &new_handle, NULL, WERR_OK, &sd)) {
561                 return false;
562         }
563
564         sd_orig = security_descriptor_copy(tctx, sd);
565         if (sd_orig == NULL) {
566                 return false;
567         }
568
569         ace = security_ace_create(tctx,
570                                   TEST_SID,
571                                   SEC_ACE_TYPE_ACCESS_ALLOWED,
572                                   SEC_STD_REQUIRED,
573                                   SEC_ACE_FLAG_CONTAINER_INHERIT);
574
575         status = security_descriptor_dacl_add(sd, ace);
576         if (!NT_STATUS_IS_OK(status)) {
577                 printf("failed to add ace: %s\n", nt_errstr(status));
578                 return false;
579         }
580
581         /* FIXME: add further tests for these flags */
582         sd->type |= SEC_DESC_DACL_AUTO_INHERIT_REQ |
583                     SEC_DESC_SACL_AUTO_INHERITED;
584
585         if (!test_SetKeySecurity(p, tctx, &new_handle, sd)) {
586                 return false;
587         }
588
589         if (!test_dacl_ace_present(p, tctx, &new_handle, ace)) {
590                 printf("new ACE not present!\n");
591                 return false;
592         }
593
594         if (!test_CloseKey(p, tctx, &new_handle)) {
595                 return false;
596         }
597
598         if (!test_CreateKey(p, tctx, handle, TEST_SUBKEY_SD, NULL)) {
599                 ret = false;
600                 goto out;
601         }
602
603         if (!test_OpenKey(p, tctx, handle, TEST_SUBKEY_SD, &new_handle)) {
604                 ret = false;
605                 goto out;
606         }
607
608         if (!test_dacl_ace_present(p, tctx, &new_handle, ace)) {
609                 printf("inherited ACE not present!\n");
610                 ret = false;
611                 goto out;
612         }
613
614         test_CloseKey(p, tctx, &new_handle);
615         if (!test_CreateKey(p, tctx, handle, TEST_SUBSUBKEY_SD, NULL)) {
616                 ret = false;
617                 goto out;
618         }
619
620         if (!test_OpenKey(p, tctx, handle, TEST_SUBSUBKEY_SD, &new_handle)) {
621                 ret = false;
622                 goto out;
623         }
624
625         if (!test_dacl_ace_present(p, tctx, &new_handle, ace)) {
626                 printf("inherited ACE not present!\n");
627                 ret = false;
628                 goto out;
629         }
630
631  out:
632         test_CloseKey(p, tctx, &new_handle);
633         test_Cleanup(p, tctx, handle, TEST_SUBSUBKEY_SD);
634         test_Cleanup(p, tctx, handle, TEST_SUBKEY_SD);
635         test_RestoreSecurity(p, tctx, handle, key, sd_orig);
636
637         return true;
638 }
639
640 static bool test_SecurityDescriptorBlockInheritance(struct dcerpc_pipe *p,
641                                                     struct torture_context *tctx,
642                                                     struct policy_handle *handle,
643                                                     const char *key)
644 {
645         /* get sd
646            add ace SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
647            set sd
648            add subkey/subkey
649            get sd
650            check ace
651            get sd from subkey
652            check ace
653            del subkey/subkey
654            del subkey
655            reset sd
656         */
657
658         struct security_descriptor *sd = NULL;
659         struct security_descriptor *sd_orig = NULL;
660         struct security_ace *ace = NULL;
661         struct policy_handle new_handle;
662         struct dom_sid *sid = NULL;
663         NTSTATUS status;
664         bool ret = true;
665         uint8_t ace_flags = 0x0;
666
667         torture_comment(tctx, "SecurityDescriptor inheritance block\n");
668
669         if (!test_OpenKey(p, tctx, handle, key, &new_handle)) {
670                 return false;
671         }
672
673         if (!_test_GetKeySecurity(p, tctx, &new_handle, NULL, WERR_OK, &sd)) {
674                 return false;
675         }
676
677         sd_orig = security_descriptor_copy(tctx, sd);
678         if (sd_orig == NULL) {
679                 return false;
680         }
681
682         ace = security_ace_create(tctx,
683                                   TEST_SID,
684                                   SEC_ACE_TYPE_ACCESS_ALLOWED,
685                                   SEC_STD_REQUIRED,
686                                   SEC_ACE_FLAG_CONTAINER_INHERIT |
687                                   SEC_ACE_FLAG_NO_PROPAGATE_INHERIT);
688
689         status = security_descriptor_dacl_add(sd, ace);
690         if (!NT_STATUS_IS_OK(status)) {
691                 printf("failed to add ace: %s\n", nt_errstr(status));
692                 return false;
693         }
694
695         if (!_test_SetKeySecurity(p, tctx, &new_handle, NULL, sd, WERR_OK)) {
696                 return false;
697         }
698
699         if (!test_dacl_ace_present(p, tctx, &new_handle, ace)) {
700                 printf("new ACE not present!\n");
701                 return false;
702         }
703
704         if (!test_CloseKey(p, tctx, &new_handle)) {
705                 return false;
706         }
707
708         if (!test_CreateKey(p, tctx, handle, TEST_SUBSUBKEY_SD, NULL)) {
709                 return false;
710         }
711
712         if (!test_OpenKey(p, tctx, handle, TEST_SUBSUBKEY_SD, &new_handle)) {
713                 ret = false;
714                 goto out;
715         }
716
717         if (test_dacl_ace_present(p, tctx, &new_handle, ace)) {
718                 printf("inherited ACE present but should not!\n");
719                 ret = false;
720                 goto out;
721         }
722
723         sid = dom_sid_parse_talloc(tctx, TEST_SID);
724         if (sid == NULL) {
725                 return false;
726         }
727
728         if (test_dacl_trustee_present(p, tctx, &new_handle, sid)) {
729                 printf("inherited trustee SID present but should not!\n");
730                 ret = false;
731                 goto out;
732         }
733
734         test_CloseKey(p, tctx, &new_handle);
735
736         if (!test_OpenKey(p, tctx, handle, TEST_SUBKEY_SD, &new_handle)) {
737                 ret = false;
738                 goto out;
739         }
740
741         if (test_dacl_ace_present(p, tctx, &new_handle, ace)) {
742                 printf("inherited ACE present but should not!\n");
743                 ret = false;
744                 goto out;
745         }
746
747         if (!test_dacl_trustee_flags_present(p, tctx, &new_handle, sid, ace_flags)) {
748                 printf("inherited trustee SID with flags 0x%02x not present!\n",
749                         ace_flags);
750                 ret = false;
751                 goto out;
752         }
753
754  out:
755         test_CloseKey(p, tctx, &new_handle);
756         test_Cleanup(p, tctx, handle, TEST_SUBSUBKEY_SD);
757         test_Cleanup(p, tctx, handle, TEST_SUBKEY_SD);
758         test_RestoreSecurity(p, tctx, handle, key, sd_orig);
759
760         return ret;
761 }
762
763 static bool test_SecurityDescriptors(struct dcerpc_pipe *p,
764                                      struct torture_context *tctx,
765                                      struct policy_handle *handle,
766                                      const char *key)
767 {
768         bool ret = true;
769
770         if (!test_SecurityDescriptor(p, tctx, handle, key)) {
771                 printf("test_SecurityDescriptor failed\n");
772                 ret = false;
773         }
774
775         if (!test_SecurityDescriptorInheritance(p, tctx, handle, key)) {
776                 printf("test_SecurityDescriptorInheritance failed\n");
777                 ret = false;
778         }
779
780         if (!test_SecurityDescriptorBlockInheritance(p, tctx, handle, key)) {
781                 printf("test_SecurityDescriptorBlockInheritance failed\n");
782                 ret = false;
783         }
784
785         return ret;
786 }
787
788 static bool test_DeleteKey(struct dcerpc_pipe *p, struct torture_context *tctx,
789                            struct policy_handle *handle, const char *key)
790 {
791         NTSTATUS status;
792         struct winreg_DeleteKey r;
793
794         r.in.handle = handle;
795         init_winreg_String(&r.in.key, key);
796
797         status = dcerpc_winreg_DeleteKey(p, tctx, &r);
798
799         torture_assert_ntstatus_ok(tctx, status, "DeleteKey failed");
800         torture_assert_werr_ok(tctx, r.out.result, "DeleteKey failed");
801
802         return true;
803 }
804
805 /* DeleteKey on a key with subkey(s) should
806  * return WERR_ACCESS_DENIED. */
807 static bool test_DeleteKeyWithSubkey(struct dcerpc_pipe *p,
808                                      struct torture_context *tctx,
809                                      struct policy_handle *handle,
810                                      const char *key)
811 {
812         struct winreg_DeleteKey r;
813
814         r.in.handle = handle;
815         init_winreg_String(&r.in.key, key);
816
817         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_DeleteKey(p, tctx, &r),
818                                    "DeleteKeyWithSubkey failed");
819
820         torture_assert_werr_equal(tctx, r.out.result, WERR_ACCESS_DENIED,
821                                   "DeleteKeyWithSubkey failed");
822
823         return true;
824 }
825
826 static bool test_QueryInfoKey(struct dcerpc_pipe *p,
827                               struct torture_context *tctx,
828                               struct policy_handle *handle, char *class)
829 {
830         struct winreg_QueryInfoKey r;
831         uint32_t num_subkeys, max_subkeylen, max_subkeysize,
832                 num_values, max_valnamelen, max_valbufsize,
833                 secdescsize;
834         NTTIME last_changed_time;
835
836         ZERO_STRUCT(r);
837         r.in.handle = handle;
838         r.out.num_subkeys = &num_subkeys;
839         r.out.max_subkeylen = &max_subkeylen;
840         r.out.max_subkeysize = &max_subkeysize;
841         r.out.num_values = &num_values;
842         r.out.max_valnamelen = &max_valnamelen;
843         r.out.max_valbufsize = &max_valbufsize;
844         r.out.secdescsize = &secdescsize;
845         r.out.last_changed_time = &last_changed_time;
846
847         r.out.classname = talloc(tctx, struct winreg_String);
848
849         r.in.classname = talloc(tctx, struct winreg_String);
850         init_winreg_String(r.in.classname, class);
851
852         torture_assert_ntstatus_ok(tctx,
853                                    dcerpc_winreg_QueryInfoKey(p, tctx, &r),
854                                    "QueryInfoKey failed");
855
856         torture_assert_werr_ok(tctx, r.out.result, "QueryInfoKey failed");
857
858         return true;
859 }
860
861 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
862                      struct policy_handle *handle, int depth);
863
864 static bool test_EnumKey(struct dcerpc_pipe *p, struct torture_context *tctx,
865                          struct policy_handle *handle, int depth)
866 {
867         struct winreg_EnumKey r;
868         struct winreg_StringBuf class, name;
869         NTSTATUS status;
870         NTTIME t = 0;
871
872         class.name   = "";
873         class.size   = 1024;
874
875         r.in.handle = handle;
876         r.in.enum_index = 0;
877         r.in.name = &name;
878         r.in.keyclass = &class;
879         r.out.name = &name;
880         r.in.last_changed_time = &t;
881
882         do {
883                 name.name   = NULL;
884                 name.size   = 1024;
885
886                 status = dcerpc_winreg_EnumKey(p, tctx, &r);
887
888                 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
889                         struct policy_handle key_handle;
890
891                         torture_comment(tctx, "EnumKey: %d: %s\n",
892                                         r.in.enum_index,
893                                         r.out.name->name);
894
895                         if (!test_OpenKey(p, tctx, handle, r.out.name->name,
896                                           &key_handle)) {
897                         } else {
898                                 test_key(p, tctx, &key_handle, depth + 1);
899                         }
900                 }
901
902                 r.in.enum_index++;
903
904         } while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result));
905
906         torture_assert_ntstatus_ok(tctx, status, "EnumKey failed");
907
908         if (!W_ERROR_IS_OK(r.out.result) &&
909                 !W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
910                 torture_fail(tctx, "EnumKey failed");
911         }
912
913         return true;
914 }
915
916 static bool test_QueryMultipleValues(struct dcerpc_pipe *p,
917                                      struct torture_context *tctx,
918                                      struct policy_handle *handle,
919                                      const char *valuename)
920 {
921         struct winreg_QueryMultipleValues r;
922         NTSTATUS status;
923         uint32_t bufsize=0;
924
925         r.in.key_handle = handle;
926         r.in.values = r.out.values = talloc_array(tctx, struct QueryMultipleValue, 1);
927         r.in.values[0].name = talloc(tctx, struct winreg_String);
928         r.in.values[0].name->name = valuename;
929         r.in.values[0].offset = 0;
930         r.in.values[0].length = 0;
931         r.in.values[0].type = 0;
932
933         r.in.num_values = 1;
934         r.in.buffer_size = r.out.buffer_size = talloc(tctx, uint32_t);
935         *r.in.buffer_size = bufsize;
936         do {
937                 *r.in.buffer_size = bufsize;
938                 r.in.buffer = r.out.buffer = talloc_zero_array(tctx, uint8_t,
939                                                                *r.in.buffer_size);
940
941                 status = dcerpc_winreg_QueryMultipleValues(p, tctx, &r);
942
943                 if(NT_STATUS_IS_ERR(status))
944                         torture_fail(tctx, "QueryMultipleValues failed");
945
946                 talloc_free(r.in.buffer);
947                 bufsize += 0x20;
948         } while (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
949
950         torture_assert_werr_ok(tctx, r.out.result, "QueryMultipleValues failed");
951
952         return true;
953 }
954
955 static bool test_QueryValue(struct dcerpc_pipe *p,
956                             struct torture_context *tctx,
957                             struct policy_handle *handle,
958                             const char *valuename)
959 {
960         struct winreg_QueryValue r;
961         NTSTATUS status;
962         enum winreg_Type zero_type = 0;
963         uint32_t offered = 0xfff;
964         uint32_t zero = 0;
965
966         r.in.handle = handle;
967         r.in.data = NULL;
968         r.in.value_name.name = valuename;
969         r.in.type = &zero_type;
970         r.in.size = &offered;
971         r.in.length = &zero;
972
973         status = dcerpc_winreg_QueryValue(p, tctx, &r);
974         if (NT_STATUS_IS_ERR(status)) {
975                 torture_fail(tctx, "QueryValue failed");
976         }
977
978         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
979
980         return true;
981 }
982
983 static bool test_EnumValue(struct dcerpc_pipe *p, struct torture_context *tctx,
984                            struct policy_handle *handle, int max_valnamelen,
985                            int max_valbufsize)
986 {
987         struct winreg_EnumValue r;
988         enum winreg_Type type = 0;
989         uint32_t size = max_valbufsize, zero = 0;
990         bool ret = true;
991         uint8_t buf8;
992         struct winreg_StringBuf name;
993
994         name.name   = "";
995         name.size   = 1024;
996
997         r.in.handle = handle;
998         r.in.enum_index = 0;
999         r.in.name = &name;
1000         r.out.name = &name;
1001         r.in.type = &type;
1002         r.in.value = &buf8;
1003         r.in.length = &zero;
1004         r.in.size = &size;
1005
1006         do {
1007                 torture_assert_ntstatus_ok(tctx,
1008                                            dcerpc_winreg_EnumValue(p, tctx, &r),
1009                                            "EnumValue failed");
1010
1011                 if (W_ERROR_IS_OK(r.out.result)) {
1012                         ret &= test_QueryValue(p, tctx, handle,
1013                                                r.out.name->name);
1014                         ret &= test_QueryMultipleValues(p, tctx, handle,
1015                                                         r.out.name->name);
1016                 }
1017
1018                 r.in.enum_index++;
1019         } while (W_ERROR_IS_OK(r.out.result));
1020
1021         torture_assert_werr_equal(tctx, r.out.result, WERR_NO_MORE_ITEMS,
1022                                   "EnumValue failed");
1023
1024         return ret;
1025 }
1026
1027 static bool test_AbortSystemShutdown(struct dcerpc_pipe *p,
1028                                      struct torture_context *tctx)
1029 {
1030         struct winreg_AbortSystemShutdown r;
1031         uint16_t server = 0x0;
1032
1033         r.in.server = &server;
1034
1035         torture_assert_ntstatus_ok(tctx,
1036                                    dcerpc_winreg_AbortSystemShutdown(p, tctx, &r),
1037                                    "AbortSystemShutdown failed");
1038
1039         torture_assert_werr_ok(tctx, r.out.result,
1040                                "AbortSystemShutdown failed");
1041
1042         return true;
1043 }
1044
1045 static bool test_InitiateSystemShutdown(struct torture_context *tctx,
1046                                         struct dcerpc_pipe *p)
1047 {
1048         struct winreg_InitiateSystemShutdown r;
1049         uint16_t hostname = 0x0;
1050
1051         r.in.hostname = &hostname;
1052         r.in.message = talloc(tctx, struct initshutdown_String);
1053         init_initshutdown_String(tctx, r.in.message, "spottyfood");
1054         r.in.force_apps = 1;
1055         r.in.timeout = 30;
1056         r.in.reboot = 1;
1057
1058         torture_assert_ntstatus_ok(tctx,
1059                                    dcerpc_winreg_InitiateSystemShutdown(p, tctx, &r),
1060                                    "InitiateSystemShutdown failed");
1061
1062         torture_assert_werr_ok(tctx, r.out.result,
1063                                "InitiateSystemShutdown failed");
1064
1065         return test_AbortSystemShutdown(p, tctx);
1066 }
1067
1068
1069 static bool test_InitiateSystemShutdownEx(struct torture_context *tctx,
1070                                           struct dcerpc_pipe *p)
1071 {
1072         struct winreg_InitiateSystemShutdownEx r;
1073         uint16_t hostname = 0x0;
1074
1075         r.in.hostname = &hostname;
1076         r.in.message = talloc(tctx, struct initshutdown_String);
1077         init_initshutdown_String(tctx, r.in.message, "spottyfood");
1078         r.in.force_apps = 1;
1079         r.in.timeout = 30;
1080         r.in.reboot = 1;
1081         r.in.reason = 0;
1082
1083         torture_assert_ntstatus_ok(tctx,
1084                 dcerpc_winreg_InitiateSystemShutdownEx(p, tctx, &r),
1085                 "InitiateSystemShutdownEx failed");
1086
1087         torture_assert_werr_ok(tctx, r.out.result,
1088                                "InitiateSystemShutdownEx failed");
1089
1090         return test_AbortSystemShutdown(p, tctx);
1091 }
1092 #define MAX_DEPTH 2             /* Only go this far down the tree */
1093
1094 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
1095                      struct policy_handle *handle, int depth)
1096 {
1097         if (depth == MAX_DEPTH)
1098                 return true;
1099
1100         if (!test_QueryInfoKey(p, tctx, handle, NULL)) {
1101         }
1102
1103         if (!test_NotifyChangeKeyValue(p, tctx, handle)) {
1104         }
1105
1106         if (!test_GetKeySecurity(p, tctx, handle, NULL)) {
1107         }
1108
1109         if (!test_EnumKey(p, tctx, handle, depth)) {
1110         }
1111
1112         if (!test_EnumValue(p, tctx, handle, 0xFF, 0xFFFF)) {
1113         }
1114
1115         test_CloseKey(p, tctx, handle);
1116
1117         return true;
1118 }
1119
1120 typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_pipe *, TALLOC_CTX *, void *);
1121
1122 static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
1123                       void *userdata)
1124 {
1125         struct policy_handle handle, newhandle;
1126         bool ret = true, created = false, created2 = false, deleted = false;
1127         bool created3 = false, created_subkey = false;
1128         bool created4 = false;
1129         struct winreg_OpenHKLM r;
1130
1131         winreg_open_fn open_fn = userdata;
1132
1133         r.in.system_name = 0;
1134         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1135         r.out.handle = &handle;
1136
1137         torture_assert_ntstatus_ok(tctx, open_fn(p, tctx, &r),
1138                                    "open");
1139
1140         test_Cleanup(p, tctx, &handle, TEST_KEY1);
1141         test_Cleanup(p, tctx, &handle, TEST_SUBSUBKEY_SD);
1142         test_Cleanup(p, tctx, &handle, TEST_SUBKEY_SD);
1143         test_Cleanup(p, tctx, &handle, TEST_KEY4);
1144         test_Cleanup(p, tctx, &handle, TEST_KEY2);
1145         test_Cleanup(p, tctx, &handle, TEST_SUBKEY);
1146         test_Cleanup(p, tctx, &handle, TEST_KEY3);
1147         test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
1148
1149         if (!test_CreateKey(p, tctx, &handle, TEST_KEY1, NULL)) {
1150                 torture_comment(tctx,
1151                                 "CreateKey failed - not considering a failure\n");
1152         } else {
1153                 created = true;
1154         }
1155
1156         if (created && !test_FlushKey(p, tctx, &handle)) {
1157                 torture_comment(tctx, "FlushKey failed\n");
1158                 ret = false;
1159         }
1160
1161         if (created && !test_OpenKey(p, tctx, &handle, TEST_KEY1, &newhandle))
1162                 torture_fail(tctx,
1163                              "CreateKey failed (OpenKey after Create didn't work)\n");
1164
1165         if (created && !test_CloseKey(p, tctx, &newhandle))
1166                 torture_fail(tctx,
1167                              "CreateKey failed (CloseKey after Open didn't work)\n");
1168
1169         if (created && !test_DeleteKey(p, tctx, &handle, TEST_KEY1)) {
1170                 torture_comment(tctx, "DeleteKey failed\n");
1171                 ret = false;
1172         } else {
1173                 deleted = true;
1174         }
1175
1176         if (created && !test_FlushKey(p, tctx, &handle)) {
1177                 torture_comment(tctx, "FlushKey failed\n");
1178                 ret = false;
1179         }
1180
1181         if (created && deleted &&
1182             test_OpenKey(p, tctx, &handle, TEST_KEY1, &newhandle)) {
1183                 torture_comment(tctx,
1184                                 "DeleteKey failed (OpenKey after Delete worked)\n");
1185                 ret = false;
1186         }
1187
1188         if (!test_GetVersion(p, tctx, &handle)) {
1189                 torture_comment(tctx, "GetVersion failed\n");
1190                 ret = false;
1191         }
1192
1193         if (created && test_CreateKey_sd(p, tctx, &handle, TEST_KEY2,
1194                                          NULL, &newhandle)) {
1195                 created2 = true;
1196         }
1197
1198         if (created2 && !test_CloseKey(p, tctx, &newhandle)) {
1199                 printf("CloseKey failed\n");
1200                 ret = false;
1201         }
1202
1203         if (test_CreateKey_sd(p, tctx, &handle, TEST_KEY4, NULL, &newhandle)) {
1204                 created4 = true;
1205         }
1206
1207         if (!created4 && !test_CloseKey(p, tctx, &newhandle)) {
1208                 printf("CloseKey failed\n");
1209                 ret = false;
1210         }
1211
1212         if (created4 && !test_SecurityDescriptors(p, tctx, &handle, TEST_KEY4)) {
1213                 ret = false;
1214         }
1215
1216         if (created4 && !test_DeleteKey(p, tctx, &handle, TEST_KEY4)) {
1217                 printf("DeleteKey failed\n");
1218                 ret = false;
1219         }
1220
1221
1222         if (created && !test_DeleteKey(p, tctx, &handle, TEST_KEY2)) {
1223                 printf("DeleteKey failed\n");
1224                 ret = false;
1225         }
1226
1227         if (created && test_CreateKey(p, tctx, &handle, TEST_KEY3, NULL)) {
1228                 created3 = true;
1229         }
1230
1231         if (created3 &&
1232             test_CreateKey(p, tctx, &handle, TEST_SUBKEY, NULL)) {
1233                 created_subkey = true;
1234         }
1235
1236         if (created_subkey &&
1237             !test_DeleteKeyWithSubkey(p, tctx, &handle, TEST_KEY3)) {
1238                 printf("DeleteKeyWithSubkey failed "
1239                        "(DeleteKey didn't return ACCESS_DENIED)\n");
1240                 ret = false;
1241         }
1242
1243         if (created_subkey &&
1244             !test_DeleteKey(p, tctx, &handle, TEST_SUBKEY)) {
1245                 printf("DeleteKey failed\n");
1246                 ret = false;
1247         }
1248
1249         if (created3 &&
1250             !test_DeleteKey(p, tctx, &handle, TEST_KEY3)) {
1251                 printf("DeleteKey failed\n");
1252                 ret = false;
1253         }
1254
1255         /* The HKCR hive has a very large fanout */
1256         if (open_fn == (void *)dcerpc_winreg_OpenHKCR) {
1257                 if(!test_key(p, tctx, &handle, MAX_DEPTH - 1)) {
1258                         ret = false;
1259                 }
1260         }
1261
1262         if (!test_key(p, tctx, &handle, 0)) {
1263                 ret = false;
1264         }
1265
1266         test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
1267
1268         return ret;
1269 }
1270
1271 struct torture_suite *torture_rpc_winreg(TALLOC_CTX *mem_ctx)
1272 {
1273         struct {
1274                 const char *name;
1275                 winreg_open_fn fn;
1276         } open_fns[] = {{"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM },
1277                         {"OpenHKU",  (winreg_open_fn)dcerpc_winreg_OpenHKU },
1278                         {"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR },
1279                         {"OpenHKCU", (winreg_open_fn)dcerpc_winreg_OpenHKCU }};
1280         int i;
1281         struct torture_rpc_tcase *tcase;
1282         struct torture_suite *suite = torture_suite_create(mem_ctx, "WINREG");
1283         struct torture_test *test;
1284
1285         tcase = torture_suite_add_rpc_iface_tcase(suite, "winreg",
1286                                                   &ndr_table_winreg);
1287
1288         test = torture_rpc_tcase_add_test(tcase, "InitiateSystemShutdown",
1289                                           test_InitiateSystemShutdown);
1290         test->dangerous = true;
1291
1292         test = torture_rpc_tcase_add_test(tcase, "InitiateSystemShutdownEx",
1293                                           test_InitiateSystemShutdownEx);
1294         test->dangerous = true;
1295
1296         for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
1297                 torture_rpc_tcase_add_test_ex(tcase, open_fns[i].name,
1298                                               test_Open, open_fns[i].fn);
1299         }
1300
1301         return suite;
1302 }