r24941: Simplify samdb_result_nttime(), and remove nttime_from_string()
[kai/samba.git] / source4 / dsdb / samdb / samdb.c
index 2d811094ff92fd2bbee72092f3ad76e8ee79aae0..9454daceee168b14810d8a22977bf5e4d4ed56fb 100644 (file)
@@ -9,7 +9,7 @@
 
    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
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -18,8 +18,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -50,6 +49,7 @@ struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx,
        if (!ldb) {
                return NULL;
        }
+       dsdb_make_schema_global(ldb);
        return ldb;
 }
 
@@ -449,9 +449,7 @@ struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, const struct ldb_me
 */
 NTTIME samdb_result_nttime(struct ldb_message *msg, const char *attr, NTTIME default_value)
 {
-       const char *str = ldb_msg_find_attr_as_string(msg, attr, NULL);
-       if (!str) return default_value;
-       return nttime_from_string(str);
+       return ldb_msg_find_attr_as_uint64(msg, attr, default_value);
 }
 
 /*
@@ -571,7 +569,7 @@ NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
        struct samr_Password *lmPwdHash, *ntPwdHash;
        if (nt_pwd) {
                int num_nt;
-               num_nt = samdb_result_hashes(mem_ctx, msg, "ntPwdHash", &ntPwdHash);
+               num_nt = samdb_result_hashes(mem_ctx, msg, "unicodePwd", &ntPwdHash);
                if (num_nt == 0) {
                        *nt_pwd = NULL;
                } else if (num_nt > 1) {
@@ -582,7 +580,7 @@ NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
        }
        if (lm_pwd) {
                int num_lm;
-               num_lm = samdb_result_hashes(mem_ctx, msg, "lmPwdHash", &lmPwdHash);
+               num_lm = samdb_result_hashes(mem_ctx, msg, "dBCSPwd", &lmPwdHash);
                if (num_lm == 0) {
                        *lm_pwd = NULL;
                } else if (num_lm > 1) {
@@ -626,6 +624,11 @@ uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
 
 
 /* Find an attribute, with a particular value */
+
+/* The current callers of this function expect a very specific
+ * behaviour: In particular, objectClass subclass equivilance is not
+ * wanted.  This means that we should not lookup the schema for the
+ * comparison function */
 struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb, 
                                                 const struct ldb_message *msg, 
                                                 const char *name, const char *value)
