Merge branch 'v4-0-test' into id10ts-registry
authorJelmer Vernooij <jelmer@samba.org>
Sun, 2 Mar 2008 23:23:09 +0000 (00:23 +0100)
committerJelmer Vernooij <jelmer@samba.org>
Sun, 2 Mar 2008 23:23:09 +0000 (00:23 +0100)
(This used to be commit f98b59021a5ea39c7970ebc5520d17775e500b8c)

source4/lib/registry/dir.c
source4/lib/registry/ldb.c
source4/lib/registry/regf.c
source4/lib/registry/tests/hive.c
source4/samba4-knownfail
source4/torture/rpc/winreg.c

index 27cae8c49062ed9ba1ba670f47f3bc594b422763..dc3717e88614e80e312df946033bf00a2a33d866 100644 (file)
@@ -55,18 +55,66 @@ static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx,
        return WERR_GENERAL_FAILURE;
 }
 
+static WERROR reg_dir_delete_recursive(const char *name)
+{
+       DIR *d;
+       struct dirent *e;
+       WERROR werr;
+
+       d = opendir(name);
+       if (d == NULL) {
+               DEBUG(3,("Unable to open '%s': %s\n", name,
+                     strerror(errno)));
+               return WERR_BADFILE;
+       }
+
+       while((e = readdir(d))) {
+               char *path;
+               struct stat stbuf;
+
+               if (ISDOT(e->d_name) || ISDOTDOT(e->d_name))
+                       continue;
+
+               path = talloc_asprintf(name, "%s/%s", name, e->d_name);
+               if (!path)
+                       return WERR_NOMEM;
+
+               stat(path, &stbuf);
+
+               if (!S_ISDIR(stbuf.st_mode)) {
+                       if (unlink(path) < 0) {
+                               talloc_free(path);
+                               closedir(d);
+                               return WERR_GENERAL_FAILURE;
+                       }
+               } else {
+                       werr = reg_dir_delete_recursive(path);
+                       if (!W_ERROR_IS_OK(werr)) {
+                               talloc_free(path);
+                               closedir(d);
+                               return werr;
+                       }
+               }
+
+               talloc_free(path);
+       }
+       closedir(d);
+
+       if (rmdir(name) == 0)
+               return WERR_OK;
+       else if (errno == ENOENT)
+               return WERR_BADFILE;
+       else
+               return WERR_GENERAL_FAILURE;
+}
+
 static WERROR reg_dir_del_key(const struct hive_key *k, const char *name)
 {
        struct dir_key *dk = talloc_get_type(k, struct dir_key);
        char *child = talloc_asprintf(NULL, "%s/%s", dk->path, name);
        WERROR ret;
 
-       if (rmdir(child) == 0)
-               ret = WERR_OK;
-       else if (errno == ENOENT)
-               ret = WERR_BADFILE;
-       else
-               ret = WERR_GENERAL_FAILURE;
+       ret = reg_dir_delete_recursive(child);
 
        talloc_free(child);
 
index dfd368ea80d06c588a14a3d2eaf3c7a0491dc033..a764ca6235322885b4d4049f4a0cfb2d66f41d72 100644 (file)
@@ -442,33 +442,6 @@ static WERROR ldb_add_key(TALLOC_CTX *mem_ctx, const struct hive_key *parent,
        return WERR_OK;
 }
 
-static WERROR ldb_del_key(const struct hive_key *key, const char *name)
-{
-       int ret;
-       struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
-       struct ldb_dn *ldap_path;
-       TALLOC_CTX *mem_ctx = talloc_init("ldb_del_key");
-
-       ldap_path = reg_path_to_ldb(mem_ctx, key, name, NULL);
-
-       ret = ldb_delete(parentkd->ldb, ldap_path);
-
-       talloc_free(mem_ctx);
-
-       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
-               return WERR_BADFILE;
-       } else if (ret != LDB_SUCCESS) {
-               DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(parentkd->ldb)));
-               return WERR_FOOBAR;
-       }
-
-       /* reset cache */
-       talloc_free(parentkd->subkeys);
-       parentkd->subkeys = NULL;
-
-       return WERR_OK;
-}
-
 static WERROR ldb_del_value (struct hive_key *key, const char *child)
 {
        int ret;
@@ -501,6 +474,122 @@ static WERROR ldb_del_value (struct hive_key *key, const char *child)
        return WERR_OK;
 }
 
