r25609: Reformat RPC-WINREG test.
[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_SUBKEY TEST_KEY3 "\\subkey"
34
35 static void init_initshutdown_String(TALLOC_CTX *mem_ctx,
36                                      struct initshutdown_String *name,
37                                      const char *s)
38 {
39         name->name = talloc(mem_ctx, struct initshutdown_String_sub);
40         name->name->name = s;
41 }
42
43 static void init_winreg_String(struct winreg_String *name, const char *s)
44 {
45         name->name = s;
46         if (s) {
47                 name->name_len = 2 * (strlen_m(s) + 1);
48                 name->name_size = name->name_len;
49         } else {
50                 name->name_len = 0;
51                 name->name_size = 0;
52         }
53 }
54
55 static bool test_GetVersion(struct dcerpc_pipe *p,
56                             struct torture_context *tctx,
57                             struct policy_handle *handle)
58 {
59         struct winreg_GetVersion r;
60         uint32_t v;
61
62         ZERO_STRUCT(r);
63         r.in.handle = handle;
64         r.out.version = &v;
65
66         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_GetVersion(p, tctx, &r),
67                                    "GetVersion failed");
68
69         torture_assert_werr_ok(tctx, r.out.result, "GetVersion failed");
70
71         return true;
72 }
73
74 static bool test_NotifyChangeKeyValue(struct dcerpc_pipe *p,
75                                       struct torture_context *tctx,
76                                       struct policy_handle *handle)
77 {
78         struct winreg_NotifyChangeKeyValue r;
79
80         r.in.handle = handle;
81         r.in.watch_subtree = 1;
82         r.in.notify_filter = 0;
83         r.in.unknown = r.in.unknown2 = 0;
84         init_winreg_String(&r.in.string1, NULL);
85         init_winreg_String(&r.in.string2, NULL);
86
87         torture_assert_ntstatus_ok(tctx,
88                                    dcerpc_winreg_NotifyChangeKeyValue(p, tctx, &r),
89                                    "NotifyChangeKeyValue failed");
90
91         if (!W_ERROR_IS_OK(r.out.result)) {
92                 torture_comment(tctx,
93                                 "NotifyChangeKeyValue failed - %s - not considering\n", win_errstr(r.out.result));
94                 return true;
95         }
96
97         return true;
98 }
99
100 static bool test_CreateKey(struct dcerpc_pipe *p, struct torture_context *tctx,
101                            struct policy_handle *handle, const char *name,
102                            const char *class)
103 {
104         struct winreg_CreateKey r;
105         struct policy_handle newhandle;
106         enum winreg_CreateAction action_taken = 0;
107
108         r.in.handle = handle;
109         r.out.new_handle = &newhandle;
110         init_winreg_String(&r.in.name, name);
111         init_winreg_String(&r.in.keyclass, class);
112         r.in.options = 0x0;
113         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
114         r.in.action_taken = r.out.action_taken = &action_taken;
115         r.in.secdesc = NULL;
116
117         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CreateKey(p, tctx, &r),
118                                    "CreateKey failed");
119
120         torture_assert_werr_ok(tctx,  r.out.result, "CreateKey failed");
121
122         return true;
123 }
124
125
126 /*
127   createkey testing with a SD
128 */
129 static bool test_CreateKey_sd(struct dcerpc_pipe *p,
130                               struct torture_context *tctx,
131                               struct policy_handle *handle, const char *name,
132                               const char *class,
133                               struct policy_handle *newhandle)
134 {
135         struct winreg_CreateKey r;
136         enum winreg_CreateAction action_taken = 0;
137         struct security_descriptor *sd;
138         DATA_BLOB sdblob;
139         struct winreg_SecBuf secbuf;
140
141         sd = security_descriptor_create(tctx,
142                                         0,
143                                         NULL, NULL,
144                                         SID_NT_AUTHENTICATED_USERS,
145                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
146                                         SEC_GENERIC_ALL,
147                                         SEC_ACE_FLAG_OBJECT_INHERIT,
148                                         NULL);
149
150         torture_assert_ntstatus_ok(tctx,
151                 ndr_push_struct_blob(&sdblob, tctx, sd,
152                                      (ndr_push_flags_fn_t)ndr_push_security_descriptor),
153                                      "Failed to push security_descriptor ?!\n");
154
155         secbuf.sd.data = sdblob.data;
156         secbuf.sd.len = sdblob.length;
157         secbuf.sd.size = sdblob.length;
158         secbuf.length = sdblob.length-10;
159         secbuf.inherit = 0;
160
161         r.in.handle = handle;
162         r.out.new_handle = newhandle;
163         init_winreg_String(&r.in.name, name);
164         init_winreg_String(&r.in.keyclass, class);
165         r.in.options = 0x0;
166         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
167         r.in.action_taken = r.out.action_taken = &action_taken;
168         r.in.secdesc = &secbuf;
169
170         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CreateKey(p, tctx, &r),
171                                    "CreateKey with sd failed");
172
173         torture_assert_werr_ok(tctx, r.out.result, "CreateKey with sd failed");
174
175         return true;
176 }
177
178 static bool test_GetKeySecurity(struct dcerpc_pipe *p,
179                                 struct torture_context *tctx,
180                                 struct policy_handle *handle,
181                                 struct security_descriptor **sd_out)
182 {
183         struct winreg_GetKeySecurity r;
184         struct security_descriptor *sd;
185         DATA_BLOB sdblob;
186
187         ZERO_STRUCT(r);
188
189         r.in.handle = handle;
190         r.in.sd = r.out.sd = talloc_zero(tctx, struct KeySecurityData);
191         r.in.sd->size = 0x1000;
192         r.in.sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
193
194         torture_assert_ntstatus_ok(tctx,
195                                    dcerpc_winreg_GetKeySecurity(p, tctx, &r),
196                                    "GetKeySecurity failed");
197
198         torture_assert_werr_ok(tctx, r.out.result, "GetKeySecurity failed");
199
200         sdblob.data = r.out.sd->data;
201         sdblob.length = r.out.sd->len;
202
203         torture_assert_ntstatus_ok(tctx,
204                 ndr_pull_struct_blob(&sdblob, tctx, sd,
205                                      (ndr_pull_flags_fn_t)ndr_pull_security_descriptor),
206                                      "pull_security_descriptor failed");
207
208         if (p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
209                 NDR_PRINT_DEBUG(security_descriptor, sd);
210         }
211
212         if (sd_out) {
213                 *sd_out = sd;
214         }
215
216         return true;
217 }
218
219 static bool test_CloseKey(struct dcerpc_pipe *p, struct torture_context *tctx,
220                           struct policy_handle *handle)
221 {
222         struct winreg_CloseKey r;
223
224         r.in.handle = r.out.handle = handle;
225
226         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey(p, tctx, &r),
227                                    "CloseKey failed");
228
229         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
230
231         return true;
232 }
233
234 static bool test_FlushKey(struct dcerpc_pipe *p, struct torture_context *tctx,
235                           struct policy_handle *handle)
236 {
237         struct winreg_FlushKey r;
238
239         r.in.handle = handle;
240
241         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_FlushKey(p, tctx, &r),
242                                    "FlushKey failed");
243
244         torture_assert_werr_ok(tctx, r.out.result, "FlushKey failed");
245
246         return true;
247 }
248
249 static bool test_OpenKey(struct dcerpc_pipe *p, struct torture_context *tctx,
250                          struct policy_handle *hive_handle,
251                          const char *keyname, struct policy_handle *key_handle)
252 {
253         struct winreg_OpenKey r;
254
255         r.in.parent_handle = hive_handle;
256         init_winreg_String(&r.in.keyname, keyname);
257         r.in.unknown = 0x00000000;
258         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
259         r.out.handle = key_handle;
260
261         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey(p, tctx, &r),
262                                    "OpenKey failed");
263
264         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
265
266         return true;
267 }
268
269 static bool test_Cleanup(struct dcerpc_pipe *p, struct torture_context *tctx,
270                          struct policy_handle *handle, const char *key)
271 {
272         struct winreg_DeleteKey r;
273
274         r.in.handle = handle;
275
276         init_winreg_String(&r.in.key, key);
277         dcerpc_winreg_DeleteKey(p, tctx, &r);
278
279         return true;
280 }
281
282
283 static bool test_DeleteKey(struct dcerpc_pipe *p, struct torture_context *tctx,
284                            struct policy_handle *handle, const char *key)
285 {
286         NTSTATUS status;
287         struct winreg_DeleteKey r;
288
289         r.in.handle = handle;
290         init_winreg_String(&r.in.key, key);
291
292         status = dcerpc_winreg_DeleteKey(p, tctx, &r);
293
294         torture_assert_ntstatus_ok(tctx, status, "DeleteKey failed");
295         torture_assert_werr_ok(tctx, r.out.result, "DeleteKey failed");
296
297         return true;
298 }
299
300 /* DeleteKey on a key with subkey(s) should
301  * return WERR_ACCESS_DENIED. */
302 static bool test_DeleteKeyWithSubkey(struct dcerpc_pipe *p,
303                                      struct torture_context *tctx,
304                                      struct policy_handle *handle,
305                                      const char *key)
306 {
307         struct winreg_DeleteKey r;
308
309         r.in.handle = handle;
310         init_winreg_String(&r.in.key, key);
311
312         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_DeleteKey(p, tctx, &r),
313                                    "DeleteKeyWithSubkey failed");
314
315         torture_assert_werr_equal(tctx, r.out.result, WERR_ACCESS_DENIED,
316                                   "DeleteKeyWithSubkey failed");
317
318         return true;
319 }
320
321 static bool test_QueryInfoKey(struct dcerpc_pipe *p,
322                               struct torture_context *tctx,
323                               struct policy_handle *handle, char *class)
324 {
325         struct winreg_QueryInfoKey r;
326         uint32_t num_subkeys, max_subkeylen, max_subkeysize,
327                 num_values, max_valnamelen, max_valbufsize,
328                 secdescsize;
329         NTTIME last_changed_time;
330
331         ZERO_STRUCT(r);
332         r.in.handle = handle;
333         r.out.num_subkeys = &num_subkeys;
334         r.out.max_subkeylen = &max_subkeylen;
335         r.out.max_subkeysize = &max_subkeysize;
336         r.out.num_values = &num_values;
337         r.out.max_valnamelen = &max_valnamelen;
338         r.out.max_valbufsize = &max_valbufsize;
339         r.out.secdescsize = &secdescsize;
340         r.out.last_changed_time = &last_changed_time;
341
342         r.out.classname = talloc(tctx, struct winreg_String);
343
344         r.in.classname = talloc(tctx, struct winreg_String);
345         init_winreg_String(r.in.classname, class);
346
347         torture_assert_ntstatus_ok(tctx,
348                                    dcerpc_winreg_QueryInfoKey(p, tctx, &r),
349                                    "QueryInfoKey failed");
350
351         torture_assert_werr_ok(tctx, r.out.result, "QueryInfoKey failed");
352
353         return true;
354 }
355
356 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
357                      struct policy_handle *handle, int depth);
358
359 static bool test_EnumKey(struct dcerpc_pipe *p, struct torture_context *tctx,
360                          struct policy_handle *handle, int depth)
361 {
362         struct winreg_EnumKey r;
363         struct winreg_StringBuf class, name;
364         NTSTATUS status;
365         NTTIME t = 0;
366
367         class.name   = "";
368         class.size   = 1024;
369
370         r.in.handle = handle;
371         r.in.enum_index = 0;
372         r.in.name = &name;
373         r.in.keyclass = &class;
374         r.out.name = &name;
375         r.in.last_changed_time = &t;
376
377         do {
378                 name.name   = NULL;
379                 name.size   = 1024;
380
381                 status = dcerpc_winreg_EnumKey(p, tctx, &r);
382
383                 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
384                         struct policy_handle key_handle;
385
386                         torture_comment(tctx, "EnumKey: %d: %s\n",
387                                         r.in.enum_index,
388                                         r.out.name->name);
389
390                         if (!test_OpenKey(p, tctx, handle, r.out.name->name,
391                                           &key_handle)) {
392                         } else {
393                                 test_key(p, tctx, &key_handle, depth + 1);
394                         }
395                 }
396
397                 r.in.enum_index++;
398
399         } while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result));
400
401         torture_assert_ntstatus_ok(tctx, status, "EnumKey failed");
402
403         if (!W_ERROR_IS_OK(r.out.result) &&
404                 !W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
405                 torture_fail(tctx, "EnumKey failed");
406         }
407
408         return true;
409 }
410
411 static bool test_QueryMultipleValues(struct dcerpc_pipe *p,
412                                      struct torture_context *tctx,
413                                      struct policy_handle *handle,
414                                      const char *valuename)
415 {
416         struct winreg_QueryMultipleValues r;
417         NTSTATUS status;
418         uint32_t bufsize=0;
419
420         r.in.key_handle = handle;
421         r.in.values = r.out.values = talloc_array(tctx, struct QueryMultipleValue, 1);
422         r.in.values[0].name = talloc(tctx, struct winreg_String);
423         r.in.values[0].name->name = valuename;
424         r.in.values[0].offset = 0;
425         r.in.values[0].length = 0;
426         r.in.values[0].type = 0;
427
428         r.in.num_values = 1;
429         r.in.buffer_size = r.out.buffer_size = talloc(tctx, uint32_t);
430         *r.in.buffer_size = bufsize;
431         do {
432                 *r.in.buffer_size = bufsize;
433                 r.in.buffer = r.out.buffer = talloc_zero_array(tctx, uint8_t,
434                                                                *r.in.buffer_size);
435
436                 status = dcerpc_winreg_QueryMultipleValues(p, tctx, &r);
437
438                 if(NT_STATUS_IS_ERR(status))
439                         torture_fail(tctx, "QueryMultipleValues failed");
440
441                 talloc_free(r.in.buffer);
442                 bufsize += 0x20;
443         } while (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
444
445         torture_assert_werr_ok(tctx, r.out.result, "QueryMultipleValues failed");
446
447         return true;
448 }
449
450 static bool test_QueryValue(struct dcerpc_pipe *p,
451                             struct torture_context *tctx,
452                             struct policy_handle *handle,
453                             const char *valuename)
454 {
455         struct winreg_QueryValue r;
456         NTSTATUS status;
457         enum winreg_Type zero_type = 0;
458         uint32_t offered = 0xfff;
459         uint32_t zero = 0;
460
461         r.in.handle = handle;
462         r.in.data = NULL;
463         r.in.value_name.name = valuename;
464         r.in.type = &zero_type;
465         r.in.size = &offered;
466         r.in.length = &zero;
467
468         status = dcerpc_winreg_QueryValue(p, tctx, &r);
469         if (NT_STATUS_IS_ERR(status)) {
470                 torture_fail(tctx, "QueryValue failed");
471         }
472
473         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
474
475         return true;
476 }
477
478 static bool test_EnumValue(struct dcerpc_pipe *p, struct torture_context *tctx,
479                            struct policy_handle *handle, int max_valnamelen,
480                            int max_valbufsize)
481 {
482         struct winreg_EnumValue r;
483         enum winreg_Type type = 0;
484         uint32_t size = max_valbufsize, zero = 0;
485         bool ret = true;
486         uint8_t buf8;
487         struct winreg_StringBuf name;
488
489         name.name   = "";
490         name.size   = 1024;
491
492         r.in.handle = handle;
493         r.in.enum_index = 0;
494         r.in.name = &name;
495         r.out.name = &name;
496         r.in.type = &type;
497         r.in.value = &buf8;
498         r.in.length = &zero;
499         r.in.size = &size;
500
501         do {
502                 torture_assert_ntstatus_ok(tctx,
503                                            dcerpc_winreg_EnumValue(p, tctx, &r),
504                                            "EnumValue failed");
505
506                 if (W_ERROR_IS_OK(r.out.result)) {
507                         ret &= test_QueryValue(p, tctx, handle,
508                                                r.out.name->name);
509                         ret &= test_QueryMultipleValues(p, tctx, handle,
510                                                         r.out.name->name);
511                 }
512
513                 r.in.enum_index++;
514         } while (W_ERROR_IS_OK(r.out.result));
515
516         torture_assert_werr_equal(tctx, r.out.result, WERR_NO_MORE_ITEMS,
517                                   "EnumValue failed");
518
519         return ret;
520 }
521
522 static bool test_AbortSystemShutdown(struct dcerpc_pipe *p,
523                                      struct torture_context *tctx)
524 {
525         struct winreg_AbortSystemShutdown r;
526         uint16_t server = 0x0;
527
528         r.in.server = &server;
529
530         torture_assert_ntstatus_ok(tctx,
531                                    dcerpc_winreg_AbortSystemShutdown(p, tctx, &r),
532                                    "AbortSystemShutdown failed");
533
534         torture_assert_werr_ok(tctx, r.out.result,
535                                "AbortSystemShutdown failed");
536
537         return true;
538 }
539
540 static bool test_InitiateSystemShutdown(struct torture_context *tctx,
541                                         struct dcerpc_pipe *p)
542 {
543         struct winreg_InitiateSystemShutdown r;
544         uint16_t hostname = 0x0;
545
546         r.in.hostname = &hostname;
547         r.in.message = talloc(tctx, struct initshutdown_String);
548         init_initshutdown_String(tctx, r.in.message, "spottyfood");
549         r.in.force_apps = 1;
550         r.in.timeout = 30;
551         r.in.reboot = 1;
552
553         torture_assert_ntstatus_ok(tctx,
554                                    dcerpc_winreg_InitiateSystemShutdown(p, tctx, &r),
555                                    "InitiateSystemShutdown failed");
556
557         torture_assert_werr_ok(tctx, r.out.result,
558                                "InitiateSystemShutdown failed");
559
560         return test_AbortSystemShutdown(p, tctx);
561 }
562
563
564 static bool test_InitiateSystemShutdownEx(struct torture_context *tctx,
565                                           struct dcerpc_pipe *p)
566 {
567         struct winreg_InitiateSystemShutdownEx r;
568         uint16_t hostname = 0x0;
569
570         r.in.hostname = &hostname;
571         r.in.message = talloc(tctx, struct initshutdown_String);
572         init_initshutdown_String(tctx, r.in.message, "spottyfood");
573         r.in.force_apps = 1;
574         r.in.timeout = 30;
575         r.in.reboot = 1;
576         r.in.reason = 0;
577
578         torture_assert_ntstatus_ok(tctx,
579                 dcerpc_winreg_InitiateSystemShutdownEx(p, tctx, &r),
580                 "InitiateSystemShutdownEx failed");
581
582         torture_assert_werr_ok(tctx, r.out.result,
583                                "InitiateSystemShutdownEx failed");
584
585         return test_AbortSystemShutdown(p, tctx);
586 }
587 #define MAX_DEPTH 2             /* Only go this far down the tree */
588
589 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
590                      struct policy_handle *handle, int depth)
591 {
592         if (depth == MAX_DEPTH)
593                 return true;
594
595         if (!test_QueryInfoKey(p, tctx, handle, NULL)) {
596         }
597
598         if (!test_NotifyChangeKeyValue(p, tctx, handle)) {
599         }
600
601         if (!test_GetKeySecurity(p, tctx, handle, NULL)) {
602         }
603
604         if (!test_EnumKey(p, tctx, handle, depth)) {
605         }
606
607         if (!test_EnumValue(p, tctx, handle, 0xFF, 0xFFFF)) {
608         }
609
610         test_CloseKey(p, tctx, handle);
611
612         return true;
613 }
614
615 typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_pipe *, TALLOC_CTX *, void *);
616
617 static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
618                       void *userdata)
619 {
620         struct policy_handle handle, newhandle;
621         bool ret = true, created = false, created2 = false, deleted = false;
622         bool created3 = false, created_subkey = false;
623         struct winreg_OpenHKLM r;
624
625         winreg_open_fn open_fn = userdata;
626
627         r.in.system_name = 0;
628         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
629         r.out.handle = &handle;
630
631         torture_assert_ntstatus_ok(tctx, open_fn(p, tctx, &r),
632                                    "open");
633
634         test_Cleanup(p, tctx, &handle, TEST_KEY1);
635         test_Cleanup(p, tctx, &handle, TEST_KEY2);
636         test_Cleanup(p, tctx, &handle, TEST_SUBKEY);
637         test_Cleanup(p, tctx, &handle, TEST_KEY3);
638         test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
639
640         if (!test_CreateKey(p, tctx, &handle, TEST_KEY1, NULL)) {
641                 torture_comment(tctx,
642                                 "CreateKey failed - not considering a failure\n");
643         } else {
644                 created = true;
645         }
646
647         if (created && !test_FlushKey(p, tctx, &handle)) {
648                 torture_comment(tctx, "FlushKey failed\n");
649                 ret = false;
650         }
651
652         if (created && !test_OpenKey(p, tctx, &handle, TEST_KEY1, &newhandle))
653                 torture_fail(tctx,
654                              "CreateKey failed (OpenKey after Create didn't work)\n");
655
656         if (created && !test_DeleteKey(p, tctx, &handle, TEST_KEY1)) {
657                 torture_comment(tctx, "DeleteKey failed\n");
658                 ret = false;
659         } else {
660                 deleted = true;
661         }
662
663         if (created && !test_FlushKey(p, tctx, &handle)) {
664                 torture_comment(tctx, "FlushKey failed\n");
665                 ret = false;
666         }
667
668         if (created && deleted &&
669             test_OpenKey(p, tctx, &handle, TEST_KEY1, &newhandle)) {
670                 torture_comment(tctx,
671                                 "DeleteKey failed (OpenKey after Delete worked)\n");
672                 ret = false;
673         }
674
675         if (!test_GetVersion(p, tctx, &handle)) {
676                 torture_comment(tctx, "GetVersion failed\n");
677                 ret = false;
678         }
679
680         if (created && test_CreateKey_sd(p, tctx, &handle, TEST_KEY2,
681                                          NULL, &newhandle)) {
682                 created2 = true;
683         }
684
685         if (created2 && !test_GetKeySecurity(p, tctx, &newhandle, NULL)) {
686                 printf("GetKeySecurity failed\n");
687                 ret = false;
688         }
689
690         if (created2 && !test_CloseKey(p, tctx, &newhandle)) {
691                 printf("CloseKey failed\n");
692                 ret = false;
693         }
694
695         if (created && !test_DeleteKey(p, tctx, &handle, TEST_KEY2)) {
696                 printf("DeleteKey failed\n");
697                 ret = false;
698         }
699
700         if (created && test_CreateKey(p, tctx, &handle, TEST_KEY3, NULL)) {
701                 created3 = true;
702         }
703
704         if (created3 &&
705             test_CreateKey(p, tctx, &handle, TEST_SUBKEY, NULL)) {
706                 created_subkey = true;
707         }
708
709         if (created_subkey &&
710             !test_DeleteKeyWithSubkey(p, tctx, &handle, TEST_KEY3)) {
711                 printf("DeleteKeyWithSubkey failed "
712                        "(DeleteKey didn't return ACCESS_DENIED)\n");
713                 ret = false;
714         }
715
716         if (created_subkey &&
717             !test_DeleteKey(p, tctx, &handle, TEST_SUBKEY)) {
718                 printf("DeleteKey failed\n");
719                 ret = false;
720         }
721
722         if (created3 &&
723             !test_DeleteKey(p, tctx, &handle, TEST_KEY3)) {
724                 printf("DeleteKey failed\n");
725                 ret = false;
726         }
727
728         /* The HKCR hive has a very large fanout */
729         if (open_fn == (void *)dcerpc_winreg_OpenHKCR) {
730                 if(!test_key(p, tctx, &handle, MAX_DEPTH - 1)) {
731                         ret = false;
732                 }
733         }
734
735         if (!test_key(p, tctx, &handle, 0)) {
736                 ret = false;
737         }
738
739         test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
740
741         return ret;
742 }
743
744 struct torture_suite *torture_rpc_winreg(TALLOC_CTX *mem_ctx)
745 {
746         struct {
747                 const char *name;
748                 winreg_open_fn fn;
749         } open_fns[] = {{"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM },
750                         {"OpenHKU",  (winreg_open_fn)dcerpc_winreg_OpenHKU },
751                         {"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR },
752                         {"OpenHKCU", (winreg_open_fn)dcerpc_winreg_OpenHKCU }};
753         int i;
754         struct torture_rpc_tcase *tcase;
755         struct torture_suite *suite = torture_suite_create(mem_ctx, "WINREG");
756         struct torture_test *test;
757
758         tcase = torture_suite_add_rpc_iface_tcase(suite, "winreg",
759                                                   &ndr_table_winreg);
760
761         test = torture_rpc_tcase_add_test(tcase, "InitiateSystemShutdown",
762                                           test_InitiateSystemShutdown);
763         test->dangerous = true;
764
765         test = torture_rpc_tcase_add_test(tcase, "InitiateSystemShutdownEx",
766                                           test_InitiateSystemShutdownEx);
767         test->dangerous = true;
768
769         for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
770                 torture_rpc_tcase_add_test_ex(tcase, open_fns[i].name,
771                                               test_Open, open_fns[i].fn);
772         }
773
774         return suite;
775 }