@@ -675,7 +678,7 @@ int samdb_find_or_add_attribute(struct ldb_context *ldb, struct ldb_message *msg
   copy from a template record to a message
 */
 int samdb_copy_template(struct ldb_context *ldb, 
-                       struct ldb_message *msg, const char *filter,
+                       struct ldb_message *msg, const char *name,
                        const char **errstring)
 {
        struct ldb_result *res;
@@ -685,15 +688,22 @@ int samdb_copy_template(struct ldb_context *ldb,
 
        *errstring = NULL;      
 
+       if (!ldb_dn_add_child_fmt(basedn, "CN=Template%s", name)) {
+               *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to contruct DN for template '%s'", 
+                                            name);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
        /* pull the template record */
-       ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, filter, NULL, &res);
+       ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, "cn=*", NULL, &res);
        talloc_free(basedn);
        if (ret != LDB_SUCCESS) {
                *errstring = talloc_steal(msg, ldb_errstring(ldb));
                return ret;
        }
        if (res->count != 1) {
-               *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: template '%s' matched %d records, expected 1\n", filter, 
+               *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: template '%s' matched %d records, expected 1", 
+                                            name, 
                                             res->count);
                talloc_free(res);
                return LDB_ERR_OPERATIONS_ERROR;
@@ -703,40 +713,22 @@ int samdb_copy_template(struct ldb_context *ldb,
        for (i = 0; i < t->num_elements; i++) {
                struct ldb_message_element *el = &t->elements[i];
                /* some elements should not be copied from the template */
-               if (strcasecmp(el->name, "cn") == 0 ||
-                   strcasecmp(el->name, "name") == 0 ||
-                   strcasecmp(el->name, "sAMAccountName") == 0 ||
-                   strcasecmp(el->name, "sAMAccountName") == 0 ||
-                   strcasecmp(el->name, "distinguishedName") == 0 ||
-                   strcasecmp(el->name, "objectGUID") == 0) {
+               if (ldb_attr_cmp(el->name, "cn") == 0 ||
+                   ldb_attr_cmp(el->name, "name") == 0 ||
+                   ldb_attr_cmp(el->name, "objectClass") == 0 ||
+                   ldb_attr_cmp(el->name, "sAMAccountName") == 0 ||
+                   ldb_attr_cmp(el->name, "sAMAccountName") == 0 ||
+                   ldb_attr_cmp(el->name, "distinguishedName") == 0 ||
+                   ldb_attr_cmp(el->name, "objectGUID") == 0) {
                        continue;
                }
                for (j = 0; j < el->num_values; j++) {
-                       if (strcasecmp(el->name, "objectClass") == 0) {
-                               if (strcasecmp((char *)el->values[j].data, "Template") == 0 ||
-                                   strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
-                                   strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 ||
-                                   strcasecmp((char *)el->values[j].data, "foreignSecurityPrincipalTemplate") == 0 ||
-                                   strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0 || 
-                                   strcasecmp((char *)el->values[j].data, "trustedDomainTemplate") == 0 || 
-                                   strcasecmp((char *)el->values[j].data, "secretTemplate") == 0) {
-                                       continue;
-                               }
-                               ret = samdb_find_or_add_value(ldb, msg, el->name, 
-                                                             (char *)el->values[j].data);
-                               if (ret) {
-                                       *errstring = talloc_asprintf(msg, "Adding objectClass %s failed.\n", el->values[j].data);
-                                       talloc_free(res);
-                                       return ret;
-                               }
-                       } else {
-                               ret = samdb_find_or_add_attribute(ldb, msg, el->name, 
-                                                                 (char *)el->values[j].data);
-                               if (ret) {
-                                       *errstring = talloc_asprintf(msg, "Adding attribute %s failed.\n", el->name);
-                                       talloc_free(res);
-                                       return ret;
-                               }
+                       ret = samdb_find_or_add_attribute(ldb, msg, el->name, 
+                                                         (char *)el->values[j].data);
+                       if (ret) {
+                               *errstring = talloc_asprintf(msg, "Adding attribute %s failed.", el->name);
+                               talloc_free(res);
+                               return ret;
                        }
                }
        }
@@ -1030,13 +1022,27 @@ struct ldb_dn *samdb_base_dn(struct ldb_context *sam_ctx)
        return ldb_get_default_basedn(sam_ctx);
 }
 
+struct ldb_dn *samdb_config_dn(struct ldb_context *sam_ctx) 
+{
+       return ldb_get_config_basedn(sam_ctx);
+}
+
+struct ldb_dn *samdb_schema_dn(struct ldb_context *sam_ctx) 
+{
+       return ldb_get_schema_basedn(sam_ctx);
+}
+
+struct ldb_dn *samdb_root_dn(struct ldb_context *sam_ctx) 
+{
+       return ldb_get_root_basedn(sam_ctx);
+}
 
 struct ldb_dn *samdb_partitions_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
 {
        struct ldb_dn *new_dn;
 
-       new_dn = ldb_dn_copy(mem_ctx, samdb_base_dn(sam_ctx));
-       if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Partitions,CN=Configuration")) {
+       new_dn = ldb_dn_copy(mem_ctx, samdb_config_dn(sam_ctx));
+       if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Partitions")) {
                talloc_free(new_dn);
                return NULL;
        }
@@ -1047,8 +1053,8 @@ struct ldb_dn *samdb_sites_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
 {
        struct ldb_dn *new_dn;
 
-       new_dn = ldb_dn_copy(mem_ctx, samdb_base_dn(sam_ctx));
-       if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Sites,CN=Configuration")) {
+       new_dn = ldb_dn_copy(mem_ctx, samdb_config_dn(sam_ctx));
+       if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Sites")) {
                talloc_free(new_dn);
                return NULL;
        }
@@ -1122,7 +1128,7 @@ const char *samdb_result_fsmo_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
 /*
   work out the ntds settings dn for the current open ldb
 */
-const struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb)
+struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb)
 {
        TALLOC_CTX *tmp_ctx;
        const char *root_attrs[] = { "dsServiceName", NULL };
@@ -1144,8 +1150,11 @@ const struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb)
 
        ret = ldb_search(ldb, ldb_dn_new(tmp_ctx, ldb, ""), LDB_SCOPE_BASE, NULL, root_attrs, &root_res);
        if (ret) {
+               DEBUG(1,("Searching for dsServiceName in rootDSE failed: %s\n", 
+                        ldb_errstring(ldb)));
                goto failed;
        }
+       talloc_steal(tmp_ctx, root_res);
 
        if (root_res->count != 1) {
                goto failed;
@@ -1169,6 +1178,192 @@ failed:
        return NULL;
 }
 
+/*
+  work out the ntds settings invocationId for the current open ldb
+*/
+const struct GUID *samdb_ntds_invocation_id(struct ldb_context *ldb)
+{
+       TALLOC_CTX *tmp_ctx;
+       const char *attrs[] = { "invocationId", NULL };
+       int ret;
+       struct ldb_result *res;
+       struct GUID *invocation_id;
+       
+       /* see if we have a cached copy */
+       invocation_id = ldb_get_opaque(ldb, "cache.invocation_id");
+       if (invocation_id) {
+               return invocation_id;
+       }
+
+       tmp_ctx = talloc_new(ldb);
+       if (tmp_ctx == NULL) {
+               goto failed;
+       }
+
+       ret = ldb_search(ldb, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, NULL, attrs, &res);
+       if (ret) {
+               goto failed;
+       }
+       talloc_steal(tmp_ctx, res);
+
+       if (res->count != 1) {
+               goto failed;
+       }
+
+       invocation_id = talloc(tmp_ctx, struct GUID);
+       if (!invocation_id) {
+               goto failed;
+       }
+
+       *invocation_id = samdb_result_guid(res->msgs[0], "invocationId");
+
+       /* cache the domain_sid in the ldb */
+       if (ldb_set_opaque(ldb, "cache.invocation_id", invocation_id) != LDB_SUCCESS) {
+               goto failed;
+       }
+
+       talloc_steal(ldb, invocation_id);
+       talloc_free(tmp_ctx);
+
+       return invocation_id;
+
+failed:
+       DEBUG(1,("Failed to find our own NTDS Settings invocationId in the ldb!\n"));
+       talloc_free(tmp_ctx);
+       return NULL;
+}
+
+bool samdb_set_ntds_invocation_id(struct ldb_context *ldb, const struct GUID *invocation_id_in)
+{
+       TALLOC_CTX *tmp_ctx;
+       struct GUID *invocation_id_new;
+       struct GUID *invocation_id_old;
+
+       /* see if we have a cached copy */
+       invocation_id_old = ldb_get_opaque(ldb, "cache.invocation_id");
+
+       tmp_ctx = talloc_new(ldb);
+       if (tmp_ctx == NULL) {
+               goto failed;
+       }
+
+       invocation_id_new = talloc(tmp_ctx, struct GUID);
+       if (!invocation_id_new) {
+               goto failed;
+       }
+
+       *invocation_id_new = *invocation_id_in;
+
+       /* cache the domain_sid in the ldb */
+       if (ldb_set_opaque(ldb, "cache.invocation_id", invocation_id_new) != LDB_SUCCESS) {
+               goto failed;
+       }
+
+       talloc_steal(ldb, invocation_id_new);
+       talloc_free(tmp_ctx);
+       talloc_free(invocation_id_old);
+
+       return true;
+
+failed:
+       DEBUG(1,("Failed to set our own cached invocationId in the ldb!\n"));
+       talloc_free(tmp_ctx);
+       return false;
+}
+
+/*
+  work out the ntds settings objectGUID for the current open ldb
+*/
+const struct GUID *samdb_ntds_objectGUID(struct ldb_context *ldb)
+{
+       TALLOC_CTX *tmp_ctx;
+       const char *attrs[] = { "objectGUID", NULL };
+       int ret;
+       struct ldb_result *res;
+       struct GUID *ntds_guid;
+       
+       /* see if we have a cached copy */
+       ntds_guid = ldb_get_opaque(ldb, "cache.ntds_guid");
+       if (ntds_guid) {
+               return ntds_guid;
+       }
+
+       tmp_ctx = talloc_new(ldb);
+       if (tmp_ctx == NULL) {
+               goto failed;
+       }
+
+       ret = ldb_search(ldb, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, NULL, attrs, &res);
+       if (ret) {
+               goto failed;
+       }
+       talloc_steal(tmp_ctx, res);
+
+       if (res->count != 1) {
+               goto failed;
+       }
+
+       ntds_guid = talloc(tmp_ctx, struct GUID);
+       if (!ntds_guid) {
+               goto failed;
+       }
+
+       *ntds_guid = samdb_result_guid(res->msgs[0], "objectGUID");
+
+       /* cache the domain_sid in the ldb */
+       if (ldb_set_opaque(ldb, "cache.ntds_guid", ntds_guid) != LDB_SUCCESS) {
+               goto failed;
+       }
+
+       talloc_steal(ldb, ntds_guid);
+       talloc_free(tmp_ctx);
+
+       return ntds_guid;
+
+failed:
+       DEBUG(1,("Failed to find our own NTDS Settings objectGUID in the ldb!\n"));
+       talloc_free(tmp_ctx);
+       return NULL;
+}
+
+bool samdb_set_ntds_objectGUID(struct ldb_context *ldb, const struct GUID *ntds_guid_in)
+{
+       TALLOC_CTX *tmp_ctx;
+       struct GUID *ntds_guid_new;
+       struct GUID *ntds_guid_old;
+       
+       /* see if we have a cached copy */
+       ntds_guid_old = ldb_get_opaque(ldb, "cache.ntds_guid");
+
+       tmp_ctx = talloc_new(ldb);
+       if (tmp_ctx == NULL) {
+               goto failed;
+       }
+
+       ntds_guid_new = talloc(tmp_ctx, struct GUID);
+       if (!ntds_guid_new) {
+               goto failed;
+       }
+
+       *ntds_guid_new = *ntds_guid_in;
+
+       /* cache the domain_sid in the ldb */
+       if (ldb_set_opaque(ldb, "cache.ntds_guid", ntds_guid_new) != LDB_SUCCESS) {
+               goto failed;
+       }
+
+       talloc_steal(ldb, ntds_guid_new);
+       talloc_free(tmp_ctx);
+       talloc_free(ntds_guid_old);
+
+       return true;
+
+failed:
+       DEBUG(1,("Failed to set our own cached invocationId in the ldb!\n"));
+       talloc_free(tmp_ctx);
+       return false;
+}
+
 /*
   work out the server dn for the current open ldb
 */
@@ -1177,6 +1372,23 @@ struct ldb_dn *samdb_server_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
        return ldb_dn_get_parent(mem_ctx, samdb_ntds_settings_dn(ldb));
 }
 
