diff options
author | Wilco Baan Hofman <wilco@synlap.(none)> | 2008-04-14 22:52:51 +0200 |
---|---|---|
committer | Wilco Baan Hofman <wilco@synlap.(none)> | 2008-04-14 22:52:51 +0200 |
commit | 12147fca2b3acd37eb20db82996714320cd4e9b2 (patch) | |
tree | 8744cccefb088a5d179978829df650ae5801c3ed /source4/lib/registry | |
parent | 212644b5a1107ad81e5ce3bc3118c8983d3f2a86 (diff) | |
download | samba-12147fca2b3acd37eb20db82996714320cd4e9b2.tar.gz samba-12147fca2b3acd37eb20db82996714320cd4e9b2.tar.bz2 samba-12147fca2b3acd37eb20db82996714320cd4e9b2.zip |
Add support for security descriptors. Also patched the regf backend to support this.
Did not touch the ldb, dir and rpc backends yet.
(This used to be commit c4626f21a898da27a051f2c67f8fd73f55d4fc7d)
Diffstat (limited to 'source4/lib/registry')
-rw-r--r-- | source4/lib/registry/hive.c | 18 | ||||
-rw-r--r-- | source4/lib/registry/interface.c | 23 | ||||
-rw-r--r-- | source4/lib/registry/local.c | 16 | ||||
-rw-r--r-- | source4/lib/registry/regf.c | 64 | ||||
-rw-r--r-- | source4/lib/registry/registry.h | 21 | ||||
-rw-r--r-- | source4/lib/registry/tests/hive.c | 56 | ||||
-rw-r--r-- | source4/lib/registry/tests/registry.c | 8 |
7 files changed, 164 insertions, 42 deletions
diff --git a/source4/lib/registry/hive.c b/source4/lib/registry/hive.c index 2a9b1a59ce..3bb5b566c9 100644 --- a/source4/lib/registry/hive.c +++ b/source4/lib/registry/hive.c @@ -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) { diff --git a/source4/lib/registry/interface.c b/source4/lib/registry/interface.c index a18fd2c28c..06b002859d 100644 --- a/source4/lib/registry/interface.c +++ b/source4/lib/registry/interface.c @@ -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); } diff --git a/source4/lib/registry/local.c b/source4/lib/registry/local.c index 5bf2d86588..da381cfbff 100644 --- a/source4/lib/registry/local.c +++ b/source4/lib/registry/local.c @@ -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, diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 46ccca922b..57a895aa00 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -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; } diff --git a/source4/lib/registry/registry.h b/source4/lib/registry/registry.h index a86294bf46..1348d1121f 100644 --- a/source4/lib/registry/registry.h +++ b/source4/lib/registry/registry.h @@ -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, diff --git a/source4/lib/registry/tests/hive.c b/source4/lib/registry/tests/hive.c index a16736c761..4fe7f66c03 100644 --- a/source4/lib/registry/tests/hive.c +++ b/source4/lib/registry/tests/hive.c @@ -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; diff --git a/source4/lib/registry/tests/registry.c b/source4/lib/registry/tests/registry.c index b19a6abffb..97c1190a68 100644 --- a/source4/lib/registry/tests/registry.c +++ b/source4/lib/registry/tests/registry.c @@ -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!"); |