r15356: Remove unused 'flags' argument from socket_send() and friends.
[bbaumbach/samba-autobuild/.git] / source4 / lib / registry / reg_backend_ldb.c
index ffb9215cf0409e587c7ddd7f45826f433f10640f..ec185cd65bcc41e6580c121707008f7cdecc3810 100644 (file)
 #include "includes.h"
 #include "registry.h"
 #include "lib/ldb/include/ldb.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "db_wrap.h"
+#include "librpc/gen_ndr/winreg.h"
 
 struct ldb_key_data 
 {
-       const char *dn;
+       const struct ldb_dn *dn;
        struct ldb_message **subkeys, **values;
        int subkey_count, value_count;
 };
 
-static int ldb_close_hive (void *_hive)
+static int ldb_free_hive (void *_hive)
 {
        struct registry_hive *hive = _hive;
-       ldb_close (hive->backend_data);
+       talloc_free(hive->backend_data);
+       hive->backend_data = NULL;
        return 0;
 }
 
-static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, char **name, uint32 *type, void **data, int *len)
+static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, char **name, uint32_t *type, DATA_BLOB *data)
 {
        const struct ldb_val *val;
        *name = talloc_strdup(mem_ctx, ldb_msg_find_string(msg, "value", NULL));
@@ -47,48 +51,46 @@ static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, c
        {
        case REG_SZ:
        case REG_EXPAND_SZ:
-               *len = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, val->data, val->length, data);
+               data->length = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, val->data, val->length, (void **)&data->data);
                break;
 
-       case REG_DWORD_LE:
-               *len = 4;
-               *data = talloc_p(mem_ctx, uint32);
-               SIVAL(*data, 0, strtol(val->data, NULL, 0));
+       case REG_DWORD: {
+               uint32_t tmp = strtoul((char *)val->data, NULL, 0);
+               *data = data_blob_talloc(mem_ctx, &tmp, 4);
+               }
                break;
 
        default:
-               *data = talloc_memdup(mem_ctx, val->data, val->length);
-               *len = val->length;
+               *data = data_blob_talloc(mem_ctx, val->data, val->length);
                break;
        }
 }
 
-static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32 type, void *data, int len)
+static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32_t type, DATA_BLOB data)
 {
        struct ldb_val val;
-       struct ldb_message *msg = talloc_zero_p(mem_ctx, struct ldb_message);
+       struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message);
        char *type_s;
 
-       ldb_msg_add_string(ctx, msg, "value", talloc_strdup(mem_ctx, name));
+       ldb_msg_add_string(msg, "value", talloc_strdup(mem_ctx, name));
 
        switch (type) {
        case REG_SZ:
        case REG_EXPAND_SZ:
-               val.length = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, data, len, &val.data);
-               ldb_msg_add_value(ctx, msg, "data", &val);
+               val.length = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, (void *)data.data, data.length, (void **)&val.data);
+               ldb_msg_add_value(msg, "data", &val);
                break;
-       case REG_DWORD_LE:
-               ldb_msg_add_string(ctx, msg, "data", talloc_asprintf(mem_ctx, "0x%x", IVAL(data, 0)));
+
+       case REG_DWORD:
+               ldb_msg_add_string(msg, "data", talloc_asprintf(mem_ctx, "0x%x", IVAL(data.data, 0)));
                break;
        default:
-               val.length = len;
-               val.data = data;
-               ldb_msg_add_value(ctx, msg, "data", &val);
+               ldb_msg_add_value(msg, "data", &data);
        }
 
 
        type_s = talloc_asprintf(mem_ctx, "%u", type);
-       ldb_msg_add_string(ctx, msg, "type", type_s); 
+       ldb_msg_add_string(msg, "type", type_s); 
 
        return msg;
 }
@@ -97,41 +99,49 @@ static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CT
 static int reg_close_ldb_key (void *data)
 {
        struct registry_key *key = data;
-       struct ldb_key_data *kd = key->backend_data;
-       struct ldb_context *c = key->hive->backend_data;
+       struct ldb_key_data *kd = talloc_get_type(key->backend_data, struct ldb_key_data);
+/*     struct ldb_context *c = key->hive->backend_data; */
 
        if (kd->subkeys) {
-               ldb_search_free(c, kd->subkeys); 
+               talloc_free(kd->subkeys); 
                kd->subkeys = NULL;
        }
 
        if (kd->values) {
-               ldb_search_free(c, kd->values); 
+               talloc_free(kd->values); 
                kd->values = NULL;
        }
        return 0;
 }
 
