2 Unix SMB/CIFS implementation.
3 test suite for winreg rpc operations
5 Copyright (C) Tim Potter 2003
6 Copyright (C) Jelmer Vernooij 2004
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.
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.
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.
24 #include "librpc/gen_ndr/ndr_winreg.h"
26 #define TEST_KEY_BASE "smbtorture test"
27 #define TEST_KEY1 TEST_KEY_BASE "\\spottyfoot"
28 #define TEST_KEY2 TEST_KEY_BASE "\\with a SD (#1)"
30 static void init_initshutdown_String(TALLOC_CTX *mem_ctx, struct initshutdown_String *name, const char *s)
32 name->name = talloc(mem_ctx, struct initshutdown_String_sub);
36 static void init_winreg_String(struct winreg_String *name, const char *s)
40 name->name_len = 2 * (strlen_m(s) + 1);
41 name->name_size = name->name_len;
48 static BOOL test_GetVersion(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
49 struct policy_handle *handle)
52 struct winreg_GetVersion r;
54 printf("\ntesting GetVersion\n");
58 status = dcerpc_winreg_GetVersion(p, mem_ctx, &r);
60 if (!NT_STATUS_IS_OK(status)) {
61 printf("GetVersion failed - %s\n", nt_errstr(status));
65 if (!W_ERROR_IS_OK(r.out.result)) {
66 printf("GetVersion failed - %s\n", win_errstr(r.out.result));
73 static BOOL test_NotifyChangeKeyValue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
74 struct policy_handle *handle)
76 struct winreg_NotifyChangeKeyValue r;
79 printf("\ntesting NotifyChangeKeyValue\n");
82 r.in.watch_subtree = 1;
83 r.in.notify_filter = 0;
84 r.in.unknown = r.in.unknown2 = 0;
85 init_winreg_String(&r.in.string1, NULL);
86 init_winreg_String(&r.in.string2, NULL);
88 status = dcerpc_winreg_NotifyChangeKeyValue(p, mem_ctx, &r);
90 if (!NT_STATUS_IS_OK(status)) {
91 printf("NotifyChangeKeyValue failed - %s\n", nt_errstr(status));
95 if (!W_ERROR_IS_OK(r.out.result)) {
96 printf("NotifyChangeKeyValue failed - %s - not considering\n", win_errstr(r.out.result));
103 static BOOL test_CreateKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
104 struct policy_handle *handle, const char *name,
107 struct winreg_CreateKey r;
108 struct policy_handle newhandle;
110 uint32_t action_taken = 0;
112 printf("\ntesting CreateKey\n");
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.class, class);
119 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
120 r.in.action_taken = r.out.action_taken = &action_taken;
123 status = dcerpc_winreg_CreateKey(p, mem_ctx, &r);
125 if (!NT_STATUS_IS_OK(status)) {
126 printf("CreateKey failed - %s\n", nt_errstr(status));
130 if (!W_ERROR_IS_OK(r.out.result)) {
131 printf("CreateKey failed - %s\n", win_errstr(r.out.result));
140 createkey testing with a SD
142 static BOOL test_CreateKey_sd(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
143 struct policy_handle *handle, const char *name,
144 const char *class, struct policy_handle *newhandle)
146 struct winreg_CreateKey r;
148 uint32_t action_taken = 0;
149 struct security_descriptor *sd;
151 struct winreg_SecBuf secbuf;
153 sd = security_descriptor_create(mem_ctx,
155 SID_NT_AUTHENTICATED_USERS,
156 SEC_ACE_TYPE_ACCESS_ALLOWED,
158 SEC_ACE_FLAG_OBJECT_INHERIT,
161 status = ndr_push_struct_blob(&sdblob, mem_ctx, sd,
162 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
163 if (!NT_STATUS_IS_OK(status)) {
164 printf("Failed to push security_descriptor ?!\n");
168 secbuf.sd.data = sdblob.data;
169 secbuf.sd.len = sdblob.length;
170 secbuf.sd.size = sdblob.length;
171 secbuf.length = sdblob.length-10;
174 printf("\ntesting CreateKey with sd\n");
176 r.in.handle = handle;
177 r.out.new_handle = newhandle;
178 init_winreg_String(&r.in.name, name);
179 init_winreg_String(&r.in.class, class);
181 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
182 r.in.action_taken = r.out.action_taken = &action_taken;
183 r.in.secdesc = &secbuf;
185 status = dcerpc_winreg_CreateKey(p, mem_ctx, &r);
187 if (!NT_STATUS_IS_OK(status)) {
188 printf("CreateKey with sd failed - %s\n", nt_errstr(status));
192 if (!W_ERROR_IS_OK(r.out.result)) {
193 printf("CreateKey with sd failed - %s\n", win_errstr(r.out.result));
200 static BOOL test_GetKeySecurity(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
201 struct policy_handle *handle)
204 struct winreg_GetKeySecurity r;
205 struct security_descriptor sd;
208 printf("\ntesting GetKeySecurity\n");
212 r.in.handle = handle;
213 r.in.sd = r.out.sd = talloc_zero(mem_ctx, struct KeySecurityData);
214 r.in.sd->size = 0x1000;
215 r.in.sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
217 status = dcerpc_winreg_GetKeySecurity(p, mem_ctx, &r);
219 if (!NT_STATUS_IS_OK(status)) {
220 printf("GetKeySecurity failed - %s\n", nt_errstr(status));
224 if (!W_ERROR_IS_OK(r.out.result)) {
225 printf("GetKeySecurity failed - %s\n", win_errstr(r.out.result));
229 sdblob.data = r.out.sd->data;
230 sdblob.length = r.out.sd->len;
232 status = ndr_pull_struct_blob(&sdblob, mem_ctx, &sd,
233 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
234 if (!NT_STATUS_IS_OK(status)) {
235 printf("pull_security_descriptor failed - %s\n", nt_errstr(status));
238 if (p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
239 NDR_PRINT_DEBUG(security_descriptor, &sd);
245 static BOOL test_CloseKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
246 struct policy_handle *handle)
249 struct winreg_CloseKey r;
251 printf("\ntesting CloseKey\n");
253 r.in.handle = r.out.handle = handle;
255 status = dcerpc_winreg_CloseKey(p, mem_ctx, &r);
257 if (!NT_STATUS_IS_OK(status)) {
258 printf("CloseKey failed - %s\n", nt_errstr(status));
262 if (!W_ERROR_IS_OK(r.out.result)) {
263 printf("CloseKey failed - %s\n", win_errstr(r.out.result));
270 static BOOL test_FlushKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
271 struct policy_handle *handle)
274 struct winreg_FlushKey r;
276 printf("\ntesting FlushKey\n");
278 r.in.handle = handle;
280 status = dcerpc_winreg_FlushKey(p, mem_ctx, &r);
282 if (!NT_STATUS_IS_OK(status)) {
283 printf("FlushKey failed - %s\n", nt_errstr(status));
287 if (!W_ERROR_IS_OK(r.out.result)) {
288 printf("FlushKey failed - %s\n", win_errstr(r.out.result));
295 static BOOL test_OpenKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
296 struct policy_handle *hive_handle,
297 const char *keyname, struct policy_handle *key_handle)
300 struct winreg_OpenKey r;
302 printf("\ntesting OpenKey\n");
304 r.in.handle = hive_handle;
305 init_winreg_String(&r.in.keyname, keyname);
306 r.in.unknown = 0x00000000;
307 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
308 r.out.handle = key_handle;
310 status = dcerpc_winreg_OpenKey(p, mem_ctx, &r);
312 if (!NT_STATUS_IS_OK(status)) {
313 printf("OpenKey failed - %s\n", nt_errstr(status));
317 if (!W_ERROR_IS_OK(r.out.result)) {
318 printf("OpenKey failed - %s\n", win_errstr(r.out.result));
326 static BOOL test_Cleanup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
327 struct policy_handle *handle, const char *key)
329 struct winreg_DeleteKey r;
331 r.in.handle = handle;
333 init_winreg_String(&r.in.key, key);
334 dcerpc_winreg_DeleteKey(p, mem_ctx, &r);
340 static BOOL test_DeleteKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
341 struct policy_handle *handle, const char *key)
344 struct winreg_DeleteKey r;
346 printf("\ntesting DeleteKey\n");
348 r.in.handle = handle;
349 init_winreg_String(&r.in.key, key);
351 status = dcerpc_winreg_DeleteKey(p, mem_ctx, &r);
353 if (!NT_STATUS_IS_OK(status)) {
354 printf("DeleteKey failed - %s\n", nt_errstr(status));
358 if (!W_ERROR_IS_OK(r.out.result)) {
359 printf("DeleteKey failed - %s\n", win_errstr(r.out.result));
366 static BOOL test_QueryInfoKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
367 struct policy_handle *handle, char *class)
370 struct winreg_QueryInfoKey r;
372 printf("\ntesting QueryInfoKey\n");
374 r.in.handle = handle;
375 init_winreg_String(&r.in.class, class);
377 status = dcerpc_winreg_QueryInfoKey(p, mem_ctx, &r);
379 if (!NT_STATUS_IS_OK(status)) {
380 printf("QueryInfoKey failed - %s\n", nt_errstr(status));
384 if (!W_ERROR_IS_OK(r.out.result)) {
385 printf("QueryInfoKey failed - %s\n", win_errstr(r.out.result));
392 static BOOL test_key(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
393 struct policy_handle *handle, int depth);
395 static BOOL test_EnumKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
396 struct policy_handle *handle, int depth)
398 struct winreg_EnumKey r;
399 struct winreg_StringBuf class, name;
403 printf("Testing EnumKey\n\n");
408 r.in.handle = handle;
413 r.in.last_changed_time = &t;
419 status = dcerpc_winreg_EnumKey(p, mem_ctx, &r);
421 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
422 struct policy_handle key_handle;
424 printf("EnumKey: %d: %s\n", r.in.enum_index, r.out.name->name);
427 p, mem_ctx, handle, r.out.name->name,
430 test_key(p, mem_ctx, &key_handle, depth + 1);
436 } while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result));
438 if (!NT_STATUS_IS_OK(status)) {
439 printf("EnumKey failed - %s\n", nt_errstr(status));
443 if (!W_ERROR_IS_OK(r.out.result) && !W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
444 printf("EnumKey failed - %s\n", win_errstr(r.out.result));
453 static BOOL test_QueryMultipleValues(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle, const char *valuename)
455 struct winreg_QueryMultipleValues r;
459 printf("Testing QueryMultipleValues\n");
461 r.in.key_handle = handle;
462 r.in.values = r.out.values = talloc_array(mem_ctx, struct QueryMultipleValue, 1);
463 r.in.values[0].name = talloc(mem_ctx, struct winreg_String);
464 r.in.values[0].name->name = valuename;
465 r.in.values[0].offset = 0;
466 r.in.values[0].length = 0;
467 r.in.values[0].type = 0;
470 r.in.buffer_size = r.out.buffer_size = talloc(mem_ctx, uint32_t);
471 *r.in.buffer_size = bufsize;
473 *r.in.buffer_size = bufsize;
474 r.in.buffer = r.out.buffer = talloc_zero_array(mem_ctx, uint8_t,
477 status = dcerpc_winreg_QueryMultipleValues(p, mem_ctx, &r);
479 if(NT_STATUS_IS_ERR(status)) {
480 printf("QueryMultipleValues failed - %s\n", nt_errstr(status));
483 talloc_free(r.in.buffer);
485 } while (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
487 if (!W_ERROR_IS_OK(r.out.result)) {
488 printf("QueryMultipleValues failed - %s\n", win_errstr(r.out.result));
495 static BOOL test_QueryValue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle, const char *valuename)
497 struct winreg_QueryValue r;
500 uint32_t offered = 0xfff;
502 printf("Testing QueryValue\n");
504 r.in.handle = handle;
506 r.in.value_name.name = valuename;
508 r.in.size = &offered;
511 status = dcerpc_winreg_QueryValue(p, mem_ctx, &r);
512 if(NT_STATUS_IS_ERR(status)) {
513 printf("QueryValue failed - %s\n", nt_errstr(status));
517 if (!W_ERROR_IS_OK(r.out.result)) {
518 printf("QueryValue failed - %s\n", win_errstr(r.out.result));
525 static BOOL test_EnumValue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
526 struct policy_handle *handle, int max_valnamelen, int max_valbufsize)
528 struct winreg_EnumValue r;
530 uint32_t size = max_valbufsize, zero = 0;
533 struct winreg_StringBuf name;
535 printf("testing EnumValue\n");
540 r.in.handle = handle;
550 NTSTATUS status = dcerpc_winreg_EnumValue(p, mem_ctx, &r);
551 if(NT_STATUS_IS_ERR(status)) {
552 printf("EnumValue failed - %s\n", nt_errstr(status));
556 if (W_ERROR_IS_OK(r.out.result)) {
557 ret &= test_QueryValue(p, mem_ctx, handle, r.out.name->name);
558 ret &= test_QueryMultipleValues(p, mem_ctx, handle, r.out.name->name);
562 } while (W_ERROR_IS_OK(r.out.result));
564 if(!W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
565 printf("EnumValue failed - %s\n", win_errstr(r.out.result));
572 static BOOL test_InitiateSystemShutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
573 const char *msg, uint32_t timeout)
575 struct winreg_InitiateSystemShutdown r;
577 uint16_t hostname = 0x0;
579 r.in.hostname = &hostname;
580 r.in.message = talloc(mem_ctx, struct initshutdown_String);
581 init_initshutdown_String(mem_ctx, r.in.message, msg);
583 r.in.timeout = timeout;
586 status = dcerpc_winreg_InitiateSystemShutdown(p, mem_ctx, &r);
588 if (!NT_STATUS_IS_OK(status)) {
589 printf("InitiateSystemShutdown failed - %s\n", nt_errstr(status));
593 if (!W_ERROR_IS_OK(r.out.result)) {
594 printf("InitiateSystemShutdown failed - %s\n", win_errstr(r.out.result));
601 static BOOL test_InitiateSystemShutdownEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
602 const char *msg, uint32_t timeout)
604 struct winreg_InitiateSystemShutdownEx r;
606 uint16_t hostname = 0x0;
608 r.in.hostname = &hostname;
609 r.in.message = talloc(mem_ctx, struct initshutdown_String);
610 init_initshutdown_String(mem_ctx, r.in.message, msg);
612 r.in.timeout = timeout;
616 status = dcerpc_winreg_InitiateSystemShutdownEx(p, mem_ctx, &r);
618 if (!NT_STATUS_IS_OK(status)) {
619 printf("InitiateSystemShutdownEx failed - %s\n", nt_errstr(status));
623 if (!W_ERROR_IS_OK(r.out.result)) {
624 printf("InitiateSystemShutdownEx failed - %s\n", win_errstr(r.out.result));
631 static BOOL test_AbortSystemShutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
633 struct winreg_AbortSystemShutdown r;
635 uint16_t server = 0x0;
637 r.in.server = &server;
639 status = dcerpc_winreg_AbortSystemShutdown(p, mem_ctx, &r);
641 if (!NT_STATUS_IS_OK(status)) {
642 printf("AbortSystemShutdown failed - %s\n", nt_errstr(status));
646 if (!W_ERROR_IS_OK(r.out.result)) {
647 printf("AbortSystemShutdown failed - %s\n", win_errstr(r.out.result));
654 #define MAX_DEPTH 2 /* Only go this far down the tree */
656 static BOOL test_key(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
657 struct policy_handle *handle, int depth)
659 if (depth == MAX_DEPTH)
662 if (!test_QueryInfoKey(p, mem_ctx, handle, NULL)) {
666 if (!test_NotifyChangeKeyValue(p, mem_ctx, handle)) {
669 if (!test_GetKeySecurity(p, mem_ctx, handle)) {
672 if (!test_EnumKey(p, mem_ctx, handle, depth)) {
675 if (!test_EnumValue(p, mem_ctx, handle, 0xFF, 0xFFFF)) {
679 test_CloseKey(p, mem_ctx, handle);
684 typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_pipe *, TALLOC_CTX *, void *);
686 static BOOL test_Open(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
687 const char *name, winreg_open_fn open_fn)
689 struct policy_handle handle, newhandle;
690 BOOL ret = True, created = False, created2 = False, deleted = False;
691 struct winreg_OpenHKLM r;
694 printf("Testing %s\n", name);
696 r.in.system_name = 0;
697 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
698 r.out.handle = &handle;
700 status = open_fn(p, mem_ctx, &r);
701 if (!NT_STATUS_IS_OK(status)) {
705 test_Cleanup(p, mem_ctx, &handle, TEST_KEY1);
706 test_Cleanup(p, mem_ctx, &handle, TEST_KEY2);
707 test_Cleanup(p, mem_ctx, &handle, TEST_KEY_BASE);
709 if (!test_CreateKey(p, mem_ctx, &handle, TEST_KEY1, NULL)) {
710 printf("CreateKey failed - not considering a failure\n");
715 if (created && !test_FlushKey(p, mem_ctx, &handle)) {
716 printf("FlushKey failed\n");
720 if (created && !test_OpenKey(p, mem_ctx, &handle, TEST_KEY1, &newhandle)) {
721 printf("CreateKey failed (OpenKey after Create didn't work)\n");
725 if (created && !test_DeleteKey(p, mem_ctx, &handle, TEST_KEY1)) {
726 printf("DeleteKey failed\n");
732 if (created && !test_FlushKey(p, mem_ctx, &handle)) {
733 printf("FlushKey failed\n");
737 if (created && deleted &&
738 test_OpenKey(p, mem_ctx, &handle, TEST_KEY1, &newhandle)) {
739 printf("DeleteKey failed (OpenKey after Delete didn't work)\n");
743 if (!test_GetVersion(p, mem_ctx, &handle)) {
744 printf("GetVersion failed\n");
748 if (created && test_CreateKey_sd(p, mem_ctx, &handle, TEST_KEY2,
753 if (created2 && !test_GetKeySecurity(p, mem_ctx, &newhandle)) {
754 printf("GetKeySecurity failed\n");
758 if (created2 && !test_CloseKey(p, mem_ctx, &newhandle)) {
759 printf("CloseKey failed\n");
763 if (created && !test_DeleteKey(p, mem_ctx, &handle, TEST_KEY2)) {
764 printf("DeleteKey failed\n");
768 /* The HKCR hive has a very large fanout */
770 if (open_fn == (void *)dcerpc_winreg_OpenHKCR) {
771 if(!test_key(p, mem_ctx, &handle, MAX_DEPTH - 1)) {
776 if(!test_key(p, mem_ctx, &handle, 0)) {
780 test_Cleanup(p, mem_ctx, &handle, TEST_KEY_BASE);
785 BOOL torture_rpc_winreg(void)
788 struct dcerpc_pipe *p;
794 } open_fns[] = {{"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM },
795 {"OpenHKU", (winreg_open_fn)dcerpc_winreg_OpenHKU },
796 {"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR },
797 {"OpenHKCU", (winreg_open_fn)dcerpc_winreg_OpenHKCU }};
799 mem_ctx = talloc_init("torture_rpc_winreg");
801 status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_winreg);
803 if (!NT_STATUS_IS_OK(status)) {
804 talloc_free(mem_ctx);
808 if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
809 printf("winreg_InitiateShutdown disabled - enable dangerous tests to use\n");
811 ret &= test_InitiateSystemShutdown(p, mem_ctx, "spottyfood", 30);
812 ret &= test_AbortSystemShutdown(p, mem_ctx);
813 ret &= test_InitiateSystemShutdownEx(p, mem_ctx, "spottyfood", 30);
814 ret &= test_AbortSystemShutdown(p, mem_ctx);
817 for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
818 if (!test_Open(p, mem_ctx, open_fns[i].name, open_fns[i].fn))
822 talloc_free(mem_ctx);