Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into registry
authorJelmer Vernooij <jelmer@samba.org>
Fri, 23 May 2008 13:24:40 +0000 (15:24 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Fri, 23 May 2008 13:24:40 +0000 (15:24 +0200)
(This used to be commit e8d96b61db1cddc2d8dca45e6e9b53d5c31ee5d4)

source4/lib/registry/hive.c
source4/lib/registry/interface.c
source4/lib/registry/local.c
source4/lib/registry/patchfile.c
source4/lib/registry/patchfile_dotreg.c
source4/lib/registry/patchfile_preg.c
source4/lib/registry/regf.c
source4/lib/registry/registry.h
source4/lib/registry/tests/diff.c
source4/lib/registry/tests/hive.c
source4/lib/registry/tests/registry.c

index 4a2309faeee00fb3fd67cde30d824c1b03220112..5105040f30618514e395cf4ad26e30d86b08486c 100644 (file)
@@ -144,6 +144,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 ff3ddf0a3599f08b8f04857e9a0e7c38b77f5de9..c9b3b064470f3d49002a2f99622c6c452d161d37 100644 (file)
@@ -248,10 +248,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);
 }
 
 /**
@@ -282,27 +282,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,
-                                struct security_descriptor *security)
+_PUBLIC_ WERROR reg_set_sec_desc(struct registry_key *key,
+                                const 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 47d6d4cd32692224316e7d6f7fd7b489878d9480..4af95e2dd62d46fc9754bae51011934d675e9c45 100644 (file)
@@ -274,7 +274,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,
@@ -288,6 +302,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 15e3a158f2b8d9a0b8683316317de4779668fb04..0ede3106f00dceecb9e95deee19aa503e867c1a3 100644 (file)
@@ -45,7 +45,7 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey,
                             void *callback_data)
 {
        int i;
-       struct registry_key *t1, *t2;
+       struct registry_key *t1 = NULL, *t2 = NULL;
        char *tmppath;
        const char *keyname1;
        WERROR error, error1, error2;
@@ -295,7 +295,7 @@ _PUBLIC_ WERROR reg_diff_load(const char *filename,
 
        /* Reset position in file */
        lseek(fd, 0, SEEK_SET);