-static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, struct registry_key *from, const char *path, const char *add)
+static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const struct registry_key *from, const char *path, const char *add)
 {
-       char *ret = talloc_strdup(mem_ctx, "");
+       TALLOC_CTX *local_ctx;
+       struct ldb_dn *ret = ldb_dn_new(mem_ctx);
        char *mypath = talloc_strdup(mem_ctx, path);
        char *begin;
-       struct ldb_key_data *kd = from->backend_data;
+       struct ldb_key_data *kd = talloc_get_type(from->backend_data, struct ldb_key_data);
 
-       if(add) 
-               ret = talloc_asprintf_append(ret, "%s", add);
+       local_ctx = talloc_new(mem_ctx);
+
+       if (add) 
+               ret = ldb_dn_compose(local_ctx, ret, ldb_dn_explode(mem_ctx, add));
 
        while(mypath) {
                char *keyname;
+
                begin = strrchr(mypath, '\\');
 
-               if(begin) keyname = begin + 1;
+               if (begin) keyname = begin + 1;
                else keyname = mypath;
 
-               if(strlen(keyname))
-                       ret = talloc_asprintf_append(ret, "key=%s,", keyname);
-                       
+               if(strlen(keyname)) {
+                       struct ldb_dn *base;
+
+                       base = ldb_dn_build_child(local_ctx, "key", keyname, NULL);
+                       ret = ldb_dn_compose(local_ctx, ret, base);
+               }
+
                if(begin) {
                        *begin = '\0';
                } else {
@@ -139,212 +149,230 @@ static char *reg_path_to_ldb(TALLOC_CTX *mem_ctx, struct registry_key *from, con
                }
        }
 
-       ret = talloc_asprintf_append(ret, "%s", kd->dn);
+       ret = ldb_dn_compose(mem_ctx, ret, kd->dn);
+
+       talloc_free(local_ctx);
 
        return ret;
 }
 
 
-static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_key **subkey)
+static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_key **subkey)
 {
-       struct ldb_context *c = k->hive->backend_data;
+       struct ldb_context *c = talloc_get_type(k->hive->backend_data, struct ldb_context);
        struct ldb_message_element *el;
-       struct ldb_key_data *kd = k->backend_data, *newkd;
+       struct ldb_key_data *kd = talloc_get_type(k->backend_data, struct ldb_key_data);
+       struct ldb_key_data *newkd;
 
        /* Do a search if necessary */
        if (kd->subkeys == NULL) {
-               kd->subkey_count = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL, &kd->subkeys);
+               struct ldb_result *res;
+               int ret;
+
+               ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL, &res);
 
-               if(kd->subkey_count < 0) {
-                       DEBUG(0, ("Error getting subkeys for '%s': %s\n", kd->dn, ldb_errstring(c)));
+               if (ret != LDB_SUCCESS) {
+                       DEBUG(0, ("Error getting subkeys for '%s': %s\n", ldb_dn_linearize(mem_ctx, kd->dn), ldb_errstring(c)));
                        return WERR_FOOBAR;
                }
+
+               kd->subkey_count = res->count;
+               kd->subkeys = talloc_steal(kd, res->msgs);
+               talloc_free(res);
        } 
 
        if (idx >= kd->subkey_count) return WERR_NO_MORE_ITEMS;
 
        el = ldb_msg_find_element(kd->subkeys[idx], "key");
        
-       *subkey = talloc_p(mem_ctx, struct registry_key);
+       *subkey = talloc(mem_ctx, struct registry_key);
        talloc_set_destructor(*subkey, reg_close_ldb_key);
-       (*subkey)->name = talloc_strdup(mem_ctx, el->values[0].data);
-       (*subkey)->backend_data = newkd = talloc_zero_p(*subkey, struct ldb_key_data);
-       newkd->dn = talloc_strdup(mem_ctx, kd->subkeys[idx]->dn);
+       (*subkey)->name = talloc_strdup(mem_ctx, (char *)el->values[0].data);
+       (*subkey)->backend_data = newkd = talloc_zero(*subkey, struct ldb_key_data);
+       (*subkey)->last_mod = 0; /* TODO: we need to add this to the
+                                   ldb backend properly */
+       newkd->dn = ldb_dn_copy(mem_ctx, kd->subkeys[idx]->dn);
 
        return WERR_OK;
 }
 