+/*
+  work out the server dn for the current open ldb
+*/
+struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
+{
+       struct ldb_dn *server_dn;
+       struct ldb_dn *server_site_dn;
+
+       server_dn = samdb_server_dn(ldb, mem_ctx);
+       if (!server_dn) return NULL;
+
+       server_site_dn = ldb_dn_get_parent(mem_ctx, server_dn);
+
+       talloc_free(server_dn);
+       return server_site_dn;
+}
+
 /*
   work out if we are the PDC for the domain of the current open ldb
 */
@@ -1191,11 +1403,15 @@ BOOL samdb_is_pdc(struct ldb_context *ldb)
 
        tmp_ctx = talloc_new(ldb);
        if (tmp_ctx == NULL) {
-               goto failed;
+               DEBUG(1, ("talloc_new failed in samdb_is_pdc"));
+               return False;
        }
 
        ret = ldb_search(ldb, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res);
        if (ret) {
+               DEBUG(1,("Searching for fSMORoleOwner in %s failed: %s\n", 
+                        ldb_dn_get_linearized(ldb_get_default_basedn(ldb)), 
+                        ldb_errstring(ldb)));
                goto failed;
        }
        talloc_steal(tmp_ctx, dom_res);
@@ -1286,13 +1502,12 @@ _PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ct
                            struct samr_Password *lmNewHash, 
                            struct samr_Password *ntNewHash,
                            BOOL user_change,