+static WERROR ldb_del_key(const struct hive_key *key, const char *name)
+{
+       int i, ret;
+       struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data);
+       struct ldb_dn *ldap_path;
+       TALLOC_CTX *mem_ctx = talloc_init("ldb_del_key");
+       struct ldb_context *c = parentkd->ldb;
+       struct ldb_result *res_keys;
+       struct ldb_result *res_vals;
+       WERROR werr;
+       struct hive_key *hk;
+
+       /* Verify key exists by opening it */
+       werr = ldb_open_key(mem_ctx, key, name, &hk);
+       if (!W_ERROR_IS_OK(werr)) {
+               talloc_free(mem_ctx);
+               return werr;
+       }
+
+       ldap_path = reg_path_to_ldb(mem_ctx, key, name, NULL);
+       if (!ldap_path) {
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       /* Search for subkeys */
+       ret = ldb_search(c, ldap_path, LDB_SCOPE_ONELEVEL,
+                        "(key=*)", NULL, &res_keys);
+
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0, ("Error getting subkeys for '%s': %s\n",
+                     ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       /* Search for values */
+       ret = ldb_search(c, ldap_path, LDB_SCOPE_ONELEVEL,
+                        "(value=*)", NULL, &res_vals);
+
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0, ("Error getting values for '%s': %s\n",
+                     ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       /* Start an explicit transaction */
+       ret = ldb_transaction_start(c);
+
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0, ("ldb_transaction_start: %s\n", ldb_errstring(c)));
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       if (res_keys->count || res_vals->count)
+       {
+               /* Delete any subkeys */
+               for (i = 0; i < res_keys->count; i++)
+               {
+                       werr = ldb_del_key(hk, ldb_msg_find_attr_as_string(
+                                                       res_keys->msgs[i],
+                                                       "key", NULL));
+                       if (!W_ERROR_IS_OK(werr)) {
+                               ret = ldb_transaction_cancel(c);
+                               talloc_free(mem_ctx);
+                               return werr;
+                       }
+               }
+
+               /* Delete any values */
+               for (i = 0; i < res_vals->count; i++)
+               {
+                       werr = ldb_del_value(hk, ldb_msg_find_attr_as_string(
+                                                       res_vals->msgs[i],
+                                                       "value", NULL));
+                       if (!W_ERROR_IS_OK(werr)) {
+                               ret = ldb_transaction_cancel(c);
+                               talloc_free(mem_ctx);
+                               return werr;
+                       }
+               }
+       }
+
+       /* Delete the key itself */
+       ret = ldb_delete(c, ldap_path);
+
+       if (ret != LDB_SUCCESS)
+       {
+               DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(c)));
+               ret = ldb_transaction_cancel(c);
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       /* Commit the transaction */
+       ret = ldb_transaction_commit(c);
+
+       if (ret != LDB_SUCCESS)
+       {
+               DEBUG(0, ("ldb_transaction_commit: %s\n", ldb_errstring(c)));
+               ret = ldb_transaction_cancel(c);
+               talloc_free(mem_ctx);
+               return WERR_FOOBAR;
+       }
+
+       talloc_free(mem_ctx);
+
+       /* reset cache */
+       talloc_free(parentkd->subkeys);
+       parentkd->subkeys = NULL;
+
+       return WERR_OK;
+}
+
 static WERROR ldb_set_value(struct hive_key *parent,
                            const char *name, uint32_t type,
                            const DATA_BLOB data)
index cf3e564c0e2c6d1369dd33eb39a9d66eae445ec7..a192f3be4ddc14c656435552d22ce3b0ed7d356a 100644 (file)
@@ -1618,10 +1618,55 @@ static WERROR regf_del_key(const struct hive_key *parent, const char *name)
                return WERR_BADFILE;
        }
 