-static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, int idx, struct registry_value **value)
+static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_value **value)
 {
-       struct ldb_context *c = k->hive->backend_data;
-       struct ldb_key_data *kd = k->backend_data;
+       struct ldb_context *c = talloc_get_type(k->hive->backend_data, struct ldb_context);
+       struct ldb_key_data *kd = talloc_get_type(k->backend_data, struct ldb_key_data);
 
        /* Do the search if necessary */
        if (kd->values == NULL) {
-               kd->value_count = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(value=*)", NULL,&kd->values);
+               struct ldb_result *res;
+               int ret;
+
+               ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(value=*)", NULL, &res);
 
-               if(kd->value_count < 0) {
-                       DEBUG(0, ("Error getting values for '%s': %s\n", kd->dn, ldb_errstring(c)));
+               if (ret != LDB_SUCCESS) {
+                       DEBUG(0, ("Error getting values for '%s': %s\n", ldb_dn_linearize(mem_ctx, kd->dn), ldb_errstring(c)));
                        return WERR_FOOBAR;
                }
+               kd->value_count = res->count;
+               kd->values = talloc_steal(kd, res->msgs);
+               talloc_free(res);
        }
 
        if(idx >= kd->value_count) return WERR_NO_MORE_ITEMS;
 
-       *value = talloc_p(mem_ctx, struct registry_value);
+       *value = talloc(mem_ctx, struct registry_value);
 
-       reg_ldb_unpack_value(mem_ctx, kd->values[idx], &(*value)->name, &(*value)->data_type, &(*value)->data_blk, &(*value)->data_len);
+       reg_ldb_unpack_value(mem_ctx, kd->values[idx], &(*value)->name, &(*value)->data_type, &(*value)->data);
 
        return WERR_OK;
 }
 
-static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key)
+static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *h, const char *name, struct registry_key **key)
 {
-       struct ldb_context *c = h->hive->backend_data;
-       struct ldb_message **msg;
-       char *ldap_path;
+       struct ldb_context *c = talloc_get_type(h->hive->backend_data, struct ldb_context);
+       struct ldb_result *res;
+       struct ldb_dn *ldap_path;
        int ret;
        struct ldb_key_data *newkd;
 
        ldap_path = reg_path_to_ldb(mem_ctx, h, name, NULL);
 
-       ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL,&msg);
+       ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL, &res);
 
-       if(ret == 0) {
-               return WERR_NO_MORE_ITEMS;
-       } else if(ret < 0) {
-               DEBUG(0, ("Error opening key '%s': %s\n", ldap_path, ldb_errstring(c)));
+       if (ret != LDB_SUCCESS) {
+               DEBUG(0, ("Error opening key '%s': %s\n", ldb_dn_linearize(ldap_path, ldap_path), ldb_errstring(c)));
                return WERR_FOOBAR;
+       } else if (res->count == 0) {
+               return WERR_BADFILE;
        }
 
-       *key = talloc_p(mem_ctx, struct registry_key);
+       *key = talloc(mem_ctx, struct registry_key);
        talloc_set_destructor(*key, reg_close_ldb_key);
        (*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')?strchr(name, '\\'):name);
-       (*key)->backend_data = newkd = talloc_zero_p(*key, struct ldb_key_data);
-       newkd->dn = talloc_strdup(mem_ctx, msg[0]->dn); 
+       (*key)->backend_data = newkd = talloc_zero(*key, struct ldb_key_data);
+       newkd->dn = ldb_dn_copy(mem_ctx, res->msgs[0]->dn); 
 
-       ldb_search_free(c, msg);
+       talloc_free(res);
 
        return WERR_OK;
 }
 
 static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k)
 {
-       struct ldb_context *c;
        struct ldb_key_data *kd;
-       struct ldb_wrap *wrap;
+       struct ldb_context *wrap;
 
        if (!hive->location) return WERR_INVALID_PARAM;
-       wrap = ldb_wrap_connect(hive, hive->location, 0, NULL);
+
+       wrap = ldb_wrap_connect(hive, hive->location, hive->session_info, hive->credentials, 0, NULL);
 
        if(!wrap) {
                DEBUG(1, ("ldb_open_hive: unable to connect\n"));
                return WERR_FOOBAR;
        }
 
-       c = wrap->ldb;
-
-       ldb_set_debug_stderr(c);
-       hive->backend_data = c;
+       ldb_set_debug_stderr(wrap);
+       hive->backend_data = wrap;
 
-       *k = talloc_zero_p(hive, struct registry_key);
+       *k = talloc_zero(hive, struct registry_key);
        talloc_set_destructor (*k, reg_close_ldb_key);
-       talloc_set_destructor (hive, ldb_close_hive);
+       talloc_set_destructor (hive, ldb_free_hive);
        (*k)->name = talloc_strdup(*k, "");
-       (*k)->backend_data = kd = talloc_zero_p(*k, struct ldb_key_data);
-       kd->dn = talloc_strdup(*k, "hive=");
+       (*k)->backend_data = kd = talloc_zero(*k, struct ldb_key_data);
+       kd->dn = ldb_dn_explode(*k, "hive=NONE");
        
 
        return WERR_OK;
 }
 