-                           BOOL restrictions,
                            enum samr_RejectReason *reject_reason,
                            struct samr_DomInfo1 **_dominfo)
 {
-       const char * const user_attrs[] = { "userAccountControl", "sambaLMPwdHistory", 
-                                           "sambaNTPwdHistory", 
-                                           "lmPwdHash", "ntPwdHash", 
+       const char * const user_attrs[] = { "userAccountControl", "lmPwdHistory", 
+                                           "ntPwdHistory", 
+                                           "dBCSPwd", "unicodePwd", 
                                            "objectSid", 
                                            "pwdLastSet", NULL };
        const char * const domain_attrs[] = { "pwdProperties", "pwdHistoryLength", 
@@ -1307,6 +1522,7 @@ _PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ct
        int sambaLMPwdHistory_len, sambaNTPwdHistory_len;
        struct dom_sid *domain_sid;
        struct ldb_message **res;
+       BOOL restrictions;
        int count;
        time_t now = time(NULL);
        NTTIME now_nt;
@@ -1322,13 +1538,20 @@ _PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ct
        }
        userAccountControl = samdb_result_uint(res[0],   "userAccountControl", 0);
        sambaLMPwdHistory_len =   samdb_result_hashes(mem_ctx, res[0], 
-                                                "sambaLMPwdHistory", &sambaLMPwdHistory);
+                                                "lmPwdHistory", &sambaLMPwdHistory);
        sambaNTPwdHistory_len =   samdb_result_hashes(mem_ctx, res[0], 
-                                                "sambaNTPwdHistory", &sambaNTPwdHistory);
-       lmPwdHash =          samdb_result_hash(mem_ctx, res[0],   "lmPwdHash");
-       ntPwdHash =          samdb_result_hash(mem_ctx, res[0],   "ntPwdHash");
+                                                "ntPwdHistory", &sambaNTPwdHistory);
+       lmPwdHash =          samdb_result_hash(mem_ctx, res[0],   "dBCSPwd");
+       ntPwdHash =          samdb_result_hash(mem_ctx, res[0],   "unicodePwd");
        pwdLastSet =         samdb_result_uint64(res[0], "pwdLastSet", 0);
 
