r3340: Various fixes in the registry code. Implement the EnumKey call
[samba.git] / source / 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
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25 static void init_winreg_String(struct winreg_String *name, const char *s)
26 {
27         name->name = s;
28         if (s) {
29                 name->name_len = 2 * (strlen_m(s) + 1);
30                 name->name_size = name->name_len;
31         } else {
32                 name->name_len = 0;
33                 name->name_size = 0;
34         }
35 }
36
37 static BOOL test_GetVersion(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
38                             struct policy_handle *handle)
39 {
40         NTSTATUS status;
41         struct winreg_GetVersion r;
42
43         printf("\ntesting GetVersion\n");
44
45         r.in.handle = handle;
46
47         status = dcerpc_winreg_GetVersion(p, mem_ctx, &r);
48
49         if (!NT_STATUS_IS_OK(status)) {
50                 printf("GetVersion failed - %s\n", nt_errstr(status));
51                 return False;
52         }
53
54         if (!W_ERROR_IS_OK(r.out.result)) {
55                 printf("GetVersion failed - %s\n", win_errstr(r.out.result));
56                 return False;
57         }
58
59         return True;
60 }
61
62 static BOOL test_CreateKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
63                           struct policy_handle *handle, const char *name, 
64                            const char *class)
65 {
66         struct winreg_CreateKey r;
67         struct policy_handle newhandle;
68         NTSTATUS status;
69         uint32_t sec_info = 0;
70
71         printf("\ntesting CreateKey\n");
72
73         r.in.handle = handle;
74         r.out.handle = &newhandle;
75         init_winreg_String(&r.in.key, name);    
76         init_winreg_String(&r.in.class, class);
77         r.in.reserved = 0x0;
78         r.in.access_mask = 0x02000000;
79         r.in.sec_info = &sec_info;
80         r.in.sec_desc = NULL;
81
82         status = dcerpc_winreg_CreateKey(p, mem_ctx, &r);
83
84         if (!NT_STATUS_IS_OK(status)) {
85                 printf("CreateKey failed - %s\n", nt_errstr(status));
86                 return False;
87         }
88
89         if (!W_ERROR_IS_OK(r.out.result)) {
90                 printf("CreateKey failed - %s\n", win_errstr(r.out.result));
91                 return False;
92         }
93
94         return True;
95 }
96
97 static BOOL test_CloseKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
98                           struct policy_handle *handle)
99 {
100         NTSTATUS status;
101         struct winreg_CloseKey r;
102
103         printf("\ntesting CloseKey\n");
104
105         r.in.handle = r.out.handle = handle;
106
107         status = dcerpc_winreg_CloseKey(p, mem_ctx, &r);
108
109         if (!NT_STATUS_IS_OK(status)) {
110                 printf("CloseKey failed - %s\n", nt_errstr(status));
111                 return False;
112         }
113
114         if (!W_ERROR_IS_OK(r.out.result)) {
115                 printf("CloseKey failed - %s\n", win_errstr(r.out.result));
116                 return False;
117         }
118
119         return True;
120 }
121
122 static BOOL test_FlushKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
123                           struct policy_handle *handle)
124 {
125         NTSTATUS status;
126         struct winreg_FlushKey r;
127
128         printf("\ntesting FlushKey\n");
129
130         r.in.handle = handle;
131
132         status = dcerpc_winreg_FlushKey(p, mem_ctx, &r);
133
134         if (!NT_STATUS_IS_OK(status)) {
135                 printf("FlushKey failed - %s\n", nt_errstr(status));
136                 return False;
137         }
138
139         if (!W_ERROR_IS_OK(r.out.result)) {
140                 printf("FlushKey failed - %s\n", win_errstr(r.out.result));
141                 return False;
142         }
143
144         return True;
145 }
146
147 static BOOL test_OpenKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
148                          struct policy_handle *hive_handle,
149                          const char *keyname, struct policy_handle *key_handle)
150 {
151         NTSTATUS status;
152         struct winreg_OpenKey r;
153
154         printf("\ntesting OpenKey\n");
155
156         r.in.handle = hive_handle;
157         init_winreg_String(&r.in.keyname, keyname);
158         r.in.unknown = 0x00000000;
159         r.in.access_mask = 0x02000000;
160         r.out.handle = key_handle;
161
162         status = dcerpc_winreg_OpenKey(p, mem_ctx, &r);
163
164         if (!NT_STATUS_IS_OK(status)) {
165                 printf("OpenKey failed - %s\n", nt_errstr(status));
166                 return False;
167         }
168
169         if (!W_ERROR_IS_OK(r.out.result)) {
170                 printf("OpenKey failed - %s\n", win_errstr(r.out.result));
171                 return False;
172         }
173
174         return True;
175 }
176
177 static BOOL test_DeleteKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
178                            struct policy_handle *handle, const char *key)
179 {
180         NTSTATUS status;
181         struct winreg_DeleteKey r;
182
183         printf("\ntesting DeleteKey\n");
184
185         r.in.handle = handle;
186         init_winreg_String(&r.in.key, key);     
187
188         status = dcerpc_winreg_DeleteKey(p, mem_ctx, &r);
189
190         if (!NT_STATUS_IS_OK(status)) {
191                 printf("DeleteKey failed - %s\n", nt_errstr(status));
192                 return False;
193         }
194
195         if (!W_ERROR_IS_OK(r.out.result)) {
196                 printf("DeleteKey failed - %s\n", win_errstr(r.out.result));
197                 return False;
198         }
199
200         return True;
201 }
202
203 static BOOL test_QueryInfoKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
204                               struct policy_handle *handle, char *class)
205 {
206         NTSTATUS status;
207         struct winreg_QueryInfoKey r;
208
209         printf("\ntesting QueryInfoKey\n");
210
211         r.in.handle = handle;
212         init_winreg_String(&r.in.class, class);
213         
214         status = dcerpc_winreg_QueryInfoKey(p, mem_ctx, &r);
215
216         if (!NT_STATUS_IS_OK(status)) {
217                 printf("QueryInfoKey failed - %s\n", nt_errstr(status));
218                 return False;
219         }
220
221         if (!W_ERROR_IS_OK(r.out.result)) {
222                 printf("QueryInfoKey failed - %s\n", win_errstr(r.out.result));
223                 return False;
224         }
225
226         return True;
227 }
228
229 static BOOL test_key(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
230                      struct policy_handle *handle, int depth);
231
232 static BOOL test_EnumKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
233                          struct policy_handle *handle, int depth)
234 {
235         struct winreg_EnumKey r;
236         struct winreg_EnumKeyNameRequest keyname;
237         struct winreg_String classname;
238         struct winreg_Time tm;
239         NTSTATUS status;
240
241         printf("Testing EnumKey\n\n");
242
243         r.in.handle = handle;
244         r.in.enum_index = 0;
245         r.in.key_name_len = r.out.key_name_len = 0;
246         r.in.unknown = r.out.unknown = 0x0414;
247         keyname.unknown = 0x0000020a;
248         init_winreg_String(&keyname.key_name, NULL);
249         init_winreg_String(&classname, NULL);
250         r.in.in_name = &keyname;
251         r.in.class = &classname;
252         tm.low = tm.high = 0x7fffffff;
253         r.in.last_changed_time = &tm;
254
255         do {
256                 status = dcerpc_winreg_EnumKey(p, mem_ctx, &r);
257
258                 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
259                         struct policy_handle key_handle;
260
261                         if (!test_OpenKey(
262                                     p, mem_ctx, handle, r.out.out_name->name,
263                                     &key_handle)) {
264                                 printf("OpenKey(%s) failed - %s\n",
265                                        r.out.out_name->name, 
266                                        win_errstr(r.out.result));
267                                 goto next_key;
268                         }
269
270                         test_key(p, mem_ctx, &key_handle, depth + 1);
271                 }
272
273         next_key:
274
275                 r.in.enum_index++;
276
277         } while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result));
278
279         return True;
280 }
281
282 static BOOL test_EnumValue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
283                            struct policy_handle *handle, int max_valnamelen, int max_valbufsize)
284 {
285         struct winreg_EnumValue r;
286         struct EnumValueIn buf_name;
287         struct EnumValueIn buf_val;
288         uint32 type;
289         uint32 len1 = max_valbufsize, len2 = 0;
290
291         printf("testing EnumValue\n");
292
293         r.in.handle = handle;
294         r.in.enum_index = 0;
295         r.in.name_in.len = 0;
296         r.in.name_in.max_len = max_valnamelen * 2;
297         buf_name.max_len = max_valnamelen;
298         buf_name.offset = 0;
299         buf_name.len = 0;
300         r.in.name_in.buffer = &buf_name;
301         r.in.type = &type;
302         buf_val.max_len = max_valbufsize;
303         buf_val.offset = 0;
304         buf_val.len = 0;
305         r.in.value_in = &buf_val;
306         r.in.value_len1 = &len1;
307         r.in.value_len2 = &len2;
308         
309         do {
310                 NTSTATUS status = dcerpc_winreg_EnumValue(p, mem_ctx, &r);
311                 if(NT_STATUS_IS_ERR(status)) {
312                         printf("EnumValue failed - %s\n", nt_errstr(status));
313                         return False;
314                 }
315
316                 r.in.enum_index++;
317         } while (W_ERROR_IS_OK(r.out.result));
318
319         if(!W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
320                 printf("EnumValue failed - %s\n", win_errstr(r.out.result));
321                 return False;
322         }
323
324         return True;
325 }
326
327 static BOOL test_OpenHKLM(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
328                           struct policy_handle *handle)
329 {
330         NTSTATUS status;
331         struct winreg_OpenHKLM r;
332         struct winreg_OpenUnknown unknown;
333         BOOL ret = True;
334
335         printf("\ntesting OpenHKLM\n");
336
337         unknown.unknown0 = 0x84e0;
338         unknown.unknown1 = 0x0000;
339         r.in.unknown = &unknown;
340         r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED;
341         r.out.handle = handle;
342
343         status = dcerpc_winreg_OpenHKLM(p, mem_ctx, &r);
344
345         if (!NT_STATUS_IS_OK(status)) {
346                 printf("OpenHKLM failed - %s\n", nt_errstr(status));
347                 return False;
348         }
349
350         if (!W_ERROR_IS_OK(r.out.result)) {
351                 printf("OpenHKLM failed - %s\n", win_errstr(r.out.result));
352                 return False;
353         }
354
355         return ret;
356 }
357
358 static BOOL test_OpenHKU(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
359                          struct policy_handle *handle)
360 {
361         NTSTATUS status;
362         struct winreg_OpenHKU r;
363         struct winreg_OpenUnknown unknown;
364         BOOL ret = True;
365
366         printf("\ntesting OpenHKU\n");
367
368         unknown.unknown0 = 0x84e0;
369         unknown.unknown1 = 0x0000;
370         r.in.unknown = &unknown;
371         r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED;
372         r.out.handle = handle;
373
374         status = dcerpc_winreg_OpenHKU(p, mem_ctx, &r);
375
376         if (!NT_STATUS_IS_OK(status)) {
377                 printf("OpenHKU failed - %s\n", nt_errstr(status));
378                 return False;
379         }
380
381         return ret;
382 }
383
384 static BOOL test_OpenHKCR(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
385                           struct policy_handle *handle)
386 {
387         NTSTATUS status;
388         struct winreg_OpenHKCR r;
389         struct winreg_OpenUnknown unknown;
390         BOOL ret = True;
391
392         printf("\ntesting OpenHKCR\n");
393
394         unknown.unknown0 = 0x84e0;
395         unknown.unknown1 = 0x0000;
396         r.in.unknown = &unknown;
397         r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED;
398         r.out.handle = handle;
399
400         status = dcerpc_winreg_OpenHKCR(p, mem_ctx, &r);
401
402         if (!NT_STATUS_IS_OK(status)) {
403                 printf("OpenHKCR failed - %s\n", nt_errstr(status));
404                 return False;
405         }
406
407         return ret;
408 }
409
410 static BOOL test_InitiateSystemShutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
411                         const char *msg, uint32_t timeout)
412 {
413         struct winreg_InitiateSystemShutdown r;
414         NTSTATUS status;
415         
416         init_winreg_String(&r.in.message, msg);
417         r.in.flags = 0;
418         r.in.timeout = timeout;
419
420         status = dcerpc_winreg_InitiateSystemShutdown(p, mem_ctx, &r);
421
422         if (!NT_STATUS_IS_OK(status)) {
423                 printf("InitiateSystemShutdown failed - %s\n", nt_errstr(status));
424                 return False;
425         }
426
427         if (!W_ERROR_IS_OK(r.out.result)) {
428                 printf("InitiateSystemShutdown failed - %s\n", win_errstr(r.out.result));
429                 return False;
430         }
431
432         return True;
433 }
434
435 static BOOL test_AbortSystemShutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
436 {
437         struct winreg_AbortSystemShutdown r;
438         NTSTATUS status;
439         uint16_t server = 0x0;
440
441         r.in.server = &server;
442         
443         status = dcerpc_winreg_AbortSystemShutdown(p, mem_ctx, &r);
444
445         if (!NT_STATUS_IS_OK(status)) {
446                 printf("AbortSystemShutdown failed - %s\n", nt_errstr(status));
447                 return False;
448         }
449
450         if (!W_ERROR_IS_OK(r.out.result)) {
451                 printf("AbortSystemShutdown failed - %s\n", win_errstr(r.out.result));
452                 return False;
453         }
454
455         return True;
456 }
457
458 static BOOL test_OpenHKCU(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
459                           struct policy_handle *handle)
460 {
461         NTSTATUS status;
462         struct winreg_OpenHKCU r;
463         struct winreg_OpenUnknown unknown;
464         BOOL ret = True;
465
466         printf("\ntesting OpenHKCU\n");
467
468         unknown.unknown0 = 0x84e0;
469         unknown.unknown1 = 0x0000;
470         r.in.unknown = &unknown;
471         r.in.access_required = SEC_RIGHTS_MAXIMUM_ALLOWED;
472         r.out.handle = handle;
473
474         status = dcerpc_winreg_OpenHKCU(p, mem_ctx, &r);
475
476         if (!NT_STATUS_IS_OK(status)) {
477                 printf("OpenHKCU failed - %s\n", nt_errstr(status));
478                 return False;
479         }
480
481         return ret;
482 }
483
484 #define MAX_DEPTH 2             /* Only go this far down the tree */
485
486 static BOOL test_key(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
487                      struct policy_handle *handle, int depth)
488 {
489         if (depth == MAX_DEPTH)
490                 return True;
491
492         if (!test_QueryInfoKey(p, mem_ctx, handle, NULL)) {
493         }
494
495         if (!test_EnumKey(p, mem_ctx, handle, depth)) {
496         }
497
498         if (!test_EnumValue(p, mem_ctx, handle, 0xFF, 0xFFFF)) {
499         }
500
501         test_CloseKey(p, mem_ctx, handle);
502
503         return True;
504 }
505
506 typedef BOOL winreg_open_fn(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
507                             struct policy_handle *handle);
508
509 static BOOL test_Open(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, void *fn)
510 {
511         struct policy_handle handle, newhandle;
512         BOOL ret = True;
513         winreg_open_fn *open_fn = (winreg_open_fn *)fn;
514
515         if (!open_fn(p, mem_ctx, &handle)) {
516                 return False;
517         }
518
519         if (!test_CreateKey(p, mem_ctx, &handle, "spottyfoot", NULL)) {
520                 printf("CreateKey failed\n");
521                 ret = False;
522         }
523
524         if (!test_FlushKey(p, mem_ctx, &handle)) {
525                 printf("FlushKey failed\n");
526                 ret = False;
527         }
528
529         if (!test_OpenKey(p, mem_ctx, &handle, "spottyfoot", &newhandle)) {
530                 printf("CreateKey failed (OpenKey after Create didn't work)\n");
531                 ret = False;
532         }
533
534         if (!test_DeleteKey(p, mem_ctx, &handle, "spottyfoot")) {
535                 printf("DeleteKey failed\n");
536                 ret = False;
537         }
538
539         if (!test_FlushKey(p, mem_ctx, &handle)) {
540                 printf("FlushKey failed\n");
541                 ret = False;
542         }
543
544         if (test_OpenKey(p, mem_ctx, &handle, "spottyfoot", &newhandle)) {
545                 printf("DeleteKey failed (OpenKey after Delete didn't work)\n");
546                 ret = False;
547         }
548
549         if (!test_GetVersion(p, mem_ctx, &handle)) {
550                 printf("GetVersion failed\n");
551                 ret = False;
552         }
553
554         /* The HKCR hive has a very large fanout */
555
556         if (open_fn == test_OpenHKCR) {
557                 if(!test_key(p, mem_ctx, &handle, MAX_DEPTH - 1)) {
558                         ret = False;
559                 }
560         }
561
562         if(!test_key(p, mem_ctx, &handle, 0)) {
563                 ret = False;
564         }
565
566         return ret;
567 }
568
569 BOOL torture_rpc_winreg(void)
570 {
571         NTSTATUS status;
572        struct dcerpc_pipe *p;
573         TALLOC_CTX *mem_ctx;
574         BOOL ret = True;
575         winreg_open_fn *open_fns[] = { test_OpenHKLM, test_OpenHKU,
576                                        test_OpenHKCR, test_OpenHKCU };
577         int i;
578
579         mem_ctx = talloc_init("torture_rpc_winreg");
580
581         status = torture_rpc_connection(&p, 
582                                         DCERPC_WINREG_NAME, 
583                                         DCERPC_WINREG_UUID, 
584                                         DCERPC_WINREG_VERSION);
585
586         if (!NT_STATUS_IS_OK(status)) {
587                 return False;
588         }
589
590         if(!test_InitiateSystemShutdown(p, mem_ctx, "spottyfood", 30))
591                 ret = False;
592
593         if(!test_AbortSystemShutdown(p, mem_ctx))
594                 ret = False;
595
596         for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
597                 if (!test_Open(p, mem_ctx, open_fns[i]))
598                         ret = False;
599         }
600
601         talloc_destroy(mem_ctx);
602
603         torture_rpc_close(p);
604
605         return ret;
606 }