2 Unix SMB/CIFS implementation.
3 test suite for winreg rpc operations
5 Copyright (C) Tim Potter 2003
6 Copyright (C) Jelmer Vernooij 2004-2007
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.
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, see <http://www.gnu.org/licenses/>.
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"
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"
35 static void init_initshutdown_String(TALLOC_CTX *mem_ctx,
36 struct initshutdown_String *name,
39 name->name = talloc(mem_ctx, struct initshutdown_String_sub);
43 static void init_winreg_String(struct winreg_String *name, const char *s)
47 name->name_len = 2 * (strlen_m(s) + 1);
48 name->name_size = name->name_len;
55 static bool test_GetVersion(struct dcerpc_pipe *p,
56 struct torture_context *tctx,
57 struct policy_handle *handle)
59 struct winreg_GetVersion r;
66 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_GetVersion(p, tctx, &r),
69 torture_assert_werr_ok(tctx, r.out.result, "GetVersion failed");
74 static bool test_NotifyChangeKeyValue(struct dcerpc_pipe *p,
75 struct torture_context *tctx,
76 struct policy_handle *handle)
78 struct winreg_NotifyChangeKeyValue r;
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);
87 torture_assert_ntstatus_ok(tctx,
88 dcerpc_winreg_NotifyChangeKeyValue(p, tctx, &r),
89 "NotifyChangeKeyValue failed");
91 if (!W_ERROR_IS_OK(r.out.result)) {
93 "NotifyChangeKeyValue failed - %s - not considering\n", win_errstr(r.out.result));
100 static bool test_CreateKey(struct dcerpc_pipe *p, struct torture_context *tctx,
101 struct policy_handle *handle, const char *name,
104 struct winreg_CreateKey r;
105 struct policy_handle newhandle;
106 enum winreg_CreateAction action_taken = 0;
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);
113 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
114 r.in.action_taken = r.out.action_taken = &action_taken;
117 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CreateKey(p, tctx, &r),
120 torture_assert_werr_ok(tctx, r.out.result, "CreateKey failed");
127 createkey testing with a SD
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, struct policy_handle *newhandle)
134 struct winreg_CreateKey r;
135 enum winreg_CreateAction action_taken = 0;
136 struct security_descriptor *sd;
138 struct winreg_SecBuf secbuf;
140 sd = security_descriptor_create(tctx,
142 SID_NT_AUTHENTICATED_USERS,
143 SEC_ACE_TYPE_ACCESS_ALLOWED,
145 SEC_ACE_FLAG_OBJECT_INHERIT,
148 torture_assert_ntstatus_ok(tctx,
149 ndr_push_struct_blob(&sdblob, tctx, sd,
150 (ndr_push_flags_fn_t)ndr_push_security_descriptor),
151 "Failed to push security_descriptor ?!\n");
153 secbuf.sd.data = sdblob.data;
154 secbuf.sd.len = sdblob.length;
155 secbuf.sd.size = sdblob.length;
156 secbuf.length = sdblob.length-10;
159 r.in.handle = handle;
160 r.out.new_handle = newhandle;
161 init_winreg_String(&r.in.name, name);
162 init_winreg_String(&r.in.keyclass, class);
164 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
165 r.in.action_taken = r.out.action_taken = &action_taken;
166 r.in.secdesc = &secbuf;
168 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CreateKey(p, tctx, &r),
169 "CreateKey with sd failed");
171 torture_assert_werr_ok(tctx, r.out.result, "CreateKey with sd failed");
176 static bool test_GetKeySecurity(struct dcerpc_pipe *p,
177 struct torture_context *tctx,
178 struct policy_handle *handle)
180 struct winreg_GetKeySecurity r;
181 struct security_descriptor sd;
186 r.in.handle = handle;
187 r.in.sd = r.out.sd = talloc_zero(tctx, struct KeySecurityData);
188 r.in.sd->size = 0x1000;
189 r.in.sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
191 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_GetKeySecurity(p, tctx, &r),
192 "GetKeySecurity failed");
194 torture_assert_werr_ok(tctx, r.out.result, "GetKeySecurity failed");
196 sdblob.data = r.out.sd->data;
197 sdblob.length = r.out.sd->len;
199 torture_assert_ntstatus_ok(tctx,
200 ndr_pull_struct_blob(&sdblob, tctx, &sd,
201 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor),
202 "pull_security_descriptor failed");
204 if (p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
205 NDR_PRINT_DEBUG(security_descriptor, &sd);
211 static bool test_CloseKey(struct dcerpc_pipe *p, struct torture_context *tctx,
212 struct policy_handle *handle)
214 struct winreg_CloseKey r;
216 r.in.handle = r.out.handle = handle;
218 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey(p, tctx, &r),
221 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
226 static bool test_FlushKey(struct dcerpc_pipe *p, struct torture_context *tctx,
227 struct policy_handle *handle)
229 struct winreg_FlushKey r;
231 r.in.handle = handle;
233 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_FlushKey(p, tctx, &r),
236 torture_assert_werr_ok(tctx, r.out.result, "FlushKey failed");
241 static bool test_OpenKey(struct dcerpc_pipe *p, struct torture_context *tctx,
242 struct policy_handle *hive_handle,
243 const char *keyname, struct policy_handle *key_handle)
245 struct winreg_OpenKey r;
247 r.in.parent_handle = hive_handle;
248 init_winreg_String(&r.in.keyname, keyname);
249 r.in.unknown = 0x00000000;
250 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
251 r.out.handle = key_handle;
253 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey(p, tctx, &r),
256 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
261 static bool test_Cleanup(struct dcerpc_pipe *p, struct torture_context *tctx,
262 struct policy_handle *handle, const char *key)
264 struct winreg_DeleteKey r;
266 r.in.handle = handle;
268 init_winreg_String(&r.in.key, key);
269 dcerpc_winreg_DeleteKey(p, tctx, &r);
275 static bool test_DeleteKey(struct dcerpc_pipe *p, struct torture_context *tctx,
276 struct policy_handle *handle, const char *key)
279 struct winreg_DeleteKey r;
281 r.in.handle = handle;
282 init_winreg_String(&r.in.key, key);
284 status = dcerpc_winreg_DeleteKey(p, tctx, &r);
286 torture_assert_ntstatus_ok(tctx, status, "DeleteKey failed");
287 torture_assert_werr_ok(tctx, r.out.result, "DeleteKey failed");
292 /* DeleteKey on a key with subkey(s) should
293 * return WERR_ACCESS_DENIED. */
294 static bool test_DeleteKeyWithSubkey(struct dcerpc_pipe *p,
295 struct torture_context *tctx,
296 struct policy_handle *handle, const char *key)
298 struct winreg_DeleteKey r;
300 r.in.handle = handle;
301 init_winreg_String(&r.in.key, key);
303 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_DeleteKey(p, tctx, &r),
304 "DeleteKeyWithSubkey failed");
306 torture_assert_werr_equal(tctx, r.out.result, WERR_ACCESS_DENIED,
307 "DeleteKeyWithSubkey failed");
312 static bool test_QueryInfoKey(struct dcerpc_pipe *p,
313 struct torture_context *tctx,
314 struct policy_handle *handle, char *class)
316 struct winreg_QueryInfoKey r;
317 uint32_t num_subkeys, max_subkeylen, max_subkeysize,
318 num_values, max_valnamelen, max_valbufsize,
320 NTTIME last_changed_time;
323 r.in.handle = handle;
324 r.out.num_subkeys = &num_subkeys;
325 r.out.max_subkeylen = &max_subkeylen;
326 r.out.max_subkeysize = &max_subkeysize;
327 r.out.num_values = &num_values;
328 r.out.max_valnamelen = &max_valnamelen;
329 r.out.max_valbufsize = &max_valbufsize;
330 r.out.secdescsize = &secdescsize;
331 r.out.last_changed_time = &last_changed_time;
333 r.out.classname = talloc(tctx, struct winreg_String);
335 r.in.classname = talloc(tctx, struct winreg_String);
336 init_winreg_String(r.in.classname, class);
338 torture_assert_ntstatus_ok(tctx,
339 dcerpc_winreg_QueryInfoKey(p, tctx, &r),
340 "QueryInfoKey failed");
342 torture_assert_werr_ok(tctx, r.out.result, "QueryInfoKey failed");
347 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
348 struct policy_handle *handle, int depth);
350 static bool test_EnumKey(struct dcerpc_pipe *p, struct torture_context *tctx,
351 struct policy_handle *handle, int depth)
353 struct winreg_EnumKey r;
354 struct winreg_StringBuf class, name;
361 r.in.handle = handle;
364 r.in.keyclass = &class;
366 r.in.last_changed_time = &t;
372 status = dcerpc_winreg_EnumKey(p, tctx, &r);
374 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
375 struct policy_handle key_handle;
377 torture_comment(tctx, "EnumKey: %d: %s\n", r.in.enum_index,
381 p, tctx, handle, r.out.name->name,
384 test_key(p, tctx, &key_handle, depth + 1);
390 } while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result));
392 torture_assert_ntstatus_ok(tctx, status, "EnumKey failed");
394 if (!W_ERROR_IS_OK(r.out.result) &&
395 !W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
396 torture_fail(tctx, "EnumKey failed");
402 static bool test_QueryMultipleValues(struct dcerpc_pipe *p,
403 struct torture_context *tctx,
404 struct policy_handle *handle,
405 const char *valuename)
407 struct winreg_QueryMultipleValues r;
411 r.in.key_handle = handle;
412 r.in.values = r.out.values = talloc_array(tctx, struct QueryMultipleValue, 1);
413 r.in.values[0].name = talloc(tctx, struct winreg_String);
414 r.in.values[0].name->name = valuename;
415 r.in.values[0].offset = 0;
416 r.in.values[0].length = 0;
417 r.in.values[0].type = 0;
420 r.in.buffer_size = r.out.buffer_size = talloc(tctx, uint32_t);
421 *r.in.buffer_size = bufsize;
423 *r.in.buffer_size = bufsize;
424 r.in.buffer = r.out.buffer = talloc_zero_array(tctx, uint8_t,
427 status = dcerpc_winreg_QueryMultipleValues(p, tctx, &r);
429 if(NT_STATUS_IS_ERR(status))
430 torture_fail(tctx, "QueryMultipleValues failed");
432 talloc_free(r.in.buffer);
434 } while (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
436 torture_assert_werr_ok(tctx, r.out.result, "QueryMultipleValues failed");
441 static bool test_QueryValue(struct dcerpc_pipe *p,
442 struct torture_context *tctx,
443 struct policy_handle *handle,
444 const char *valuename)
446 struct winreg_QueryValue r;
448 enum winreg_Type zero_type = 0;
449 uint32_t offered = 0xfff;
452 r.in.handle = handle;
454 r.in.value_name.name = valuename;
455 r.in.type = &zero_type;
456 r.in.size = &offered;
459 status = dcerpc_winreg_QueryValue(p, tctx, &r);
460 if (NT_STATUS_IS_ERR(status)) {
461 torture_fail(tctx, "QueryValue failed");
464 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
469 static bool test_EnumValue(struct dcerpc_pipe *p, struct torture_context *tctx,
470 struct policy_handle *handle, int max_valnamelen, int max_valbufsize)
472 struct winreg_EnumValue r;
473 enum winreg_Type type = 0;
474 uint32_t size = max_valbufsize, zero = 0;
477 struct winreg_StringBuf name;
482 r.in.handle = handle;
492 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_EnumValue(p, tctx, &r),
495 if (W_ERROR_IS_OK(r.out.result)) {
496 ret &= test_QueryValue(p, tctx, handle, r.out.name->name);
497 ret &= test_QueryMultipleValues(p, tctx, handle, r.out.name->name);
501 } while (W_ERROR_IS_OK(r.out.result));
503 torture_assert_werr_equal(tctx, r.out.result, WERR_NO_MORE_ITEMS,
509 static bool test_AbortSystemShutdown(struct dcerpc_pipe *p,
510 struct torture_context *tctx)
512 struct winreg_AbortSystemShutdown r;
513 uint16_t server = 0x0;
515 r.in.server = &server;
517 torture_assert_ntstatus_ok(tctx,
518 dcerpc_winreg_AbortSystemShutdown(p, tctx, &r),
519 "AbortSystemShutdown failed");
521 torture_assert_werr_ok(tctx, r.out.result, "AbortSystemShutdown failed");
526 static bool test_InitiateSystemShutdown(struct torture_context *tctx,
527 struct dcerpc_pipe *p)
529 struct winreg_InitiateSystemShutdown r;
530 uint16_t hostname = 0x0;
532 if (!torture_setting_bool(tctx, "dangerous", false))
534 "winreg_InitiateShutdown disabled - enable dangerous tests to use");
536 r.in.hostname = &hostname;
537 r.in.message = talloc(tctx, struct initshutdown_String);
538 init_initshutdown_String(tctx, r.in.message, "spottyfood");
543 torture_assert_ntstatus_ok(tctx,
544 dcerpc_winreg_InitiateSystemShutdown(p, tctx, &r),
545 "InitiateSystemShutdown failed");
547 torture_assert_werr_ok(tctx, r.out.result, "InitiateSystemShutdown failed");
549 return test_AbortSystemShutdown(p, tctx);
553 static bool test_InitiateSystemShutdownEx(struct torture_context *tctx,
554 struct dcerpc_pipe *p)
556 struct winreg_InitiateSystemShutdownEx r;
557 uint16_t hostname = 0x0;
559 if (!torture_setting_bool(tctx, "dangerous", false))
561 "winreg_InitiateShutdownEx disabled - enable dangerous tests to use");
563 r.in.hostname = &hostname;
564 r.in.message = talloc(tctx, struct initshutdown_String);
565 init_initshutdown_String(tctx, r.in.message, "spottyfood");
571 torture_assert_ntstatus_ok(tctx,
572 dcerpc_winreg_InitiateSystemShutdownEx(p, tctx, &r),
573 "InitiateSystemShutdownEx failed");
575 torture_assert_werr_ok(tctx, r.out.result,
576 "InitiateSystemShutdownEx failed");
578 return test_AbortSystemShutdown(p, tctx);
580 #define MAX_DEPTH 2 /* Only go this far down the tree */
582 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
583 struct policy_handle *handle, int depth)
585 if (depth == MAX_DEPTH)
588 if (!test_QueryInfoKey(p, tctx, handle, NULL)) {
591 if (!test_NotifyChangeKeyValue(p, tctx, handle)) {
594 if (!test_GetKeySecurity(p, tctx, handle)) {
597 if (!test_EnumKey(p, tctx, handle, depth)) {
600 if (!test_EnumValue(p, tctx, handle, 0xFF, 0xFFFF)) {
603 test_CloseKey(p, tctx, handle);
608 typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_pipe *, TALLOC_CTX *, void *);
610 static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
613 struct policy_handle handle, newhandle;
614 bool ret = true, created = false, created2 = false, deleted = false;
615 bool created3 = false, created_subkey = false;
616 struct winreg_OpenHKLM r;
618 winreg_open_fn open_fn = userdata;
620 r.in.system_name = 0;
621 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
622 r.out.handle = &handle;
624 torture_assert_ntstatus_ok(tctx, open_fn(p, tctx, &r),
627 test_Cleanup(p, tctx, &handle, TEST_KEY1);
628 test_Cleanup(p, tctx, &handle, TEST_KEY2);
629 test_Cleanup(p, tctx, &handle, TEST_SUBKEY);
630 test_Cleanup(p, tctx, &handle, TEST_KEY3);
631 test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
633 if (!test_CreateKey(p, tctx, &handle, TEST_KEY1, NULL)) {
634 torture_comment(tctx, "CreateKey failed - not considering a failure\n");
639 if (created && !test_FlushKey(p, tctx, &handle)) {
640 torture_comment(tctx, "FlushKey failed\n");
644 if (created && !test_OpenKey(p, tctx, &handle, TEST_KEY1, &newhandle))
646 "CreateKey failed (OpenKey after Create didn't work)\n");
648 if (created && !test_DeleteKey(p, tctx, &handle, TEST_KEY1)) {
649 torture_comment(tctx, "DeleteKey failed\n");
655 if (created && !test_FlushKey(p, tctx, &handle)) {
656 torture_comment(tctx, "FlushKey failed\n");
660 if (created && deleted &&
661 test_OpenKey(p, tctx, &handle, TEST_KEY1, &newhandle)) {
662 torture_comment(tctx,
663 "DeleteKey failed (OpenKey after Delete worked)\n");
667 if (!test_GetVersion(p, tctx, &handle)) {
668 torture_comment(tctx, "GetVersion failed\n");
672 if (created && test_CreateKey_sd(p, tctx, &handle, TEST_KEY2,
677 if (created2 && !test_GetKeySecurity(p, tctx, &newhandle)) {
678 printf("GetKeySecurity failed\n");
682 if (created2 && !test_CloseKey(p, tctx, &newhandle)) {
683 printf("CloseKey failed\n");
687 if (created && !test_DeleteKey(p, tctx, &handle, TEST_KEY2)) {
688 printf("DeleteKey failed\n");
692 if (created && test_CreateKey(p, tctx, &handle, TEST_KEY3, NULL)) {
697 test_CreateKey(p, tctx, &handle, TEST_SUBKEY, NULL))
699 created_subkey = true;
702 if (created_subkey &&
703 !test_DeleteKeyWithSubkey(p, tctx, &handle, TEST_KEY3))
705 printf("DeleteKeyWithSubkey failed "
706 "(DeleteKey didn't return ACCESS_DENIED)\n");
710 if (created_subkey &&
711 !test_DeleteKey(p, tctx, &handle, TEST_SUBKEY))
713 printf("DeleteKey failed\n");
718 !test_DeleteKey(p, tctx, &handle, TEST_KEY3))
720 printf("DeleteKey failed\n");
724 /* The HKCR hive has a very large fanout */
725 if (open_fn == (void *)dcerpc_winreg_OpenHKCR) {
726 if(!test_key(p, tctx, &handle, MAX_DEPTH - 1)) {
731 if(!test_key(p, tctx, &handle, 0)) {
735 test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
740 struct torture_suite *torture_rpc_winreg(TALLOC_CTX *mem_ctx)
745 } open_fns[] = {{"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM },
746 {"OpenHKU", (winreg_open_fn)dcerpc_winreg_OpenHKU },
747 {"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR },
748 {"OpenHKCU", (winreg_open_fn)dcerpc_winreg_OpenHKCU }};
750 struct torture_tcase *tcase;
751 struct torture_suite *suite = torture_suite_create(mem_ctx, "WINREG");
753 tcase = torture_suite_add_rpc_iface_tcase(suite, "winreg",
756 torture_rpc_tcase_add_test(tcase, "InitiateSystemShutdown",
757 test_InitiateSystemShutdown);
759 torture_rpc_tcase_add_test(tcase, "InitiateSystemShutdownEx",
760 test_InitiateSystemShutdownEx);
762 for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
763 torture_rpc_tcase_add_test_ex(tcase, open_fns[i].name, test_Open,