+       /* Only non-trust accounts have restrictions (possibly this
+        * test is the wrong way around, but I like to be restrictive
+        * if possible */
+       restrictions = !(userAccountControl & (UF_INTERDOMAIN_TRUST_ACCOUNT
+                                              |UF_WORKSTATION_TRUST_ACCOUNT
+                                              |UF_SERVER_TRUST_ACCOUNT)); 
+
        if (domain_dn) {
                /* pull the domain parameters */
                count = gendb_search_dn(ctx, mem_ctx, domain_dn, &res, domain_attrs);
@@ -1376,7 +1599,8 @@ _PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ct
                *_dominfo = dominfo;
        }
 
-       if (new_pass) {
+       if (restrictions && new_pass) {
+
                /* check the various password restrictions */
                if (restrictions && minPwdLength > strlen_m(new_pass)) {
                        if (reject_reason) {
@@ -1408,7 +1632,7 @@ _PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ct
                ntNewHash = &local_ntNewHash;
        }
 
-       if (restrictions && user_change) {
+       if (user_change) {
                /* are all password changes disallowed? */
                if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
                        if (reject_reason) {
@@ -1486,15 +1710,15 @@ _PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ct
                CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "sambaPassword"));
 
                if (lmNewHash) {
-                       CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "lmPwdHash", lmNewHash));
+                       CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "dBCSPwd", lmNewHash));
                } else {
-                       CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "lmPwdHash"));
+                       CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "dBCSPwd"));
                }
                
                if (ntNewHash) {
-                       CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "ntPwdHash", ntNewHash));
+                       CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "unicodePwd", ntNewHash));
                } else {
-                       CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "ntPwdHash"));
+                       CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "unicodePwd"));
                }
        }
 
