Add support for security descriptors. Also patched the regf backend to support this.
authorWilco Baan Hofman <wilco@synlap.(none)>
Mon, 14 Apr 2008 20:52:51 +0000 (22:52 +0200)
committerWilco Baan Hofman <wilco@synlap.(none)>
Mon, 14 Apr 2008 20:52:51 +0000 (22:52 +0200)
Did not touch the ldb, dir and rpc backends yet.
(This used to be commit c4626f21a898da27a051f2c67f8fd73f55d4fc7d)

source4/lib/registry/hive.c
source4/lib/registry/interface.c
source4/lib/registry/local.c
source4/lib/registry/regf.c
source4/lib/registry/registry.h
source4/lib/registry/tests/hive.c
source4/lib/registry/tests/registry.c

index 2a9b1a59ceff6d91cfaf679b16d7c94f7a03abc0..3bb5b566c916e9309b562f682806b374df7949a6 100644 (file)
@@ -143,6 +143,24 @@ WERROR hive_get_value_by_index(TALLOC_CTX *mem_ctx,
        return key->ops->enum_value(mem_ctx, key, idx, name, type, data);
 }
 
+WERROR hive_get_sec_desc(TALLOC_CTX *mem_ctx,
+                        struct hive_key *key, 
+                        struct security_descriptor **security)
+{
+       if (key->ops->get_sec_desc == NULL)
+               return WERR_NOT_SUPPORTED;
+
+       return key->ops->get_sec_desc(mem_ctx, key, security);
+}
+
+WERROR hive_set_sec_desc(struct hive_key *key, 
+                        const struct security_descriptor *security)
+{
+       if (key->ops->set_sec_desc == NULL)
+               return WERR_NOT_SUPPORTED;
+
+       return key->ops->set_sec_desc(key, security);
+}
 
 WERROR hive_key_del_value(struct hive_key *key, const char *name)
 {
index a18fd2c28c88fa61fc07cb66d5b941721c0d67fa..06b002859d4e3875acd57847dab0659f65a88907 100644 (file)
@@ -249,10 +249,10 @@ _PUBLIC_ WERROR reg_get_sec_desc(TALLOC_CTX *ctx,
                return WERR_INVALID_PARAM;
 
        /* A 'real' set function has preference */
-       if (key->context->ops->get_security == NULL)
+       if (key->context->ops->get_sec_desc == NULL)
                return WERR_NOT_SUPPORTED;
 
-       return key->context->ops->get_security(ctx, key, secdesc);
+       return key->context->ops->get_sec_desc(ctx, key, secdesc);
 }
 
 /**
@@ -283,27 +283,14 @@ _PUBLIC_ WERROR reg_key_flush(struct registry_key *key)
        return key->context->ops->flush_key(key);
 }
 
-_PUBLIC_ WERROR reg_get_security(TALLOC_CTX *mem_ctx,
-                                const struct registry_key *key,
-                                struct security_descriptor **security)
-{
-       if (key == NULL)
-               return WERR_INVALID_PARAM;
-
-       if (key->context->ops->get_security == NULL)
-               return WERR_NOT_SUPPORTED;
-
-       return key->context->ops->get_security(mem_ctx, key, security);
-}
-
-_PUBLIC_ WERROR reg_set_security(struct registry_key *key,
+_PUBLIC_ WERROR reg_set_sec_desc(struct registry_key *key,
                                 struct security_descriptor *security)
 {
        if (key == NULL)
                return WERR_INVALID_PARAM;
 
-       if (key->context->ops->set_security == NULL)
+       if (key->context->ops->set_sec_desc == NULL)
                return WERR_NOT_SUPPORTED;
 
-       return key->context->ops->set_security(key, security);
+       return key->context->ops->set_sec_desc(key, security);
 }
index 5bf2d86588f97987a33b4641143418f6fe142fe1..da381cfbff39dcea613e4f4ace9a0b9f0a8d0c8d 100644 (file)
@@ -278,7 +278,21 @@ static WERROR local_get_key_info(TALLOC_CTX *mem_ctx,
                                 last_change_time, max_subkeynamelen, 
                                 max_valnamelen, max_valbufsize);
 }
+static WERROR local_get_sec_desc(TALLOC_CTX *mem_ctx, 
+                                const struct registry_key *key, 
+                                struct security_descriptor **security)
+{
+       const struct local_key *local = (const struct local_key *)key;
 
+       return hive_get_sec_desc(mem_ctx, local->hive_key, security);
+}
+static WERROR local_set_sec_desc(struct registry_key *key, 
+                                const struct security_descriptor *security)
+{
+       const struct local_key *local = (const struct local_key *)key;
+
+       return hive_set_sec_desc(local->hive_key, security);
+}
 const static struct registry_operations local_ops = {
        .name = "local",
        .open_key = local_open_key,
@@ -292,6 +306,8 @@ const static struct registry_operations local_ops = {
        .delete_value = local_delete_value,
        .flush_key = local_flush_key,
        .get_key_info = local_get_key_info,
+       .get_sec_desc = local_get_sec_desc,
+       .set_sec_desc = local_set_sec_desc,
 };
 
 WERROR reg_open_local(TALLOC_CTX *mem_ctx, struct registry_context **ctx,
index 46ccca922b8903d7892c908326ee4eff21a31319..57a895aa000b6cd17803093a2e58d12b1951bcf4 100644 (file)
@@ -25,6 +25,8 @@
 #include "librpc/gen_ndr/winreg.h"
 #include "param/param.h"
 #include "lib/registry/registry.h"
+#include "libcli/security/security.h"
+
 
 static struct hive_operations reg_backend_regf;
 
@@ -1915,9 +1917,12 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx,
 {
        struct regf_data *regf;
        struct regf_hdr *regf_hdr;
-       int i;
        struct nk_block nk;
+       struct sk_block sk;
        WERROR error;
+       DATA_BLOB data;
+       struct security_descriptor *sd;
+       uint32_t sk_offset;
 
        regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
 
@@ -1945,20 +1950,17 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx,
        regf_hdr->version.minor = minor_version;
        regf_hdr->last_block = 0x1000; /* Block size */
        regf_hdr->description = talloc_strdup(regf_hdr,
-                                             "registry created by Samba 4");
+                                             "Registry created by Samba 4");
        W_ERROR_HAVE_NO_MEMORY(regf_hdr->description);
        regf_hdr->chksum = 0;
 
        regf->header = regf_hdr;
 