-#if 0
+#if 0 /* These backends are not supported yet. */
        if (strncmp(hdr, "CREG", 4) == 0) {
                /* Must be a W9x CREG Config.pol file */
                return reg_creg_diff_load(diff, fd);
@@ -320,12 +320,33 @@ static WERROR reg_diff_apply_add_key(void *_ctx, const char *key_name)
 {
        struct registry_context *ctx = (struct registry_context *)_ctx;
        struct registry_key *tmp;
+       char *buf, *buf_ptr;
        WERROR error;
 
+       /* Recursively create the path */
+       buf = talloc_strdup(ctx, key_name);
+       buf_ptr = buf;
+
+       while (*buf_ptr++ != '\0' ) {
+               if (*buf_ptr == '\\') {
+                       *buf_ptr = '\0';
+                       error = reg_key_add_abs(ctx, ctx, buf, 0, NULL, &tmp);
+
+                       if (!W_ERROR_EQUAL(error, WERR_ALREADY_EXISTS) &&
+                                   !W_ERROR_IS_OK(error)) {
+                               DEBUG(0, ("Error adding new key '%s': %s\n",
+                                       key_name, win_errstr(error)));
+                               return error;
+                       }
+                       *buf_ptr++ = '\\';
+               }
+       }
+
+       /* Add the key */
        error = reg_key_add_abs(ctx, ctx, key_name, 0, NULL, &tmp);
 
        if (!W_ERROR_EQUAL(error, WERR_ALREADY_EXISTS) &&
-           !W_ERROR_IS_OK(error)) {
+                   !W_ERROR_IS_OK(error)) {
                DEBUG(0, ("Error adding new key '%s': %s\n",
                        key_name, win_errstr(error)));
                return error;
index 59f40447135a9b332e1fdc1cb12fac7767a30624..1bc9c607536a9d732b0f0758e4cf798b039742ba 100644 (file)
@@ -3,7 +3,7 @@
    Reading .REG files
 
    Copyright (C) Jelmer Vernooij 2004-2007
-   Copyright (C) Wilco Baan Hofman 2006
+   Copyright (C) Wilco Baan Hofman 2006-2008
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* FIXME Newer .REG files, created by Windows XP and above use unicode UTF-16 */
+/* FIXME Newer .REG files, created by Windows XP and above use unicode UCS-2 */
 
 #include "includes.h"
 #include "lib/registry/registry.h"
@@ -112,8 +112,8 @@ _PUBLIC_ WERROR reg_dotreg_diff_save(TALLOC_CTX *ctx, const char *filename,
        data->iconv_convenience = iconv_convenience;
 
        if (filename) {
-               data->fd = open(filename, O_CREAT, 0755);
-               if (data->fd == -1) {
+               data->fd = open(filename, O_CREAT|O_WRONLY, 0755);
+               if (data->fd < 0) {
                        DEBUG(0, ("Unable to open %s\n", filename));
                        return WERR_BADFILE;
                }
@@ -121,7 +121,7 @@ _PUBLIC_ WERROR reg_dotreg_diff_save(TALLOC_CTX *ctx, const char *filename,
                data->fd = STDOUT_FILENO;
        }
 
-       fdprintf(data->fd, "%s\n", HEADER_STRING);
+       fdprintf(data->fd, "%s\n\n", HEADER_STRING);
 
        *callbacks = talloc(ctx, struct reg_diff_callbacks);
 
index 0fa367bfcb7ee8a915b9316ff8877b351dac3e0c..bb46495c19c5a21e180cc4bd934c25d3b5e6d1e6 100644 (file)
@@ -2,7 +2,7 @@
    Unix SMB/CIFS implementation.
    Reading Registry.pol PReg registry files
 
-   Copyright (C) Wilco Baan Hofman 2006
+   Copyright (C) Wilco Baan Hofman 2006-2008
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include "lib/registry/registry.h"
 #include "system/filesys.h"
 #include "param/param.h"
+#include "librpc/gen_ndr/winreg.h"
 
 struct preg_data {
        int fd;
+       TALLOC_CTX *ctx;
+       struct smb_iconv_convenience *ic;
 };
 
 static WERROR preg_read_utf16(struct smb_iconv_convenience *ic, int fd, char *c)
@@ -38,14 +41,22 @@ static WERROR preg_read_utf16(struct smb_iconv_convenience *ic, int fd, char *c)
        push_codepoint(ic, c, v);
        return WERR_OK;
 }
-
-/* FIXME These functions need to be implemented */
-static WERROR reg_preg_diff_add_key(void *_data, const char *key_name)
+static WERROR preg_write_utf16(struct smb_iconv_convenience *ic, int fd, const char *string)
 {
+       codepoint_t v;
+       uint16_t i;
+       size_t size;
+
+       for (i = 0; i < strlen(string); i+=size) {
+               v = next_codepoint(ic, &string[i], &size);
+               if (write(fd, &v, 2) < 2) {
+                       return WERR_GENERAL_FAILURE;
+               }
+       }
        return WERR_OK;
 }
-
-static WERROR reg_preg_diff_del_key(void *_data, const char *key_name)
+/* PReg does not support adding keys. */
+static WERROR reg_preg_diff_add_key(void *_data, const char *key_name)
 {
        return WERR_OK;
 }
@@ -54,24 +65,73 @@ static WERROR reg_preg_diff_set_value(void *_data, const char *key_name,
                                      const char *value_name,
                                      uint32_t value_type, DATA_BLOB value_data)
 {
+       struct preg_data *data = _data;
+       uint32_t buf;
+       
+       preg_write_utf16(data->ic, data->fd, "[");
+       preg_write_utf16(data->ic, data->fd, key_name);
+       preg_write_utf16(data->ic, data->fd, ";");
+       preg_write_utf16(data->ic, data->fd, value_name);
+       preg_write_utf16(data->ic, data->fd, ";");
+       SIVAL(&buf, 0, value_type);
+       write(data->fd, &buf, sizeof(uint32_t));
+       preg_write_utf16(data->ic, data->fd, ";");
+       SIVAL(&buf, 0, value_data.length);
+       write(data->fd, &buf, sizeof(uint32_t));
+       preg_write_utf16(data->ic, data->fd, ";");
+       write(data->fd, value_data.data, value_data.length);
+       preg_write_utf16(data->ic, data->fd, "]");
+       
        return WERR_OK;
 }
 
+static WERROR reg_preg_diff_del_key(void *_data, const char *key_name)
+{
+       struct preg_data *data = _data;
+       char *parent_name;
+       DATA_BLOB blob;
+
+       parent_name = talloc_strndup(data->ctx, key_name, strrchr(key_name, '\\')-key_name);
+       blob.data = (void *)talloc_strndup(data->ctx, key_name+(strrchr(key_name, '\\')-key_name)+1, 
+                       strlen(key_name)-(strrchr(key_name, '\\')-key_name));
+       blob.length = strlen((char *)blob.data)+1;
+       
+
+       /* FIXME: These values should be accumulated to be written at done(). */
+       return reg_preg_diff_set_value(data, parent_name, "**DeleteKeys", REG_SZ, blob);
+}
+
 static WERROR reg_preg_diff_del_value(void *_data, const char *key_name,
                                      const char *value_name)
 {
-       return WERR_OK;
+       struct preg_data *data = _data;
+       char *val;
+       DATA_BLOB blob;
+
+       val = talloc_asprintf(data->ctx, "**Del.%s", value_name);
+
+       blob.data = (void *)talloc(data->ctx, uint32_t);
+       *(uint32_t *)blob.data = 0;
+       blob.length = 4;
+       return reg_preg_diff_set_value(data, key_name, val, REG_DWORD, blob);
 }
 
 static WERROR reg_preg_diff_del_all_values(void *_data, const char *key_name)
 {
-       return WERR_OK;
+       struct preg_data *data = _data;
+       DATA_BLOB blob;
+
+       blob.data = (void *)talloc(data->ctx, uint32_t);
+       *(uint32_t *)blob.data = 0;     
+       blob.length = 4;
+
+       return reg_preg_diff_set_value(data, key_name, "**DelVals.", REG_DWORD, blob);
 }
 
 static WERROR reg_preg_diff_done(void *_data)
 {
        struct preg_data *data = (struct preg_data *)_data;
-
+       
        close(data->fd);
        talloc_free(data);
        return WERR_OK;
@@ -81,6 +141,7 @@ static WERROR reg_preg_diff_done(void *_data)
  * Save registry diff
  */
 _PUBLIC_ WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename,
+                                  struct smb_iconv_convenience *ic,
                                   struct reg_diff_callbacks **callbacks,
                                   void **callback_data)
 {
@@ -95,18 +156,22 @@ _PUBLIC_ WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename,
        *callback_data = data;
 
        if (filename) {
-               data->fd = open(filename, O_CREAT, 0755);
-               if (data->fd == -1) {
+               data->fd = open(filename, O_CREAT|O_WRONLY, 0755);
+               if (data->fd < 0) {
                        DEBUG(0, ("Unable to open %s\n", filename));
                        return WERR_BADFILE;
                }
        } else {
                data->fd = STDOUT_FILENO;
        }
-       snprintf(preg_header.hdr, 4, "PReg");
+
+       strncpy(preg_header.hdr, "PReg", 4);
        SIVAL(&preg_header, 4, 1);
        write(data->fd, (uint8_t *)&preg_header,8);
 
+       data->ctx = ctx;
+       data->ic = ic;
+
        *callbacks = talloc(ctx, struct reg_diff_callbacks);
 
        (*callbacks)->add_key = reg_preg_diff_add_key;
@@ -149,6 +214,8 @@ _PUBLIC_ WERROR reg_preg_diff_load(int fd,
                ret = WERR_GENERAL_FAILURE;
                goto cleanup;
        }
+       preg_header.version = IVAL(&preg_header.version, 0);
+
        if (strncmp(preg_header.hdr, "PReg", 4) != 0) {
                DEBUG(0, ("This file is not a valid preg registry file\n"));
                ret = WERR_GENERAL_FAILURE;
@@ -177,7 +244,8 @@ _PUBLIC_ WERROR reg_preg_diff_load(int fd,
                       *buf_ptr != ';' && buf_ptr-buf < buf_size) {
                        buf_ptr++;
                }
-               key = talloc_asprintf(mem_ctx, "\\%s", buf);
+               buf[buf_ptr-buf] = '\0';
+               key = talloc_strdup(mem_ctx, buf);
 
                /* Get the name */
                buf_ptr = buf;
@@ -185,6 +253,7 @@ _PUBLIC_ WERROR reg_preg_diff_load(int fd,
                       *buf_ptr != ';' && buf_ptr-buf < buf_size) {
                        buf_ptr++;
                }
+               buf[buf_ptr-buf] = '\0';
                value_name = talloc_strdup(mem_ctx, buf);
 
                /* Get the type */
@@ -193,6 +262,8 @@ _PUBLIC_ WERROR reg_preg_diff_load(int fd,
                        ret = WERR_GENERAL_FAILURE;
                        goto cleanup;
                }
+               value_type = IVAL(&value_type, 0);
+
                /* Read past delimiter */
                buf_ptr = buf;
                if (!(W_ERROR_IS_OK(preg_read_utf16(iconv_convenience, fd, buf_ptr)) &&
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 9c0f66b6d6ea9db922fa184b91e52aad2c9cb7b7..e134e3e5321147ba3e3fbf99b43def8eea0226b2 100644 (file)
@@ -186,6 +186,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);
 
@@ -314,11 +320,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,
@@ -463,12 +469,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);
@@ -492,11 +494,19 @@ 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 smb_iconv_convenience *ic,
+                         struct reg_diff_callbacks **callbacks,
+                         void **callback_data);
 WERROR reg_generate_diff_key(struct registry_key *oldkey,
                             struct registry_key *newkey,
                             const char *path,
                             const struct reg_diff_callbacks *callbacks,
                             void *callback_data);
+WERROR reg_diff_load(const char *filename,
+                    struct smb_iconv_convenience *iconv_convenience,
+                    const struct reg_diff_callbacks *callbacks,
+                    void *callback_data);
 
 
 
index 690f71fcf7e9d865825478327b54c280ba8b86af..c7726545f673377acd7dd93c058e669dad2bf598 100644 (file)
@@ -4,6 +4,7 @@
    local testing of registry diff functionality
 
    Copyright (C) Jelmer Vernooij 2007
+   Copyright (C) Wilco Baan Hofman 2008
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include "lib/registry/registry.h"
 #include "torture/torture.h"
 #include "librpc/gen_ndr/winreg.h"
+#include "param/param.h"
 
-static bool test_generate_diff(struct torture_context *test)
+struct diff_tcase_data {
+       struct registry_context *r1_ctx;
+       struct registry_context *r2_ctx;
+       struct reg_diff_callbacks *callbacks;
+       void *callback_data;
+       char *tempdir;
+       char *filename;
+};
+
+static bool test_generate_diff(struct torture_context *tctx, void *tcase_data)
 {
-       /* WERROR reg_generate_diff(struct registry_context *ctx1,
-                                 struct registry_context *ctx2,
-                                 const struct reg_diff_callbacks *callbacks,
-                                 void *callback_data)
-                                 */
+       WERROR error;
+       struct diff_tcase_data *td = tcase_data;
+
+       error = reg_generate_diff(td->r1_ctx, td->r2_ctx, 
+                       td->callbacks,
+                       td->callback_data);
+       torture_assert_werr_ok(tctx, error, "reg_generate_diff");
+
        return true;
 }
 
-
-static bool test_diff_load(struct torture_context *test)
+#if 0
+static bool test_diff_load(struct torture_context *tctx, void *tcase_data)
 {
-       /* WERROR reg_diff_load(const char *filename, const struct reg_diff_callbacks *callbacks, void *callback_data) */
+       struct diff_tcase_data *td = tcase_data;
+       struct smb_iconv_convenience *ic;
+       struct reg_diff_callbacks *callbacks;
+       void *data;
+       WERROR error;
+
+       ic = lp_iconv_convenience(tctx->lp_ctx);
+
+       error = reg_diff_load(td->filename, iconv_convenience, callbacks, data);
+       torture_assert_werr_ok(tctx, error, "reg_diff_load");
 
        return true;
 }
-
-static bool test_diff_apply(struct torture_context *test)
+#endif
+static bool test_diff_apply(struct torture_context *tctx, void *tcase_data)
 {
-       /* _PUBLIC_ WERROR reg_diff_apply (const char *filename, struct registry_context *ctx) */
+       struct diff_tcase_data *td = tcase_data;
+       struct registry_key *key;
+       WERROR error;
+
+       error = reg_diff_apply(td->r1_ctx, td->filename);
+       torture_assert_werr_ok(tctx, error, "reg_diff_apply");
+
+       error = td->r1_ctx->ops->get_predefined_key(td->r1_ctx, HKEY_LOCAL_MACHINE, &key);
+       torture_assert_werr_ok(tctx, error, "Opening HKEY_LOCAL_MACHINE failed");
+
+       /* If this generates an error it could be that the apply doesn't work,
+        * but also that the reg_generate_diff didn't work. */
+       error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "Software", &key);
+       torture_assert_werr_ok(tctx, error, "Opening HKLM\\Software failed");
+       error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "Microsoft", &key);
+       torture_assert_werr_ok(tctx, error, "Opening HKLM\\Software\\Microsoft failed");
+       error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "Windows", &key);
+       torture_assert_werr_ok(tctx, error, "Opening HKLM\\..\\Microsoft\\Windows failed");
+       error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "CurrentVersion", &key);
+       torture_assert_werr_ok(tctx, error, "Opening HKLM\\..\\Windows\\CurrentVersion failed");
+       error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "Policies", &key);
+       torture_assert_werr_ok(tctx, error, "Opening HKLM\\..\\CurrentVersion\\Policies failed");
+       error = td->r1_ctx->ops->open_key(td->r1_ctx, key, "Explorer", &key);
+       torture_assert_werr_ok(tctx, error, "Opening HKLM\\..\\Policies\\Explorer failed");
 
        return true;
 }
@@ -58,7 +104,7 @@ static WERROR test_add_key(void *callback_data, const char *key_name)
        return WERR_OK;
 }
 
-static bool test_generate_diff_key_add(struct torture_context *test)
+static bool test_generate_diff_key_add(struct torture_context *tctx, void *tcase_data)
 {
        struct reg_diff_callbacks cb;
        struct registry_key rk;
@@ -69,15 +115,15 @@ static bool test_generate_diff_key_add(struct torture_context *test)
 
        cb.add_key = test_add_key;
 
-       if (W_ERROR_IS_OK(reg_generate_diff_key(&rk, NULL, "bla", &cb, test)))
+       if (W_ERROR_IS_OK(reg_generate_diff_key(&rk, NULL, "bla", &cb, tctx)))
                return false;
 
-       torture_assert_str_equal(test, added_key, "bla", "key added");
+       torture_assert_str_equal(tctx, added_key, "bla", "key added");
 
        return true;
 }
 
-static bool test_generate_diff_key_null(struct torture_context *test)
+static bool test_generate_diff_key_null(struct torture_context *tctx, void *tcase_data)
 {
        struct reg_diff_callbacks cb;
 
@@ -89,18 +135,162 @@ static bool test_generate_diff_key_null(struct torture_context *test)
        return true;
 }
 
+static void tcase_add_tests (struct torture_tcase *tcase) 
+{
+       torture_tcase_add_simple_test(tcase, "test_generate_diff_key_add",
+                       test_generate_diff_key_add);
+       torture_tcase_add_simple_test(tcase, "test_generate_diff_key_null",
+                       test_generate_diff_key_null);
+       torture_tcase_add_simple_test(tcase, "test_generate_diff",
+                       test_generate_diff);
+       torture_tcase_add_simple_test(tcase, "test_diff_apply",
+                       test_diff_apply);
+/*     torture_tcase_add_simple_test(tcase, "test_diff_load",
+                       test_diff_load);
+*/
+}
+
+static bool diff_setup_tcase(struct torture_context *tctx, void **data)
+{
+       struct registry_context *r1_ctx, *r2_ctx;
+       WERROR error;
+       NTSTATUS status;
+       struct hive_key *r1_hklm, *r1_hkcu;
+       struct hive_key *r2_hklm, *r2_hkcu;
+       const char *filename;
+       struct diff_tcase_data *td;
+       struct registry_key *key, *newkey;
+       DATA_BLOB blob;
+
+       td = talloc(tctx, struct diff_tcase_data);
+
+       /* Create two registry contexts */
+       error = reg_open_local(tctx, &r1_ctx, NULL, NULL);
+       torture_assert_werr_ok(tctx, error, "Opening registry 1 for patch tests failed");
+       
+       error = reg_open_local(tctx, &r2_ctx, NULL, NULL);
+       torture_assert_werr_ok(tctx, error, "Opening registry 2 for patch tests failed");
+
+       /* Create temp directory */
+       status = torture_temp_dir(tctx, "patchfile", &td->tempdir);
+       torture_assert_ntstatus_ok(tctx, status, "Creating temp dir failed");
+
+       /* Create and mount HKLM and HKCU hives for registry 1 */
+       filename = talloc_asprintf(tctx, "%s/r1_local_machine.ldb", td->tempdir);
+       error = reg_open_ldb_file(tctx, filename, NULL, NULL, tctx->lp_ctx, &r1_hklm);
+       torture_assert_werr_ok(tctx, error, "Opening local machine file failed");
+
+       error = reg_mount_hive(r1_ctx, r1_hklm, HKEY_LOCAL_MACHINE, NULL);
+       torture_assert_werr_ok(tctx, error, "Mounting hive failed");
+       
+       filename = talloc_asprintf(tctx, "%s/r1_current_user.ldb", td->tempdir);
+       error = reg_open_ldb_file(tctx, filename, NULL, NULL, tctx->lp_ctx, &r1_hkcu);
+       torture_assert_werr_ok(tctx, error, "Opening current user file failed");
+
+       error = reg_mount_hive(r1_ctx, r1_hkcu, HKEY_CURRENT_USER, NULL);
+       torture_assert_werr_ok(tctx, error, "Mounting hive failed");
+       
+       /* Create and mount HKLM and HKCU hives for registry 2 */
+       filename = talloc_asprintf(tctx, "%s/r2_local_machine.ldb", td->tempdir);
+       error = reg_open_ldb_file(tctx, filename, NULL, NULL, tctx->lp_ctx, &r2_hklm);
+       torture_assert_werr_ok(tctx, error, "Opening local machine file failed");
+
+       error = reg_mount_hive(r2_ctx, r2_hklm, HKEY_LOCAL_MACHINE, NULL);
+       torture_assert_werr_ok(tctx, error, "Mounting hive failed");
+       
+       filename = talloc_asprintf(tctx, "%s/r2_current_user.ldb", td->tempdir);
+       error = reg_open_ldb_file(tctx, filename, NULL, NULL, tctx->lp_ctx, &r2_hkcu);
+       torture_assert_werr_ok(tctx, error, "Opening current user file failed");
+       
+       error = reg_mount_hive(r2_ctx, r2_hkcu, HKEY_CURRENT_USER, NULL);
+       torture_assert_werr_ok(tctx, error, "Mounting hive failed");
+
+       error = r1_ctx->ops->get_predefined_key(r1_ctx, HKEY_CURRENT_USER, &key);
+       torture_assert_werr_ok(tctx, error, "Opening HKEY_CURRENT_USER failed");
+       error = r1_ctx->ops->create_key(r1_ctx, key, "Network", NULL, NULL, &newkey);
+       torture_assert_werr_ok(tctx, error, "Opening HKCU\\Network failed");
+       error = r1_ctx->ops->create_key(r1_ctx, newkey, "L", NULL, NULL, &newkey);
+       torture_assert_werr_ok(tctx, error, "Opening HKCU\\Network\\L failed");
+
+       error = r2_ctx->ops->get_predefined_key(r2_ctx, HKEY_LOCAL_MACHINE, &key);
+       torture_assert_werr_ok(tctx, error, "Opening HKEY_LOCAL_MACHINE failed");
+       error = r2_ctx->ops->create_key(r2_ctx, key, "Software", NULL, NULL, &newkey);
+       torture_assert_werr_ok(tctx, error, "Creating HKLM\\Sofware failed");
+       error = r2_ctx->ops->create_key(r2_ctx, newkey, "Microsoft", NULL, NULL, &newkey);
+       torture_assert_werr_ok(tctx, error, "Creating HKLM\\Software\\Microsoft failed");
+       error = r2_ctx->ops->create_key(r2_ctx, newkey, "Windows", NULL, NULL, &newkey);
+       torture_assert_werr_ok(tctx, error, "Creating HKLM\\Software\\Microsoft\\Windows failed");
+       error = r2_ctx->ops->create_key(r2_ctx, newkey, "CurrentVersion", NULL, NULL, &newkey);
+       torture_assert_werr_ok(tctx, error, "Creating HKLM\\..\\Windows\\CurrentVersion failed");
+       error = r2_ctx->ops->create_key(r2_ctx, newkey, "Policies", NULL, NULL, &newkey);
+       torture_assert_werr_ok(tctx, error, "Creating HKLM\\..\\CurrentVersion\\Policies failed");
+       error = r2_ctx->ops->create_key(r2_ctx, newkey, "Explorer", NULL, NULL, &newkey);
+       torture_assert_werr_ok(tctx, error, "Creating HKLM\\..\\Policies\\Explorer failed");
+
+
+       blob.data = (void *)talloc(r2_ctx, uint32_t);
+       SIVAL(blob.data, 0, 0x03ffffff);
+       blob.length = sizeof(uint32_t);
+
+       r1_ctx->ops->set_value(newkey, "NoDrives", REG_DWORD, blob);
+
+       /* Set test case data */
+       td->r1_ctx = r1_ctx;
+       td->r2_ctx = r2_ctx;
+
+       *data = td;
+
+       return true;
+}
+
+static bool diff_setup_preg_tcase (struct torture_context *tctx, void **data)
+{
+       struct diff_tcase_data *td;
+       struct smb_iconv_convenience *ic;
+       WERROR error;
+
+       diff_setup_tcase(tctx, data);
+       td = *data;
+
+       ic = lp_iconv_convenience(tctx->lp_ctx);
+
+       td->filename = talloc_asprintf(tctx, "%s/test.pol", td->tempdir);
+       error = reg_preg_diff_save(tctx, td->filename, ic, &td->callbacks, &td->callback_data);
+       torture_assert_werr_ok(tctx, error, "reg_preg_diff_save");
+
+       return true;
+}
+
+static bool diff_setup_dotreg_tcase (struct torture_context *tctx, void **data)
+{
+       struct diff_tcase_data *td;
+       struct smb_iconv_convenience *ic;
+       WERROR error;
+
+       diff_setup_tcase(tctx, data);
+       td = *data;
+
+       ic = lp_iconv_convenience(tctx->lp_ctx);
+       
+       td->filename = talloc_asprintf(tctx, "%s/test.reg", td->tempdir);
+       error = reg_dotreg_diff_save(tctx, td->filename, ic, &td->callbacks, &td->callback_data);
+       torture_assert_werr_ok(tctx, error, "reg_dotreg_diff_save");
+
+       return true;
+}
+
 struct torture_suite *torture_registry_diff(TALLOC_CTX *mem_ctx)
 {
+       struct torture_tcase *tcase;
        struct torture_suite *suite = torture_suite_create(mem_ctx, "DIFF");
-       torture_suite_add_simple_test(suite, "test_generate_diff_key_add",
-                                     test_generate_diff_key_add);
-       torture_suite_add_simple_test(suite, "test_generate_diff_key_null",
-                                     test_generate_diff_key_null);
-       torture_suite_add_simple_test(suite, "test_diff_apply",
-                                     test_diff_apply);
-       torture_suite_add_simple_test(suite, "test_generate_diff",
-                                     test_generate_diff);
-       torture_suite_add_simple_test(suite, "test_diff_load",
-                                     test_diff_load);
+
+       tcase = torture_suite_add_tcase(suite, "PReg");
+       torture_tcase_set_fixture(tcase, diff_setup_preg_tcase, NULL);
+       tcase_add_tests(tcase);
+
+       tcase = torture_suite_add_tcase(suite, "dotreg");
+       torture_tcase_set_fixture(tcase, diff_setup_dotreg_tcase, NULL);
+       tcase_add_tests(tcase);
+
        return suite;
 }
index 29f7e685c102faadf0e15cdedcfa5b8269d7d540..edc97c2468ebe8ca774b2f6cd7c336af4406a64a 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)
@@ -306,6 +307,56 @@ 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");
+       
+       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",
@@ -333,6 +384,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)
@@ -390,7 +443,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 661d7c2c6985ba16d0a87f70911511750479be05..7274bf009d1e09f641f38e31051d57564bda0afd 100644 (file)
@@ -390,11 +390,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!");