@@ -1516,7 +1740,6 @@ _PUBLIC_ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *me
                                struct samr_Password *lmNewHash, 
                                struct samr_Password *ntNewHash,
                                BOOL user_change,
-                               BOOL restrictions,
                                enum samr_RejectReason *reject_reason,
                                struct samr_DomInfo1 **_dominfo) 
 {
@@ -1558,7 +1781,6 @@ _PUBLIC_ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *me
                                       msg, new_pass, 
                                       lmNewHash, ntNewHash,
                                       user_change, /* This is a password set, not change */
-                                      restrictions, /* run restriction tests */
                                       reject_reason, _dominfo);
        if (!NT_STATUS_IS_OK(nt_status)) {
                ldb_transaction_cancel(ctx);
@@ -1713,6 +1935,45 @@ NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TA
        return NT_STATUS_OK;
 }
 
+
+/*
+  Find the DN of a domain, assuming it to be a dotted.dns name
+*/
+
+struct ldb_dn *samdb_dns_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *dns_domain) 
+{
+       int i;
+       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+       const char *binary_encoded;
+       const char **split_realm;
+       struct ldb_dn *dn;
+       
+       if (!tmp_ctx) {
+               return NULL;
+       }
+       
+       split_realm = str_list_make(tmp_ctx, dns_domain, ".");
+       if (!split_realm) {
+               talloc_free(tmp_ctx);
+               return NULL;
+       }
+       dn = ldb_dn_new(mem_ctx, ldb, NULL);
+       for (i=0; split_realm[i]; i++) {
+               binary_encoded = ldb_binary_encode_string(tmp_ctx, split_realm[i]);
+               if (!ldb_dn_add_base_fmt(dn, "dc=%s", binary_encoded)) {
+                       DEBUG(2, ("Failed to add dc=%s element to DN %s\n",
+                                 binary_encoded, ldb_dn_get_linearized(dn)));
+                       talloc_free(tmp_ctx);
+                       return NULL;
+               }
+       }
+       if (!ldb_dn_validate(dn)) {
+               DEBUG(2, ("Failed to validated DN %s\n",
+                         ldb_dn_get_linearized(dn)));
+               return NULL;
+       }
+       return dn;
+}
 /*
   Find the DN of a domain, be it the netbios or DNS name 
 */
@@ -1723,6 +1984,9 @@ struct ldb_dn *samdb_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
        const char * const domain_ref_attrs[] = {
                "ncName", NULL
        };
+       const char * const domain_ref2_attrs[] = {
+               NULL
+       };
        struct ldb_result *res_domain_ref;
        char *escaped_domain = ldb_binary_encode_string(mem_ctx, domain_name);
        /* find the domain's DN */
@@ -1731,15 +1995,26 @@ struct ldb_dn *samdb_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
                                            samdb_partitions_dn(ldb, mem_ctx), 
                                            LDB_SCOPE_ONELEVEL, 
                                            domain_ref_attrs,
-                                           "(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))", 
-                                           escaped_domain, escaped_domain);
+                                           "(&(nETBIOSName=%s)(objectclass=crossRef))", 
+                                           escaped_domain);
        if (ret_domain != 0) {
                return NULL;
        }
        
        if (res_domain_ref->count == 0) {
-               DEBUG(3,("sam_search_user: Couldn't find domain [%s] in samdb.\n", 
-                        domain_name));
+               ret_domain = ldb_search_exp_fmt(ldb, mem_ctx, 
+                                               &res_domain_ref, 
+                                               samdb_dns_domain_to_dn(ldb, mem_ctx, domain_name),
+                                               LDB_SCOPE_BASE,
+                                               domain_ref2_attrs,
+                                               "(objectclass=domain)");
+               if (ret_domain != 0) {
+                       return NULL;
+               }
+       
+               if (res_domain_ref->count == 1) {
+                       return res_domain_ref->msgs[0]->dn;
+               }
                return NULL;
        }