-       i = 0;
        /* Create all hbin blocks */
        regf->hbins = talloc_array(regf, struct hbin_block *, 1);
        W_ERROR_HAVE_NO_MEMORY(regf->hbins);
        regf->hbins[0] = NULL;
 
-       regf_hdr->data_offset = -1; /* FIXME */
-
        nk.header = "nk";
        nk.type = REG_SUB_KEY;
        unix_to_nt_time(&nk.last_change, time(NULL));
@@ -1971,27 +1973,67 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx,
        nk.num_values = 0;
        nk.values_offset = -1;
        memset(nk.unk3, 0, 5);
-       nk.clsname_offset = -1; /* FIXME: fill in */
+       nk.clsname_offset = -1;
        nk.clsname_length = 0;
-       nk.key_name = "";
+       nk.sk_offset = 0x80;
+       nk.key_name = "SambaRootKey";
+
+       /*
+        * It should be noted that changing the key_name to something shorter
+        * creates a shorter nk block, which makes the position of the sk block
+        * change. All Windows registries I've seen have the sk at 0x80. 
+        * I therefore recommend that our regf files share that offset -- Wilco
+        */
+
+       /* Create a security descriptor. */
+       sd = security_descriptor_dacl_create(regf,
+                                        0,
+                                        NULL, NULL,
+                                        SID_NT_AUTHENTICATED_USERS,
+                                        SEC_ACE_TYPE_ACCESS_ALLOWED,
+                                        SEC_GENERIC_ALL,
+                                        SEC_ACE_FLAG_OBJECT_INHERIT,
+                                        NULL);
+       
+       /* Push the security descriptor to a blob */
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL, 
+                                    sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
+               DEBUG(0, ("Unable to push security descriptor\n"));
+               return WERR_GENERAL_FAILURE;
+       }
 
