When Windows attempts to create a new key, it looks for an available key name
authorAndrew Kroeger <andrew@sprocks.gotdns.com>
Fri, 18 Jan 2008 01:51:51 +0000 (02:51 +0100)
committerJelmer Vernooij <jelmer@samba.org>
Fri, 18 Jan 2008 02:41:59 +0000 (03:41 +0100)
starting with "New Key #1" and iterating up to "New Key #99" before giving up.
ldb_open_key() calls reg_path_to_ldb() to build the appropriate dn from the key
name.  reg_path_to_ldb() was not catching the error returned by
ldb_dn_add_base_fmt() due to the unescaped '#' character, causing the returned
dn to be that of the parent key, not the potential new key.  Additionally,
Windows expects a return value of WERR_BADFILE when a key does not exist, but
WERR_NOT_FOUND was being returned instead.  Correcting the building of the dn
and the providing the expected return value allows new key creation to succeed.

When attempting to delete a key, Windows passes the complete path to the key,
not just the name of the child key to be deleted.  Using reg_path_to_ldb() to
build the correct dn allows key deletion to succeed.

source/lib/registry/ldb.c
source/rpc_server/winreg/rpc_winreg.c

index 17fac4abb24b20f1f9b0a4c3b7dbc8384cfbf0b8..edfb1f2e593aa6759bd443a6165f91c761444b52 100644 (file)
@@ -168,7 +168,13 @@ static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx,
                else keyname = mypath;
 
                if(strlen(keyname)) {
-                       ldb_dn_add_base_fmt(ret, "key=%s", keyname);
+                       if (!ldb_dn_add_base_fmt(ret, "key=%s",
+                                                reg_ldb_escape(local_ctx,
+                                                               keyname)))
+                       {
+                               talloc_free(local_ctx);
+                               return NULL;
+                       }
                }
 
                if(begin) {
@@ -430,18 +436,18 @@ 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 *child)
+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 *childdn;
+       struct ldb_dn *ldap_path;
+       TALLOC_CTX *mem_ctx = talloc_init("ldb_del_key");
 
-       childdn = ldb_dn_copy(parentkd->ldb, parentkd->dn);
-       ldb_dn_add_child_fmt(childdn, "key=%s", child);
+       ldap_path = reg_path_to_ldb(mem_ctx, key, name, NULL);
 
-       ret = ldb_delete(parentkd->ldb, childdn);
+       ret = ldb_delete(parentkd->ldb, ldap_path);
 
-       talloc_free(childdn);
+       talloc_free(mem_ctx);
 
        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
                return WERR_NOT_FOUND;
index 681e3b918f870afc11f38ce47c81539fbd3ee8c0..3c00944d595a8df0922509c29c8591f134aa81d9 100644 (file)
@@ -356,6 +356,13 @@ static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call,
                r->out.handle = &newh->wire_handle;
        } else {
                talloc_free(newh);
+               /*
+                * Windows expects WERR_BADFILE when a particular key
+                * is not found.  If we receive WERR_NOT_FOUND from the lower
+                * layer calls, translate it here to return what is expected.
+                */
+               if (W_ERROR_EQUAL(result, WERR_NOT_FOUND))
+                       return WERR_BADFILE;
        }
 
        return result;