-       if (key->nk->subkeys_offset != -1 ||
-               key->nk->values_offset != -1) {
-               DEBUG(0, ("Key '%s' is not empty.\n", name));
-               return WERR_FILE_EXISTS;
+       if (key->nk->subkeys_offset != -1) {
+               char *sk_name;
+               struct hive_key *sk = (struct hive_key *)key;
+               int i = key->nk->num_subkeys;
+               while (i--) {
+                       /* Get subkey information. */
+                       error = regf_get_subkey_by_index(parent_nk, sk, 0,
+                                                        (const char **)&sk_name,
+                                                        NULL, NULL);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't retrieve subkey by index.\n"));
+                               return error;
+                       }
+
+                       /* Delete subkey. */
+                       error = regf_del_key(sk, sk_name);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't delete key '%s'.\n", sk_name));
+                               return error;
+                       }
+
+                       talloc_free(sk_name);
+               }
+       }
+
+       if (key->nk->values_offset != -1) {
+               char *val_name;
+               struct hive_key *sk = (struct hive_key *)key;
+               DATA_BLOB data;
+               int i = key->nk->num_values;
+               while (i--) {
+                       /* Get value information. */
+                       error = regf_get_value(parent_nk, sk, 0,
+                                              (const char **)&val_name,
+                                              NULL, &data);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't retrieve value by index.\n"));
+                               return error;
+                       }
+
+                       /* Delete value. */
+                       error = regf_del_value(sk, val_name);
+                       if (!W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Can't delete value '%s'.\n", val_name));
+                               return error;
+                       }
+
+                       talloc_free(val_name);
+               }
        }
 
        /* Delete it from the subkey list. */
index 1dcb464d8015f2b808fc2af982a6bf1fd4c33cf0..1e56f125c5d168eac047c08a69328aff48881181 100644 (file)
@@ -111,6 +111,38 @@ static bool test_add_subkey(struct torture_context *tctx,
        return true;
 }
 
+static bool test_del_recursive(struct torture_context *tctx,
+                              const void *test_data)
+{
+       WERROR error;
+       struct hive_key *subkey;
+       struct hive_key *subkey2;
+       const struct hive_key *root = (const struct hive_key *)test_data;
+       TALLOC_CTX *mem_ctx = tctx;
+       uint32_t data = 42;
+
+       /* Create a new key under the root */
+       error = hive_key_add_name(mem_ctx, root, "Parent Key", NULL,
+                                 NULL, &subkey);
+       torture_assert_werr_ok(tctx, error, "hive_key_add_name");
+
+       /* Create a new key under "Parent Key" */
+       error = hive_key_add_name(mem_ctx, subkey, "Child Key", NULL,
+                                 NULL, &subkey2);
+       torture_assert_werr_ok(tctx, error, "hive_key_add_name");
+
+       /* Create a new value under "Child Key" */
+       error = hive_key_set_value(subkey2, "Answer Recursive", REG_DWORD,
+                              data_blob_talloc(mem_ctx, &data, sizeof(data)));
+       torture_assert_werr_ok(tctx, error, "hive_key_set_value");
+
+       /* Deleting "Parent Key" will also delete "Child Key" and the value. */
+       error = hive_key_del(root, "Parent Key");
+       torture_assert_werr_ok(tctx, error, "hive_key_del");
+
+       return true;
+}
+
 static bool test_flush_key(struct torture_context *tctx, void *test_data)
 {
        struct hive_key *root = (struct hive_key *)test_data;
@@ -273,6 +305,11 @@ static void tcase_add_tests(struct torture_tcase *tcase)
                                                test_add_subkey);
        torture_tcase_add_simple_test(tcase, "flush_key",
                                                test_flush_key);
