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