-       nk.sk_offset = -1; /* FIXME: fill in */
+       ZERO_STRUCT(sk);
+       sk.header = "sk";
+       sk.prev_offset = 0x80;
+       sk.next_offset = 0x80;
+       sk.ref_cnt = 1;
+       sk.rec_size = data.length;
+       sk.sec_desc = data.data;
 
        /* Store the new nk key */
        regf->header->data_offset = hbin_store_tdr(regf,
                                                   (tdr_push_fn_t)tdr_push_nk_block,
                                                   &nk);
+       /* Store the sk block */
+       sk_offset = hbin_store_tdr(regf,
+                                  (tdr_push_fn_t) tdr_push_sk_block,
+                                  &sk);
+       if (sk_offset != 0x80) {
+               DEBUG(0, ("Error storing sk block, should be at 0x80, stored at 0x%x\n", nk.sk_offset));
+               return WERR_GENERAL_FAILURE;
+       }
+
 
        *key = (struct hive_key *)regf_get_key(parent_ctx, regf,
                                               regf->header->data_offset);
 
-       /* We can drop our own reference now that *key will have created one */
-       talloc_free(regf);
-
        error = regf_save_hbin(regf);
        if (!W_ERROR_IS_OK(error)) {
                return error;
        }
+       
+       /* We can drop our own reference now that *key will have created one */
+       talloc_free(regf);
 
        return WERR_OK;
 }
index a86294bf4656c1ab996a6c9d027d093c53560089..1348d1121f1cbb80b4c495909db35dc211e67566 100644 (file)
@@ -184,6 +184,12 @@ WERROR hive_get_value_by_index(TALLOC_CTX *mem_ctx,
                               struct hive_key *key, uint32_t idx,
                               const char **name,
                               uint32_t *type, DATA_BLOB *data);
+WERROR hive_get_sec_desc(TALLOC_CTX *mem_ctx,
+                        struct hive_key *key,
+                        struct security_descriptor **security);
+
+WERROR hive_set_sec_desc(struct hive_key *key, 
+                        const struct security_descriptor *security);
 
 WERROR hive_key_del_value(struct hive_key *key, const char *name);
 
@@ -311,11 +317,11 @@ struct registry_operations {
                              uint32_t *type,
                              DATA_BLOB *data);
 