+       /* test_del_recursive() test must run before test_keyinfo_root().
+          test_keyinfo_root() checks the number of subkeys, which verifies
+          the recursive delete worked properly. */
+       torture_tcase_add_simple_test_const(tcase, "del_recursive",
+                                               test_del_recursive);
        torture_tcase_add_simple_test_const(tcase, "get_info",
                                                test_keyinfo_root);
        torture_tcase_add_simple_test(tcase, "get_info_nums",
index 4d850caae5fe9543e2ce8756a5a741a47ffa2242..e6a4ea1517e5d131bb98fef2b6296a9f0f81905b 100644 (file)
@@ -3,7 +3,7 @@ local.iconv.*.next_codepoint()
 base.delaywrite.finfo update on close
 base.delete.*.deltest20a
 base.delete.*.deltest20b
-rpc.winreg
+rpc.winreg.*security
 local.registry.*.security # Not implemented yet
 rpc.wkssvc
 rpc.handles.*.lsarpc-shared
index 469573367102b7d34982150718e8fcd5db21f23d..8b602ef652dce3d270b29fa1f1f9ab51e07e8edd 100644 (file)
@@ -848,7 +848,6 @@ static bool test_SecurityDescriptorInheritance(struct dcerpc_pipe *p,
 
  out:
        test_CloseKey(p, tctx, &new_handle);
-       test_Cleanup(p, tctx, handle, TEST_SUBSUBKEY_SD);
        test_Cleanup(p, tctx, handle, TEST_SUBKEY_SD);
        test_RestoreSecurity(p, tctx, handle, key, sd_orig);
 
@@ -971,7 +970,6 @@ static bool test_SecurityDescriptorBlockInheritance(struct dcerpc_pipe *p,
 
  out:
        test_CloseKey(p, tctx, &new_handle);
-       test_Cleanup(p, tctx, handle, TEST_SUBSUBKEY_SD);
        test_Cleanup(p, tctx, handle, TEST_SUBKEY_SD);
        test_RestoreSecurity(p, tctx, handle, key, sd_orig);
 
@@ -1386,27 +1384,6 @@ static bool test_DeleteKey(struct dcerpc_pipe *p, struct torture_context *tctx,
        return true;
 }
 
-/* DeleteKey on a key with subkey(s) should
- * return WERR_ACCESS_DENIED. */
-static bool test_DeleteKeyWithSubkey(struct dcerpc_pipe *p,
-                                    struct torture_context *tctx,
-                                    struct policy_handle *handle,
-                                    const char *key)
-{
-       struct winreg_DeleteKey r;
-
-       r.in.handle = handle;
-       init_winreg_String(&r.in.key, key);
-
-       torture_assert_ntstatus_ok(tctx, dcerpc_winreg_DeleteKey(p, tctx, &r),
-                                  "DeleteKeyWithSubkey failed");
-
-       torture_assert_werr_equal(tctx, r.out.result, WERR_ACCESS_DENIED,
-                                 "DeleteKeyWithSubkey failed");
-
-       return true;
-}
-
 static bool test_QueryInfoKey(struct dcerpc_pipe *p,
                              struct torture_context *tctx,
                              struct policy_handle *handle, char *class)
@@ -1443,10 +1420,12 @@ static bool test_QueryInfoKey(struct dcerpc_pipe *p,
 }
 
 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
-                    struct policy_handle *handle, int depth);
+                    struct policy_handle *handle, int depth,
+                    bool test_security);
 
 static bool test_EnumKey(struct dcerpc_pipe *p, struct torture_context *tctx,
-                        struct policy_handle *handle, int depth)
+                        struct policy_handle *handle, int depth,
+                        bool test_security)
 {
        struct winreg_EnumKey r;
        struct winreg_StringBuf class, name;
@@ -1479,7 +1458,8 @@ static bool test_EnumKey(struct dcerpc_pipe *p, struct torture_context *tctx,
                        if (!test_OpenKey(p, tctx, handle, r.out.name->name,
                                          &key_handle)) {
                        } else {
-                               test_key(p, tctx, &key_handle, depth + 1);
+                               test_key(p, tctx, &key_handle,
+                                        depth + 1, test_security);
                        }
                }
 
@@ -1676,7 +1656,8 @@ static bool test_InitiateSystemShutdownEx(struct torture_context *tctx,
 #define MAX_DEPTH 2            /* Only go this far down the tree */
 
 static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
-                    struct policy_handle *handle, int depth)
+                    struct policy_handle *handle, int depth,
+                    bool test_security)
 {
        if (depth == MAX_DEPTH)
                return true;
@@ -1687,10 +1668,10 @@ static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
        if (!test_NotifyChangeKeyValue(p, tctx, handle)) {
        }
 
-       if (!test_GetKeySecurity(p, tctx, handle, NULL)) {
+       if (test_security && !test_GetKeySecurity(p, tctx, handle, NULL)) {
        }
 
-       if (!test_EnumKey(p, tctx, handle, depth)) {
+       if (!test_EnumKey(p, tctx, handle, depth, test_security)) {
        }
 
        if (!test_EnumValue(p, tctx, handle, 0xFF, 0xFFFF)) {
@@ -1703,13 +1684,85 @@ static bool test_key(struct dcerpc_pipe *p, struct torture_context *tctx,
 
 typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_pipe *, TALLOC_CTX *, void *);
 
+static bool test_Open_Security(struct torture_context *tctx,
+                              struct dcerpc_pipe *p, void *userdata)
+{
+       struct policy_handle handle, newhandle;
+       bool ret = true, created2 = false;
+       bool created4 = false;
+       struct winreg_OpenHKLM r;
+
+       winreg_open_fn open_fn = userdata;
+
+       r.in.system_name = 0;
+       r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       r.out.handle = &handle;
+
+       torture_assert_ntstatus_ok(tctx, open_fn(p, tctx, &r),
+                                  "open");
+
+       test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
+
+       if (!test_CreateKey(p, tctx, &handle, TEST_KEY_BASE, NULL)) {
+               torture_comment(tctx,
+                               "CreateKey (TEST_KEY_BASE) failed\n");
+       }
+
+       if (test_CreateKey_sd(p, tctx, &handle, TEST_KEY2,
+                             NULL, &newhandle)) {
+               created2 = true;
+       }
+
+       if (created2 && !test_CloseKey(p, tctx, &newhandle)) {
+               printf("CloseKey failed\n");
+               ret = false;
+       }
+
+       if (test_CreateKey_sd(p, tctx, &handle, TEST_KEY4, NULL, &newhandle)) {
+               created4 = true;
+       }
+
+       if (created4 && !test_CloseKey(p, tctx, &newhandle)) {
+               printf("CloseKey failed\n");
+               ret = false;
+       }
+
+       if (created4 && !test_SecurityDescriptors(p, tctx, &handle, TEST_KEY4)) {
+               ret = false;
+       }
+
+       if (created4 && !test_DeleteKey(p, tctx, &handle, TEST_KEY4)) {
+               printf("DeleteKey failed\n");
+               ret = false;
+       }
+
+       if (created2 && !test_DeleteKey(p, tctx, &handle, TEST_KEY2)) {
+               printf("DeleteKey failed\n");
+               ret = false;
+       }
+
+       /* The HKCR hive has a very large fanout */
+       if (open_fn == (void *)dcerpc_winreg_OpenHKCR) {
+               if(!test_key(p, tctx, &handle, MAX_DEPTH - 1, true)) {
+                       ret = false;
+               }
+       } else {
+               if (!test_key(p, tctx, &handle, 0, true)) {
+                       ret = false;
+               }
+       }
+
+       test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
+
+       return ret;
+}
+
 static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
                      void *userdata)
 {
        struct policy_handle handle, newhandle;
-       bool ret = true, created = false, created2 = false, deleted = false;
+       bool ret = true, created = false, deleted = false;
        bool created3 = false, created_subkey = false;
-       bool created4 = false;
        struct winreg_OpenHKLM r;
 
        winreg_open_fn open_fn = userdata;
@@ -1721,15 +1774,13 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
        torture_assert_ntstatus_ok(tctx, open_fn(p, tctx, &r),
                                   "open");
 
-       test_Cleanup(p, tctx, &handle, TEST_KEY1);
-       test_Cleanup(p, tctx, &handle, TEST_SUBSUBKEY_SD);
-       test_Cleanup(p, tctx, &handle, TEST_SUBKEY_SD);
-       test_Cleanup(p, tctx, &handle, TEST_KEY4);
-       test_Cleanup(p, tctx, &handle, TEST_KEY2);
-       test_Cleanup(p, tctx, &handle, TEST_SUBKEY);
-       test_Cleanup(p, tctx, &handle, TEST_KEY3);
        test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
 
+       if (!test_CreateKey(p, tctx, &handle, TEST_KEY_BASE, NULL)) {
+               torture_comment(tctx,
+                               "CreateKey (TEST_KEY_BASE) failed\n");
+       }
+
        if (!test_CreateKey(p, tctx, &handle, TEST_KEY1, NULL)) {
                torture_comment(tctx,
                                "CreateKey failed - not considering a failure\n");
@@ -1763,9 +1814,12 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
        }
 
        if (created && deleted &&
-           test_OpenKey(p, tctx, &handle, TEST_KEY1, &newhandle)) {
+           !_test_OpenKey(p, tctx, &handle, TEST_KEY1,
+                          SEC_FLAG_MAXIMUM_ALLOWED, &newhandle,
+                          WERR_BADFILE, NULL)) {
                torture_comment(tctx,
-                               "DeleteKey failed (OpenKey after Delete worked)\n");
+                               "DeleteKey failed (OpenKey after Delete "
+                               "did not return WERR_BADFILE)\n");
                ret = false;
        }
 
@@ -1774,40 +1828,6 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
                ret = false;
        }
 
-       if (created && test_CreateKey_sd(p, tctx, &handle, TEST_KEY2,
-                                        NULL, &newhandle)) {
-               created2 = true;
-       }
-
-       if (created2 && !test_CloseKey(p, tctx, &newhandle)) {
-               printf("CloseKey failed\n");
-               ret = false;
-       }
-
-       if (test_CreateKey_sd(p, tctx, &handle, TEST_KEY4, NULL, &newhandle)) {
-               created4 = true;
-       }
-
-       if (!created4 && !test_CloseKey(p, tctx, &newhandle)) {
-               printf("CloseKey failed\n");
-               ret = false;
-       }
-
-       if (created4 && !test_SecurityDescriptors(p, tctx, &handle, TEST_KEY4)) {
-               ret = false;
-       }
-
-       if (created4 && !test_DeleteKey(p, tctx, &handle, TEST_KEY4)) {
-               printf("DeleteKey failed\n");
-               ret = false;
-       }
-
-
-       if (created && !test_DeleteKey(p, tctx, &handle, TEST_KEY2)) {
-               printf("DeleteKey failed\n");
-               ret = false;
-       }
-
        if (created && test_CreateKey(p, tctx, &handle, TEST_KEY3, NULL)) {
                created3 = true;
        }
@@ -1818,19 +1838,6 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
        }
 
        if (created_subkey &&
-           !test_DeleteKeyWithSubkey(p, tctx, &handle, TEST_KEY3)) {
-               printf("DeleteKeyWithSubkey failed "
-                      "(DeleteKey didn't return ACCESS_DENIED)\n");
-               ret = false;
-       }
-
-       if (created_subkey &&
-           !test_DeleteKey(p, tctx, &handle, TEST_SUBKEY)) {
-               printf("DeleteKey failed\n");
-               ret = false;
-       }
-
-       if (created3 &&
            !test_DeleteKey(p, tctx, &handle, TEST_KEY3)) {
                printf("DeleteKey failed\n");
                ret = false;
@@ -1838,13 +1845,13 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
 
        /* The HKCR hive has a very large fanout */
        if (open_fn == (void *)dcerpc_winreg_OpenHKCR) {
-               if(!test_key(p, tctx, &handle, MAX_DEPTH - 1)) {
+               if(!test_key(p, tctx, &handle, MAX_DEPTH - 1, false)) {
+                       ret = false;
+               }
+       } else {
+               if (!test_key(p, tctx, &handle, 0, false)) {
                        ret = false;
                }
-       }
-
-       if (!test_key(p, tctx, &handle, 0)) {
-               ret = false;
        }
 
        test_Cleanup(p, tctx, &handle, TEST_KEY_BASE);
@@ -1854,14 +1861,6 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p,
 
 struct torture_suite *torture_rpc_winreg(TALLOC_CTX *mem_ctx)
 {
-       struct {
-               const char *name;
-               winreg_open_fn fn;
-       } open_fns[] = {{"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM },
-                       {"OpenHKU",  (winreg_open_fn)dcerpc_winreg_OpenHKU },
-                       {"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR },
-                       {"OpenHKCU", (winreg_open_fn)dcerpc_winreg_OpenHKCU }};
-       int i;
        struct torture_rpc_tcase *tcase;
        struct torture_suite *suite = torture_suite_create(mem_ctx, "WINREG");
        struct torture_test *test;
@@ -1877,10 +1876,33 @@ struct torture_suite *torture_rpc_winreg(TALLOC_CTX *mem_ctx)
                                          test_InitiateSystemShutdownEx);
        test->dangerous = true;
 
-       for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
-               torture_rpc_tcase_add_test_ex(tcase, open_fns[i].name,
-                                             test_Open, open_fns[i].fn);
-       }
+       /* Basic tests without security descriptors */
+       torture_rpc_tcase_add_test_ex(tcase, "HKLM-basic",
+                                     test_Open,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKLM);
+       torture_rpc_tcase_add_test_ex(tcase, "HKU-basic",
+                                     test_Open,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKU);
+       torture_rpc_tcase_add_test_ex(tcase, "HKCR-basic",
+                                     test_Open,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKCR);
+       torture_rpc_tcase_add_test_ex(tcase, "HKCU-basic",
+                                     test_Open,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKCU);
+
+       /* Security descriptor tests */
+       torture_rpc_tcase_add_test_ex(tcase, "HKLM-security",
+                                     test_Open_Security,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKLM);
+       torture_rpc_tcase_add_test_ex(tcase, "HKU-security",
+                                     test_Open_Security,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKU);
+       torture_rpc_tcase_add_test_ex(tcase, "HKCR-security",
+                                     test_Open_Security,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKCR);
+       torture_rpc_tcase_add_test_ex(tcase, "HKCU-security",
+                                     test_Open_Security,
+                                     (winreg_open_fn)dcerpc_winreg_OpenHKCU);
 
        return suite;
 }