-static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sd, struct registry_key **newkey)
+static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sd, struct registry_key **newkey)
 {
-       struct ldb_context *ctx = parent->hive->backend_data;
-       struct ldb_message msg;
+       struct ldb_context *ctx = talloc_get_type(parent->hive->backend_data, struct ldb_context);
+       struct ldb_message *msg;
        struct ldb_key_data *newkd;
        int ret;
 
-       ZERO_STRUCT(msg);
+       msg = ldb_msg_new(mem_ctx);
 
-       msg.dn = reg_path_to_ldb(mem_ctx, parent, name, NULL);
+       msg->dn = reg_path_to_ldb(msg, parent, name, NULL);
 
-       ldb_msg_add_string(ctx, &msg, "key", talloc_strdup(mem_ctx, name));
+       ldb_msg_add_string(msg, "key", talloc_strdup(mem_ctx, name));
 
-       ret = ldb_add(ctx, &msg);
+       ret = ldb_add(ctx, msg);
        if (ret < 0) {
-               DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data)));
+               DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(ctx)));
                return WERR_FOOBAR;
        }
 
-       *newkey = talloc_zero_p(mem_ctx, struct registry_key);
+       *newkey = talloc_zero(mem_ctx, struct registry_key);
        (*newkey)->name = talloc_strdup(mem_ctx, name);
 
-       (*newkey)->backend_data = newkd = talloc_zero_p(*newkey, struct ldb_key_data);
-       newkd->dn = msg.dn; 
+       (*newkey)->backend_data = newkd = talloc_zero(*newkey, struct ldb_key_data);
+       newkd->dn = talloc_steal(newkd, msg->dn);
 
        return WERR_OK;
 }
 
-static WERROR ldb_del_key (struct registry_key *key, const char *child)
+static WERROR ldb_del_key (const struct registry_key *key, const char *child)
 {
+       struct ldb_context *ctx = talloc_get_type(key->hive->backend_data, struct ldb_context);
        int ret;
-       struct ldb_key_data *kd = key->backend_data;
-       char *childdn = talloc_asprintf(NULL, "key=%s,%s", child, kd->dn);
+       struct ldb_key_data *kd = talloc_get_type(key->backend_data, struct ldb_key_data);
+       struct ldb_dn *childdn = ldb_dn_build_child(ctx, "key", child, kd->dn);
 
-       ret = ldb_delete(key->hive->backend_data, childdn);
+       ret = ldb_delete(ctx, childdn);
 
-       talloc_destroy(childdn);
+       talloc_free(childdn);
 
        if (ret < 0) {
-               DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(key->hive->backend_data)));
+               DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(ctx)));
                return WERR_FOOBAR;
        }
 
        return WERR_OK;
 }
 
-static WERROR ldb_del_value (struct registry_key *key, const char *child)
+static WERROR ldb_del_value (const struct registry_key *key, const char *child)
 {
        int ret;
-       struct ldb_key_data *kd = key->backend_data;
-       char *childdn = talloc_asprintf(NULL, "value=%s,%s", child, kd->dn);
+       struct ldb_context *ctx = talloc_get_type(key->hive->backend_data, struct ldb_context);
+       struct ldb_key_data *kd = talloc_get_type(key->backend_data, struct ldb_key_data);
+       struct ldb_dn *childdn = ldb_dn_build_child(ctx, "value", child, kd->dn);
 
-       ret = ldb_delete(key->hive->backend_data, childdn);
+       ret = ldb_delete(ctx, childdn);
 
-       talloc_destroy(childdn);
+       talloc_free(childdn);
 
        if (ret < 0) {
-               DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(key->hive->backend_data)));
+               DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(ctx)));
                return WERR_FOOBAR;
        }
 
        return WERR_OK;
 }
 
-static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint32 type, void *data, int len)
+static WERROR ldb_set_value (const struct registry_key *parent, const char *name, uint32_t type, DATA_BLOB data)
 {
-       struct ldb_context *ctx = parent->hive->backend_data;
+       struct ldb_context *ctx = talloc_get_type(parent->hive->backend_data, struct ldb_context);
        struct ldb_message *msg;
-       struct ldb_key_data *kd = parent->backend_data;
+       struct ldb_key_data *kd = talloc_get_type(parent->backend_data, struct ldb_key_data);
        int ret;
        TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value");
 
-       msg = reg_ldb_pack_value(ctx, mem_ctx, name, type, data, len);
+       msg = reg_ldb_pack_value(ctx, mem_ctx, name, type, data);
 
-       msg->dn = talloc_asprintf(mem_ctx, "value=%s,%s", name, kd->dn);
+       msg->dn = ldb_dn_build_child(msg, "value", name, kd->dn);
 
        ret = ldb_add(ctx, msg);
        if (ret < 0) {
                ret = ldb_modify(ctx, msg);
                if (ret < 0) {
-                       DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data)));
-                       talloc_destroy(mem_ctx);
+                       DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(ctx)));
+                       talloc_free(mem_ctx);
                        return WERR_FOOBAR;
                }
        }
        
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
        return WERR_OK;
 }