-       WERROR (*get_security) (TALLOC_CTX *mem_ctx,
+       WERROR (*get_sec_desc) (TALLOC_CTX *mem_ctx,
                                const struct registry_key *key,
                                struct security_descriptor **security);
 
-       WERROR (*set_security) (struct registry_key *key,
+       WERROR (*set_sec_desc) (struct registry_key *key,
                                const struct security_descriptor *security);
 
        WERROR (*load_key) (struct registry_key *key,
@@ -461,12 +467,8 @@ struct registry_key *reg_import_hive_key(struct registry_context *ctx,
                                         struct hive_key *hive,
                                         uint32_t predef_key,
                                         const char **elements);
-WERROR reg_get_security(TALLOC_CTX *mem_ctx,
-                       const struct registry_key *key,
-                       struct security_descriptor **security);
-
-WERROR reg_set_security(struct registry_key *key,
-                       struct security_descriptor *security);
+WERROR reg_set_sec_desc(struct registry_key *key,
+                       const struct security_descriptor *security);
 
 struct reg_diff_callbacks {
        WERROR (*add_key) (void *callback_data, const char *key_name);
@@ -490,6 +492,9 @@ WERROR reg_dotreg_diff_save(TALLOC_CTX *ctx, const char *filename,
                            struct smb_iconv_convenience *iconv_convenience,
                            struct reg_diff_callbacks **callbacks,
                            void **callback_data);
+WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename,
+                         struct reg_diff_callbacks **callbacks,
+                         void **callback_data);
 WERROR reg_generate_diff_key(struct registry_key *oldkey,
                             struct registry_key *newkey,
                             const char *path,
index a16736c761dec4b6415eca49875bd4937369b70e..4fe7f66c03d6f5055ebab84f287ac7cda457c4af 100644 (file)
@@ -26,6 +26,7 @@
 #include "librpc/gen_ndr/winreg.h"
 #include "system/filesys.h"
 #include "param/param.h"
+#include "libcli/security/security.h"
 
 static bool test_del_nonexistant_key(struct torture_context *tctx,
                                     const void *test_data)
@@ -297,6 +298,57 @@ static bool test_list_values(struct torture_context *tctx,
        return true;
 }
 
+static bool test_hive_security(struct torture_context *tctx, const void *_data)
+{
+       struct hive_key *subkey = NULL;
+        const struct hive_key *root = _data;
+       WERROR error;
+       struct security_descriptor *osd, *nsd;
+       
+       osd = security_descriptor_dacl_create(tctx,
+                                        0,
+                                        NULL, NULL,
+                                        SID_NT_AUTHENTICATED_USERS,
+                                        SEC_ACE_TYPE_ACCESS_ALLOWED,
+                                        SEC_GENERIC_ALL,
+                                        SEC_ACE_FLAG_OBJECT_INHERIT,
+                                        NULL);
+
+
+       error = hive_key_add_name(tctx, root, "SecurityKey", NULL,
+                                 osd, &subkey);
+       torture_assert_werr_ok(tctx, error, "hive_key_add_name");
+
+       error = hive_get_sec_desc(tctx, subkey, &nsd);
+       torture_assert_werr_ok (tctx, error, "getting security descriptor");
+
+       torture_assert(tctx, security_descriptor_equal(osd, nsd),
+                      "security descriptor changed!");
+
+       /* Create a fresh security descriptor */        
+       talloc_free(osd);
+       osd = security_descriptor_dacl_create(tctx,
+                                        0,
+                                        NULL, NULL,
+                                        SID_NT_AUTHENTICATED_USERS,
+                                        SEC_ACE_TYPE_ACCESS_ALLOWED,
+                                        SEC_GENERIC_ALL,
+                                        SEC_ACE_FLAG_OBJECT_INHERIT,
+                                        NULL);
+
+       error = hive_set_sec_desc(subkey, osd);
+       torture_assert_werr_ok(tctx, error, "setting security descriptor");
+       
+       printf("The second one is done.\n");
+       error = hive_get_sec_desc(tctx, subkey, &nsd);
+       torture_assert_werr_ok (tctx, error, "getting security descriptor");
+       
+       torture_assert(tctx, security_descriptor_equal(osd, nsd),
+                      "security descriptor changed!");
+
+       return true;
+}
+
 static void tcase_add_tests(struct torture_tcase *tcase)
 {
        torture_tcase_add_simple_test_const(tcase, "del_nonexistant_key",
@@ -324,6 +376,8 @@ static void tcase_add_tests(struct torture_tcase *tcase)
                                                test_del_key);
        torture_tcase_add_simple_test_const(tcase, "del_value",
                                                test_del_value);
+       torture_tcase_add_simple_test_const(tcase, "check hive security",
+                                               test_hive_security);
 }
 
 static bool hive_setup_dir(struct torture_context *tctx, void **data)
@@ -381,7 +435,7 @@ static bool hive_setup_regf(struct torture_context *tctx, void **data)
        char *dirname;
        NTSTATUS status;
 
-       status = torture_temp_dir(tctx, "hive-dir", &dirname);
+       status = torture_temp_dir(tctx, "hive-regf", &dirname);
        if (!NT_STATUS_IS_OK(status))
                return false;
 
index b19a6abffb91bdf9a7e638115547a662df8f7d46..97c1190a684bbf08857e26d16cbfc6a52d89d184 100644 (file)
@@ -387,11 +387,11 @@ static bool test_security(struct torture_context *tctx, void *_data)
                                         SEC_ACE_FLAG_OBJECT_INHERIT,
                                         NULL);
 
-       error = reg_set_security(subkey, osd);
-       torture_assert_werr_ok(tctx, error, "setting security");
+       error = reg_set_sec_desc(subkey, osd);
+       torture_assert_werr_ok(tctx, error, "setting security descriptor");
 
-       error = reg_get_security(tctx, subkey, &nsd);
-       torture_assert_werr_ok (tctx, error, "setting security");
+       error = reg_get_sec_desc(tctx, subkey, &nsd);
+       torture_assert_werr_ok (tctx, error, "getting security descriptor");
 
        torture_assert(tctx, security_descriptor_equal(osd, nsd),
                       "security descriptor changed!");