From c82c9fe7bb47aa95d112159e46e79f52afe6f58d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 30 Dec 2005 08:40:16 +0000 Subject: r12599: This new LDB module (and associated changes) allows Samba4 to operate using pre-calculated passwords for all kerberos key types. (Previously we could only use these for the NT# type). The module handles all of the hash/string2key tasks for all parts of Samba, which was previously in the rpc_server/samr/samr_password.c code. We also update the msDS-KeyVersionNumber, and the password history. This new module can be called at provision time, which ensures we start with a database that is consistent in this respect. By ensuring that the krb5key attribute is the only one we need to retrieve, this also simplifies the run-time KDC logic. (Each value of the multi-valued attribute is encoded as a 'Key' in ASN.1, using the definition from Heimdal's HDB. This simplfies the KDC code.). It is hoped that this will speed up the KDC enough that it can again operate under valgrind. (This used to be commit e9022743210b59f19f370d772e532e0f08bfebd9) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 711 +++++++++++++++++++++++++ 1 file changed, 711 insertions(+) create mode 100644 source4/dsdb/samdb/ldb_modules/password_hash.c (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c new file mode 100644 index 0000000000..bb42a0e634 --- /dev/null +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -0,0 +1,711 @@ +/* + ldb database module + + Copyright (C) Simo Sorce 2004 + Copyright (C) Andrew Bartlett 2005 + Copyright (C) Andrew Tridgell 2004 + + 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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. +*/ + +/* + * Name: ldb + * + * Component: ldb password_hash module + * + * Description: correctly update hash values based on changes to unicodePwd and friends + * + * Author: Andrew Bartlett + */ + +#include "includes.h" +#include "libcli/ldap/ldap.h" +#include "ldb/include/ldb_errors.h" +#include "ldb/include/ldb_private.h" +#include "librpc/gen_ndr/ndr_misc.h" +#include "librpc/gen_ndr/ndr_samr.h" +#include "system/kerberos.h" +#include "auth/kerberos/kerberos.h" +#include "system/time.h" +#include "dsdb/samdb/samdb.h" +#include "ads.h" +#include "hdb.h" + +/* If we have decided there is reason to work on this request, then + * setup all the password hash types correctly. + * + * If the administrator doesn't want the unicodePwd stored (set in the + * domain and per-account policies) then we must strip that out before + * we do the first operation. + * + * Once this is done (which could update anything at all), we + * calculate the password hashes. + * + * This function must not only update the ntPwdHash, lmPwdHash and + * krb5Key fields, it must also atomicly increment the + * msDS-KeyVersionNumber. We should be in a transaction, so all this + * should be quite safe... + * + * Finally, if the administrator has requested that a password history + * be maintained, then this should also be written out. + * + */ + + +static int password_hash_handle(struct ldb_module *module, struct ldb_request *req, + const struct ldb_message *msg) +{ + int ret, old_ret = -1; + uint_t pwdProperties, pwdHistoryLength; + uint_t userAccountControl; + const char *dnsDomain, *realm; + const char *unicodePwd; + struct samr_Password *lmPwdHistory, *ntPwdHistory; + struct samr_Password *lmPwdHash, *ntPwdHash; + struct samr_Password *lmOldHash = NULL, *ntOldHash = NULL; + struct samr_Password *new_lmPwdHistory, *new_ntPwdHistory; + struct samr_Password local_lmNewHash, local_ntNewHash; + int lmPwdHistory_len, ntPwdHistory_len; + uint_t kvno; + struct dom_sid *domain_sid; + time_t now = time(NULL); + NTTIME now_nt; + int i; + krb5_error_code krb5_ret; + + struct smb_krb5_context *smb_krb5_context; + + struct ldb_message_element *attribute; + struct ldb_dn *dn = msg->dn; + struct ldb_message *msg2; + + struct ldb_request search_request; + struct ldb_request modify_request; + struct ldb_request modified_orig_request; + struct ldb_result *res, *dom_res, *old_res; + + struct ldb_message_element *objectclasses; + struct ldb_val computer_val; + struct ldb_val person_val; + BOOL is_computer; + + struct ldb_message *modify_msg; + + const char *domain_expression; + const char *old_user_attrs[] = { "lmPwdHash", "ntPwdHash", NULL }; + const char *user_attrs[] = { "userAccountControl", "lmPwdHistory", + "ntPwdHistory", + "ntPwdHash", + "objectSid", "msDS-KeyVersionNumber", + "objectClass", "userPrincipalName", + "samAccountName", + NULL }; + const char * const domain_attrs[] = { "pwdProperties", "pwdHistoryLength", + "dnsDomain", NULL }; + + TALLOC_CTX *mem_ctx; + + /* Do the original action */ + + /* If no part of this touches the unicodePwd, then we don't + * need to make any changes. For password changes/set there should + * be a 'delete' or a 'modify' on this attribute. */ + if ((attribute = ldb_msg_find_element(msg, "unicodePwd")) == NULL ) { + return ldb_next_request(module, req); + } + + mem_ctx = talloc_new(module); + if (!mem_ctx) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (req->operation == LDB_REQ_MODIFY) { + /* Look up the old ntPwdHash and lmPwdHash values, so + * we can later place these into the password + * history */ + + search_request.operation = LDB_REQ_SEARCH; + search_request.op.search.base = dn; + search_request.op.search.scope = LDB_SCOPE_BASE; + search_request.op.search.tree = ldb_parse_tree(module->ldb, NULL); + search_request.op.search.attrs = old_user_attrs; + + old_ret = ldb_next_request(module, &search_request); + } + + /* we can't change things untill we copy it */ + msg2 = ldb_msg_copy_shallow(mem_ctx, msg); + + /* look again, this time at the copied attribute */ + if (!msg2 || (attribute = ldb_msg_find_element(msg2, "unicodePwd")) == NULL ) { + /* Gah? where did it go? Oh well... */ + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Wipe out the unicodePwd attribute set, we will handle it in + * the second modify. We might not want it written to disk */ + + if (req->operation == LDB_REQ_ADD) { + if (attribute->num_values != 1) { + ldb_set_errstring(module, + talloc_asprintf(mem_ctx, "unicodePwd_handle: " + "attempted set of multiple unicodePwd attributes on %s rejected", + ldb_dn_linearize(mem_ctx, dn))); + return LDB_ERR_CONSTRAINT_VIOLAION; + } + + unicodePwd = (const char *)attribute->values[0].data; + ldb_msg_remove_attr(msg2, "unicodePwd"); + } else if (((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_ADD) + || ((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE)) { + if (attribute->num_values != 1) { + return LDB_ERR_CONSTRAINT_VIOLAION; + } + + unicodePwd = (const char *)attribute->values[0].data; + ldb_msg_remove_attr(msg2, "unicodePwd"); + } else { + unicodePwd = NULL; + } + + modified_orig_request = *req; + switch (modified_orig_request.operation) { + case LDB_REQ_ADD: + modified_orig_request.op.add.message = msg2; + break; + case LDB_REQ_MODIFY: + modified_orig_request.op.mod.message = msg2; + break; + } + + /* Send the (modified) request of the original caller down to the database */ + ret = ldb_next_request(module, &modified_orig_request); + if (ret) { + return ret; + } + + /* While we do the search first (for the old password hashes), + * we don't want to override any error that the modify may + * have returned. Now check the error */ + if (req->operation == LDB_REQ_MODIFY) { + if (old_ret) { + talloc_free(mem_ctx); + return old_ret; + } + + /* Find out the old passwords details of the user */ + old_res = search_request.op.search.res; + + if (old_res->count != 1) { + ldb_set_errstring(module, + talloc_asprintf(mem_ctx, "password_hash_handle: " + "(pre) search for %s found %d != 1 objects, for entry we just modified", + ldb_dn_linearize(mem_ctx, dn), + old_res->count)); + /* What happend? The above add/modify worked... */ + talloc_free(mem_ctx); + return LDB_ERR_NO_SUCH_OBJECT; + } + + lmOldHash = samdb_result_hash(mem_ctx, old_res->msgs[0], "lmPwdHash"); + ntOldHash = samdb_result_hash(mem_ctx, old_res->msgs[0], "ntPwdHash"); + } + + /* Start finding out details we need for the second modify. + * We do this after the first add/modify because other modules + * will have filled in the templates, and we may have had + * things like the username (affecting the salt) changed along + * with the password. */ + + /* Now find out what is on the entry after the above add/modify */ + search_request.operation = LDB_REQ_SEARCH; + search_request.op.search.base = dn; + search_request.op.search.scope = LDB_SCOPE_BASE; + search_request.op.search.tree = ldb_parse_tree(module->ldb, NULL); + search_request.op.search.attrs = user_attrs; + + ret = ldb_next_request(module, &search_request); + if (ret) { + talloc_free(mem_ctx); + return ret; + } + + /* Find out the full details of the user */ + res = search_request.op.search.res; + if (res->count != 1) { + ldb_set_errstring(module, + talloc_asprintf(mem_ctx, "password_hash_handle: " + "search for %s found %d != 1 objects, for entry we just added/modified", + ldb_dn_linearize(mem_ctx, dn), + res->count)); + /* What happend? The above add/modify worked... */ + talloc_free(mem_ctx); + return LDB_ERR_NO_SUCH_OBJECT; + } + + userAccountControl = samdb_result_uint(res->msgs[0], "userAccountControl", 0); + lmPwdHistory_len = samdb_result_hashes(mem_ctx, res->msgs[0], + "lmPwdHistory", &lmPwdHistory); + ntPwdHistory_len = samdb_result_hashes(mem_ctx, res->msgs[0], + "ntPwdHistory", &ntPwdHistory); + ntPwdHash = samdb_result_hash(mem_ctx, res->msgs[0], "ntPwdHash"); + kvno = samdb_result_uint(res->msgs[0], "msDS-KeyVersionNumber", 0); + + domain_sid = samdb_result_sid_prefix(mem_ctx, res->msgs[0], "objectSid"); + + + objectclasses = ldb_msg_find_element(res->msgs[0], "objectClass"); + person_val = data_blob_string_const("person"); + + if (!objectclasses || !ldb_msg_find_val(objectclasses, &person_val)) { + /* Not a 'person', so the rest of this doesn't make + * sense. How we got a unicodePwd this far I don't + * know... */ + ldb_set_errstring(module, + talloc_asprintf(mem_ctx, "password_hash_handle: " + "attempted set of unicodePwd on non-'person' object %s rejected", + ldb_dn_linearize(mem_ctx, dn))); + talloc_free(mem_ctx); + return LDB_ERR_CONSTRAINT_VIOLAION; + } + + computer_val = data_blob_string_const("computer"); + + if (ldb_msg_find_val(objectclasses, &computer_val)) { + is_computer = True; + } else { + is_computer = False; + } + + domain_expression = talloc_asprintf(mem_ctx, "(&(objectSid=%s)(objectClass=domain))", + ldap_encode_ndr_dom_sid(mem_ctx, domain_sid)); + + /* Find the user's domain, then find out the domain password + * properties */ + ret = ldb_search(module->ldb, NULL, LDB_SCOPE_SUBTREE, domain_expression, + domain_attrs, &dom_res); + if (ret) { + talloc_free(mem_ctx); + return ret; + } + + if (dom_res->count != 1) { + /* What happend? The user we are modifying must be odd... */ + ldb_set_errstring(module, + talloc_asprintf(mem_ctx, "password_hash_handle: " + "search for domain %s found %d != 1 objects", + dom_sid_string(mem_ctx, domain_sid), + dom_res->count)); + talloc_free(mem_ctx); + return LDB_ERR_NO_SUCH_OBJECT; + } + + pwdProperties = samdb_result_uint(dom_res->msgs[0], "pwdProperties", 0); + pwdHistoryLength = samdb_result_uint(dom_res->msgs[0], "pwdHistoryLength", 0); + dnsDomain = ldb_msg_find_string(dom_res->msgs[0], "dnsDomain", NULL); + realm = strupper_talloc(mem_ctx, dnsDomain); + + /* Some operations below require kerberos contexts */ + if (smb_krb5_init_context(mem_ctx, &smb_krb5_context) != 0) { + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Prepare the modifications to set all the hash/key types */ + modify_msg = ldb_msg_new(req); + modify_msg->dn = talloc_reference(modify_msg, dn); + +#define CHECK_RET(x) \ + do { \ + int check_ret = x; \ + if (check_ret != LDB_SUCCESS) { \ + talloc_free(mem_ctx); \ + return check_ret; \ + } \ + } while(0) + + /* Setup krb5Key (we want to either delete an existing value, + * or replace with a new one). Both the unicode and NT hash + * only branches append keys to this multivalued entry. */ + CHECK_RET(ldb_msg_add_empty(modify_msg, "krb5Key", LDB_FLAG_MOD_REPLACE)); + /* Yay, we can compute new password hashes from the unicode + * password */ + if (unicodePwd) { + Principal *salt_principal; + const char *user_principal_name = ldb_msg_find_string(res->msgs[0], "userPrincipalName", NULL); + + Key *keys; + size_t num_keys; + + /* compute the new nt and lm hashes */ + if (E_deshash(unicodePwd, local_lmNewHash.hash)) { + lmPwdHash = &local_lmNewHash; + } else { + lmPwdHash = NULL; + } + E_md4hash(unicodePwd, local_ntNewHash.hash); + ntPwdHash = &local_ntNewHash; + CHECK_RET(ldb_msg_add_empty(modify_msg, "ntPwdHash", + LDB_FLAG_MOD_REPLACE)); + CHECK_RET(samdb_msg_add_hash(module->ldb, req, + modify_msg, "ntPwdHash", + ntPwdHash)); + CHECK_RET(ldb_msg_add_empty(modify_msg, "lmPwdHash", + LDB_FLAG_MOD_REPLACE)); + if (lmPwdHash) { + CHECK_RET(samdb_msg_add_hash(module->ldb, req, + modify_msg, "lmPwdHash", + lmPwdHash)); + } + + /* Many, many thanks to lukeh@padl.com for this + * algorithm, described in his Nov 10 2004 mail to + * samba-technical@samba.org */ + + if (is_computer) { + /* Determine a salting principal */ + char *samAccountName = talloc_strdup(mem_ctx, ldb_msg_find_string(res->msgs[0], "samAccountName", NULL)); + char *saltbody; + if (!samAccountName) { + ldb_set_errstring(module, + talloc_asprintf(mem_ctx, "password_hash_handle: " + "generation of new kerberos keys failed: %s is a computer without a samAccountName", + ldb_dn_linearize(mem_ctx, dn))); + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + if (samAccountName[strlen(samAccountName)-1] == '$') { + samAccountName[strlen(samAccountName)-1] = '\0'; + } + saltbody = talloc_asprintf(mem_ctx, "%s.%s", samAccountName, dnsDomain); + + krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, &salt_principal, realm, "host", saltbody, NULL); + } else if (user_principal_name) { + char *p; + user_principal_name = talloc_strdup(mem_ctx, user_principal_name); + if (!user_principal_name) { + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } else { + p = strchr(user_principal_name, '@'); + if (p) { + p[0] = '\0'; + } + krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, &salt_principal, realm, user_principal_name, NULL); + } + } else { + const char *samAccountName = ldb_msg_find_string(res->msgs[0], "samAccountName", NULL); + if (!samAccountName) { + ldb_set_errstring(module, + talloc_asprintf(mem_ctx, "password_hash_handle: " + "generation of new kerberos keys failed: %s has no samAccountName", + ldb_dn_linearize(mem_ctx, dn))); + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, &salt_principal, realm, samAccountName, NULL); + } + + + if (krb5_ret) { + ldb_set_errstring(module, + talloc_asprintf(mem_ctx, "password_hash_handle: " + "generation of a saltking principal failed: %s", + smb_get_krb5_error_message(smb_krb5_context->krb5_context, + krb5_ret, mem_ctx))); + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* TODO: We may wish to control the encryption types chosen in future */ + krb5_ret = hdb_generate_key_set_password(smb_krb5_context->krb5_context, + salt_principal, unicodePwd, &keys, &num_keys); + krb5_free_principal(smb_krb5_context->krb5_context, salt_principal); + + if (krb5_ret) { + ldb_set_errstring(module, + talloc_asprintf(mem_ctx, "password_hash_handle: " + "generation of new kerberos keys failed: %s", + smb_get_krb5_error_message(smb_krb5_context->krb5_context, + krb5_ret, mem_ctx))); + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Walking + */ + for (i=0; i < num_keys; i++) { + unsigned char *buf; + size_t buf_size; + size_t len; + struct ldb_val val; + + if (keys[i].key.keytype == ENCTYPE_ARCFOUR_HMAC) { + /* We might end up doing this below: + * This ensures we get the unicode + * conversion right. This should also + * be fixed in the Heimdal libs */ + continue; + } + ASN1_MALLOC_ENCODE(Key, buf, buf_size, &keys[i], &len, krb5_ret); + + val.data = talloc_memdup(req, buf, len); + val.length = len; + free(buf); + if (!val.data || krb5_ret) { + hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + ret = ldb_msg_add_value(modify_msg, "krb5Key", &val); + if (ret != LDB_SUCCESS) { + hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); + talloc_free(mem_ctx); + return ret; + } + } + + hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); + } + + /* Possibly kill off the cleartext or store it */ + CHECK_RET(ldb_msg_add_empty(modify_msg, "unicodePwd", LDB_FLAG_MOD_REPLACE)); + + if (unicodePwd && (pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT) && + (userAccountControl & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { + CHECK_RET(ldb_msg_add_string(modify_msg, "unicodePwd", unicodePwd)); + } + + /* Even if we didn't get a unicodePwd, we can still setup + * krb5Key from the NT hash. + * + * This is an append, so it works with the 'continue' in the + * unicode loop above, to use Samba's NT hash function, which + * is more correct than Heimdal's + */ + if (ntPwdHash) { + unsigned char *buf; + size_t buf_size; + size_t len; + struct ldb_val val; + Key key; + + key.mkvno = 0; + key.salt = NULL; /* No salt for this enc type */ + + krb5_ret = krb5_keyblock_init(smb_krb5_context->krb5_context, + ENCTYPE_ARCFOUR_HMAC, + ntPwdHash->hash, sizeof(ntPwdHash->hash), + &key.key); + if (krb5_ret) { + return LDB_ERR_OPERATIONS_ERROR; + } + ASN1_MALLOC_ENCODE(Key, buf, buf_size, &key, &len, krb5_ret); + krb5_free_keyblock_contents(smb_krb5_context->krb5_context, + &key.key); + + val.data = talloc_memdup(req, buf, len); + val.length = len; + free(buf); + if (!val.data || ret) { + return LDB_ERR_OPERATIONS_ERROR; + } + CHECK_RET(ldb_msg_add_value(modify_msg, "krb5Key", &val)); + } + + /* If the original caller did anything with pwdLastSet then skip this. It could be an incoming samsync */ + if ((attribute = ldb_msg_find_element(msg, "pwdLastSet")) == NULL ) { + /* Update the password last set time */ + unix_to_nt_time(&now_nt, now); + CHECK_RET(ldb_msg_add_empty(modify_msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE)); + CHECK_RET(samdb_msg_add_uint64(module->ldb, mem_ctx, modify_msg, "pwdLastSet", now_nt)); + } + + /* If the original caller did anything with "msDS-KeyVersionNumber" then skip this. It could be an incoming samsync */ + if ((attribute = ldb_msg_find_element(msg, "msDS-KeyVersionNumber")) == NULL ) { + if (kvno == 0) { + CHECK_RET(ldb_msg_add_empty(modify_msg, "msDS-KeyVersionNumber", + LDB_FLAG_MOD_REPLACE)); + CHECK_RET(samdb_msg_add_uint(module->ldb, mem_ctx, modify_msg, "msDS-KeyVersionNumber", kvno + 1)); + } else { + /* While we should be in a transaction, go one extra + * step in the dance for an 'atomic' increment. This + * may be of value against remote LDAP servers. (Note + * however that Mulitmaster replication stil offers no + * such guarantee) */ + + struct ldb_val old_kvno, new_kvno; + old_kvno.data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", kvno); + if (!old_kvno.data) { + return -1; + } + old_kvno.length = strlen((char *)old_kvno.data); + + new_kvno.data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", kvno + 1); + if (!new_kvno.data) { + return -1; + } + new_kvno.length = strlen((char *)new_kvno.data); + + CHECK_RET(ldb_msg_add_empty(modify_msg, "msDS-KeyVersionNumber", + LDB_FLAG_MOD_DELETE)); + CHECK_RET(ldb_msg_add_empty(modify_msg, "msDS-KeyVersionNumber", + LDB_FLAG_MOD_ADD)); + modify_msg->elements[modify_msg->num_elements - 2].num_values = 1; + modify_msg->elements[modify_msg->num_elements - 2].values = &old_kvno; + modify_msg->elements[modify_msg->num_elements - 1].num_values = 1; + modify_msg->elements[modify_msg->num_elements - 1].values = &new_kvno; + } + } + + CHECK_RET(ldb_msg_add_empty(modify_msg, "lmPwdHistory", + LDB_FLAG_MOD_REPLACE)); + CHECK_RET(ldb_msg_add_empty(modify_msg, "ntPwdHistory", + LDB_FLAG_MOD_REPLACE)); + + /* If we have something to put into the history, or an old + * history element to expire, update the history */ + if (pwdHistoryLength > 0 && + ((ntPwdHistory_len > 0) || (lmPwdHistory_len > 0) + || lmOldHash || ntOldHash)) { + /* store the password history */ + new_lmPwdHistory = talloc_array(mem_ctx, struct samr_Password, + pwdHistoryLength); + if (!new_lmPwdHistory) { + return LDB_ERR_OPERATIONS_ERROR; + } + new_ntPwdHistory = talloc_array(mem_ctx, struct samr_Password, + pwdHistoryLength); + if (!new_ntPwdHistory) { + return LDB_ERR_OPERATIONS_ERROR; + } + for (i=0;ildb, mem_ctx, modify_msg, + "lmPwdHistory", + new_lmPwdHistory, + lmPwdHistory_len)); + + CHECK_RET(samdb_msg_add_hashes(module->ldb, mem_ctx, modify_msg, + "ntPwdHistory", + new_ntPwdHistory, + ntPwdHistory_len)); + } + + /* Too much code above, we should check we got it close to reasonable */ + CHECK_RET(ldb_msg_sanity_check(modify_msg)); + + modify_request.operation = LDB_REQ_MODIFY; + modify_request.op.mod.message = modify_msg; + + ret = ldb_next_request(module, &modify_request); + + talloc_free(mem_ctx); + return ret; +} + +/* add_record: do things with the unicodePwd attribute */ +static int password_hash_add(struct ldb_module *module, struct ldb_request *req) +{ + const struct ldb_message *msg = req->op.add.message; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_add_record\n"); + + if (ldb_dn_is_special(msg->dn)) { /* do not manipulate our control entries */ + return ldb_next_request(module, req); + } + + return password_hash_handle(module, req, msg); +} + +/* modify_record: do things with the unicodePwd attribute */ +static int password_hash_modify(struct ldb_module *module, struct ldb_request *req) +{ + const struct ldb_message *msg = req->op.mod.message; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_modify_record\n"); + + if (ldb_dn_is_special(msg->dn)) { /* do not manipulate our control entries */ + return ldb_next_request(module, req); + } + + return password_hash_handle(module, req, msg); +} + +static int password_hash_request(struct ldb_module *module, struct ldb_request *req) +{ + switch (req->operation) { + + case LDB_REQ_ADD: + return password_hash_add(module, req); + + case LDB_REQ_MODIFY: + return password_hash_modify(module, req); + + default: + return ldb_next_request(module, req); + + } +} + +static const struct ldb_module_ops password_hash_ops = { + .name = "password_hash", + .request = password_hash_request +}; + + +/* the init function */ +#ifdef HAVE_DLOPEN_DISABLED + struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) +#else +struct ldb_module *password_hash_module_init(struct ldb_context *ldb, const char *options[]) +#endif +{ + struct ldb_module *ctx; + + ctx = talloc(ldb, struct ldb_module); + if (!ctx) + return NULL; + + ctx->private_data = NULL; + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &password_hash_ops; + + return ctx; +} -- cgit From 3b99d9c5bd563203adc4b017d6e6599dd84b8d57 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 1 Jan 2006 17:32:10 +0000 Subject: r12658: Couple of fixes related to shared module builds. (This used to be commit c297c93faf3b748de68679f5a4be50845ebe25fe) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index bb42a0e634..212c9c91d1 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -690,11 +690,7 @@ static const struct ldb_module_ops password_hash_ops = { /* the init function */ -#ifdef HAVE_DLOPEN_DISABLED - struct ldb_module *init_module(struct ldb_context *ldb, const char *options[]) -#else struct ldb_module *password_hash_module_init(struct ldb_context *ldb, const char *options[]) -#endif { struct ldb_module *ctx; -- cgit From 5cea3edcefc8bec3caed077a5712cb06c7f14816 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 5 Jan 2006 02:14:01 +0000 Subject: r12716: Tridge points out that the request argument to ldb_next_request must be a valid talloc() pointer, as other modules may rely on this. Andrew Bartlett (This used to be commit 356c8c56090a7c4254609c0cc138c994b618fa55) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 74 +++++++++++++++++--------- 1 file changed, 49 insertions(+), 25 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 212c9c91d1..b8554e4885 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -91,9 +91,9 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r struct ldb_dn *dn = msg->dn; struct ldb_message *msg2; - struct ldb_request search_request; - struct ldb_request modify_request; - struct ldb_request modified_orig_request; + struct ldb_request *search_request = NULL; + struct ldb_request *modify_request; + struct ldb_request *modified_orig_request; struct ldb_result *res, *dom_res, *old_res; struct ldb_message_element *objectclasses; @@ -132,17 +132,23 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } if (req->operation == LDB_REQ_MODIFY) { + search_request = talloc(mem_ctx, struct ldb_request); + if (!search_request) { + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + /* Look up the old ntPwdHash and lmPwdHash values, so * we can later place these into the password * history */ - search_request.operation = LDB_REQ_SEARCH; - search_request.op.search.base = dn; - search_request.op.search.scope = LDB_SCOPE_BASE; - search_request.op.search.tree = ldb_parse_tree(module->ldb, NULL); - search_request.op.search.attrs = old_user_attrs; + search_request->operation = LDB_REQ_SEARCH; + search_request->op.search.base = dn; + search_request->op.search.scope = LDB_SCOPE_BASE; + search_request->op.search.tree = ldb_parse_tree(module->ldb, NULL); + search_request->op.search.attrs = old_user_attrs; - old_ret = ldb_next_request(module, &search_request); + old_ret = ldb_next_request(module, search_request); } /* we can't change things untill we copy it */ @@ -180,18 +186,24 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r unicodePwd = NULL; } - modified_orig_request = *req; - switch (modified_orig_request.operation) { + modified_orig_request = talloc(mem_ctx, struct ldb_request); + if (!modified_orig_request) { + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + + *modified_orig_request = *req; + switch (modified_orig_request->operation) { case LDB_REQ_ADD: - modified_orig_request.op.add.message = msg2; + modified_orig_request->op.add.message = msg2; break; case LDB_REQ_MODIFY: - modified_orig_request.op.mod.message = msg2; + modified_orig_request->op.mod.message = msg2; break; } /* Send the (modified) request of the original caller down to the database */ - ret = ldb_next_request(module, &modified_orig_request); + ret = ldb_next_request(module, modified_orig_request); if (ret) { return ret; } @@ -206,7 +218,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } /* Find out the old passwords details of the user */ - old_res = search_request.op.search.res; + old_res = search_request->op.search.res; if (old_res->count != 1) { ldb_set_errstring(module, @@ -230,20 +242,26 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r * with the password. */ /* Now find out what is on the entry after the above add/modify */ - search_request.operation = LDB_REQ_SEARCH; - search_request.op.search.base = dn; - search_request.op.search.scope = LDB_SCOPE_BASE; - search_request.op.search.tree = ldb_parse_tree(module->ldb, NULL); - search_request.op.search.attrs = user_attrs; + search_request = talloc(mem_ctx, struct ldb_request); + if (!search_request) { + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + + search_request->operation = LDB_REQ_SEARCH; + search_request->op.search.base = dn; + search_request->op.search.scope = LDB_SCOPE_BASE; + search_request->op.search.tree = ldb_parse_tree(module->ldb, NULL); + search_request->op.search.attrs = user_attrs; - ret = ldb_next_request(module, &search_request); + ret = ldb_next_request(module, search_request); if (ret) { talloc_free(mem_ctx); return ret; } /* Find out the full details of the user */ - res = search_request.op.search.res; + res = search_request->op.search.res; if (res->count != 1) { ldb_set_errstring(module, talloc_asprintf(mem_ctx, "password_hash_handle: " @@ -630,10 +648,16 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r /* Too much code above, we should check we got it close to reasonable */ CHECK_RET(ldb_msg_sanity_check(modify_msg)); - modify_request.operation = LDB_REQ_MODIFY; - modify_request.op.mod.message = modify_msg; + modify_request = talloc(mem_ctx, struct ldb_request); + if (!modify_request) { + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + + modify_request->operation = LDB_REQ_MODIFY; + modify_request->op.mod.message = modify_msg; - ret = ldb_next_request(module, &modify_request); + ret = ldb_next_request(module, modify_request); talloc_free(mem_ctx); return ret; -- cgit From 4bfe2907e77809e499e998dd63f41985c5a02279 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 5 Jan 2006 06:53:39 +0000 Subject: r12719: Rename unicodePwd -> sambaPassword. Because we don't know the syntax of unicodePwd, we want to avoid using that attribute name. It may cause problems later when we get replication form windows. I'm doing this before the tech preview, so we don't get too many supprises as folks upgrade databases into later versions. Andrew Bartlett (This used to be commit 097d9d0b7fd3b1a10fb7039f0671fd459bed2d1b) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 52 +++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index b8554e4885..80017548d2 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -25,7 +25,7 @@ * * Component: ldb password_hash module * - * Description: correctly update hash values based on changes to unicodePwd and friends + * Description: correctly update hash values based on changes to sambaPassword and friends * * Author: Andrew Bartlett */ @@ -46,7 +46,7 @@ /* If we have decided there is reason to work on this request, then * setup all the password hash types correctly. * - * If the administrator doesn't want the unicodePwd stored (set in the + * If the administrator doesn't want the sambaPassword stored (set in the * domain and per-account policies) then we must strip that out before * we do the first operation. * @@ -71,7 +71,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r uint_t pwdProperties, pwdHistoryLength; uint_t userAccountControl; const char *dnsDomain, *realm; - const char *unicodePwd; + const char *sambaPassword; struct samr_Password *lmPwdHistory, *ntPwdHistory; struct samr_Password *lmPwdHash, *ntPwdHash; struct samr_Password *lmOldHash = NULL, *ntOldHash = NULL; @@ -119,10 +119,10 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r /* Do the original action */ - /* If no part of this touches the unicodePwd, then we don't + /* If no part of this touches the sambaPassword, then we don't * need to make any changes. For password changes/set there should * be a 'delete' or a 'modify' on this attribute. */ - if ((attribute = ldb_msg_find_element(msg, "unicodePwd")) == NULL ) { + if ((attribute = ldb_msg_find_element(msg, "sambaPassword")) == NULL ) { return ldb_next_request(module, req); } @@ -155,35 +155,35 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r msg2 = ldb_msg_copy_shallow(mem_ctx, msg); /* look again, this time at the copied attribute */ - if (!msg2 || (attribute = ldb_msg_find_element(msg2, "unicodePwd")) == NULL ) { + if (!msg2 || (attribute = ldb_msg_find_element(msg2, "sambaPassword")) == NULL ) { /* Gah? where did it go? Oh well... */ return LDB_ERR_OPERATIONS_ERROR; } - /* Wipe out the unicodePwd attribute set, we will handle it in + /* Wipe out the sambaPassword attribute set, we will handle it in * the second modify. We might not want it written to disk */ if (req->operation == LDB_REQ_ADD) { if (attribute->num_values != 1) { ldb_set_errstring(module, - talloc_asprintf(mem_ctx, "unicodePwd_handle: " - "attempted set of multiple unicodePwd attributes on %s rejected", + talloc_asprintf(mem_ctx, "sambaPassword_handle: " + "attempted set of multiple sambaPassword attributes on %s rejected", ldb_dn_linearize(mem_ctx, dn))); return LDB_ERR_CONSTRAINT_VIOLAION; } - unicodePwd = (const char *)attribute->values[0].data; - ldb_msg_remove_attr(msg2, "unicodePwd"); + sambaPassword = (const char *)attribute->values[0].data; + ldb_msg_remove_attr(msg2, "sambaPassword"); } else if (((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_ADD) || ((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE)) { if (attribute->num_values != 1) { return LDB_ERR_CONSTRAINT_VIOLAION; } - unicodePwd = (const char *)attribute->values[0].data; - ldb_msg_remove_attr(msg2, "unicodePwd"); + sambaPassword = (const char *)attribute->values[0].data; + ldb_msg_remove_attr(msg2, "sambaPassword"); } else { - unicodePwd = NULL; + sambaPassword = NULL; } modified_orig_request = talloc(mem_ctx, struct ldb_request); @@ -289,11 +289,11 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r if (!objectclasses || !ldb_msg_find_val(objectclasses, &person_val)) { /* Not a 'person', so the rest of this doesn't make - * sense. How we got a unicodePwd this far I don't + * sense. How we got a sambaPassword this far I don't * know... */ ldb_set_errstring(module, talloc_asprintf(mem_ctx, "password_hash_handle: " - "attempted set of unicodePwd on non-'person' object %s rejected", + "attempted set of sambaPassword on non-'person' object %s rejected", ldb_dn_linearize(mem_ctx, dn))); talloc_free(mem_ctx); return LDB_ERR_CONSTRAINT_VIOLAION; @@ -360,7 +360,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r CHECK_RET(ldb_msg_add_empty(modify_msg, "krb5Key", LDB_FLAG_MOD_REPLACE)); /* Yay, we can compute new password hashes from the unicode * password */ - if (unicodePwd) { + if (sambaPassword) { Principal *salt_principal; const char *user_principal_name = ldb_msg_find_string(res->msgs[0], "userPrincipalName", NULL); @@ -368,12 +368,12 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r size_t num_keys; /* compute the new nt and lm hashes */ - if (E_deshash(unicodePwd, local_lmNewHash.hash)) { + if (E_deshash(sambaPassword, local_lmNewHash.hash)) { lmPwdHash = &local_lmNewHash; } else { lmPwdHash = NULL; } - E_md4hash(unicodePwd, local_ntNewHash.hash); + E_md4hash(sambaPassword, local_ntNewHash.hash); ntPwdHash = &local_ntNewHash; CHECK_RET(ldb_msg_add_empty(modify_msg, "ntPwdHash", LDB_FLAG_MOD_REPLACE)); @@ -449,7 +449,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r /* TODO: We may wish to control the encryption types chosen in future */ krb5_ret = hdb_generate_key_set_password(smb_krb5_context->krb5_context, - salt_principal, unicodePwd, &keys, &num_keys); + salt_principal, sambaPassword, &keys, &num_keys); krb5_free_principal(smb_krb5_context->krb5_context, salt_principal); if (krb5_ret) { @@ -499,14 +499,14 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } /* Possibly kill off the cleartext or store it */ - CHECK_RET(ldb_msg_add_empty(modify_msg, "unicodePwd", LDB_FLAG_MOD_REPLACE)); + CHECK_RET(ldb_msg_add_empty(modify_msg, "sambaPassword", LDB_FLAG_MOD_REPLACE)); - if (unicodePwd && (pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT) && + if (sambaPassword && (pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT) && (userAccountControl & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { - CHECK_RET(ldb_msg_add_string(modify_msg, "unicodePwd", unicodePwd)); + CHECK_RET(ldb_msg_add_string(modify_msg, "sambaPassword", sambaPassword)); } - /* Even if we didn't get a unicodePwd, we can still setup + /* Even if we didn't get a sambaPassword, we can still setup * krb5Key from the NT hash. * * This is an append, so it works with the 'continue' in the @@ -663,7 +663,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r return ret; } -/* add_record: do things with the unicodePwd attribute */ +/* add_record: do things with the sambaPassword attribute */ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) { const struct ldb_message *msg = req->op.add.message; @@ -677,7 +677,7 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) return password_hash_handle(module, req, msg); } -/* modify_record: do things with the unicodePwd attribute */ +/* modify_record: do things with the sambaPassword attribute */ static int password_hash_modify(struct ldb_module *module, struct ldb_request *req) { const struct ldb_message *msg = req->op.mod.message; -- cgit From ff90c1c5c3b291d3d7ed5027743e1227df7a96d1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 5 Jan 2006 09:03:13 +0000 Subject: r12720: By metze's request, rename the ntPwdHistory attribute to sambaNTPassword. Likewise lmPwdHistory -> sambaLMPwdHistory. The idea here is to avoid having conflicting formats when we get to replication. We know the base data matches, but we may need to use a module to munge formats. Andrew Bartlett (This used to be commit 8e608dd4bf4f108e02274a9977ced04a0a270570) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 64 +++++++++++++------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 80017548d2..e0fc50f242 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -72,12 +72,12 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r uint_t userAccountControl; const char *dnsDomain, *realm; const char *sambaPassword; - struct samr_Password *lmPwdHistory, *ntPwdHistory; + struct samr_Password *sambaLMPwdHistory, *sambaNTPwdHistory; struct samr_Password *lmPwdHash, *ntPwdHash; struct samr_Password *lmOldHash = NULL, *ntOldHash = NULL; - struct samr_Password *new_lmPwdHistory, *new_ntPwdHistory; + struct samr_Password *new_sambaLMPwdHistory, *new_sambaNTPwdHistory; struct samr_Password local_lmNewHash, local_ntNewHash; - int lmPwdHistory_len, ntPwdHistory_len; + int sambaLMPwdHistory_len, sambaNTPwdHistory_len; uint_t kvno; struct dom_sid *domain_sid; time_t now = time(NULL); @@ -105,8 +105,8 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r const char *domain_expression; const char *old_user_attrs[] = { "lmPwdHash", "ntPwdHash", NULL }; - const char *user_attrs[] = { "userAccountControl", "lmPwdHistory", - "ntPwdHistory", + const char *user_attrs[] = { "userAccountControl", "sambaLMPwdHistory", + "sambaNTPwdHistory", "ntPwdHash", "objectSid", "msDS-KeyVersionNumber", "objectClass", "userPrincipalName", @@ -274,10 +274,10 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } userAccountControl = samdb_result_uint(res->msgs[0], "userAccountControl", 0); - lmPwdHistory_len = samdb_result_hashes(mem_ctx, res->msgs[0], - "lmPwdHistory", &lmPwdHistory); - ntPwdHistory_len = samdb_result_hashes(mem_ctx, res->msgs[0], - "ntPwdHistory", &ntPwdHistory); + sambaLMPwdHistory_len = samdb_result_hashes(mem_ctx, res->msgs[0], + "sambaLMPwdHistory", &sambaLMPwdHistory); + sambaNTPwdHistory_len = samdb_result_hashes(mem_ctx, res->msgs[0], + "sambaNTPwdHistory", &sambaNTPwdHistory); ntPwdHash = samdb_result_hash(mem_ctx, res->msgs[0], "ntPwdHash"); kvno = samdb_result_uint(res->msgs[0], "msDS-KeyVersionNumber", 0); @@ -588,61 +588,61 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } } - CHECK_RET(ldb_msg_add_empty(modify_msg, "lmPwdHistory", + CHECK_RET(ldb_msg_add_empty(modify_msg, "sambaLMPwdHistory", LDB_FLAG_MOD_REPLACE)); - CHECK_RET(ldb_msg_add_empty(modify_msg, "ntPwdHistory", + CHECK_RET(ldb_msg_add_empty(modify_msg, "sambaNTPwdHistory", LDB_FLAG_MOD_REPLACE)); /* If we have something to put into the history, or an old * history element to expire, update the history */ if (pwdHistoryLength > 0 && - ((ntPwdHistory_len > 0) || (lmPwdHistory_len > 0) + ((sambaNTPwdHistory_len > 0) || (sambaLMPwdHistory_len > 0) || lmOldHash || ntOldHash)) { /* store the password history */ - new_lmPwdHistory = talloc_array(mem_ctx, struct samr_Password, + new_sambaLMPwdHistory = talloc_array(mem_ctx, struct samr_Password, pwdHistoryLength); - if (!new_lmPwdHistory) { + if (!new_sambaLMPwdHistory) { return LDB_ERR_OPERATIONS_ERROR; } - new_ntPwdHistory = talloc_array(mem_ctx, struct samr_Password, + new_sambaNTPwdHistory = talloc_array(mem_ctx, struct samr_Password, pwdHistoryLength); - if (!new_ntPwdHistory) { + if (!new_sambaNTPwdHistory) { return LDB_ERR_OPERATIONS_ERROR; } - for (i=0;ildb, mem_ctx, modify_msg, - "lmPwdHistory", - new_lmPwdHistory, - lmPwdHistory_len)); + "sambaLMPwdHistory", + new_sambaLMPwdHistory, + sambaLMPwdHistory_len)); CHECK_RET(samdb_msg_add_hashes(module->ldb, mem_ctx, modify_msg, - "ntPwdHistory", - new_ntPwdHistory, - ntPwdHistory_len)); + "sambaNTPwdHistory", + new_sambaNTPwdHistory, + sambaNTPwdHistory_len)); } /* Too much code above, we should check we got it close to reasonable */ -- cgit From c908d0b2aa111659e57a73efb8c33c413965c846 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 6 Jan 2006 04:01:23 +0000 Subject: r12733: Merge ldap/ldb controls into main tree There's still lot of work to do but the patch is stable enough to be pushed into the main samba4 tree. Simo. (This used to be commit 77125feaff252cab44d26593093a9c211c846ce8) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index e0fc50f242..82e4639a23 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -147,6 +147,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r search_request->op.search.scope = LDB_SCOPE_BASE; search_request->op.search.tree = ldb_parse_tree(module->ldb, NULL); search_request->op.search.attrs = old_user_attrs; + search_request->controls = NULL; old_ret = ldb_next_request(module, search_request); } @@ -253,6 +254,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r search_request->op.search.scope = LDB_SCOPE_BASE; search_request->op.search.tree = ldb_parse_tree(module->ldb, NULL); search_request->op.search.attrs = user_attrs; + search_request->controls = NULL; ret = ldb_next_request(module, search_request); if (ret) { @@ -656,6 +658,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r modify_request->operation = LDB_REQ_MODIFY; modify_request->op.mod.message = modify_msg; + modify_request->controls = NULL; ret = ldb_next_request(module, modify_request); @@ -714,10 +717,12 @@ static const struct ldb_module_ops password_hash_ops = { /* the init function */ -struct ldb_module *password_hash_module_init(struct ldb_context *ldb, const char *options[]) +struct ldb_module *password_hash_module_init(struct ldb_context *ldb, int stage, const char *options[]) { struct ldb_module *ctx; + if (stage != LDB_MODULES_INIT_STAGE_1) return NULL; + ctx = talloc(ldb, struct ldb_module); if (!ctx) return NULL; -- cgit From dbef4d76de92c3388f4e1819a76d6febf90be290 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 6 Jan 2006 16:12:45 +0000 Subject: r12743: Remove the ugly way we had to make a second stage init and introduce a second_stage_init private function for modules that need a second stage init. Simo. (This used to be commit 5e8b365fa2d93801a5de1d9ea76ce9d5546bd248) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 82e4639a23..2b979857d9 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -717,12 +717,10 @@ static const struct ldb_module_ops password_hash_ops = { /* the init function */ -struct ldb_module *password_hash_module_init(struct ldb_context *ldb, int stage, const char *options[]) +struct ldb_module *password_hash_module_init(struct ldb_context *ldb, const char *options[]) { struct ldb_module *ctx; - if (stage != LDB_MODULES_INIT_STAGE_1) return NULL; - ctx = talloc(ldb, struct ldb_module); if (!ctx) return NULL; -- cgit From 0b3deb20defaedb0570c17ec8b28e5d11979cb35 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 11 Jan 2006 18:14:55 +0000 Subject: r12851: Fix some typos (This used to be commit 61ae77beecd573809d917dd86d1fac6cc40e967d) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 2b979857d9..e52d4e6563 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -170,7 +170,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r talloc_asprintf(mem_ctx, "sambaPassword_handle: " "attempted set of multiple sambaPassword attributes on %s rejected", ldb_dn_linearize(mem_ctx, dn))); - return LDB_ERR_CONSTRAINT_VIOLAION; + return LDB_ERR_CONSTRAINT_VIOLATION; } sambaPassword = (const char *)attribute->values[0].data; @@ -178,7 +178,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } else if (((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_ADD) || ((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE)) { if (attribute->num_values != 1) { - return LDB_ERR_CONSTRAINT_VIOLAION; + return LDB_ERR_CONSTRAINT_VIOLATION; } sambaPassword = (const char *)attribute->values[0].data; @@ -298,7 +298,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r "attempted set of sambaPassword on non-'person' object %s rejected", ldb_dn_linearize(mem_ctx, dn))); talloc_free(mem_ctx); - return LDB_ERR_CONSTRAINT_VIOLAION; + return LDB_ERR_CONSTRAINT_VIOLATION; } computer_val = data_blob_string_const("computer"); -- cgit From 87625070becd33af5064204645d091fb178331f4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 13 Jan 2006 04:49:49 +0000 Subject: r12895: Error strings save lives. err, they save time at least. The correct use of an error string in this case quickly pinpoited an overzealous check, and saved me hours of painful debugging. Andrew Bartlett (This used to be commit 26946c90e87a94453a5ad3e9e26ef19b36656237) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index e52d4e6563..6e55816d72 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -71,7 +71,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r uint_t pwdProperties, pwdHistoryLength; uint_t userAccountControl; const char *dnsDomain, *realm; - const char *sambaPassword; + const char *sambaPassword = NULL; struct samr_Password *sambaLMPwdHistory, *sambaNTPwdHistory; struct samr_Password *lmPwdHash, *ntPwdHash; struct samr_Password *lmOldHash = NULL, *ntOldHash = NULL; @@ -165,26 +165,32 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r * the second modify. We might not want it written to disk */ if (req->operation == LDB_REQ_ADD) { - if (attribute->num_values != 1) { + if (attribute->num_values > 1) { ldb_set_errstring(module, talloc_asprintf(mem_ctx, "sambaPassword_handle: " "attempted set of multiple sambaPassword attributes on %s rejected", ldb_dn_linearize(mem_ctx, dn))); return LDB_ERR_CONSTRAINT_VIOLATION; } - - sambaPassword = (const char *)attribute->values[0].data; - ldb_msg_remove_attr(msg2, "sambaPassword"); + + if (attribute->num_values == 1) { + sambaPassword = (const char *)attribute->values[0].data; + ldb_msg_remove_attr(msg2, "sambaPassword"); + } } else if (((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_ADD) || ((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE)) { - if (attribute->num_values != 1) { + if (attribute->num_values > 1) { + ldb_set_errstring(module, + talloc_asprintf(mem_ctx, "sambaPassword_handle: " + "attempted set of multiple sambaPassword attributes on %s rejected", + ldb_dn_linearize(mem_ctx, dn))); return LDB_ERR_CONSTRAINT_VIOLATION; } - sambaPassword = (const char *)attribute->values[0].data; - ldb_msg_remove_attr(msg2, "sambaPassword"); - } else { - sambaPassword = NULL; + if (attribute->num_values == 1) { + sambaPassword = (const char *)attribute->values[0].data; + ldb_msg_remove_attr(msg2, "sambaPassword"); + } } modified_orig_request = talloc(mem_ctx, struct ldb_request); -- cgit From f9316daa4697bea13d2795c95a1486119de56e67 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 31 Jan 2006 10:03:44 +0000 Subject: r13256: Free temporary memory on error cases, and try to clean up what's left earlier. Move gendb_search() to use talloc_vasprintf() and steal only the parts actually being used for the results. Andrew Bartlett (This used to be commit 53efb3e3e980c768e0aee216ccd8dc3e14707246) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 6e55816d72..630edf1c7a 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -157,6 +157,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r /* look again, this time at the copied attribute */ if (!msg2 || (attribute = ldb_msg_find_element(msg2, "sambaPassword")) == NULL ) { + talloc_free(mem_ctx); /* Gah? where did it go? Oh well... */ return LDB_ERR_OPERATIONS_ERROR; } @@ -170,6 +171,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r talloc_asprintf(mem_ctx, "sambaPassword_handle: " "attempted set of multiple sambaPassword attributes on %s rejected", ldb_dn_linearize(mem_ctx, dn))); + talloc_free(mem_ctx); return LDB_ERR_CONSTRAINT_VIOLATION; } @@ -184,6 +186,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r talloc_asprintf(mem_ctx, "sambaPassword_handle: " "attempted set of multiple sambaPassword attributes on %s rejected", ldb_dn_linearize(mem_ctx, dn))); + talloc_free(mem_ctx); return LDB_ERR_CONSTRAINT_VIOLATION; } @@ -212,6 +215,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r /* Send the (modified) request of the original caller down to the database */ ret = ldb_next_request(module, modified_orig_request); if (ret) { + talloc_free(mem_ctx); return ret; } @@ -226,6 +230,8 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r /* Find out the old passwords details of the user */ old_res = search_request->op.search.res; + talloc_steal(mem_ctx, old_res); + talloc_free(search_request); if (old_res->count != 1) { ldb_set_errstring(module, @@ -270,6 +276,9 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r /* Find out the full details of the user */ res = search_request->op.search.res; + talloc_steal(mem_ctx, res); + talloc_free(search_request); + if (res->count != 1) { ldb_set_errstring(module, talloc_asprintf(mem_ctx, "password_hash_handle: " -- cgit From d590dea10b3abf93fcc8138189291e8b66bae7d7 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 22 Feb 2006 05:21:43 +0000 Subject: r13615: Make ldb_set_errstring get ldb instead of module as parameter. The module was just used to get to the ldb so it was meningless. Also add LDB_WAIT_ONCE e relative code in ldb_ildap.c (This used to be commit d5b467b7c132b0bd4d23918ba7bf3370b1afcce8) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 630edf1c7a..e28c85ae37 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -167,7 +167,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r if (req->operation == LDB_REQ_ADD) { if (attribute->num_values > 1) { - ldb_set_errstring(module, + ldb_set_errstring(module->ldb, talloc_asprintf(mem_ctx, "sambaPassword_handle: " "attempted set of multiple sambaPassword attributes on %s rejected", ldb_dn_linearize(mem_ctx, dn))); @@ -182,7 +182,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } else if (((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_ADD) || ((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE)) { if (attribute->num_values > 1) { - ldb_set_errstring(module, + ldb_set_errstring(module->ldb, talloc_asprintf(mem_ctx, "sambaPassword_handle: " "attempted set of multiple sambaPassword attributes on %s rejected", ldb_dn_linearize(mem_ctx, dn))); @@ -234,7 +234,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r talloc_free(search_request); if (old_res->count != 1) { - ldb_set_errstring(module, + ldb_set_errstring(module->ldb, talloc_asprintf(mem_ctx, "password_hash_handle: " "(pre) search for %s found %d != 1 objects, for entry we just modified", ldb_dn_linearize(mem_ctx, dn), @@ -280,7 +280,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r talloc_free(search_request); if (res->count != 1) { - ldb_set_errstring(module, + ldb_set_errstring(module->ldb, talloc_asprintf(mem_ctx, "password_hash_handle: " "search for %s found %d != 1 objects, for entry we just added/modified", ldb_dn_linearize(mem_ctx, dn), @@ -308,7 +308,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r /* Not a 'person', so the rest of this doesn't make * sense. How we got a sambaPassword this far I don't * know... */ - ldb_set_errstring(module, + ldb_set_errstring(module->ldb, talloc_asprintf(mem_ctx, "password_hash_handle: " "attempted set of sambaPassword on non-'person' object %s rejected", ldb_dn_linearize(mem_ctx, dn))); @@ -338,7 +338,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r if (dom_res->count != 1) { /* What happend? The user we are modifying must be odd... */ - ldb_set_errstring(module, + ldb_set_errstring(module->ldb, talloc_asprintf(mem_ctx, "password_hash_handle: " "search for domain %s found %d != 1 objects", dom_sid_string(mem_ctx, domain_sid), @@ -414,7 +414,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r char *samAccountName = talloc_strdup(mem_ctx, ldb_msg_find_string(res->msgs[0], "samAccountName", NULL)); char *saltbody; if (!samAccountName) { - ldb_set_errstring(module, + ldb_set_errstring(module->ldb, talloc_asprintf(mem_ctx, "password_hash_handle: " "generation of new kerberos keys failed: %s is a computer without a samAccountName", ldb_dn_linearize(mem_ctx, dn))); @@ -443,7 +443,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } else { const char *samAccountName = ldb_msg_find_string(res->msgs[0], "samAccountName", NULL); if (!samAccountName) { - ldb_set_errstring(module, + ldb_set_errstring(module->ldb, talloc_asprintf(mem_ctx, "password_hash_handle: " "generation of new kerberos keys failed: %s has no samAccountName", ldb_dn_linearize(mem_ctx, dn))); @@ -455,7 +455,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r if (krb5_ret) { - ldb_set_errstring(module, + ldb_set_errstring(module->ldb, talloc_asprintf(mem_ctx, "password_hash_handle: " "generation of a saltking principal failed: %s", smb_get_krb5_error_message(smb_krb5_context->krb5_context, @@ -470,7 +470,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r krb5_free_principal(smb_krb5_context->krb5_context, salt_principal); if (krb5_ret) { - ldb_set_errstring(module, + ldb_set_errstring(module->ldb, talloc_asprintf(mem_ctx, "password_hash_handle: " "generation of new kerberos keys failed: %s", smb_get_krb5_error_message(smb_krb5_context->krb5_context, -- cgit From 26af14c39b88b0e7eb53657b89be65d865804688 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 2 Mar 2006 16:32:53 +0000 Subject: r13786: [merge] Add registration functions for LDB modules Applications that use LDB modules will now have to run ldb_global_init() before they can use LDB. The next step will be adding support for loading LDB modules from .so files. This will also allow us to use one LDB without difference between the standalone and the Samba-specific build (This used to be commit 52a235650514039bf8ffee99a784bbc1b6ae6b92) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index e28c85ae37..414f79ea10 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -731,19 +731,7 @@ static const struct ldb_module_ops password_hash_ops = { }; -/* the init function */ -struct ldb_module *password_hash_module_init(struct ldb_context *ldb, const char *options[]) +int password_hash_module_init(void) { - struct ldb_module *ctx; - - ctx = talloc(ldb, struct ldb_module); - if (!ctx) - return NULL; - - ctx->private_data = NULL; - ctx->ldb = ldb; - ctx->prev = ctx->next = NULL; - ctx->ops = &password_hash_ops; - - return ctx; + return ldb_register_module(&password_hash_ops); } -- cgit From 6a73835b0946a015d1bad0b502c35d92777d2446 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 7 Mar 2006 03:30:59 +0000 Subject: r13909: Make this code clearer. Andrew Bartlett (This used to be commit b89893ab90b50d6b04a6407441fe3e0e4f1688ec) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 414f79ea10..0530c63774 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -561,7 +561,8 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } /* If the original caller did anything with pwdLastSet then skip this. It could be an incoming samsync */ - if ((attribute = ldb_msg_find_element(msg, "pwdLastSet")) == NULL ) { + attribute = ldb_msg_find_element(msg, "pwdLastSet"); + if (attribute == NULL) { /* Update the password last set time */ unix_to_nt_time(&now_nt, now); CHECK_RET(ldb_msg_add_empty(modify_msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE)); @@ -569,7 +570,8 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } /* If the original caller did anything with "msDS-KeyVersionNumber" then skip this. It could be an incoming samsync */ - if ((attribute = ldb_msg_find_element(msg, "msDS-KeyVersionNumber")) == NULL ) { + attribute = ldb_msg_find_element(msg, "msDS-KeyVersionNumber"); + if (attribute == NULL) { if (kvno == 0) { CHECK_RET(ldb_msg_add_empty(modify_msg, "msDS-KeyVersionNumber", LDB_FLAG_MOD_REPLACE)); -- cgit From 4ac2be99588b48b0652a524bf12fb1aa9c3f5fbb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 7 Mar 2006 11:07:23 +0000 Subject: r13924: Split more prototypes out of include/proto.h + initial work on header file dependencies (This used to be commit 122835876748a3eaf5e8d31ad1abddab9acb8781) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 0530c63774..2abf060a0f 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -36,6 +36,7 @@ #include "ldb/include/ldb_private.h" #include "librpc/gen_ndr/ndr_misc.h" #include "librpc/gen_ndr/ndr_samr.h" +#include "libcli/auth/proto.h" #include "system/kerberos.h" #include "auth/kerberos/kerberos.h" #include "system/time.h" -- cgit From 964373b25d3dc015951fb00d9c8c68632890a55e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Mar 2006 05:00:45 +0000 Subject: r14293: fixed some errors found with beam (This used to be commit 230636a00ed9bd968356badad596ba7f93ba6c85) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 2abf060a0f..6980fe48b8 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -496,6 +496,9 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r continue; } ASN1_MALLOC_ENCODE(Key, buf, buf_size, &keys[i], &len, krb5_ret); + if (krb5_ret) { + return LDB_ERR_OPERATIONS_ERROR; + } val.data = talloc_memdup(req, buf, len); val.length = len; @@ -549,6 +552,9 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r return LDB_ERR_OPERATIONS_ERROR; } ASN1_MALLOC_ENCODE(Key, buf, buf_size, &key, &len, krb5_ret); + if (krb5_ret) { + return LDB_ERR_OPERATIONS_ERROR; + } krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &key.key); -- cgit From 54b33de0fc93bc068fcd04ac12eb2e71b14eefa7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 13 Mar 2006 11:12:46 +0000 Subject: r14312: Formatting and comments. Andrew Bartlett (This used to be commit 1905a27c78165972aaa78b72a199ee9230fbf73d) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 6980fe48b8..bdbbafd955 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -376,6 +376,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r * or replace with a new one). Both the unicode and NT hash * only branches append keys to this multivalued entry. */ CHECK_RET(ldb_msg_add_empty(modify_msg, "krb5Key", LDB_FLAG_MOD_REPLACE)); + /* Yay, we can compute new password hashes from the unicode * password */ if (sambaPassword) { @@ -467,7 +468,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r /* TODO: We may wish to control the encryption types chosen in future */ krb5_ret = hdb_generate_key_set_password(smb_krb5_context->krb5_context, - salt_principal, sambaPassword, &keys, &num_keys); + salt_principal, sambaPassword, &keys, &num_keys); krb5_free_principal(smb_krb5_context->krb5_context, salt_principal); if (krb5_ret) { @@ -480,7 +481,8 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r return LDB_ERR_OPERATIONS_ERROR; } - /* Walking + /* Walking all the key types generated, transform each + * key into an ASN.1 blob */ for (i=0; i < num_keys; i++) { unsigned char *buf; @@ -651,8 +653,8 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } sambaLMPwdHistory_len = MIN(sambaLMPwdHistory_len + 1, pwdHistoryLength); - /* Likewise, we might not have a new NT password (lm - * only password change function) */ + /* Likewise, we might not have an old NT password (lm + * only password change function on previous change) */ if (ntOldHash) { new_sambaNTPwdHistory[0] = *ntOldHash; } else { -- cgit From 3f16241a1d3243447d0244ebac05b447aec94df8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 14 Mar 2006 01:29:56 +0000 Subject: r14363: Remove credentials.h from the global includes. (This used to be commit 98c4c3051391c6f89df5d133665f51bef66b1563) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index bdbbafd955..6943a5f356 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -36,6 +36,7 @@ #include "ldb/include/ldb_private.h" #include "librpc/gen_ndr/ndr_misc.h" #include "librpc/gen_ndr/ndr_samr.h" +#include "auth/credentials/credentials.h" #include "libcli/auth/proto.h" #include "system/kerberos.h" #include "auth/kerberos/kerberos.h" -- cgit From e3f2414cf9e582a4e4deecc662b64a7bb2679a34 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 14 Mar 2006 15:03:25 +0000 Subject: r14380: Reduce the size of structs.h (This used to be commit 1a16a6f1dfa66499af43a6b88b3ea69a6a75f1fe) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 6943a5f356..32d226b2b7 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -36,8 +36,7 @@ #include "ldb/include/ldb_private.h" #include "librpc/gen_ndr/ndr_misc.h" #include "librpc/gen_ndr/ndr_samr.h" -#include "auth/credentials/credentials.h" -#include "libcli/auth/proto.h" +#include "libcli/auth/libcli_auth.h" #include "system/kerberos.h" #include "auth/kerberos/kerberos.h" #include "system/time.h" -- cgit From 8528016978b084213ef53d66e1b6e831b1a01acc Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 16 Mar 2006 00:23:11 +0000 Subject: r14464: Don't include ndr_BASENAME.h files unless strictly required, instead try to include just the BASENAME.h files (containing only structs) (This used to be commit 3dd477ca5147f28a962b8437e2611a8222d706bd) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 32d226b2b7..047cb97b35 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -34,8 +34,9 @@ #include "libcli/ldap/ldap.h" #include "ldb/include/ldb_errors.h" #include "ldb/include/ldb_private.h" -#include "librpc/gen_ndr/ndr_misc.h" -#include "librpc/gen_ndr/ndr_samr.h" +#include "librpc/gen_ndr/misc.h" +#include "librpc/gen_ndr/samr.h" +#include "librpc/gen_ndr/ndr_security.h" #include "libcli/auth/libcli_auth.h" #include "system/kerberos.h" #include "auth/kerberos/kerberos.h" -- cgit From 7de4a5b135daddcbbe21ca11419491dac7c88c6c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Mar 2006 21:49:38 +0000 Subject: r14662: To allow the RPC-SAMR test to pass, we need to look for both domains and the builtinDomain objectClasses, when trying to find domain policies. Andrew Bartlett (This used to be commit 9fc1196f0ca0235aa764d4ae770e3c31978396fa) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 047cb97b35..8a5f94042a 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -326,7 +326,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r is_computer = False; } - domain_expression = talloc_asprintf(mem_ctx, "(&(objectSid=%s)(objectClass=domain))", + domain_expression = talloc_asprintf(mem_ctx, "(&(objectSid=%s)(|(objectClass=domain)(objectClass=builtinDomain)))", ldap_encode_ndr_dom_sid(mem_ctx, domain_sid)); /* Find the user's domain, then find out the domain password -- cgit From e002300f238dd0937dd9f768e366c006945e8baa Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 29 Apr 2006 17:34:49 +0000 Subject: r15328: Move some functions around, remove dependencies. Remove some autogenerated headers (which had prototypes now autogenerated by pidl) Remove ndr_security.h from a few places - it's no longer necessary (This used to be commit c19c2b51d3e1ad347120b06a22bda5ec586c22e8) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 8a5f94042a..0310fbf9e3 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -36,8 +36,8 @@ #include "ldb/include/ldb_private.h" #include "librpc/gen_ndr/misc.h" #include "librpc/gen_ndr/samr.h" -#include "librpc/gen_ndr/ndr_security.h" #include "libcli/auth/libcli_auth.h" +#include "libcli/security/security.h" #include "system/kerberos.h" #include "auth/kerberos/kerberos.h" #include "system/time.h" -- cgit From c07db9b462da739387b390bffe7adcf30fa2c11e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 8 May 2006 09:24:07 +0000 Subject: r15511: Using this name causes less warnings on the IBM checker, due to using the original, rather than equivilant, enum type. Andrew Bartlett (This used to be commit 3d43e458a828801a294e56a1aeb74a4d7cbf9f23) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 0310fbf9e3..46bafeefc2 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -491,7 +491,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r size_t len; struct ldb_val val; - if (keys[i].key.keytype == ENCTYPE_ARCFOUR_HMAC) { + if (keys[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { /* We might end up doing this below: * This ensures we get the unicode * conversion right. This should also @@ -548,9 +548,9 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r key.salt = NULL; /* No salt for this enc type */ krb5_ret = krb5_keyblock_init(smb_krb5_context->krb5_context, - ENCTYPE_ARCFOUR_HMAC, - ntPwdHash->hash, sizeof(ntPwdHash->hash), - &key.key); + ETYPE_ARCFOUR_HMAC_MD5, + ntPwdHash->hash, sizeof(ntPwdHash->hash), + &key.key); if (krb5_ret) { return LDB_ERR_OPERATIONS_ERROR; } -- cgit From 1fdd6a6e68359bccc4998e416cb2395ac8e6eaca Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 19 May 2006 21:12:26 +0000 Subject: r15725: First shot at making password_hash async The async path is not yet enabled by default so it should make no harm (This used to be commit b7d5f2325726757a4fcd0b5ac03de1b867085a89) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 1087 +++++++++++++++++++++++- 1 file changed, 1076 insertions(+), 11 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 46bafeefc2..b7f4aff67a 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -121,13 +121,6 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r /* Do the original action */ - /* If no part of this touches the sambaPassword, then we don't - * need to make any changes. For password changes/set there should - * be a 'delete' or a 'modify' on this attribute. */ - if ((attribute = ldb_msg_find_element(msg, "sambaPassword")) == NULL ) { - return ldb_next_request(module, req); - } - mem_ctx = talloc_new(module); if (!mem_ctx) { return LDB_ERR_OPERATIONS_ERROR; @@ -326,7 +319,7 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r is_computer = False; } - domain_expression = talloc_asprintf(mem_ctx, "(&(objectSid=%s)(|(objectClass=domain)(objectClass=builtinDomain)))", + domain_expression = talloc_asprintf(mem_ctx, "(&(objectSid=%s)(objectClass=domain))", ldap_encode_ndr_dom_sid(mem_ctx, domain_sid)); /* Find the user's domain, then find out the domain password @@ -663,12 +656,12 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r } sambaNTPwdHistory_len = MIN(sambaNTPwdHistory_len + 1, pwdHistoryLength); - CHECK_RET(samdb_msg_add_hashes(module->ldb, mem_ctx, modify_msg, + CHECK_RET(samdb_msg_add_hashes(mem_ctx, modify_msg, "sambaLMPwdHistory", new_sambaLMPwdHistory, sambaLMPwdHistory_len)); - CHECK_RET(samdb_msg_add_hashes(module->ldb, mem_ctx, modify_msg, + CHECK_RET(samdb_msg_add_hashes(mem_ctx, modify_msg, "sambaNTPwdHistory", new_sambaNTPwdHistory, sambaNTPwdHistory_len)); @@ -704,6 +697,13 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } + /* If no part of this touches the sambaPassword, then we don't + * need to make any changes. For password changes/set there should + * be a 'delete' or a 'modify' on this attribute. */ + if (ldb_msg_find_element(msg, "sambaPassword") == NULL ) { + return ldb_next_request(module, req); + } + return password_hash_handle(module, req, msg); } @@ -718,9 +718,1067 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r return ldb_next_request(module, req); } + /* If no part of this touches the sambaPassword, then we don't + * need to make any changes. For password changes/set there should + * be a 'delete' or a 'modify' on this attribute. */ + if (ldb_msg_find_element(msg, "sambaPassword") == NULL ) { + return ldb_next_request(module, req); + } + return password_hash_handle(module, req, msg); } +enum ph_type {PH_ADD, PH_MOD}; +enum ph_step {PH_ADD_SEARCH_DOM, PH_ADD_DO_ADD, PH_MOD_DO_REQ, PH_MOD_SEARCH_SELF, PH_MOD_SEARCH_DOM, PH_MOD_DO_MOD}; + +struct ph_async_context { + + enum ph_type type; + enum ph_step step; + + struct ldb_module *module; + struct ldb_request *orig_req; + + struct ldb_request *dom_req; + struct ldb_async_result *dom_res; + + struct ldb_request *down_req; + + struct ldb_request *search_req; + struct ldb_async_result *search_res; + + struct ldb_request *mod_req; +}; + +struct domain_data { + uint_t pwdProperties; + uint_t pwdHistoryLength; + char *dnsDomain; + char *realm; +}; + +static int add_password_hashes(struct ldb_module *module, struct ldb_message *msg, int is_mod) +{ + const char *sambaPassword; + struct samr_Password tmp_hash; + + sambaPassword = ldb_msg_find_string(msg, "sambaPassword", NULL); + if (sambaPassword == NULL) { /* impossible, what happened ?! */ + return LDB_ERR_OPERATIONS_ERROR; + } + + /* compute the new nt and lm hashes */ + if (is_mod) { + if (ldb_msg_add_empty(msg, "ntPwdHash", LDB_FLAG_MOD_REPLACE) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + E_md4hash(sambaPassword, tmp_hash.hash); + if (samdb_msg_add_hash(module->ldb, msg, msg, "ntPwdHash", &tmp_hash) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (E_deshash(sambaPassword, tmp_hash.hash)) { + if (is_mod) { + if (ldb_msg_add_empty(msg, "lmPwdHash", LDB_FLAG_MOD_REPLACE) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + if (samdb_msg_add_hash(module->ldb, msg, msg, "lmPwdHash", &tmp_hash) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + return LDB_SUCCESS; +} + +static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_message *msg, + struct smb_krb5_context *smb_krb5_context, + struct domain_data *domain, + const char *samAccountName, + const char *user_principal_name, + int is_computer) +{ + const char *sambaPassword; + Principal *salt_principal; + krb5_error_code krb5_ret; + size_t num_keys; + Key *keys; + int i; + + /* Many, many thanks to lukeh@padl.com for this + * algorithm, described in his Nov 10 2004 mail to + * samba-technical@samba.org */ + + sambaPassword = ldb_msg_find_string(msg, "sambaPassword", NULL); + if (sambaPassword == NULL) { /* impossible, what happened ?! */ + return LDB_ERR_OPERATIONS_ERROR; + } + + if (is_computer) { + /* Determine a salting principal */ + char *name = talloc_strdup(msg, samAccountName); + char *saltbody; + if (name == NULL) { + ldb_set_errstring(module->ldb, + talloc_asprintf(msg, "password_hash_handle: " + "generation of new kerberos keys failed: %s is a computer without a samAccountName", + ldb_dn_linearize(msg, msg->dn))); + return LDB_ERR_OPERATIONS_ERROR; + } + if (name[strlen(name)-1] == '$') { + name[strlen(name)-1] = '\0'; + } + saltbody = talloc_asprintf(msg, "%s.%s", name, domain->dnsDomain); + + krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, + &salt_principal, + domain->realm, "host", + saltbody, NULL); + } else if (user_principal_name) { + char *p; + user_principal_name = talloc_strdup(msg, user_principal_name); + if (user_principal_name == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } else { + p = strchr(user_principal_name, '@'); + if (p) { + p[0] = '\0'; + } + krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, + &salt_principal, + domain->realm, user_principal_name, NULL); + } + } else { + if (!samAccountName) { + ldb_set_errstring(module->ldb, + talloc_asprintf(msg, "password_hash_handle: " + "generation of new kerberos keys failed: %s has no samAccountName", + ldb_dn_linearize(msg, msg->dn))); + return LDB_ERR_OPERATIONS_ERROR; + } + krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, + &salt_principal, + domain->realm, samAccountName, + NULL); + } + + if (krb5_ret) { + ldb_set_errstring(module->ldb, + talloc_asprintf(msg, "password_hash_handle: " + "generation of a saltking principal failed: %s", + smb_get_krb5_error_message(smb_krb5_context->krb5_context, + krb5_ret, msg))); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* TODO: We may wish to control the encryption types chosen in future */ + krb5_ret = hdb_generate_key_set_password(smb_krb5_context->krb5_context, + salt_principal, sambaPassword, &keys, &num_keys); + krb5_free_principal(smb_krb5_context->krb5_context, salt_principal); + + if (krb5_ret) { + ldb_set_errstring(module->ldb, + talloc_asprintf(msg, "password_hash_handle: " + "generation of new kerberos keys failed: %s", + smb_get_krb5_error_message(smb_krb5_context->krb5_context, + krb5_ret, msg))); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Walking all the key types generated, transform each + * key into an ASN.1 blob + */ + for (i=0; i < num_keys; i++) { + unsigned char *buf; + size_t buf_size; + size_t len; + struct ldb_val val; + int ret; + + if (keys[i].key.keytype == ENCTYPE_ARCFOUR_HMAC) { + /* We might end up doing this below: + * This ensures we get the unicode + * conversion right. This should also + * be fixed in the Heimdal libs */ + continue; + } + ASN1_MALLOC_ENCODE(Key, buf, buf_size, &keys[i], &len, krb5_ret); + if (krb5_ret) { + return LDB_ERR_OPERATIONS_ERROR; + } + + val.data = talloc_memdup(msg, buf, len); + val.length = len; + free(buf); + if (!val.data || krb5_ret) { + hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); + return LDB_ERR_OPERATIONS_ERROR; + } + ret = ldb_msg_add_value(msg, "krb5Key", &val); + if (ret != LDB_SUCCESS) { + hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); + return ret; + } + } + + hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); + + return LDB_SUCCESS; +} + +static int add_krb5_keys_from_NThash(struct ldb_module *module, struct ldb_message *msg, + struct smb_krb5_context *smb_krb5_context) +{ + struct samr_Password *ntPwdHash; + krb5_error_code krb5_ret; + unsigned char *buf; + size_t buf_size; + size_t len; + struct ldb_val val; + Key key; + + key.mkvno = 0; + key.salt = NULL; /* No salt for this enc type */ + + ntPwdHash = samdb_result_hash(msg, msg, "ntPwdHash"); + if (ntPwdHash == NULL) { /* what happened ?! */ + return LDB_ERR_OPERATIONS_ERROR; + } + + krb5_ret = krb5_keyblock_init(smb_krb5_context->krb5_context, + ENCTYPE_ARCFOUR_HMAC, + ntPwdHash->hash, sizeof(ntPwdHash->hash), + &key.key); + if (krb5_ret) { + return LDB_ERR_OPERATIONS_ERROR; + } + ASN1_MALLOC_ENCODE(Key, buf, buf_size, &key, &len, krb5_ret); + if (krb5_ret) { + return LDB_ERR_OPERATIONS_ERROR; + } + krb5_free_keyblock_contents(smb_krb5_context->krb5_context, + &key.key); + + val.data = talloc_memdup(msg, buf, len); + val.length = len; + free(buf); + if (!val.data) { + return LDB_ERR_OPERATIONS_ERROR; + } + if (ldb_msg_add_value(msg, "krb5Key", &val) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + +static int set_pwdLastSet(struct ldb_module *module, struct ldb_message *msg) +{ + NTTIME now_nt; + + /* set it as now */ + unix_to_nt_time(&now_nt, time(NULL)); + + /* replace or add */ + if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (samdb_msg_add_uint64(module->ldb, msg, msg, "pwdLastSet", now_nt) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + +static int add_keyVersionNumber(struct ldb_module *module, struct ldb_message *msg, int previous) +{ + /* replace or add */ + if (ldb_msg_add_empty(msg, "msDS-KeyVersionNumber", LDB_FLAG_MOD_REPLACE) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (samdb_msg_add_uint(module->ldb, msg, msg, "msDS-KeyVersionNumber", previous+1) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + +static int setPwdHistory(struct ldb_module *module, struct ldb_message *msg, struct ldb_message *old_msg, int hlen) +{ + struct samr_Password *nt_hash; + struct samr_Password *lm_hash; + struct samr_Password *nt_history; + struct samr_Password *lm_history; + struct samr_Password *new_nt_history; + struct samr_Password *new_lm_history; + int nt_hist_len; + int lm_hist_len; + int i; + + nt_hash = samdb_result_hash(msg, old_msg, "ntPwdHash"); + lm_hash = samdb_result_hash(msg, old_msg, "lmPwdHash"); + + /* if no previous passwords just return */ + if (nt_hash == NULL && lm_hash == NULL) return LDB_SUCCESS; + + nt_hist_len = samdb_result_hashes(msg, old_msg, "sambaNTPwdHistory", &nt_history); + lm_hist_len = samdb_result_hashes(msg, old_msg, "sambaLMPwdHistory", &lm_history); + + /* We might not have an old NT password */ + new_nt_history = talloc_array(msg, struct samr_Password, hlen); + if (new_nt_history == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + for (i = 0; i < MIN(hlen-1, nt_hist_len); i++) { + new_nt_history[i+1] = nt_history[i]; + } + nt_hist_len = i + 1; + if (nt_hash) { + new_nt_history[0] = *nt_hash; + } else { + ZERO_STRUCT(new_nt_history[0]); + } + if (ldb_msg_add_empty(msg, "sambaNTPwdHistory", LDB_FLAG_MOD_REPLACE) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + if (samdb_msg_add_hashes(msg, msg, "sambaNTPwdHistory", new_nt_history, nt_hist_len) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + + /* Don't store 'long' passwords in the LM history, + but make sure to 'expire' one password off the other end */ + new_lm_history = talloc_array(msg, struct samr_Password, hlen); + if (new_lm_history == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + for (i = 0; i < MIN(hlen-1, lm_hist_len); i++) { + new_lm_history[i+1] = lm_history[i]; + } + lm_hist_len = i + 1; + if (lm_hash) { + new_lm_history[0] = *lm_hash; + } else { + ZERO_STRUCT(new_lm_history[0]); + } + if (ldb_msg_add_empty(msg, "sambaLMPwdHistory", LDB_FLAG_MOD_REPLACE) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + if (samdb_msg_add_hashes(msg, msg, "sambaLMPwdHistory", new_lm_history, lm_hist_len) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return LDB_SUCCESS; +} + +static struct ldb_async_handle *ph_init_handle(struct ldb_request *req, struct ldb_module *module, enum ph_type type) +{ + struct ph_async_context *ac; + struct ldb_async_handle *h; + + h = talloc_zero(req, struct ldb_async_handle); + if (h == NULL) { + ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory")); + return NULL; + } + + h->module = module; + + ac = talloc_zero(h, struct ph_async_context); + if (ac == NULL) { + ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory")); + talloc_free(h); + return NULL; + } + + h->private_data = (void *)ac; + + h->state = LDB_ASYNC_INIT; + h->status = LDB_SUCCESS; + + ac->type = type; + ac->module = module; + ac->orig_req = req; + + return h; +} + +static int get_domain_data_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares) +{ + struct ph_async_context *ac; + + if (!context || !ares) { + ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context or Result in callback")); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac = talloc_get_type(context, struct ph_async_context); + + /* we are interested only in the single reply (base search) we receive here */ + if (ares->type == LDB_REPLY_ENTRY) { + if (ac->dom_res != NULL) { + ldb_set_errstring(ldb, talloc_asprintf(ldb, "Too many results")); + talloc_free(ares); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->dom_res = talloc_steal(ac, ares); + } else { + talloc_free(ares); + } + + return LDB_SUCCESS; +} + +static int build_domain_data_request(struct ph_async_context *ac, + struct dom_sid *sid) +{ + const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", "dnsDomain", NULL }; + char *filter; + + ac->dom_req = talloc_zero(ac, struct ldb_request); + if (ac->dom_req == NULL) { + ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n"); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->dom_req->operation = LDB_ASYNC_SEARCH; + ac->dom_req->op.search.base = NULL; + ac->dom_req->op.search.scope = LDB_SCOPE_SUBTREE; + + filter = talloc_asprintf(ac->dom_req, "(&(objectSid=%s)(objectClass=domain))", dom_sid_string(ac->dom_req, sid)); + if (filter == NULL) { + ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n"); + talloc_free(ac->dom_req); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->dom_req->op.search.tree = ldb_parse_tree(ac->module->ldb, filter); + if (ac->dom_req->op.search.tree == NULL) { + ldb_set_errstring(ac->module->ldb, talloc_asprintf(ac, "Invalid search filter")); + talloc_free(ac->dom_req); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->dom_req->op.search.attrs = attrs; + ac->dom_req->controls = NULL; + ac->dom_req->creds = ac->orig_req->creds; + ac->dom_req->async.context = ac; + ac->dom_req->async.callback = get_domain_data_callback; + ac->dom_req->async.timeout = ac->orig_req->async.timeout; + + return LDB_SUCCESS; +} + +static struct domain_data *get_domain_data(struct ldb_module *module, void *mem_ctx, struct ldb_async_result *res) +{ + struct domain_data *data; + const char *tmp; + + data = talloc_zero(mem_ctx, struct domain_data); + if (data == NULL) { + return NULL; + } + + data->pwdProperties = samdb_result_uint(res->message, "pwdProperties", 0); + data->pwdHistoryLength = samdb_result_uint(res->message, "pwdHistoryLength", 0); + tmp = ldb_msg_find_string(res->message, "dnsDomain", NULL); + + if (tmp != NULL) { + data->dnsDomain = talloc_strdup(data, tmp); + if (data->dnsDomain == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n"); + return NULL; + } + data->realm = strupper_talloc(mem_ctx, tmp); + if (data->realm == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n"); + return NULL; + } + } + + return data; +} + +static int password_hash_add_async(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_async_handle *h; + struct ph_async_context *ac; + struct ldb_message_element *attribute; + struct dom_sid *domain_sid; + int ret; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_add_async\n"); + + if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */ + return ldb_next_request(module, req); + } + + /* nobody must touch password Histories */ + if (ldb_msg_find_element(req->op.add.message, "sambaNTPwdHistory") || + ldb_msg_find_element(req->op.add.message, "sambaLMPwdHistory")) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + /* If no part of this touches the sambaPassword, then we don't + * need to make any changes. For password changes/set there should + * be a 'delete' or a 'modify' on this attribute. */ + if ((attribute = ldb_msg_find_element(req->op.add.message, "sambaPassword")) == NULL ) { + return ldb_next_request(module, req); + } + + /* if it is not an entry of type person its an error */ + /* TODO: remove this when sambaPassword will be in schema */ + if (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "person")) { + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + + /* check sambaPassword is single valued here */ + /* TODO: remove this when sambaPassword will be single valued in schema */ + if (attribute->num_values > 1) { + ldb_set_errstring(module->ldb, talloc_asprintf(req, + "mupltiple values for sambaPassword not allowed!\n")); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + /* get user domain data */ + domain_sid = samdb_result_sid_prefix(req, req->op.add.message, "objectSid"); + if (domain_sid == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "can't handle entry with missing objectSid!\n"); + return LDB_ERR_OPERATIONS_ERROR; + } + + h = ph_init_handle(req, module, PH_ADD); + if (!h) { + return LDB_ERR_OPERATIONS_ERROR; + } + ac = talloc_get_type(h->private_data, struct ph_async_context); + + ret = build_domain_data_request(ac, domain_sid); + if (ret != LDB_SUCCESS) { + return ret; + } + + ac->step = PH_ADD_SEARCH_DOM; + + req->async.handle = h; + + return ldb_next_request(module, ac->dom_req); +} + +static int password_hash_add_async_do_add(struct ldb_async_handle *h) { + + struct ph_async_context *ac; + struct domain_data *domain; + struct smb_krb5_context *smb_krb5_context; + struct ldb_message *msg; + + ac = talloc_get_type(h->private_data, struct ph_async_context); + + domain = get_domain_data(ac->module, ac, ac->search_res); + if (domain == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->down_req = talloc(ac, struct ldb_request); + if (ac->down_req == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + *(ac->down_req) = *(ac->orig_req); + ac->down_req->op.add.message = msg = ldb_msg_copy_shallow(ac->down_req, ac->orig_req->op.add.message); + if (ac->down_req->op.add.message == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Some operations below require kerberos contexts */ + if (smb_krb5_init_context(ac->down_req, &smb_krb5_context) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* we can compute new password hashes from the unicode password */ + if (add_password_hashes(ac->module, msg, 0) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* now add krb5 keys based on unicode password */ + if (add_krb5_keys_from_password(ac->module, msg, smb_krb5_context, domain, + ldb_msg_find_string(msg, "samAccountName", NULL), + ldb_msg_find_string(msg, "userPrincipalName", NULL), + ldb_msg_check_string_attribute(msg, "objectClass", "computer") + ) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* add also kr5 keys based on NT the hash */ + if (add_krb5_keys_from_NThash(ac->module, msg, smb_krb5_context) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* if both the domain properties and the user account controls do not permit + * clear text passwords then wipe out the sambaPassword */ + if ((!(domain->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT)) || + (!(ldb_msg_find_uint(msg, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED))) { + ldb_msg_remove_attr(msg, "sambaPassword"); + } + + /* don't touch it if a value is set. It could be an incoming samsync */ + if (ldb_msg_find_uint64(msg, "pwdLastSet", 0) == 0) { + if (set_pwdLastSet(ac->module, msg) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + /* don't touch it if a value is set. It could be an incoming samsync */ + if (!ldb_msg_find_element(msg, "msDS-KeyVersionNumber")) { + if (add_keyVersionNumber(ac->module, msg, 0) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + h->state = LDB_ASYNC_INIT; + h->status = LDB_SUCCESS; + + ac->step = PH_ADD_DO_ADD; + + /* perform the operation */ + return ldb_next_request(ac->module, ac->down_req); +} + +static int password_hash_mod_async_search_self(struct ldb_async_handle *h); + +static int password_hash_modify_async(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_async_handle *h; + struct ph_async_context *ac; + struct ldb_message_element *sambaAttr; + struct ldb_message_element *ntAttr; + struct ldb_message_element *lmAttr; + + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_add_async\n"); + + if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */ + return ldb_next_request(module, req); + } + + /* nobody must touch password Histories */ + if (ldb_msg_find_element(req->op.mod.message, "sambaNTPwdHistory") || + ldb_msg_find_element(req->op.mod.message, "sambaLMPwdHistory")) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + sambaAttr = ldb_msg_find_element(req->op.mod.message, "sambaPassword"); + ntAttr = ldb_msg_find_element(req->op.mod.message, "ntPwdHash"); + lmAttr = ldb_msg_find_element(req->op.mod.message, "lmPwdHash"); + + /* check passwords are single valued here */ + /* TODO: remove this when passwords will be single valued in schema */ + if (sambaAttr && (sambaAttr->num_values > 1)) { + return LDB_ERR_CONSTRAINT_VIOLATION; + } + if (ntAttr && (ntAttr->num_values > 1)) { + return LDB_ERR_CONSTRAINT_VIOLATION; + } + if (lmAttr && (lmAttr->num_values > 1)) { + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + /* If no part of this touches the sambaPassword OR ntPwdHash and/or lmPwdHash, then we don't + * need to make any changes. For password changes/set there should + * be a 'delete' or a 'modify' on this attribute. */ + /* If the only operation is the deletion of the passwords then go on */ + if ( ((!sambaAttr) || ((sambaAttr->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_DELETE)) + && ((!ntAttr) || ((ntAttr->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_DELETE)) + && ((!lmAttr) || ((lmAttr->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_DELETE)) ) { + + return ldb_next_request(module, req); + } + + h = ph_init_handle(req, module, PH_MOD); + if (!h) { + return LDB_ERR_OPERATIONS_ERROR; + } + ac = talloc_get_type(h->private_data, struct ph_async_context); + + /* return or own handle to deal with this call */ + req->async.handle = h; + + /* prepare the first operation */ + ac->down_req = talloc_zero(ac, struct ldb_request); + if (ac->down_req == NULL) { + ldb_set_errstring(module->ldb, talloc_asprintf(module->ldb, "Out of memory!")); + return LDB_ERR_OPERATIONS_ERROR; + } + + *(ac->down_req) = *req; /* copy the request */ + + /* use a new message structure so that we can modify it */ + ac->down_req->op.mod.message = ldb_msg_copy_shallow(ac->down_req, req->op.mod.message); + + /* - remove any imodification to the password from the first commit + * we will make the real modification later */ + if (sambaAttr) ldb_msg_remove_attr(ac->down_req->op.mod.message, "sambaPassword"); + if (ntAttr) ldb_msg_remove_attr(ac->down_req->op.mod.message, "ntPwdHash"); + if (lmAttr) ldb_msg_remove_attr(ac->down_req->op.mod.message, "lmPwdHash"); + + /* if there was nothing else to be modify skip to next step */ + if (ac->down_req->op.mod.message->num_elements == 0) { + talloc_free(ac->down_req); + ac->down_req = NULL; + return password_hash_mod_async_search_self(h); + } + + ac->down_req->async.context = NULL; + ac->down_req->async.callback = NULL; + + ac->step = PH_MOD_DO_REQ; + + return ldb_next_request(module, ac->down_req); +} + +static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares) +{ + struct ph_async_context *ac; + + if (!context || !ares) { + ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context or Result in callback")); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac = talloc_get_type(context, struct ph_async_context); + + /* we are interested only in the single reply (base search) we receive here */ + if (ares->type == LDB_REPLY_ENTRY) { + if (ac->search_res != NULL) { + ldb_set_errstring(ldb, talloc_asprintf(ldb, "Too many results")); + talloc_free(ares); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* if it is not an entry of type person this is an error */ + /* TODO: remove this when sambaPassword will be in schema */ + if (!ldb_msg_check_string_attribute(ares->message, "objectClass", "person")) { + ldb_set_errstring(ldb, talloc_asprintf(ldb, "Object class violation")); + talloc_free(ares); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + + ac->search_res = talloc_steal(ac, ares); + } else { + talloc_free(ares); + } + + return LDB_SUCCESS; +} + +static int password_hash_mod_async_search_self(struct ldb_async_handle *h) { + + struct ph_async_context *ac; + + ac = talloc_get_type(h->private_data, struct ph_async_context); + + /* prepare the search operation */ + ac->search_req = talloc_zero(ac, struct ldb_request); + if (ac->search_req == NULL) { + ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n"); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->search_req->operation = LDB_ASYNC_SEARCH; + ac->search_req->op.search.base = ac->orig_req->op.mod.message->dn; + ac->search_req->op.search.scope = LDB_SCOPE_BASE; + ac->search_req->op.search.tree = ldb_parse_tree(ac->module->ldb, NULL); + if (ac->search_req->op.search.tree == NULL) { + ldb_set_errstring(ac->module->ldb, talloc_asprintf(ac, "Invalid search filter")); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->search_req->op.search.attrs = NULL; + ac->search_req->controls = NULL; + ac->search_req->creds = ac->orig_req->creds; + ac->search_req->async.context = ac; + ac->search_req->async.callback = get_self_callback; + ac->search_req->async.timeout = ac->orig_req->async.timeout; + + ac->step = PH_MOD_SEARCH_SELF; + + return ldb_next_request(ac->module, ac->search_req); +} + +static int password_hash_mod_async_search_dom(struct ldb_async_handle *h) { + + struct ph_async_context *ac; + struct dom_sid *domain_sid; + int ret; + + ac = talloc_get_type(h->private_data, struct ph_async_context); + + /* get object domain sid */ + domain_sid = samdb_result_sid_prefix(ac, ac->search_res->message, "objectSid"); + if (domain_sid == NULL) { + ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "can't handle entry with missing objectSid!\n"); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* get user domain data */ + ret = build_domain_data_request(ac, domain_sid); + if (ret != LDB_SUCCESS) { + return ret; + } + + ac->step = PH_MOD_SEARCH_DOM; + + return ldb_next_request(ac->module, ac->dom_req); +} + +static int password_hash_mod_async_do_mod(struct ldb_async_handle *h) { + + struct ph_async_context *ac; + struct domain_data *domain; + struct smb_krb5_context *smb_krb5_context; + struct ldb_message_element *sambaAttr; + struct ldb_message *msg; + int phlen; + + ac = talloc_get_type(h->private_data, struct ph_async_context); + + domain = get_domain_data(ac->module, ac, ac->dom_res); + if (domain == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->mod_req = talloc(ac, struct ldb_request); + if (ac->mod_req == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + *(ac->mod_req) = *(ac->orig_req); + + /* use a new message structure so that we can modify it */ + ac->mod_req->op.mod.message = msg = ldb_msg_new(ac->mod_req); + if (msg == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* modify dn */ + msg->dn = ac->orig_req->op.mod.message->dn; + + /* Some operations below require kerberos contexts */ + if (smb_krb5_init_context(ac->mod_req, &smb_krb5_context) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* we are going to replace the existing krb5key or delete it */ + if (ldb_msg_add_empty(msg, "krb5key", LDB_FLAG_MOD_REPLACE) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* if we have sambaPassword in the original message add the operatio on it here */ + sambaAttr = ldb_msg_find_element(ac->orig_req->op.mod.message, "sambaPassword"); + if (sambaAttr) { + + if (ldb_msg_add(msg, sambaAttr, sambaAttr->flags) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* we are not deleteing it add password hashes */ + if ((sambaAttr->flags & LDB_FLAG_MOD_MASK) != LDB_FLAG_MOD_DELETE) { + + /* we can compute new password hashes from the unicode password */ + if (add_password_hashes(ac->module, msg, 1) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* now add krb5 keys based on unicode password */ + if (add_krb5_keys_from_password(ac->module, msg, smb_krb5_context, domain, + ldb_msg_find_string(ac->search_res->message, "samAccountName", NULL), + ldb_msg_find_string(ac->search_res->message, "userPrincipalName", NULL), + ldb_msg_check_string_attribute(ac->search_res->message, "objectClass", "computer") + ) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* if the domain properties or the user account controls do not permit + * clear text passwords then wipe out the sambaPassword */ + if ((!(domain->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT)) || + (!(ldb_msg_find_uint(ac->search_res->message, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED))) { + ldb_msg_remove_attr(msg, "sambaPassword"); + } + + } + } + + /* if we don't have sambaPassword or we are trying to delete it try with nt or lm hasehs */ + if ((!sambaAttr) || ((sambaAttr->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_DELETE)) { + struct ldb_message_element *el; + + el = ldb_msg_find_element(ac->orig_req->op.mod.message, "ntPwdHash"); + if (ldb_msg_add(msg, el, el->flags) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + el = ldb_msg_find_element(ac->orig_req->op.mod.message, "lmPwdHash"); + if (ldb_msg_add(msg, el, el->flags) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + /* add also kr5 keys based on NT the hash */ + if (add_krb5_keys_from_NThash(ac->module, msg, smb_krb5_context) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* set change time */ + if (set_pwdLastSet(ac->module, msg) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* don't touch it if a value is set. It could be an incoming samsync */ + if (add_keyVersionNumber(ac->module, msg, + ldb_msg_find_uint(msg, "msDS-KeyVersionNumber", 0) + ) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if ((phlen = samdb_result_uint(ac->dom_res->message, "pwdHistoryLength", 0)) > 0) { + if (setPwdHistory(ac->module, msg, ac->search_res->message, phlen) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + h->state = LDB_ASYNC_INIT; + h->status = LDB_SUCCESS; + + ac->step = PH_MOD_DO_MOD; + + /* perform the search */ + return ldb_next_request(ac->module, ac->mod_req); +} + +static int ph_async_wait(struct ldb_async_handle *handle) { + struct ph_async_context *ac; + int ret; + + if (!handle || !handle->private_data) { + return LDB_ERR_OPERATIONS_ERROR; + } + + if (handle->state == LDB_ASYNC_DONE) { + return handle->status; + } + + handle->state = LDB_ASYNC_PENDING; + + ac = talloc_get_type(handle->private_data, struct ph_async_context); + + switch (ac->step) { + case PH_ADD_SEARCH_DOM: + if (ac->dom_req->async.handle->status != LDB_ASYNC_DONE) { + ret = ldb_async_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); + if (ret != LDB_SUCCESS) goto error; + + if (ac->dom_req->async.handle->status != LDB_ASYNC_DONE) { + return LDB_SUCCESS; + } + } + + /* domain search done, go on */ + return password_hash_add_async_do_add(handle); + + case PH_ADD_DO_ADD: + if (ac->down_req->async.handle->status != LDB_ASYNC_DONE) { + ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE); + if (ret != LDB_SUCCESS) goto error; + + if (ac->down_req->async.handle->status != LDB_ASYNC_DONE) { + return LDB_SUCCESS; + } + } + return LDB_SUCCESS; + + case PH_MOD_DO_REQ: + if (ac->down_req->async.handle->status != LDB_ASYNC_DONE) { + ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE); + if (ret != LDB_SUCCESS) goto error; + + if (ac->down_req->async.handle->status != LDB_ASYNC_DONE) { + return LDB_SUCCESS; + } + } + + /* non-password mods done, go on */ + return password_hash_mod_async_search_self(handle); + + case PH_MOD_SEARCH_SELF: + if (ac->search_req->async.handle->status != LDB_ASYNC_DONE) { + ret = ldb_async_wait(ac->search_req->async.handle, LDB_WAIT_NONE); + if (ret != LDB_SUCCESS) goto error; + + if (ac->search_req->async.handle->status != LDB_ASYNC_DONE) { + return LDB_SUCCESS; + } + } + + /* self search done, go on */ + return password_hash_mod_async_search_dom(handle); + + case PH_MOD_SEARCH_DOM: + if (ac->dom_req->async.handle->status != LDB_ASYNC_DONE) { + ret = ldb_async_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); + if (ret != LDB_SUCCESS) goto error; + + if (ac->dom_req->async.handle->status != LDB_ASYNC_DONE) { + return LDB_SUCCESS; + } + } + + /* domain search done, go on */ + return password_hash_mod_async_do_mod(handle); + + case PH_MOD_DO_MOD: + if (ac->mod_req->async.handle->status != LDB_ASYNC_DONE) { + ret = ldb_async_wait(ac->mod_req->async.handle, LDB_WAIT_NONE); + if (ret != LDB_SUCCESS) goto error; + + if (ac->mod_req->async.handle->status != LDB_ASYNC_DONE) { + return LDB_SUCCESS; + } + } + return LDB_SUCCESS; + + default: + ret = LDB_ERR_OPERATIONS_ERROR; + goto error; + } + +error: + handle->state = LDB_ASYNC_DONE; + handle->status = ret; + return ret; +} + +static int ph_async_wait_all(struct ldb_async_handle *handle) { + + int ret; + + while (handle->state != LDB_ASYNC_DONE) { + ret = ph_async_wait(handle); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + return handle->status; +} + +static int password_hash_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type) +{ + if (type == LDB_WAIT_ALL) { + return ph_async_wait_all(handle); + } else { + return ph_async_wait(handle); + } +} + static int password_hash_request(struct ldb_module *module, struct ldb_request *req) { switch (req->operation) { @@ -731,6 +1789,12 @@ static int password_hash_request(struct ldb_module *module, struct ldb_request * case LDB_REQ_MODIFY: return password_hash_modify(module, req); + case LDB_ASYNC_ADD: + return password_hash_add_async(module, req); + + case LDB_ASYNC_MODIFY: + return password_hash_modify_async(module, req); + default: return ldb_next_request(module, req); @@ -739,7 +1803,8 @@ static int password_hash_request(struct ldb_module *module, struct ldb_request * static const struct ldb_module_ops password_hash_ops = { .name = "password_hash", - .request = password_hash_request + .request = password_hash_request, + .async_wait = password_hash_async_wait }; -- cgit From 6d0969aa1adff4c7f134bd6e3e42997e72b41cf6 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 20 May 2006 19:37:21 +0000 Subject: r15761: Fix-as-you-go ... Testing various async paths and uncovering bugs (This used to be commit 099d873ea596ece18efe63b06bc64e7f97a96f82) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 45 ++++++++++++++------------ 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index b7f4aff67a..617962b909 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1672,11 +1672,11 @@ static int ph_async_wait(struct ldb_async_handle *handle) { switch (ac->step) { case PH_ADD_SEARCH_DOM: - if (ac->dom_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { ret = ldb_async_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto error; + if (ret != LDB_SUCCESS) goto done; - if (ac->dom_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } } @@ -1685,22 +1685,22 @@ static int ph_async_wait(struct ldb_async_handle *handle) { return password_hash_add_async_do_add(handle); case PH_ADD_DO_ADD: - if (ac->down_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto error; + if (ret != LDB_SUCCESS) goto done; - if (ac->down_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } } return LDB_SUCCESS; case PH_MOD_DO_REQ: - if (ac->down_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto error; + if (ret != LDB_SUCCESS) goto done; - if (ac->down_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } } @@ -1709,11 +1709,11 @@ static int ph_async_wait(struct ldb_async_handle *handle) { return password_hash_mod_async_search_self(handle); case PH_MOD_SEARCH_SELF: - if (ac->search_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->search_req->async.handle->state != LDB_ASYNC_DONE) { ret = ldb_async_wait(ac->search_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto error; + if (ret != LDB_SUCCESS) goto done; - if (ac->search_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->search_req->async.handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } } @@ -1722,11 +1722,11 @@ static int ph_async_wait(struct ldb_async_handle *handle) { return password_hash_mod_async_search_dom(handle); case PH_MOD_SEARCH_DOM: - if (ac->dom_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { ret = ldb_async_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto error; + if (ret != LDB_SUCCESS) goto done; - if (ac->dom_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } } @@ -1735,22 +1735,25 @@ static int ph_async_wait(struct ldb_async_handle *handle) { return password_hash_mod_async_do_mod(handle); case PH_MOD_DO_MOD: - if (ac->mod_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->mod_req->async.handle->state != LDB_ASYNC_DONE) { ret = ldb_async_wait(ac->mod_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto error; + if (ret != LDB_SUCCESS) goto done; - if (ac->mod_req->async.handle->status != LDB_ASYNC_DONE) { + if (ac->mod_req->async.handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } } - return LDB_SUCCESS; + + break; default: ret = LDB_ERR_OPERATIONS_ERROR; - goto error; + goto done; } -error: + ret = LDB_SUCCESS; + +done: handle->state = LDB_ASYNC_DONE; handle->status = ret; return ret; -- cgit From e2112ba3b7d491f6b6d9957b57a36a78efed18a9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 21 May 2006 20:06:01 +0000 Subject: r15782: More fixes for async cases (This used to be commit 3c9434e264710a1fa29adedbe571d5324ecae906) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 617962b909..0d4f0c6a0f 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -205,6 +205,8 @@ static int password_hash_handle(struct ldb_module *module, struct ldb_request *r case LDB_REQ_MODIFY: modified_orig_request->op.mod.message = msg2; break; + default: + return LDB_ERR_OPERATIONS_ERROR; } /* Send the (modified) request of the original caller down to the database */ @@ -1275,7 +1277,7 @@ static int password_hash_add_async_do_add(struct ldb_async_handle *h) { ac = talloc_get_type(h->private_data, struct ph_async_context); - domain = get_domain_data(ac->module, ac, ac->search_res); + domain = get_domain_data(ac->module, ac, ac->dom_res); if (domain == NULL) { return LDB_ERR_OPERATIONS_ERROR; } @@ -1693,7 +1695,8 @@ static int ph_async_wait(struct ldb_async_handle *handle) { return LDB_SUCCESS; } } - return LDB_SUCCESS; + + break; case PH_MOD_DO_REQ: if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { -- cgit From 8081e4f40276034c47bd799aca64a7d01ffb1bce Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 22 May 2006 03:55:01 +0000 Subject: r15795: Try to use the async code by default It passess all my tests, but I still need to work on a lot of stuff. Shouldn't impact anybody else work, so I want to commit now and see what happens Will work to remove the old code from modules and backends soon, and make some more restyling in ldb internals. So, if there is something you don't like in this desgin please speak now. Simo. (This used to be commit 8b2a563e716a789ea77cbfbf2f372724de5361ce) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 0d4f0c6a0f..c1eb244e19 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -975,16 +975,25 @@ static int add_krb5_keys_from_NThash(struct ldb_module *module, struct ldb_messa return LDB_SUCCESS; } -static int set_pwdLastSet(struct ldb_module *module, struct ldb_message *msg) +static int set_pwdLastSet(struct ldb_module *module, struct ldb_message *msg, int is_mod) { NTTIME now_nt; /* set it as now */ unix_to_nt_time(&now_nt, time(NULL)); - /* replace or add */ - if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE) != 0) { - return LDB_ERR_OPERATIONS_ERROR; + if (!is_mod) { + /* be sure there isn't a 0 value set (eg. coming from the template) */ + ldb_msg_remove_attr(msg, "pwdLastSet"); + /* add */ + if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_ADD) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + } else { + /* replace */ + if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } } if (samdb_msg_add_uint64(module->ldb, msg, msg, "pwdLastSet", now_nt) != 0) { @@ -1326,7 +1335,7 @@ static int password_hash_add_async_do_add(struct ldb_async_handle *h) { /* don't touch it if a value is set. It could be an incoming samsync */ if (ldb_msg_find_uint64(msg, "pwdLastSet", 0) == 0) { - if (set_pwdLastSet(ac->module, msg) != LDB_SUCCESS) { + if (set_pwdLastSet(ac->module, msg, 0) != LDB_SUCCESS) { return LDB_ERR_OPERATIONS_ERROR; } } @@ -1630,7 +1639,7 @@ static int password_hash_mod_async_do_mod(struct ldb_async_handle *h) { } /* set change time */ - if (set_pwdLastSet(ac->module, msg) != LDB_SUCCESS) { + if (set_pwdLastSet(ac->module, msg, 1) != LDB_SUCCESS) { return LDB_ERR_OPERATIONS_ERROR; } -- cgit From d6aaca599b8094b47246dd341dde165f204df090 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 22 May 2006 15:17:12 +0000 Subject: r15804: Fix SAMLOGON test (This used to be commit 2e9a840bb975f3269de4ca299a3d6e5b19f3cad1) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index c1eb244e19..1a2ca629bc 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -769,23 +769,22 @@ static int add_password_hashes(struct ldb_module *module, struct ldb_message *ms return LDB_ERR_OPERATIONS_ERROR; } - /* compute the new nt and lm hashes */ if (is_mod) { if (ldb_msg_add_empty(msg, "ntPwdHash", LDB_FLAG_MOD_REPLACE) != 0) { return LDB_ERR_OPERATIONS_ERROR; } + if (ldb_msg_add_empty(msg, "lmPwdHash", LDB_FLAG_MOD_REPLACE) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } } + + /* compute the new nt and lm hashes */ E_md4hash(sambaPassword, tmp_hash.hash); if (samdb_msg_add_hash(module->ldb, msg, msg, "ntPwdHash", &tmp_hash) != 0) { return LDB_ERR_OPERATIONS_ERROR; } if (E_deshash(sambaPassword, tmp_hash.hash)) { - if (is_mod) { - if (ldb_msg_add_empty(msg, "lmPwdHash", LDB_FLAG_MOD_REPLACE) != 0) { - return LDB_ERR_OPERATIONS_ERROR; - } - } if (samdb_msg_add_hash(module->ldb, msg, msg, "lmPwdHash", &tmp_hash) != 0) { return LDB_ERR_OPERATIONS_ERROR; } -- cgit From b22d15a0f80be0de1bb123f79058ec85d083cd75 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 24 May 2006 12:33:06 +0000 Subject: r15859: fixed a crash bug in the ldb password_hash module. This one is quite sublte - please have a look at the change if you are not certain you know the semantics of constant arrays declared on the stack (they must be static if you return them from the function) (This used to be commit 1848078fee2041195e3d65fcc090d7b6330b8ea0) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 1a2ca629bc..2885fb82a2 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1145,7 +1145,10 @@ static int get_domain_data_callback(struct ldb_context *ldb, void *context, stru static int build_domain_data_request(struct ph_async_context *ac, struct dom_sid *sid) { - const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", "dnsDomain", NULL }; + /* attrs[] is returned from this function in + ac->dom_req->op.search.attrs, so it must be static, as + otherwise the compiler can put it on the stack */ + static const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", "dnsDomain", NULL }; char *filter; ac->dom_req = talloc_zero(ac, struct ldb_request); -- cgit From 90a5e19e03842b77fd7811965fb2603e552261bc Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 28 May 2006 02:10:44 +0000 Subject: r15913: Error passing in the async code is not in agood shape Start enhancing it and fix some problems with incorrect evalutaion of the codes Implement rdn rename (async only) (This used to be commit 6af1d738b9668d4f0eb6194ac0f84af9e73f8c2e) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 110 ++++++++++++++++--------- 1 file changed, 73 insertions(+), 37 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 2885fb82a2..67cb01b9d8 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1680,82 +1680,119 @@ static int ph_async_wait(struct ldb_async_handle *handle) { } handle->state = LDB_ASYNC_PENDING; + handle->status = LDB_SUCCESS; ac = talloc_get_type(handle->private_data, struct ph_async_context); switch (ac->step) { case PH_ADD_SEARCH_DOM: - if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { - ret = ldb_async_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto done; + ret = ldb_async_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); - if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { - return LDB_SUCCESS; - } + if (ret != LDB_SUCCESS) { + handle->status = ret; + goto done; + } + if (ac->dom_req->async.handle->status != LDB_SUCCESS) { + handle->status = ac->dom_req->async.handle->status; + goto done; + } + + if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { + return LDB_SUCCESS; } /* domain search done, go on */ return password_hash_add_async_do_add(handle); case PH_ADD_DO_ADD: - if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { - ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto done; + ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE); - if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { - return LDB_SUCCESS; - } + if (ret != LDB_SUCCESS) { + handle->status = ret; + goto done; + } + if (ac->down_req->async.handle->status != LDB_SUCCESS) { + handle->status = ac->down_req->async.handle->status; + goto done; + } + + if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { + return LDB_SUCCESS; } break; case PH_MOD_DO_REQ: - if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { - ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto done; + ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE); - if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { - return LDB_SUCCESS; - } + if (ret != LDB_SUCCESS) { + handle->status = ret; + goto done; + } + if (ac->down_req->async.handle->status != LDB_SUCCESS) { + handle->status = ac->down_req->async.handle->status; + goto done; + } + + if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { + return LDB_SUCCESS; } /* non-password mods done, go on */ return password_hash_mod_async_search_self(handle); case PH_MOD_SEARCH_SELF: - if (ac->search_req->async.handle->state != LDB_ASYNC_DONE) { - ret = ldb_async_wait(ac->search_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto done; + ret = ldb_async_wait(ac->search_req->async.handle, LDB_WAIT_NONE); - if (ac->search_req->async.handle->state != LDB_ASYNC_DONE) { - return LDB_SUCCESS; - } + if (ret != LDB_SUCCESS) { + handle->status = ret; + goto done; + } + if (ac->search_req->async.handle->status != LDB_SUCCESS) { + handle->status = ac->search_req->async.handle->status; + goto done; + } + + if (ac->search_req->async.handle->state != LDB_ASYNC_DONE) { + return LDB_SUCCESS; } /* self search done, go on */ return password_hash_mod_async_search_dom(handle); case PH_MOD_SEARCH_DOM: - if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { - ret = ldb_async_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto done; + ret = ldb_async_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); - if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { - return LDB_SUCCESS; - } + if (ret != LDB_SUCCESS) { + handle->status = ret; + goto done; + } + if (ac->dom_req->async.handle->status != LDB_SUCCESS) { + handle->status = ac->dom_req->async.handle->status; + goto done; + } + + if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { + return LDB_SUCCESS; } /* domain search done, go on */ return password_hash_mod_async_do_mod(handle); case PH_MOD_DO_MOD: - if (ac->mod_req->async.handle->state != LDB_ASYNC_DONE) { - ret = ldb_async_wait(ac->mod_req->async.handle, LDB_WAIT_NONE); - if (ret != LDB_SUCCESS) goto done; + ret = ldb_async_wait(ac->mod_req->async.handle, LDB_WAIT_NONE); - if (ac->mod_req->async.handle->state != LDB_ASYNC_DONE) { - return LDB_SUCCESS; - } + if (ret != LDB_SUCCESS) { + handle->status = ret; + goto done; + } + if (ac->mod_req->async.handle->status != LDB_SUCCESS) { + handle->status = ac->mod_req->async.handle->status; + goto done; + } + + if (ac->mod_req->async.handle->state != LDB_ASYNC_DONE) { + return LDB_SUCCESS; } break; @@ -1769,7 +1806,6 @@ static int ph_async_wait(struct ldb_async_handle *handle) { done: handle->state = LDB_ASYNC_DONE; - handle->status = ret; return ret; } -- cgit From 3a4d7eb2c08a06fac89c34d132f1c32751ce7ad5 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 29 May 2006 01:30:02 +0000 Subject: r15927: Optimize ldb module traverse while keeping the API intact. I was sick of jumping inot each module for each request, even the ones not handle by that module. (This used to be commit 7d65105e885a28584e8555453b90232c43a92bf7) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 67cb01b9d8..0be0fff0ff 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1842,12 +1842,6 @@ static int password_hash_request(struct ldb_module *module, struct ldb_request * case LDB_REQ_MODIFY: return password_hash_modify(module, req); - case LDB_ASYNC_ADD: - return password_hash_add_async(module, req); - - case LDB_ASYNC_MODIFY: - return password_hash_modify_async(module, req); - default: return ldb_next_request(module, req); @@ -1856,6 +1850,8 @@ static int password_hash_request(struct ldb_module *module, struct ldb_request * static const struct ldb_module_ops password_hash_ops = { .name = "password_hash", + .add = password_hash_add_async, + .modify = password_hash_modify_async, .request = password_hash_request, .async_wait = password_hash_async_wait }; -- cgit From 03703a58d7fe441ec5dcbe1814cea3f55544de55 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 29 May 2006 11:57:09 +0000 Subject: r15932: Remove per request creds They have never benn used and make little sense too imo (This used to be commit f0c1d08d50f8a3e25650ac85b178ec7a43e433d9) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 0be0fff0ff..bdf1bcc27a 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1175,7 +1175,6 @@ static int build_domain_data_request(struct ph_async_context *ac, } ac->dom_req->op.search.attrs = attrs; ac->dom_req->controls = NULL; - ac->dom_req->creds = ac->orig_req->creds; ac->dom_req->async.context = ac; ac->dom_req->async.callback = get_domain_data_callback; ac->dom_req->async.timeout = ac->orig_req->async.timeout; @@ -1507,7 +1506,6 @@ static int password_hash_mod_async_search_self(struct ldb_async_handle *h) { } ac->search_req->op.search.attrs = NULL; ac->search_req->controls = NULL; - ac->search_req->creds = ac->orig_req->creds; ac->search_req->async.context = ac; ac->search_req->async.callback = get_self_callback; ac->search_req->async.timeout = ac->orig_req->async.timeout; -- cgit From 0c7b82e5f6063de4114de21cf854ac67346e31f6 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 29 May 2006 23:46:43 +0000 Subject: r15942: Remove the sync internal ldb calls altogether. This means that some modules have been disabled as well as they have not been ported to the async interface One of them is the ugly objectclass module. I hope that the change in samldb module will make the MMC happy without the need of this crappy module, we need proper handling in a decent schema module. proxy and ldb_map have also been disabled ldb_sqlite3 need to be ported as well (currenlty just broken). (This used to be commit 51083de795bdcbf649de926e86969adc20239b6d) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 721 +------------------------ 1 file changed, 18 insertions(+), 703 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index bdf1bcc27a..16fe6b8f4d 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -65,678 +65,10 @@ * */ - -static int password_hash_handle(struct ldb_module *module, struct ldb_request *req, - const struct ldb_message *msg) -{ - int ret, old_ret = -1; - uint_t pwdProperties, pwdHistoryLength; - uint_t userAccountControl; - const char *dnsDomain, *realm; - const char *sambaPassword = NULL; - struct samr_Password *sambaLMPwdHistory, *sambaNTPwdHistory; - struct samr_Password *lmPwdHash, *ntPwdHash; - struct samr_Password *lmOldHash = NULL, *ntOldHash = NULL; - struct samr_Password *new_sambaLMPwdHistory, *new_sambaNTPwdHistory; - struct samr_Password local_lmNewHash, local_ntNewHash; - int sambaLMPwdHistory_len, sambaNTPwdHistory_len; - uint_t kvno; - struct dom_sid *domain_sid; - time_t now = time(NULL); - NTTIME now_nt; - int i; - krb5_error_code krb5_ret; - - struct smb_krb5_context *smb_krb5_context; - - struct ldb_message_element *attribute; - struct ldb_dn *dn = msg->dn; - struct ldb_message *msg2; - - struct ldb_request *search_request = NULL; - struct ldb_request *modify_request; - struct ldb_request *modified_orig_request; - struct ldb_result *res, *dom_res, *old_res; - - struct ldb_message_element *objectclasses; - struct ldb_val computer_val; - struct ldb_val person_val; - BOOL is_computer; - - struct ldb_message *modify_msg; - - const char *domain_expression; - const char *old_user_attrs[] = { "lmPwdHash", "ntPwdHash", NULL }; - const char *user_attrs[] = { "userAccountControl", "sambaLMPwdHistory", - "sambaNTPwdHistory", - "ntPwdHash", - "objectSid", "msDS-KeyVersionNumber", - "objectClass", "userPrincipalName", - "samAccountName", - NULL }; - const char * const domain_attrs[] = { "pwdProperties", "pwdHistoryLength", - "dnsDomain", NULL }; - - TALLOC_CTX *mem_ctx; - - /* Do the original action */ - - mem_ctx = talloc_new(module); - if (!mem_ctx) { - return LDB_ERR_OPERATIONS_ERROR; - } - - if (req->operation == LDB_REQ_MODIFY) { - search_request = talloc(mem_ctx, struct ldb_request); - if (!search_request) { - talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - - /* Look up the old ntPwdHash and lmPwdHash values, so - * we can later place these into the password - * history */ - - search_request->operation = LDB_REQ_SEARCH; - search_request->op.search.base = dn; - search_request->op.search.scope = LDB_SCOPE_BASE; - search_request->op.search.tree = ldb_parse_tree(module->ldb, NULL); - search_request->op.search.attrs = old_user_attrs; - search_request->controls = NULL; - - old_ret = ldb_next_request(module, search_request); - } - - /* we can't change things untill we copy it */ - msg2 = ldb_msg_copy_shallow(mem_ctx, msg); - - /* look again, this time at the copied attribute */ - if (!msg2 || (attribute = ldb_msg_find_element(msg2, "sambaPassword")) == NULL ) { - talloc_free(mem_ctx); - /* Gah? where did it go? Oh well... */ - return LDB_ERR_OPERATIONS_ERROR; - } - - /* Wipe out the sambaPassword attribute set, we will handle it in - * the second modify. We might not want it written to disk */ - - if (req->operation == LDB_REQ_ADD) { - if (attribute->num_values > 1) { - ldb_set_errstring(module->ldb, - talloc_asprintf(mem_ctx, "sambaPassword_handle: " - "attempted set of multiple sambaPassword attributes on %s rejected", - ldb_dn_linearize(mem_ctx, dn))); - talloc_free(mem_ctx); - return LDB_ERR_CONSTRAINT_VIOLATION; - } - - if (attribute->num_values == 1) { - sambaPassword = (const char *)attribute->values[0].data; - ldb_msg_remove_attr(msg2, "sambaPassword"); - } - } else if (((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_ADD) - || ((attribute->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE)) { - if (attribute->num_values > 1) { - ldb_set_errstring(module->ldb, - talloc_asprintf(mem_ctx, "sambaPassword_handle: " - "attempted set of multiple sambaPassword attributes on %s rejected", - ldb_dn_linearize(mem_ctx, dn))); - talloc_free(mem_ctx); - return LDB_ERR_CONSTRAINT_VIOLATION; - } - - if (attribute->num_values == 1) { - sambaPassword = (const char *)attribute->values[0].data; - ldb_msg_remove_attr(msg2, "sambaPassword"); - } - } - - modified_orig_request = talloc(mem_ctx, struct ldb_request); - if (!modified_orig_request) { - talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - - *modified_orig_request = *req; - switch (modified_orig_request->operation) { - case LDB_REQ_ADD: - modified_orig_request->op.add.message = msg2; - break; - case LDB_REQ_MODIFY: - modified_orig_request->op.mod.message = msg2; - break; - default: - return LDB_ERR_OPERATIONS_ERROR; - } - - /* Send the (modified) request of the original caller down to the database */ - ret = ldb_next_request(module, modified_orig_request); - if (ret) { - talloc_free(mem_ctx); - return ret; - } - - /* While we do the search first (for the old password hashes), - * we don't want to override any error that the modify may - * have returned. Now check the error */ - if (req->operation == LDB_REQ_MODIFY) { - if (old_ret) { - talloc_free(mem_ctx); - return old_ret; - } - - /* Find out the old passwords details of the user */ - old_res = search_request->op.search.res; - talloc_steal(mem_ctx, old_res); - talloc_free(search_request); - - if (old_res->count != 1) { - ldb_set_errstring(module->ldb, - talloc_asprintf(mem_ctx, "password_hash_handle: " - "(pre) search for %s found %d != 1 objects, for entry we just modified", - ldb_dn_linearize(mem_ctx, dn), - old_res->count)); - /* What happend? The above add/modify worked... */ - talloc_free(mem_ctx); - return LDB_ERR_NO_SUCH_OBJECT; - } - - lmOldHash = samdb_result_hash(mem_ctx, old_res->msgs[0], "lmPwdHash"); - ntOldHash = samdb_result_hash(mem_ctx, old_res->msgs[0], "ntPwdHash"); - } - - /* Start finding out details we need for the second modify. - * We do this after the first add/modify because other modules - * will have filled in the templates, and we may have had - * things like the username (affecting the salt) changed along - * with the password. */ - - /* Now find out what is on the entry after the above add/modify */ - search_request = talloc(mem_ctx, struct ldb_request); - if (!search_request) { - talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - - search_request->operation = LDB_REQ_SEARCH; - search_request->op.search.base = dn; - search_request->op.search.scope = LDB_SCOPE_BASE; - search_request->op.search.tree = ldb_parse_tree(module->ldb, NULL); - search_request->op.search.attrs = user_attrs; - search_request->controls = NULL; - - ret = ldb_next_request(module, search_request); - if (ret) { - talloc_free(mem_ctx); - return ret; - } - - /* Find out the full details of the user */ - res = search_request->op.search.res; - talloc_steal(mem_ctx, res); - talloc_free(search_request); - - if (res->count != 1) { - ldb_set_errstring(module->ldb, - talloc_asprintf(mem_ctx, "password_hash_handle: " - "search for %s found %d != 1 objects, for entry we just added/modified", - ldb_dn_linearize(mem_ctx, dn), - res->count)); - /* What happend? The above add/modify worked... */ - talloc_free(mem_ctx); - return LDB_ERR_NO_SUCH_OBJECT; - } - - userAccountControl = samdb_result_uint(res->msgs[0], "userAccountControl", 0); - sambaLMPwdHistory_len = samdb_result_hashes(mem_ctx, res->msgs[0], - "sambaLMPwdHistory", &sambaLMPwdHistory); - sambaNTPwdHistory_len = samdb_result_hashes(mem_ctx, res->msgs[0], - "sambaNTPwdHistory", &sambaNTPwdHistory); - ntPwdHash = samdb_result_hash(mem_ctx, res->msgs[0], "ntPwdHash"); - kvno = samdb_result_uint(res->msgs[0], "msDS-KeyVersionNumber", 0); - - domain_sid = samdb_result_sid_prefix(mem_ctx, res->msgs[0], "objectSid"); - - - objectclasses = ldb_msg_find_element(res->msgs[0], "objectClass"); - person_val = data_blob_string_const("person"); - - if (!objectclasses || !ldb_msg_find_val(objectclasses, &person_val)) { - /* Not a 'person', so the rest of this doesn't make - * sense. How we got a sambaPassword this far I don't - * know... */ - ldb_set_errstring(module->ldb, - talloc_asprintf(mem_ctx, "password_hash_handle: " - "attempted set of sambaPassword on non-'person' object %s rejected", - ldb_dn_linearize(mem_ctx, dn))); - talloc_free(mem_ctx); - return LDB_ERR_CONSTRAINT_VIOLATION; - } - - computer_val = data_blob_string_const("computer"); - - if (ldb_msg_find_val(objectclasses, &computer_val)) { - is_computer = True; - } else { - is_computer = False; - } - - domain_expression = talloc_asprintf(mem_ctx, "(&(objectSid=%s)(objectClass=domain))", - ldap_encode_ndr_dom_sid(mem_ctx, domain_sid)); - - /* Find the user's domain, then find out the domain password - * properties */ - ret = ldb_search(module->ldb, NULL, LDB_SCOPE_SUBTREE, domain_expression, - domain_attrs, &dom_res); - if (ret) { - talloc_free(mem_ctx); - return ret; - } - - if (dom_res->count != 1) { - /* What happend? The user we are modifying must be odd... */ - ldb_set_errstring(module->ldb, - talloc_asprintf(mem_ctx, "password_hash_handle: " - "search for domain %s found %d != 1 objects", - dom_sid_string(mem_ctx, domain_sid), - dom_res->count)); - talloc_free(mem_ctx); - return LDB_ERR_NO_SUCH_OBJECT; - } - - pwdProperties = samdb_result_uint(dom_res->msgs[0], "pwdProperties", 0); - pwdHistoryLength = samdb_result_uint(dom_res->msgs[0], "pwdHistoryLength", 0); - dnsDomain = ldb_msg_find_string(dom_res->msgs[0], "dnsDomain", NULL); - realm = strupper_talloc(mem_ctx, dnsDomain); - - /* Some operations below require kerberos contexts */ - if (smb_krb5_init_context(mem_ctx, &smb_krb5_context) != 0) { - talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - - /* Prepare the modifications to set all the hash/key types */ - modify_msg = ldb_msg_new(req); - modify_msg->dn = talloc_reference(modify_msg, dn); - -#define CHECK_RET(x) \ - do { \ - int check_ret = x; \ - if (check_ret != LDB_SUCCESS) { \ - talloc_free(mem_ctx); \ - return check_ret; \ - } \ - } while(0) - - /* Setup krb5Key (we want to either delete an existing value, - * or replace with a new one). Both the unicode and NT hash - * only branches append keys to this multivalued entry. */ - CHECK_RET(ldb_msg_add_empty(modify_msg, "krb5Key", LDB_FLAG_MOD_REPLACE)); - - /* Yay, we can compute new password hashes from the unicode - * password */ - if (sambaPassword) { - Principal *salt_principal; - const char *user_principal_name = ldb_msg_find_string(res->msgs[0], "userPrincipalName", NULL); - - Key *keys; - size_t num_keys; - - /* compute the new nt and lm hashes */ - if (E_deshash(sambaPassword, local_lmNewHash.hash)) { - lmPwdHash = &local_lmNewHash; - } else { - lmPwdHash = NULL; - } - E_md4hash(sambaPassword, local_ntNewHash.hash); - ntPwdHash = &local_ntNewHash; - CHECK_RET(ldb_msg_add_empty(modify_msg, "ntPwdHash", - LDB_FLAG_MOD_REPLACE)); - CHECK_RET(samdb_msg_add_hash(module->ldb, req, - modify_msg, "ntPwdHash", - ntPwdHash)); - CHECK_RET(ldb_msg_add_empty(modify_msg, "lmPwdHash", - LDB_FLAG_MOD_REPLACE)); - if (lmPwdHash) { - CHECK_RET(samdb_msg_add_hash(module->ldb, req, - modify_msg, "lmPwdHash", - lmPwdHash)); - } - - /* Many, many thanks to lukeh@padl.com for this - * algorithm, described in his Nov 10 2004 mail to - * samba-technical@samba.org */ - - if (is_computer) { - /* Determine a salting principal */ - char *samAccountName = talloc_strdup(mem_ctx, ldb_msg_find_string(res->msgs[0], "samAccountName", NULL)); - char *saltbody; - if (!samAccountName) { - ldb_set_errstring(module->ldb, - talloc_asprintf(mem_ctx, "password_hash_handle: " - "generation of new kerberos keys failed: %s is a computer without a samAccountName", - ldb_dn_linearize(mem_ctx, dn))); - talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - if (samAccountName[strlen(samAccountName)-1] == '$') { - samAccountName[strlen(samAccountName)-1] = '\0'; - } - saltbody = talloc_asprintf(mem_ctx, "%s.%s", samAccountName, dnsDomain); - - krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, &salt_principal, realm, "host", saltbody, NULL); - } else if (user_principal_name) { - char *p; - user_principal_name = talloc_strdup(mem_ctx, user_principal_name); - if (!user_principal_name) { - talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } else { - p = strchr(user_principal_name, '@'); - if (p) { - p[0] = '\0'; - } - krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, &salt_principal, realm, user_principal_name, NULL); - } - } else { - const char *samAccountName = ldb_msg_find_string(res->msgs[0], "samAccountName", NULL); - if (!samAccountName) { - ldb_set_errstring(module->ldb, - talloc_asprintf(mem_ctx, "password_hash_handle: " - "generation of new kerberos keys failed: %s has no samAccountName", - ldb_dn_linearize(mem_ctx, dn))); - talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, &salt_principal, realm, samAccountName, NULL); - } - - - if (krb5_ret) { - ldb_set_errstring(module->ldb, - talloc_asprintf(mem_ctx, "password_hash_handle: " - "generation of a saltking principal failed: %s", - smb_get_krb5_error_message(smb_krb5_context->krb5_context, - krb5_ret, mem_ctx))); - talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - - /* TODO: We may wish to control the encryption types chosen in future */ - krb5_ret = hdb_generate_key_set_password(smb_krb5_context->krb5_context, - salt_principal, sambaPassword, &keys, &num_keys); - krb5_free_principal(smb_krb5_context->krb5_context, salt_principal); - - if (krb5_ret) { - ldb_set_errstring(module->ldb, - talloc_asprintf(mem_ctx, "password_hash_handle: " - "generation of new kerberos keys failed: %s", - smb_get_krb5_error_message(smb_krb5_context->krb5_context, - krb5_ret, mem_ctx))); - talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - - /* Walking all the key types generated, transform each - * key into an ASN.1 blob - */ - for (i=0; i < num_keys; i++) { - unsigned char *buf; - size_t buf_size; - size_t len; - struct ldb_val val; - - if (keys[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { - /* We might end up doing this below: - * This ensures we get the unicode - * conversion right. This should also - * be fixed in the Heimdal libs */ - continue; - } - ASN1_MALLOC_ENCODE(Key, buf, buf_size, &keys[i], &len, krb5_ret); - if (krb5_ret) { - return LDB_ERR_OPERATIONS_ERROR; - } - - val.data = talloc_memdup(req, buf, len); - val.length = len; - free(buf); - if (!val.data || krb5_ret) { - hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); - talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - ret = ldb_msg_add_value(modify_msg, "krb5Key", &val); - if (ret != LDB_SUCCESS) { - hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); - talloc_free(mem_ctx); - return ret; - } - } - - hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); - } - - /* Possibly kill off the cleartext or store it */ - CHECK_RET(ldb_msg_add_empty(modify_msg, "sambaPassword", LDB_FLAG_MOD_REPLACE)); - - if (sambaPassword && (pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT) && - (userAccountControl & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { - CHECK_RET(ldb_msg_add_string(modify_msg, "sambaPassword", sambaPassword)); - } - - /* Even if we didn't get a sambaPassword, we can still setup - * krb5Key from the NT hash. - * - * This is an append, so it works with the 'continue' in the - * unicode loop above, to use Samba's NT hash function, which - * is more correct than Heimdal's - */ - if (ntPwdHash) { - unsigned char *buf; - size_t buf_size; - size_t len; - struct ldb_val val; - Key key; - - key.mkvno = 0; - key.salt = NULL; /* No salt for this enc type */ - - krb5_ret = krb5_keyblock_init(smb_krb5_context->krb5_context, - ETYPE_ARCFOUR_HMAC_MD5, - ntPwdHash->hash, sizeof(ntPwdHash->hash), - &key.key); - if (krb5_ret) { - return LDB_ERR_OPERATIONS_ERROR; - } - ASN1_MALLOC_ENCODE(Key, buf, buf_size, &key, &len, krb5_ret); - if (krb5_ret) { - return LDB_ERR_OPERATIONS_ERROR; - } - krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &key.key); - - val.data = talloc_memdup(req, buf, len); - val.length = len; - free(buf); - if (!val.data || ret) { - return LDB_ERR_OPERATIONS_ERROR; - } - CHECK_RET(ldb_msg_add_value(modify_msg, "krb5Key", &val)); - } - - /* If the original caller did anything with pwdLastSet then skip this. It could be an incoming samsync */ - attribute = ldb_msg_find_element(msg, "pwdLastSet"); - if (attribute == NULL) { - /* Update the password last set time */ - unix_to_nt_time(&now_nt, now); - CHECK_RET(ldb_msg_add_empty(modify_msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE)); - CHECK_RET(samdb_msg_add_uint64(module->ldb, mem_ctx, modify_msg, "pwdLastSet", now_nt)); - } - - /* If the original caller did anything with "msDS-KeyVersionNumber" then skip this. It could be an incoming samsync */ - attribute = ldb_msg_find_element(msg, "msDS-KeyVersionNumber"); - if (attribute == NULL) { - if (kvno == 0) { - CHECK_RET(ldb_msg_add_empty(modify_msg, "msDS-KeyVersionNumber", - LDB_FLAG_MOD_REPLACE)); - CHECK_RET(samdb_msg_add_uint(module->ldb, mem_ctx, modify_msg, "msDS-KeyVersionNumber", kvno + 1)); - } else { - /* While we should be in a transaction, go one extra - * step in the dance for an 'atomic' increment. This - * may be of value against remote LDAP servers. (Note - * however that Mulitmaster replication stil offers no - * such guarantee) */ - - struct ldb_val old_kvno, new_kvno; - old_kvno.data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", kvno); - if (!old_kvno.data) { - return -1; - } - old_kvno.length = strlen((char *)old_kvno.data); - - new_kvno.data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", kvno + 1); - if (!new_kvno.data) { - return -1; - } - new_kvno.length = strlen((char *)new_kvno.data); - - CHECK_RET(ldb_msg_add_empty(modify_msg, "msDS-KeyVersionNumber", - LDB_FLAG_MOD_DELETE)); - CHECK_RET(ldb_msg_add_empty(modify_msg, "msDS-KeyVersionNumber", - LDB_FLAG_MOD_ADD)); - modify_msg->elements[modify_msg->num_elements - 2].num_values = 1; - modify_msg->elements[modify_msg->num_elements - 2].values = &old_kvno; - modify_msg->elements[modify_msg->num_elements - 1].num_values = 1; - modify_msg->elements[modify_msg->num_elements - 1].values = &new_kvno; - } - } - - CHECK_RET(ldb_msg_add_empty(modify_msg, "sambaLMPwdHistory", - LDB_FLAG_MOD_REPLACE)); - CHECK_RET(ldb_msg_add_empty(modify_msg, "sambaNTPwdHistory", - LDB_FLAG_MOD_REPLACE)); - - /* If we have something to put into the history, or an old - * history element to expire, update the history */ - if (pwdHistoryLength > 0 && - ((sambaNTPwdHistory_len > 0) || (sambaLMPwdHistory_len > 0) - || lmOldHash || ntOldHash)) { - /* store the password history */ - new_sambaLMPwdHistory = talloc_array(mem_ctx, struct samr_Password, - pwdHistoryLength); - if (!new_sambaLMPwdHistory) { - return LDB_ERR_OPERATIONS_ERROR; - } - new_sambaNTPwdHistory = talloc_array(mem_ctx, struct samr_Password, - pwdHistoryLength); - if (!new_sambaNTPwdHistory) { - return LDB_ERR_OPERATIONS_ERROR; - } - for (i=0;ioperation = LDB_REQ_MODIFY; - modify_request->op.mod.message = modify_msg; - modify_request->controls = NULL; - - ret = ldb_next_request(module, modify_request); - - talloc_free(mem_ctx); - return ret; -} - -/* add_record: do things with the sambaPassword attribute */ -static int password_hash_add(struct ldb_module *module, struct ldb_request *req) -{ - const struct ldb_message *msg = req->op.add.message; - - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_add_record\n"); - - if (ldb_dn_is_special(msg->dn)) { /* do not manipulate our control entries */ - return ldb_next_request(module, req); - } - - /* If no part of this touches the sambaPassword, then we don't - * need to make any changes. For password changes/set there should - * be a 'delete' or a 'modify' on this attribute. */ - if (ldb_msg_find_element(msg, "sambaPassword") == NULL ) { - return ldb_next_request(module, req); - } - - return password_hash_handle(module, req, msg); -} - -/* modify_record: do things with the sambaPassword attribute */ -static int password_hash_modify(struct ldb_module *module, struct ldb_request *req) -{ - const struct ldb_message *msg = req->op.mod.message; - - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_modify_record\n"); - - if (ldb_dn_is_special(msg->dn)) { /* do not manipulate our control entries */ - return ldb_next_request(module, req); - } - - /* If no part of this touches the sambaPassword, then we don't - * need to make any changes. For password changes/set there should - * be a 'delete' or a 'modify' on this attribute. */ - if (ldb_msg_find_element(msg, "sambaPassword") == NULL ) { - return ldb_next_request(module, req); - } - - return password_hash_handle(module, req, msg); -} - -enum ph_type {PH_ADD, PH_MOD}; -enum ph_step {PH_ADD_SEARCH_DOM, PH_ADD_DO_ADD, PH_MOD_DO_REQ, PH_MOD_SEARCH_SELF, PH_MOD_SEARCH_DOM, PH_MOD_DO_MOD}; - struct ph_async_context { - enum ph_type type; - enum ph_step step; + enum ph_type {PH_ADD, PH_MOD} type; + enum ph_step {PH_ADD_SEARCH_DOM, PH_ADD_DO_ADD, PH_MOD_DO_REQ, PH_MOD_SEARCH_SELF, PH_MOD_SEARCH_DOM, PH_MOD_DO_MOD} step; struct ldb_module *module; struct ldb_request *orig_req; @@ -1212,7 +544,7 @@ static struct domain_data *get_domain_data(struct ldb_module *module, void *mem_ return data; } -static int password_hash_add_async(struct ldb_module *module, struct ldb_request *req) +static int password_hash_add(struct ldb_module *module, struct ldb_request *req) { struct ldb_async_handle *h; struct ph_async_context *ac; @@ -1220,7 +552,7 @@ static int password_hash_add_async(struct ldb_module *module, struct ldb_request struct dom_sid *domain_sid; int ret; - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_add_async\n"); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_add\n"); if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */ return ldb_next_request(module, req); @@ -1278,7 +610,7 @@ static int password_hash_add_async(struct ldb_module *module, struct ldb_request return ldb_next_request(module, ac->dom_req); } -static int password_hash_add_async_do_add(struct ldb_async_handle *h) { +static int password_hash_add_do_add(struct ldb_async_handle *h) { struct ph_async_context *ac; struct domain_data *domain; @@ -1357,9 +689,9 @@ static int password_hash_add_async_do_add(struct ldb_async_handle *h) { return ldb_next_request(ac->module, ac->down_req); } -static int password_hash_mod_async_search_self(struct ldb_async_handle *h); +static int password_hash_mod_search_self(struct ldb_async_handle *h); -static int password_hash_modify_async(struct ldb_module *module, struct ldb_request *req) +static int password_hash_modify(struct ldb_module *module, struct ldb_request *req) { struct ldb_async_handle *h; struct ph_async_context *ac; @@ -1367,7 +699,7 @@ static int password_hash_modify_async(struct ldb_module *module, struct ldb_requ struct ldb_message_element *ntAttr; struct ldb_message_element *lmAttr; - ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_add_async\n"); + ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_modify\n"); if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */ return ldb_next_request(module, req); @@ -1437,7 +769,7 @@ static int password_hash_modify_async(struct ldb_module *module, struct ldb_requ if (ac->down_req->op.mod.message->num_elements == 0) { talloc_free(ac->down_req); ac->down_req = NULL; - return password_hash_mod_async_search_self(h); + return password_hash_mod_search_self(h); } ac->down_req->async.context = NULL; @@ -1483,7 +815,7 @@ static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_ return LDB_SUCCESS; } -static int password_hash_mod_async_search_self(struct ldb_async_handle *h) { +static int password_hash_mod_search_self(struct ldb_async_handle *h) { struct ph_async_context *ac; @@ -1515,7 +847,7 @@ static int password_hash_mod_async_search_self(struct ldb_async_handle *h) { return ldb_next_request(ac->module, ac->search_req); } -static int password_hash_mod_async_search_dom(struct ldb_async_handle *h) { +static int password_hash_mod_search_dom(struct ldb_async_handle *h) { struct ph_async_context *ac; struct dom_sid *domain_sid; @@ -1541,7 +873,7 @@ static int password_hash_mod_async_search_dom(struct ldb_async_handle *h) { return ldb_next_request(ac->module, ac->dom_req); } -static int password_hash_mod_async_do_mod(struct ldb_async_handle *h) { +static int password_hash_mod_do_mod(struct ldb_async_handle *h) { struct ph_async_context *ac; struct domain_data *domain; @@ -1700,7 +1032,7 @@ static int ph_async_wait(struct ldb_async_handle *handle) { } /* domain search done, go on */ - return password_hash_add_async_do_add(handle); + return password_hash_add_do_add(handle); case PH_ADD_DO_ADD: ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE); @@ -1737,7 +1069,7 @@ static int ph_async_wait(struct ldb_async_handle *handle) { } /* non-password mods done, go on */ - return password_hash_mod_async_search_self(handle); + return password_hash_mod_search_self(handle); case PH_MOD_SEARCH_SELF: ret = ldb_async_wait(ac->search_req->async.handle, LDB_WAIT_NONE); @@ -1756,7 +1088,7 @@ static int ph_async_wait(struct ldb_async_handle *handle) { } /* self search done, go on */ - return password_hash_mod_async_search_dom(handle); + return password_hash_mod_search_dom(handle); case PH_MOD_SEARCH_DOM: ret = ldb_async_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); @@ -1775,7 +1107,7 @@ static int ph_async_wait(struct ldb_async_handle *handle) { } /* domain search done, go on */ - return password_hash_mod_async_do_mod(handle); + return password_hash_mod_do_mod(handle); case PH_MOD_DO_MOD: ret = ldb_async_wait(ac->mod_req->async.handle, LDB_WAIT_NONE); @@ -1830,27 +1162,10 @@ static int password_hash_async_wait(struct ldb_async_handle *handle, enum ldb_as } } -static int password_hash_request(struct ldb_module *module, struct ldb_request *req) -{ - switch (req->operation) { - - case LDB_REQ_ADD: - return password_hash_add(module, req); - - case LDB_REQ_MODIFY: - return password_hash_modify(module, req); - - default: - return ldb_next_request(module, req); - - } -} - static const struct ldb_module_ops password_hash_ops = { .name = "password_hash", - .add = password_hash_add_async, - .modify = password_hash_modify_async, - .request = password_hash_request, + .add = password_hash_add, + .modify = password_hash_modify, .async_wait = password_hash_async_wait }; -- cgit From 2d19dca9c80a5e3990296dde67163fce36ac883d Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 30 May 2006 00:33:52 +0000 Subject: r15944: rename LDB_ASYNC_ADD -> LDB_ADD, LDB_ASYNC_MODIFY -> LDB_MODIFY, etc... (This used to be commit 55d97ef88f377ef1dbf7b1774a15cf9035e2f320) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 16fe6b8f4d..79c863374c 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -488,7 +488,7 @@ static int build_domain_data_request(struct ph_async_context *ac, ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n"); return LDB_ERR_OPERATIONS_ERROR; } - ac->dom_req->operation = LDB_ASYNC_SEARCH; + ac->dom_req->operation = LDB_SEARCH; ac->dom_req->op.search.base = NULL; ac->dom_req->op.search.scope = LDB_SCOPE_SUBTREE; @@ -828,7 +828,7 @@ static int password_hash_mod_search_self(struct ldb_async_handle *h) { return LDB_ERR_OPERATIONS_ERROR; } - ac->search_req->operation = LDB_ASYNC_SEARCH; + ac->search_req->operation = LDB_SEARCH; ac->search_req->op.search.base = ac->orig_req->op.mod.message->dn; ac->search_req->op.search.scope = LDB_SCOPE_BASE; ac->search_req->op.search.tree = ldb_parse_tree(ac->module->ldb, NULL); -- cgit From 08a48b1803678aee7b51f7625533f1ac7a4ee8ee Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 2 Jun 2006 02:54:24 +0000 Subject: r15999: password_hash module changes: - Quiet some IBM Checker warnings (enum mismatch) - Only search for the attributes we need - fix comments - fix copyrights Andrew Bartlett (This used to be commit ee6fe3a80fd5038c2b141bf8a85139f99ac96e4d) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 79c863374c..a04fb52cd2 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1,8 +1,8 @@ /* ldb database module - Copyright (C) Simo Sorce 2004 - Copyright (C) Andrew Bartlett 2005 + Copyright (C) Simo Sorce 2004-2006 + Copyright (C) Andrew Bartlett 2005-2006 Copyright (C) Andrew Tridgell 2004 This program is free software; you can redistribute it and/or modify @@ -229,7 +229,7 @@ static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_mes struct ldb_val val; int ret; - if (keys[i].key.keytype == ENCTYPE_ARCFOUR_HMAC) { + if (keys[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { /* We might end up doing this below: * This ensures we get the unicode * conversion right. This should also @@ -280,9 +280,9 @@ static int add_krb5_keys_from_NThash(struct ldb_module *module, struct ldb_messa } krb5_ret = krb5_keyblock_init(smb_krb5_context->krb5_context, - ENCTYPE_ARCFOUR_HMAC, - ntPwdHash->hash, sizeof(ntPwdHash->hash), - &key.key); + ETYPE_ARCFOUR_HMAC_MD5, + ntPwdHash->hash, sizeof(ntPwdHash->hash), + &key.key); if (krb5_ret) { return LDB_ERR_OPERATIONS_ERROR; } @@ -818,6 +818,14 @@ static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_ static int password_hash_mod_search_self(struct ldb_async_handle *h) { struct ph_async_context *ac; + static const char * const attrs[] = { "userAccountControl", "sambaLMPwdHistory", + "sambaNTPwdHistory", + "ntPwdHash", + "objectSid", "msDS-KeyVersionNumber", + "objectClass", "userPrincipalName", + "samAccountName", + "lmPwdHash", "ntPwdHash", + NULL }; ac = talloc_get_type(h->private_data, struct ph_async_context); @@ -836,7 +844,7 @@ static int password_hash_mod_search_self(struct ldb_async_handle *h) { ldb_set_errstring(ac->module->ldb, talloc_asprintf(ac, "Invalid search filter")); return LDB_ERR_OPERATIONS_ERROR; } - ac->search_req->op.search.attrs = NULL; + ac->search_req->op.search.attrs = attrs; ac->search_req->controls = NULL; ac->search_req->async.context = ac; ac->search_req->async.callback = get_self_callback; @@ -965,7 +973,7 @@ static int password_hash_mod_do_mod(struct ldb_async_handle *h) { } } - /* add also kr5 keys based on NT the hash */ + /* add also krb5 keys based on NT the hash */ if (add_krb5_keys_from_NThash(ac->module, msg, smb_krb5_context) != LDB_SUCCESS) { return LDB_ERR_OPERATIONS_ERROR; } -- cgit From ca5accf224dc3ef998235603797b519866b57b1c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 4 Jun 2006 05:28:13 +0000 Subject: r16036: Add a couple of new functions to corretly deal with timeouts. Check timeouts are correctly verified. Some minor fixed and removal of unused code. (This used to be commit b52e5d6a0cb1a32e62759eaa49ce3e4cc804cc92) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index a04fb52cd2..8a400fbc63 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -510,6 +510,7 @@ static int build_domain_data_request(struct ph_async_context *ac, ac->dom_req->async.context = ac; ac->dom_req->async.callback = get_domain_data_callback; ac->dom_req->async.timeout = ac->orig_req->async.timeout; + ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->dom_req); return LDB_SUCCESS; } @@ -634,7 +635,7 @@ static int password_hash_add_do_add(struct ldb_async_handle *h) { if (ac->down_req->op.add.message == NULL) { return LDB_ERR_OPERATIONS_ERROR; } - + /* Some operations below require kerberos contexts */ if (smb_krb5_init_context(ac->down_req, &smb_krb5_context) != 0) { return LDB_ERR_OPERATIONS_ERROR; @@ -685,6 +686,8 @@ static int password_hash_add_do_add(struct ldb_async_handle *h) { ac->step = PH_ADD_DO_ADD; + ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->down_req); + /* perform the operation */ return ldb_next_request(ac->module, ac->down_req); } @@ -777,6 +780,8 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r ac->step = PH_MOD_DO_REQ; + ldb_set_timeout_from_prev_req(module->ldb, req, ac->down_req); + return ldb_next_request(module, ac->down_req); } @@ -848,7 +853,7 @@ static int password_hash_mod_search_self(struct ldb_async_handle *h) { ac->search_req->controls = NULL; ac->search_req->async.context = ac; ac->search_req->async.callback = get_self_callback; - ac->search_req->async.timeout = ac->orig_req->async.timeout; + ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->search_req); ac->step = PH_MOD_SEARCH_SELF; @@ -1001,6 +1006,8 @@ static int password_hash_mod_do_mod(struct ldb_async_handle *h) { ac->step = PH_MOD_DO_MOD; + ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->mod_req); + /* perform the search */ return ldb_next_request(ac->module, ac->mod_req); } -- cgit From 4a687bc44fa92a2a3c1848e7431ecc8c26bb9f31 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 15 Jun 2006 00:29:11 +0000 Subject: r16240: Add better error reporting in the password_hash module Remove duplicate attribute in search request Search for the domain by NDR-encoded SID, not string (consistant with the rest of the C code, and helps partially-constructed LDAP backends). Use the default basedn for the domain search. Andrew Bartlett (This used to be commit 2f104612cd6f170dd28fd4ce09156168d47a681a) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 8a400fbc63..2466aac423 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -489,10 +489,11 @@ static int build_domain_data_request(struct ph_async_context *ac, return LDB_ERR_OPERATIONS_ERROR; } ac->dom_req->operation = LDB_SEARCH; - ac->dom_req->op.search.base = NULL; + ac->dom_req->op.search.base = samdb_base_dn(ac); ac->dom_req->op.search.scope = LDB_SCOPE_SUBTREE; - filter = talloc_asprintf(ac->dom_req, "(&(objectSid=%s)(objectClass=domain))", dom_sid_string(ac->dom_req, sid)); + filter = talloc_asprintf(ac->dom_req, "(&(objectSid=%s)(objectClass=domain))", + ldap_encode_ndr_dom_sid(ac->dom_req, sid)); if (filter == NULL) { ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n"); talloc_free(ac->dom_req); @@ -525,6 +526,12 @@ static struct domain_data *get_domain_data(struct ldb_module *module, void *mem_ return NULL; } + if (res == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Could not find this user's domain!\n"); + talloc_free(data); + return NULL; + } + data->pwdProperties = samdb_result_uint(res->message, "pwdProperties", 0); data->pwdHistoryLength = samdb_result_uint(res->message, "pwdHistoryLength", 0); tmp = ldb_msg_find_string(res->message, "dnsDomain", NULL); @@ -575,14 +582,16 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) /* if it is not an entry of type person its an error */ /* TODO: remove this when sambaPassword will be in schema */ if (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "person")) { + ldb_set_errstring(module->ldb, talloc_asprintf(module, "Cannot set a password on entry that does not have objectClass 'person'")); return LDB_ERR_OBJECT_CLASS_VIOLATION; } /* check sambaPassword is single valued here */ /* TODO: remove this when sambaPassword will be single valued in schema */ if (attribute->num_values > 1) { - ldb_set_errstring(module->ldb, talloc_asprintf(req, - "mupltiple values for sambaPassword not allowed!\n")); + ldb_set_errstring(module->ldb, + talloc_asprintf(req, + "mupltiple values for sambaPassword not allowed!\n")); return LDB_ERR_CONSTRAINT_VIOLATION; } @@ -825,7 +834,6 @@ static int password_hash_mod_search_self(struct ldb_async_handle *h) { struct ph_async_context *ac; static const char * const attrs[] = { "userAccountControl", "sambaLMPwdHistory", "sambaNTPwdHistory", - "ntPwdHash", "objectSid", "msDS-KeyVersionNumber", "objectClass", "userPrincipalName", "samAccountName", -- cgit From 6218aef0cab79dd79818adf351b7d5d64562ac05 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 3 Jul 2006 03:37:55 +0000 Subject: r16769: Working on fixing the RPC-SAMR test against Samba4. This fixes password changes which only include the LM and NT hash, such as the original ChangePassword. It also fixes setting passwords on the BUILTIN domain. Finally, the msDS-KeyVersionNumber is only incremented if not explicity set by the modify. Andrew Bartlett (This used to be commit e957f6f4c61c121f79ad518822691e4fd4bf4341) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 172 +++++++++++++++---------- 1 file changed, 106 insertions(+), 66 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 2466aac423..a4816f13db 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -82,6 +82,8 @@ struct ph_async_context { struct ldb_async_result *search_res; struct ldb_request *mod_req; + + struct dom_sid *domain_sid; }; struct domain_data { @@ -474,8 +476,7 @@ static int get_domain_data_callback(struct ldb_context *ldb, void *context, stru return LDB_SUCCESS; } -static int build_domain_data_request(struct ph_async_context *ac, - struct dom_sid *sid) +static int build_domain_data_request(struct ph_async_context *ac) { /* attrs[] is returned from this function in ac->dom_req->op.search.attrs, so it must be static, as @@ -492,8 +493,8 @@ static int build_domain_data_request(struct ph_async_context *ac, ac->dom_req->op.search.base = samdb_base_dn(ac); ac->dom_req->op.search.scope = LDB_SCOPE_SUBTREE; - filter = talloc_asprintf(ac->dom_req, "(&(objectSid=%s)(objectClass=domain))", - ldap_encode_ndr_dom_sid(ac->dom_req, sid)); + filter = talloc_asprintf(ac->dom_req, "(&(objectSid=%s)(|(objectClass=domain)(objectClass=builtinDomain)))", + ldap_encode_ndr_dom_sid(ac->dom_req, ac->domain_sid)); if (filter == NULL) { ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n"); talloc_free(ac->dom_req); @@ -516,18 +517,21 @@ static int build_domain_data_request(struct ph_async_context *ac, return LDB_SUCCESS; } -static struct domain_data *get_domain_data(struct ldb_module *module, void *mem_ctx, struct ldb_async_result *res) +static struct domain_data *get_domain_data(struct ldb_module *module, void *ctx, struct ldb_async_result *res) { struct domain_data *data; const char *tmp; + struct ph_async_context *ac; - data = talloc_zero(mem_ctx, struct domain_data); + ac = talloc_get_type(ctx, struct ph_async_context); + + data = talloc_zero(ac, struct domain_data); if (data == NULL) { return NULL; } if (res == NULL) { - ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Could not find this user's domain!\n"); + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Could not find this user's domain: %s!\n", dom_sid_string(data, ac->domain_sid)); talloc_free(data); return NULL; } @@ -542,7 +546,7 @@ static struct domain_data *get_domain_data(struct ldb_module *module, void *mem_ ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n"); return NULL; } - data->realm = strupper_talloc(mem_ctx, tmp); + data->realm = strupper_talloc(data, tmp); if (data->realm == NULL) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n"); return NULL; @@ -556,8 +560,9 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) { struct ldb_async_handle *h; struct ph_async_context *ac; - struct ldb_message_element *attribute; - struct dom_sid *domain_sid; + struct ldb_message_element *sambaAttr; + struct ldb_message_element *ntAttr; + struct ldb_message_element *lmAttr; int ret; ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_add\n"); @@ -572,10 +577,14 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_UNWILLING_TO_PERFORM; } - /* If no part of this touches the sambaPassword, then we don't - * need to make any changes. For password changes/set there should - * be a 'delete' or a 'modify' on this attribute. */ - if ((attribute = ldb_msg_find_element(req->op.add.message, "sambaPassword")) == NULL ) { + /* If no part of this ADD touches the sambaPassword, or the NT + * or LM hashes, then we don't need to make any changes. */ + + sambaAttr = ldb_msg_find_element(req->op.mod.message, "sambaPassword"); + ntAttr = ldb_msg_find_element(req->op.mod.message, "ntPwdHash"); + lmAttr = ldb_msg_find_element(req->op.mod.message, "lmPwdHash"); + + if ((!sambaAttr) && (!ntAttr) && (!lmAttr)) { return ldb_next_request(module, req); } @@ -588,16 +597,31 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) /* check sambaPassword is single valued here */ /* TODO: remove this when sambaPassword will be single valued in schema */ - if (attribute->num_values > 1) { + if (sambaAttr->num_values > 1) { ldb_set_errstring(module->ldb, talloc_asprintf(req, "mupltiple values for sambaPassword not allowed!\n")); return LDB_ERR_CONSTRAINT_VIOLATION; } + if (ntAttr && (ntAttr->num_values > 1)) { + ldb_set_errstring(module->ldb, + talloc_asprintf(req, + "mupltiple values for lmPwdHash not allowed!\n")); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + if (lmAttr && (lmAttr->num_values > 1)) { + ldb_set_errstring(module->ldb, + talloc_asprintf(req, + "mupltiple values for lmPwdHash not allowed!\n")); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + ac = talloc_get_type(h->private_data, struct ph_async_context); + /* get user domain data */ - domain_sid = samdb_result_sid_prefix(req, req->op.add.message, "objectSid"); - if (domain_sid == NULL) { + ac->domain_sid = samdb_result_sid_prefix(ac, req->op.add.message, "objectSid"); + if (ac->domain_sid == NULL) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, "can't handle entry with missing objectSid!\n"); return LDB_ERR_OPERATIONS_ERROR; } @@ -606,9 +630,7 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) if (!h) { return LDB_ERR_OPERATIONS_ERROR; } - ac = talloc_get_type(h->private_data, struct ph_async_context); - - ret = build_domain_data_request(ac, domain_sid); + ret = build_domain_data_request(ac); if (ret != LDB_SUCCESS) { return ret; } @@ -625,7 +647,9 @@ static int password_hash_add_do_add(struct ldb_async_handle *h) { struct ph_async_context *ac; struct domain_data *domain; struct smb_krb5_context *smb_krb5_context; + struct ldb_message_element *sambaAttr; struct ldb_message *msg; + int ret; ac = talloc_get_type(h->private_data, struct ph_async_context); @@ -650,30 +674,36 @@ static int password_hash_add_do_add(struct ldb_async_handle *h) { return LDB_ERR_OPERATIONS_ERROR; } - /* we can compute new password hashes from the unicode password */ - if (add_password_hashes(ac->module, msg, 0) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - - /* now add krb5 keys based on unicode password */ - if (add_krb5_keys_from_password(ac->module, msg, smb_krb5_context, domain, - ldb_msg_find_string(msg, "samAccountName", NULL), - ldb_msg_find_string(msg, "userPrincipalName", NULL), - ldb_msg_check_string_attribute(msg, "objectClass", "computer") - ) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - - /* add also kr5 keys based on NT the hash */ - if (add_krb5_keys_from_NThash(ac->module, msg, smb_krb5_context) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; - } - - /* if both the domain properties and the user account controls do not permit - * clear text passwords then wipe out the sambaPassword */ - if ((!(domain->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT)) || - (!(ldb_msg_find_uint(msg, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED))) { - ldb_msg_remove_attr(msg, "sambaPassword"); + /* if we have sambaPassword in the original message add the operatio on it here */ + sambaAttr = ldb_msg_find_element(msg, "sambaPassword"); + if (sambaAttr) { + ret = add_password_hashes(ac->module, msg, 0); + /* we can compute new password hashes from the unicode password */ + if (ret != LDB_SUCCESS) { + return ret; + } + + /* now add krb5 keys based on unicode password */ + ret = add_krb5_keys_from_password(ac->module, msg, smb_krb5_context, domain, + ldb_msg_find_string(msg, "samAccountName", NULL), + ldb_msg_find_string(msg, "userPrincipalName", NULL), + ldb_msg_check_string_attribute(msg, "objectClass", "computer")); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* add also kr5 keys based on NT the hash */ + ret = add_krb5_keys_from_NThash(ac->module, msg, smb_krb5_context); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* if both the domain properties and the user account controls do not permit + * clear text passwords then wipe out the sambaPassword */ + if ((!(domain->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT)) || + (!(ldb_msg_find_uint(msg, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED))) { + ldb_msg_remove_attr(msg, "sambaPassword"); + } } /* don't touch it if a value is set. It could be an incoming samsync */ @@ -871,20 +901,19 @@ static int password_hash_mod_search_self(struct ldb_async_handle *h) { static int password_hash_mod_search_dom(struct ldb_async_handle *h) { struct ph_async_context *ac; - struct dom_sid *domain_sid; int ret; ac = talloc_get_type(h->private_data, struct ph_async_context); /* get object domain sid */ - domain_sid = samdb_result_sid_prefix(ac, ac->search_res->message, "objectSid"); - if (domain_sid == NULL) { + ac->domain_sid = samdb_result_sid_prefix(ac, ac->search_res->message, "objectSid"); + if (ac->domain_sid == NULL) { ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "can't handle entry with missing objectSid!\n"); return LDB_ERR_OPERATIONS_ERROR; } /* get user domain data */ - ret = build_domain_data_request(ac, domain_sid); + ret = build_domain_data_request(ac); if (ret != LDB_SUCCESS) { return ret; } @@ -902,6 +931,8 @@ static int password_hash_mod_do_mod(struct ldb_async_handle *h) { struct ldb_message_element *sambaAttr; struct ldb_message *msg; int phlen; + int ret; + BOOL added_hashes = False; ac = talloc_get_type(h->private_data, struct ph_async_context); @@ -936,7 +967,7 @@ static int password_hash_mod_do_mod(struct ldb_async_handle *h) { return LDB_ERR_OPERATIONS_ERROR; } - /* if we have sambaPassword in the original message add the operatio on it here */ + /* if we have sambaPassword in the original message add the operation on it here */ sambaAttr = ldb_msg_find_element(ac->orig_req->op.mod.message, "sambaPassword"); if (sambaAttr) { @@ -944,21 +975,26 @@ static int password_hash_mod_do_mod(struct ldb_async_handle *h) { return LDB_ERR_OPERATIONS_ERROR; } - /* we are not deleteing it add password hashes */ - if ((sambaAttr->flags & LDB_FLAG_MOD_MASK) != LDB_FLAG_MOD_DELETE) { - + /* if we are actually settting a new unicode password, + * use it to generate the password hashes */ + if (((sambaAttr->flags & LDB_FLAG_MOD_MASK) != LDB_FLAG_MOD_DELETE) + && (sambaAttr->num_values == 1)) { /* we can compute new password hashes from the unicode password */ - if (add_password_hashes(ac->module, msg, 1) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + ret = add_password_hashes(ac->module, msg, 1); + if (ret != LDB_SUCCESS) { + return ret; } + added_hashes = True; + /* now add krb5 keys based on unicode password */ - if (add_krb5_keys_from_password(ac->module, msg, smb_krb5_context, domain, - ldb_msg_find_string(ac->search_res->message, "samAccountName", NULL), - ldb_msg_find_string(ac->search_res->message, "userPrincipalName", NULL), - ldb_msg_check_string_attribute(ac->search_res->message, "objectClass", "computer") - ) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + ret = add_krb5_keys_from_password(ac->module, msg, smb_krb5_context, domain, + ldb_msg_find_string(ac->search_res->message, "samAccountName", NULL), + ldb_msg_find_string(ac->search_res->message, "userPrincipalName", NULL), + ldb_msg_check_string_attribute(ac->search_res->message, "objectClass", "computer")); + + if (ret != LDB_SUCCESS) { + return ret; } /* if the domain properties or the user account controls do not permit @@ -971,8 +1007,8 @@ static int password_hash_mod_do_mod(struct ldb_async_handle *h) { } } - /* if we don't have sambaPassword or we are trying to delete it try with nt or lm hasehs */ - if ((!sambaAttr) || ((sambaAttr->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_DELETE)) { + /* if we didn't create the hashes above, try using values supplied directly */ + if (!added_hashes) { struct ldb_message_element *el; el = ldb_msg_find_element(ac->orig_req->op.mod.message, "ntPwdHash"); @@ -997,10 +1033,14 @@ static int password_hash_mod_do_mod(struct ldb_async_handle *h) { } /* don't touch it if a value is set. It could be an incoming samsync */ - if (add_keyVersionNumber(ac->module, msg, - ldb_msg_find_uint(msg, "msDS-KeyVersionNumber", 0) - ) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + if (!ldb_msg_find_element(ac->orig_req->op.mod.message, + "msDS-KeyVersionNumber")) { + if (add_keyVersionNumber(ac->module, msg, + ldb_msg_find_uint(ac->search_res->message, + "msDS-KeyVersionNumber", 0) + ) != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } } if ((phlen = samdb_result_uint(ac->dom_res->message, "pwdHistoryLength", 0)) > 0) { -- cgit From a3f606f6cab58e7e15f8a4f6a05a7437dc0569c8 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 3 Jul 2006 15:49:23 +0000 Subject: r16784: - make some function in ldb static, they not need to be exported anywhere - fix a bad segfault Andrew please make test before committing. Simo. (This used to be commit b9b6bb3e89d3b0e04ccce15156c1a128b6f20d88) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index a4816f13db..9d7c78487a 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -617,6 +617,10 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_CONSTRAINT_VIOLATION; } + h = ph_init_handle(req, module, PH_ADD); + if (!h) { + return LDB_ERR_OPERATIONS_ERROR; + } ac = talloc_get_type(h->private_data, struct ph_async_context); /* get user domain data */ @@ -626,10 +630,6 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_OPERATIONS_ERROR; } - h = ph_init_handle(req, module, PH_ADD); - if (!h) { - return LDB_ERR_OPERATIONS_ERROR; - } ret = build_domain_data_request(ac); if (ret != LDB_SUCCESS) { return ret; -- cgit From 3ed1e8ff3c351296adfa78a99c19cc7b0fd5d7e7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 6 Jul 2006 05:51:39 +0000 Subject: r16829: Fix a number of issues raised by the IBM checker, or gcc warnings. In particular, this removes one use of the LDB_DN_NULL_FAILED macro, which was being used on more than DNs, had an embedded goto, and confused the IBM checker. In the password_hash code, ensure that sambaAttr is not, before checking the number of values. In GENSEC, note that this switch value can't occour. This seems to be the only way to quiet both the IBM checker and gcc, as well as cope with possibly invalid inputs. Andrew Bartlet (This used to be commit 3e58350ec2ab883795b1dd03ac46a3520cac67d0) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 9d7c78487a..abb267d884 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -597,7 +597,7 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) /* check sambaPassword is single valued here */ /* TODO: remove this when sambaPassword will be single valued in schema */ - if (sambaAttr->num_values > 1) { + if (sambaAttr && sambaAttr->num_values > 1) { ldb_set_errstring(module->ldb, talloc_asprintf(req, "mupltiple values for sambaPassword not allowed!\n")); -- cgit From c93817b36d3ff7f44cb7b3e1d1a29e37ec12affe Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 22 Jul 2006 16:56:33 +0000 Subject: r17185: Oh, I wanted to do this for sooo long time. Finally acknowledge that ldb is inherently async and does not have a dual personality anymore Rename all ldb_async_XXX functions to ldb_XXX except for ldb_async_result, it is now ldb_reply to reflect the real function of this structure. Simo. (This used to be commit 25fc7354049d62efeba17681ef1cdd326bc3f2ef) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 104 ++++++++++++------------- 1 file changed, 52 insertions(+), 52 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index abb267d884..d6c2a45217 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -65,7 +65,7 @@ * */ -struct ph_async_context { +struct ph_context { enum ph_type {PH_ADD, PH_MOD} type; enum ph_step {PH_ADD_SEARCH_DOM, PH_ADD_DO_ADD, PH_MOD_DO_REQ, PH_MOD_SEARCH_SELF, PH_MOD_SEARCH_DOM, PH_MOD_DO_MOD} step; @@ -74,12 +74,12 @@ struct ph_async_context { struct ldb_request *orig_req; struct ldb_request *dom_req; - struct ldb_async_result *dom_res; + struct ldb_reply *dom_res; struct ldb_request *down_req; struct ldb_request *search_req; - struct ldb_async_result *search_res; + struct ldb_reply *search_res; struct ldb_request *mod_req; @@ -418,12 +418,12 @@ static int setPwdHistory(struct ldb_module *module, struct ldb_message *msg, str return LDB_SUCCESS; } -static struct ldb_async_handle *ph_init_handle(struct ldb_request *req, struct ldb_module *module, enum ph_type type) +static struct ldb_handle *ph_init_handle(struct ldb_request *req, struct ldb_module *module, enum ph_type type) { - struct ph_async_context *ac; - struct ldb_async_handle *h; + struct ph_context *ac; + struct ldb_handle *h; - h = talloc_zero(req, struct ldb_async_handle); + h = talloc_zero(req, struct ldb_handle); if (h == NULL) { ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory")); return NULL; @@ -431,7 +431,7 @@ static struct ldb_async_handle *ph_init_handle(struct ldb_request *req, struct l h->module = module; - ac = talloc_zero(h, struct ph_async_context); + ac = talloc_zero(h, struct ph_context); if (ac == NULL) { ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory")); talloc_free(h); @@ -450,16 +450,16 @@ static struct ldb_async_handle *ph_init_handle(struct ldb_request *req, struct l return h; } -static int get_domain_data_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares) +static int get_domain_data_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) { - struct ph_async_context *ac; + struct ph_context *ac; if (!context || !ares) { ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context or Result in callback")); return LDB_ERR_OPERATIONS_ERROR; } - ac = talloc_get_type(context, struct ph_async_context); + ac = talloc_get_type(context, struct ph_context); /* we are interested only in the single reply (base search) we receive here */ if (ares->type == LDB_REPLY_ENTRY) { @@ -476,7 +476,7 @@ static int get_domain_data_callback(struct ldb_context *ldb, void *context, stru return LDB_SUCCESS; } -static int build_domain_data_request(struct ph_async_context *ac) +static int build_domain_data_request(struct ph_context *ac) { /* attrs[] is returned from this function in ac->dom_req->op.search.attrs, so it must be static, as @@ -517,13 +517,13 @@ static int build_domain_data_request(struct ph_async_context *ac) return LDB_SUCCESS; } -static struct domain_data *get_domain_data(struct ldb_module *module, void *ctx, struct ldb_async_result *res) +static struct domain_data *get_domain_data(struct ldb_module *module, void *ctx, struct ldb_reply *res) { struct domain_data *data; const char *tmp; - struct ph_async_context *ac; + struct ph_context *ac; - ac = talloc_get_type(ctx, struct ph_async_context); + ac = talloc_get_type(ctx, struct ph_context); data = talloc_zero(ac, struct domain_data); if (data == NULL) { @@ -558,8 +558,8 @@ static struct domain_data *get_domain_data(struct ldb_module *module, void *ctx, static int password_hash_add(struct ldb_module *module, struct ldb_request *req) { - struct ldb_async_handle *h; - struct ph_async_context *ac; + struct ldb_handle *h; + struct ph_context *ac; struct ldb_message_element *sambaAttr; struct ldb_message_element *ntAttr; struct ldb_message_element *lmAttr; @@ -621,7 +621,7 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) if (!h) { return LDB_ERR_OPERATIONS_ERROR; } - ac = talloc_get_type(h->private_data, struct ph_async_context); + ac = talloc_get_type(h->private_data, struct ph_context); /* get user domain data */ ac->domain_sid = samdb_result_sid_prefix(ac, req->op.add.message, "objectSid"); @@ -642,16 +642,16 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, ac->dom_req); } -static int password_hash_add_do_add(struct ldb_async_handle *h) { +static int password_hash_add_do_add(struct ldb_handle *h) { - struct ph_async_context *ac; + struct ph_context *ac; struct domain_data *domain; struct smb_krb5_context *smb_krb5_context; struct ldb_message_element *sambaAttr; struct ldb_message *msg; int ret; - ac = talloc_get_type(h->private_data, struct ph_async_context); + ac = talloc_get_type(h->private_data, struct ph_context); domain = get_domain_data(ac->module, ac, ac->dom_res); if (domain == NULL) { @@ -731,12 +731,12 @@ static int password_hash_add_do_add(struct ldb_async_handle *h) { return ldb_next_request(ac->module, ac->down_req); } -static int password_hash_mod_search_self(struct ldb_async_handle *h); +static int password_hash_mod_search_self(struct ldb_handle *h); static int password_hash_modify(struct ldb_module *module, struct ldb_request *req) { - struct ldb_async_handle *h; - struct ph_async_context *ac; + struct ldb_handle *h; + struct ph_context *ac; struct ldb_message_element *sambaAttr; struct ldb_message_element *ntAttr; struct ldb_message_element *lmAttr; @@ -784,7 +784,7 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r if (!h) { return LDB_ERR_OPERATIONS_ERROR; } - ac = talloc_get_type(h->private_data, struct ph_async_context); + ac = talloc_get_type(h->private_data, struct ph_context); /* return or own handle to deal with this call */ req->async.handle = h; @@ -824,16 +824,16 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r return ldb_next_request(module, ac->down_req); } -static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares) +static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) { - struct ph_async_context *ac; + struct ph_context *ac; if (!context || !ares) { ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context or Result in callback")); return LDB_ERR_OPERATIONS_ERROR; } - ac = talloc_get_type(context, struct ph_async_context); + ac = talloc_get_type(context, struct ph_context); /* we are interested only in the single reply (base search) we receive here */ if (ares->type == LDB_REPLY_ENTRY) { @@ -859,9 +859,9 @@ static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_ return LDB_SUCCESS; } -static int password_hash_mod_search_self(struct ldb_async_handle *h) { +static int password_hash_mod_search_self(struct ldb_handle *h) { - struct ph_async_context *ac; + struct ph_context *ac; static const char * const attrs[] = { "userAccountControl", "sambaLMPwdHistory", "sambaNTPwdHistory", "objectSid", "msDS-KeyVersionNumber", @@ -870,7 +870,7 @@ static int password_hash_mod_search_self(struct ldb_async_handle *h) { "lmPwdHash", "ntPwdHash", NULL }; - ac = talloc_get_type(h->private_data, struct ph_async_context); + ac = talloc_get_type(h->private_data, struct ph_context); /* prepare the search operation */ ac->search_req = talloc_zero(ac, struct ldb_request); @@ -898,12 +898,12 @@ static int password_hash_mod_search_self(struct ldb_async_handle *h) { return ldb_next_request(ac->module, ac->search_req); } -static int password_hash_mod_search_dom(struct ldb_async_handle *h) { +static int password_hash_mod_search_dom(struct ldb_handle *h) { - struct ph_async_context *ac; + struct ph_context *ac; int ret; - ac = talloc_get_type(h->private_data, struct ph_async_context); + ac = talloc_get_type(h->private_data, struct ph_context); /* get object domain sid */ ac->domain_sid = samdb_result_sid_prefix(ac, ac->search_res->message, "objectSid"); @@ -923,9 +923,9 @@ static int password_hash_mod_search_dom(struct ldb_async_handle *h) { return ldb_next_request(ac->module, ac->dom_req); } -static int password_hash_mod_do_mod(struct ldb_async_handle *h) { +static int password_hash_mod_do_mod(struct ldb_handle *h) { - struct ph_async_context *ac; + struct ph_context *ac; struct domain_data *domain; struct smb_krb5_context *smb_krb5_context; struct ldb_message_element *sambaAttr; @@ -934,7 +934,7 @@ static int password_hash_mod_do_mod(struct ldb_async_handle *h) { int ret; BOOL added_hashes = False; - ac = talloc_get_type(h->private_data, struct ph_async_context); + ac = talloc_get_type(h->private_data, struct ph_context); domain = get_domain_data(ac->module, ac, ac->dom_res); if (domain == NULL) { @@ -1060,8 +1060,8 @@ static int password_hash_mod_do_mod(struct ldb_async_handle *h) { return ldb_next_request(ac->module, ac->mod_req); } -static int ph_async_wait(struct ldb_async_handle *handle) { - struct ph_async_context *ac; +static int ph_wait(struct ldb_handle *handle) { + struct ph_context *ac; int ret; if (!handle || !handle->private_data) { @@ -1075,11 +1075,11 @@ static int ph_async_wait(struct ldb_async_handle *handle) { handle->state = LDB_ASYNC_PENDING; handle->status = LDB_SUCCESS; - ac = talloc_get_type(handle->private_data, struct ph_async_context); + ac = talloc_get_type(handle->private_data, struct ph_context); switch (ac->step) { case PH_ADD_SEARCH_DOM: - ret = ldb_async_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; @@ -1098,7 +1098,7 @@ static int ph_async_wait(struct ldb_async_handle *handle) { return password_hash_add_do_add(handle); case PH_ADD_DO_ADD: - ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->down_req->async.handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; @@ -1116,7 +1116,7 @@ static int ph_async_wait(struct ldb_async_handle *handle) { break; case PH_MOD_DO_REQ: - ret = ldb_async_wait(ac->down_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->down_req->async.handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; @@ -1135,7 +1135,7 @@ static int ph_async_wait(struct ldb_async_handle *handle) { return password_hash_mod_search_self(handle); case PH_MOD_SEARCH_SELF: - ret = ldb_async_wait(ac->search_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->search_req->async.handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; @@ -1154,7 +1154,7 @@ static int ph_async_wait(struct ldb_async_handle *handle) { return password_hash_mod_search_dom(handle); case PH_MOD_SEARCH_DOM: - ret = ldb_async_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; @@ -1173,7 +1173,7 @@ static int ph_async_wait(struct ldb_async_handle *handle) { return password_hash_mod_do_mod(handle); case PH_MOD_DO_MOD: - ret = ldb_async_wait(ac->mod_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->mod_req->async.handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; @@ -1202,12 +1202,12 @@ done: return ret; } -static int ph_async_wait_all(struct ldb_async_handle *handle) { +static int ph_wait_all(struct ldb_handle *handle) { int ret; while (handle->state != LDB_ASYNC_DONE) { - ret = ph_async_wait(handle); + ret = ph_wait(handle); if (ret != LDB_SUCCESS) { return ret; } @@ -1216,12 +1216,12 @@ static int ph_async_wait_all(struct ldb_async_handle *handle) { return handle->status; } -static int password_hash_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type) +static int password_hash_wait(struct ldb_handle *handle, enum ldb_wait_type type) { if (type == LDB_WAIT_ALL) { - return ph_async_wait_all(handle); + return ph_wait_all(handle); } else { - return ph_async_wait(handle); + return ph_wait(handle); } } @@ -1229,7 +1229,7 @@ static const struct ldb_module_ops password_hash_ops = { .name = "password_hash", .add = password_hash_add, .modify = password_hash_modify, - .async_wait = password_hash_async_wait + .wait = password_hash_wait }; -- cgit From 49f68caed20d2a7d1850e493005bdf85929d6365 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 22 Jul 2006 17:21:59 +0000 Subject: r17186: "async" word abuse clean-up part 2 (This used to be commit c6aa60c7e69abf1f83efc150b1c3ed02751c45fc) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 66 +++++++++++++------------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index d6c2a45217..ec42249633 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -509,9 +509,9 @@ static int build_domain_data_request(struct ph_context *ac) } ac->dom_req->op.search.attrs = attrs; ac->dom_req->controls = NULL; - ac->dom_req->async.context = ac; - ac->dom_req->async.callback = get_domain_data_callback; - ac->dom_req->async.timeout = ac->orig_req->async.timeout; + ac->dom_req->context = ac; + ac->dom_req->callback = get_domain_data_callback; + ac->dom_req->timeout = ac->orig_req->timeout; ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->dom_req); return LDB_SUCCESS; @@ -637,7 +637,7 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) ac->step = PH_ADD_SEARCH_DOM; - req->async.handle = h; + req->handle = h; return ldb_next_request(module, ac->dom_req); } @@ -787,7 +787,7 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r ac = talloc_get_type(h->private_data, struct ph_context); /* return or own handle to deal with this call */ - req->async.handle = h; + req->handle = h; /* prepare the first operation */ ac->down_req = talloc_zero(ac, struct ldb_request); @@ -814,8 +814,8 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r return password_hash_mod_search_self(h); } - ac->down_req->async.context = NULL; - ac->down_req->async.callback = NULL; + ac->down_req->context = NULL; + ac->down_req->callback = NULL; ac->step = PH_MOD_DO_REQ; @@ -889,8 +889,8 @@ static int password_hash_mod_search_self(struct ldb_handle *h) { } ac->search_req->op.search.attrs = attrs; ac->search_req->controls = NULL; - ac->search_req->async.context = ac; - ac->search_req->async.callback = get_self_callback; + ac->search_req->context = ac; + ac->search_req->callback = get_self_callback; ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->search_req); ac->step = PH_MOD_SEARCH_SELF; @@ -1079,18 +1079,18 @@ static int ph_wait(struct ldb_handle *handle) { switch (ac->step) { case PH_ADD_SEARCH_DOM: - ret = ldb_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->dom_req->handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; goto done; } - if (ac->dom_req->async.handle->status != LDB_SUCCESS) { - handle->status = ac->dom_req->async.handle->status; + if (ac->dom_req->handle->status != LDB_SUCCESS) { + handle->status = ac->dom_req->handle->status; goto done; } - if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { + if (ac->dom_req->handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } @@ -1098,36 +1098,36 @@ static int ph_wait(struct ldb_handle *handle) { return password_hash_add_do_add(handle); case PH_ADD_DO_ADD: - ret = ldb_wait(ac->down_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->down_req->handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; goto done; } - if (ac->down_req->async.handle->status != LDB_SUCCESS) { - handle->status = ac->down_req->async.handle->status; + if (ac->down_req->handle->status != LDB_SUCCESS) { + handle->status = ac->down_req->handle->status; goto done; } - if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { + if (ac->down_req->handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } break; case PH_MOD_DO_REQ: - ret = ldb_wait(ac->down_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->down_req->handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; goto done; } - if (ac->down_req->async.handle->status != LDB_SUCCESS) { - handle->status = ac->down_req->async.handle->status; + if (ac->down_req->handle->status != LDB_SUCCESS) { + handle->status = ac->down_req->handle->status; goto done; } - if (ac->down_req->async.handle->state != LDB_ASYNC_DONE) { + if (ac->down_req->handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } @@ -1135,18 +1135,18 @@ static int ph_wait(struct ldb_handle *handle) { return password_hash_mod_search_self(handle); case PH_MOD_SEARCH_SELF: - ret = ldb_wait(ac->search_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; goto done; } - if (ac->search_req->async.handle->status != LDB_SUCCESS) { - handle->status = ac->search_req->async.handle->status; + if (ac->search_req->handle->status != LDB_SUCCESS) { + handle->status = ac->search_req->handle->status; goto done; } - if (ac->search_req->async.handle->state != LDB_ASYNC_DONE) { + if (ac->search_req->handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } @@ -1154,18 +1154,18 @@ static int ph_wait(struct ldb_handle *handle) { return password_hash_mod_search_dom(handle); case PH_MOD_SEARCH_DOM: - ret = ldb_wait(ac->dom_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->dom_req->handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; goto done; } - if (ac->dom_req->async.handle->status != LDB_SUCCESS) { - handle->status = ac->dom_req->async.handle->status; + if (ac->dom_req->handle->status != LDB_SUCCESS) { + handle->status = ac->dom_req->handle->status; goto done; } - if (ac->dom_req->async.handle->state != LDB_ASYNC_DONE) { + if (ac->dom_req->handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } @@ -1173,18 +1173,18 @@ static int ph_wait(struct ldb_handle *handle) { return password_hash_mod_do_mod(handle); case PH_MOD_DO_MOD: - ret = ldb_wait(ac->mod_req->async.handle, LDB_WAIT_NONE); + ret = ldb_wait(ac->mod_req->handle, LDB_WAIT_NONE); if (ret != LDB_SUCCESS) { handle->status = ret; goto done; } - if (ac->mod_req->async.handle->status != LDB_SUCCESS) { - handle->status = ac->mod_req->async.handle->status; + if (ac->mod_req->handle->status != LDB_SUCCESS) { + handle->status = ac->mod_req->handle->status; goto done; } - if (ac->mod_req->async.handle->state != LDB_ASYNC_DONE) { + if (ac->mod_req->handle->state != LDB_ASYNC_DONE) { return LDB_SUCCESS; } -- cgit From 56b1714e9c40dfeae855d0917d78fc0ddc04162e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 28 Jul 2006 06:30:03 +0000 Subject: r17288: Don't mess with entries in the local password prefix, and fix const warnings. Andrew Bartlett (This used to be commit 4569c58a42e1d65ae71ee57e391b9e3dbaba2218) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index ec42249633..ae02eb9e98 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -44,6 +44,7 @@ #include "dsdb/samdb/samdb.h" #include "ads.h" #include "hdb.h" +#include "dsdb/samdb/ldb_modules/password_modules.h" /* If we have decided there is reason to work on this request, then * setup all the password hash types correctly. @@ -571,6 +572,13 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } + /* If the caller is manipulating the local passwords directly, let them pass */ + if (ldb_dn_compare_base(module->ldb, + ldb_dn_explode(req, LOCAL_BASE), + req->op.add.message->dn) == 0) { + return ldb_next_request(module, req); + } + /* nobody must touch password Histories */ if (ldb_msg_find_element(req->op.add.message, "sambaNTPwdHistory") || ldb_msg_find_element(req->op.add.message, "sambaLMPwdHistory")) { @@ -740,6 +748,7 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r struct ldb_message_element *sambaAttr; struct ldb_message_element *ntAttr; struct ldb_message_element *lmAttr; + struct ldb_message *msg; ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_modify\n"); @@ -747,6 +756,13 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r return ldb_next_request(module, req); } + /* If the caller is manipulating the local passwords directly, let them pass */ + if (ldb_dn_compare_base(module->ldb, + ldb_dn_explode(req, LOCAL_BASE), + req->op.mod.message->dn) == 0) { + return ldb_next_request(module, req); + } + /* nobody must touch password Histories */ if (ldb_msg_find_element(req->op.mod.message, "sambaNTPwdHistory") || ldb_msg_find_element(req->op.mod.message, "sambaLMPwdHistory")) { @@ -799,16 +815,16 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r *(ac->down_req) = *req; /* copy the request */ /* use a new message structure so that we can modify it */ - ac->down_req->op.mod.message = ldb_msg_copy_shallow(ac->down_req, req->op.mod.message); + ac->down_req->op.mod.message = msg = ldb_msg_copy_shallow(ac->down_req, req->op.mod.message); /* - remove any imodification to the password from the first commit * we will make the real modification later */ - if (sambaAttr) ldb_msg_remove_attr(ac->down_req->op.mod.message, "sambaPassword"); - if (ntAttr) ldb_msg_remove_attr(ac->down_req->op.mod.message, "ntPwdHash"); - if (lmAttr) ldb_msg_remove_attr(ac->down_req->op.mod.message, "lmPwdHash"); + if (sambaAttr) ldb_msg_remove_attr(msg, "sambaPassword"); + if (ntAttr) ldb_msg_remove_attr(msg, "ntPwdHash"); + if (lmAttr) ldb_msg_remove_attr(msg, "lmPwdHash"); /* if there was nothing else to be modify skip to next step */ - if (ac->down_req->op.mod.message->num_elements == 0) { + if (msg->num_elements == 0) { talloc_free(ac->down_req); ac->down_req = NULL; return password_hash_mod_search_self(h); -- cgit From 8b9e08fe76bb324b78ff33b766a46dec2f7492ec Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 12 Aug 2006 15:22:58 +0000 Subject: r17505: we are setting the timeout with the provide function right after. (This used to be commit 6520e3c83acfbb7b6aa63d1cbebe8f8801db292f) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index ae02eb9e98..804235258f 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -512,7 +512,6 @@ static int build_domain_data_request(struct ph_context *ac) ac->dom_req->controls = NULL; ac->dom_req->context = ac; ac->dom_req->callback = get_domain_data_callback; - ac->dom_req->timeout = ac->orig_req->timeout; ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->dom_req); return LDB_SUCCESS; -- cgit From faed8175063b16df94d5332581baf1af0562bb09 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 13 Aug 2006 07:33:57 +0000 Subject: r17514: Simplify the way to set ldb errors and add another helper function to set them. (This used to be commit 260868bae56194fcb98d55afc22fc66d96a303df) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 68 ++++++++++++-------------- 1 file changed, 30 insertions(+), 38 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 804235258f..93af3ae260 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -156,10 +156,10 @@ static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_mes char *name = talloc_strdup(msg, samAccountName); char *saltbody; if (name == NULL) { - ldb_set_errstring(module->ldb, - talloc_asprintf(msg, "password_hash_handle: " - "generation of new kerberos keys failed: %s is a computer without a samAccountName", - ldb_dn_linearize(msg, msg->dn))); + ldb_asprintf_errstring(module->ldb, + "password_hash_handle: " + "generation of new kerberos keys failed: %s is a computer without a samAccountName", + ldb_dn_linearize(msg, msg->dn)); return LDB_ERR_OPERATIONS_ERROR; } if (name[strlen(name)-1] == '$') { @@ -187,10 +187,10 @@ static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_mes } } else { if (!samAccountName) { - ldb_set_errstring(module->ldb, - talloc_asprintf(msg, "password_hash_handle: " - "generation of new kerberos keys failed: %s has no samAccountName", - ldb_dn_linearize(msg, msg->dn))); + ldb_asprintf_errstring(module->ldb, + "password_hash_handle: " + "generation of new kerberos keys failed: %s has no samAccountName", + ldb_dn_linearize(msg, msg->dn)); return LDB_ERR_OPERATIONS_ERROR; } krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, @@ -200,11 +200,10 @@ static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_mes } if (krb5_ret) { - ldb_set_errstring(module->ldb, - talloc_asprintf(msg, "password_hash_handle: " - "generation of a saltking principal failed: %s", - smb_get_krb5_error_message(smb_krb5_context->krb5_context, - krb5_ret, msg))); + ldb_asprintf_errstring(module->ldb, + "password_hash_handle: " + "generation of a saltking principal failed: %s", + smb_get_krb5_error_message(smb_krb5_context->krb5_context, krb5_ret, msg)); return LDB_ERR_OPERATIONS_ERROR; } @@ -214,11 +213,10 @@ static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_mes krb5_free_principal(smb_krb5_context->krb5_context, salt_principal); if (krb5_ret) { - ldb_set_errstring(module->ldb, - talloc_asprintf(msg, "password_hash_handle: " - "generation of new kerberos keys failed: %s", - smb_get_krb5_error_message(smb_krb5_context->krb5_context, - krb5_ret, msg))); + ldb_asprintf_errstring(module->ldb, + "password_hash_handle: " + "generation of new kerberos keys failed: %s", + smb_get_krb5_error_message(smb_krb5_context->krb5_context, krb5_ret, msg)); return LDB_ERR_OPERATIONS_ERROR; } @@ -426,7 +424,7 @@ static struct ldb_handle *ph_init_handle(struct ldb_request *req, struct ldb_mod h = talloc_zero(req, struct ldb_handle); if (h == NULL) { - ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory")); + ldb_set_errstring(module->ldb, "Out of Memory"); return NULL; } @@ -434,7 +432,7 @@ static struct ldb_handle *ph_init_handle(struct ldb_request *req, struct ldb_mod ac = talloc_zero(h, struct ph_context); if (ac == NULL) { - ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory")); + ldb_set_errstring(module->ldb, "Out of Memory"); talloc_free(h); return NULL; } @@ -456,7 +454,7 @@ static int get_domain_data_callback(struct ldb_context *ldb, void *context, stru struct ph_context *ac; if (!context || !ares) { - ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context or Result in callback")); + ldb_set_errstring(ldb, "NULL Context or Result in callback"); return LDB_ERR_OPERATIONS_ERROR; } @@ -465,7 +463,7 @@ static int get_domain_data_callback(struct ldb_context *ldb, void *context, stru /* we are interested only in the single reply (base search) we receive here */ if (ares->type == LDB_REPLY_ENTRY) { if (ac->dom_res != NULL) { - ldb_set_errstring(ldb, talloc_asprintf(ldb, "Too many results")); + ldb_set_errstring(ldb, "Too many results"); talloc_free(ares); return LDB_ERR_OPERATIONS_ERROR; } @@ -504,7 +502,7 @@ static int build_domain_data_request(struct ph_context *ac) ac->dom_req->op.search.tree = ldb_parse_tree(ac->module->ldb, filter); if (ac->dom_req->op.search.tree == NULL) { - ldb_set_errstring(ac->module->ldb, talloc_asprintf(ac, "Invalid search filter")); + ldb_set_errstring(ac->module->ldb, "Invalid search filter"); talloc_free(ac->dom_req); return LDB_ERR_OPERATIONS_ERROR; } @@ -598,29 +596,23 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) /* if it is not an entry of type person its an error */ /* TODO: remove this when sambaPassword will be in schema */ if (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "person")) { - ldb_set_errstring(module->ldb, talloc_asprintf(module, "Cannot set a password on entry that does not have objectClass 'person'")); + ldb_set_errstring(module->ldb, "Cannot set a password on entry that does not have objectClass 'person'"); return LDB_ERR_OBJECT_CLASS_VIOLATION; } /* check sambaPassword is single valued here */ /* TODO: remove this when sambaPassword will be single valued in schema */ if (sambaAttr && sambaAttr->num_values > 1) { - ldb_set_errstring(module->ldb, - talloc_asprintf(req, - "mupltiple values for sambaPassword not allowed!\n")); + ldb_set_errstring(module->ldb, "mupltiple values for sambaPassword not allowed!\n"); return LDB_ERR_CONSTRAINT_VIOLATION; } if (ntAttr && (ntAttr->num_values > 1)) { - ldb_set_errstring(module->ldb, - talloc_asprintf(req, - "mupltiple values for lmPwdHash not allowed!\n")); + ldb_set_errstring(module->ldb, "mupltiple values for lmPwdHash not allowed!\n"); return LDB_ERR_CONSTRAINT_VIOLATION; } if (lmAttr && (lmAttr->num_values > 1)) { - ldb_set_errstring(module->ldb, - talloc_asprintf(req, - "mupltiple values for lmPwdHash not allowed!\n")); + ldb_set_errstring(module->ldb, "mupltiple values for lmPwdHash not allowed!\n"); return LDB_ERR_CONSTRAINT_VIOLATION; } @@ -807,7 +799,7 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r /* prepare the first operation */ ac->down_req = talloc_zero(ac, struct ldb_request); if (ac->down_req == NULL) { - ldb_set_errstring(module->ldb, talloc_asprintf(module->ldb, "Out of memory!")); + ldb_set_errstring(module->ldb, "Out of memory!"); return LDB_ERR_OPERATIONS_ERROR; } @@ -844,7 +836,7 @@ static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_ struct ph_context *ac; if (!context || !ares) { - ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context or Result in callback")); + ldb_set_errstring(ldb, "NULL Context or Result in callback"); return LDB_ERR_OPERATIONS_ERROR; } @@ -853,7 +845,7 @@ static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_ /* we are interested only in the single reply (base search) we receive here */ if (ares->type == LDB_REPLY_ENTRY) { if (ac->search_res != NULL) { - ldb_set_errstring(ldb, talloc_asprintf(ldb, "Too many results")); + ldb_set_errstring(ldb, "Too many results"); talloc_free(ares); return LDB_ERR_OPERATIONS_ERROR; } @@ -861,7 +853,7 @@ static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_ /* if it is not an entry of type person this is an error */ /* TODO: remove this when sambaPassword will be in schema */ if (!ldb_msg_check_string_attribute(ares->message, "objectClass", "person")) { - ldb_set_errstring(ldb, talloc_asprintf(ldb, "Object class violation")); + ldb_set_errstring(ldb, "Object class violation"); talloc_free(ares); return LDB_ERR_OBJECT_CLASS_VIOLATION; } @@ -899,7 +891,7 @@ static int password_hash_mod_search_self(struct ldb_handle *h) { ac->search_req->op.search.scope = LDB_SCOPE_BASE; ac->search_req->op.search.tree = ldb_parse_tree(ac->module->ldb, NULL); if (ac->search_req->op.search.tree == NULL) { - ldb_set_errstring(ac->module->ldb, talloc_asprintf(ac, "Invalid search filter")); + ldb_set_errstring(ac->module->ldb, "Invalid search filter"); return LDB_ERR_OPERATIONS_ERROR; } ac->search_req->op.search.attrs = attrs; -- cgit From a23b63a8e54db7d0ec98ad95cdca11dd4d039e17 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 13 Aug 2006 08:00:36 +0000 Subject: r17516: Change helper function names to make more clear what they are meant to do (This used to be commit ad75cf869550af66119d0293503024d41d834e02) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 93af3ae260..273cc60c30 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -99,7 +99,7 @@ static int add_password_hashes(struct ldb_module *module, struct ldb_message *ms const char *sambaPassword; struct samr_Password tmp_hash; - sambaPassword = ldb_msg_find_string(msg, "sambaPassword", NULL); + sambaPassword = ldb_msg_find_attr_as_string(msg, "sambaPassword", NULL); if (sambaPassword == NULL) { /* impossible, what happened ?! */ return LDB_ERR_OPERATIONS_ERROR; } @@ -146,7 +146,7 @@ static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_mes * algorithm, described in his Nov 10 2004 mail to * samba-technical@samba.org */ - sambaPassword = ldb_msg_find_string(msg, "sambaPassword", NULL); + sambaPassword = ldb_msg_find_attr_as_string(msg, "sambaPassword", NULL); if (sambaPassword == NULL) { /* impossible, what happened ?! */ return LDB_ERR_OPERATIONS_ERROR; } @@ -536,7 +536,7 @@ static struct domain_data *get_domain_data(struct ldb_module *module, void *ctx, data->pwdProperties = samdb_result_uint(res->message, "pwdProperties", 0); data->pwdHistoryLength = samdb_result_uint(res->message, "pwdHistoryLength", 0); - tmp = ldb_msg_find_string(res->message, "dnsDomain", NULL); + tmp = ldb_msg_find_attr_as_string(res->message, "dnsDomain", NULL); if (tmp != NULL) { data->dnsDomain = talloc_strdup(data, tmp); @@ -684,8 +684,8 @@ static int password_hash_add_do_add(struct ldb_handle *h) { /* now add krb5 keys based on unicode password */ ret = add_krb5_keys_from_password(ac->module, msg, smb_krb5_context, domain, - ldb_msg_find_string(msg, "samAccountName", NULL), - ldb_msg_find_string(msg, "userPrincipalName", NULL), + ldb_msg_find_attr_as_string(msg, "samAccountName", NULL), + ldb_msg_find_attr_as_string(msg, "userPrincipalName", NULL), ldb_msg_check_string_attribute(msg, "objectClass", "computer")); if (ret != LDB_SUCCESS) { return ret; @@ -700,13 +700,13 @@ static int password_hash_add_do_add(struct ldb_handle *h) { /* if both the domain properties and the user account controls do not permit * clear text passwords then wipe out the sambaPassword */ if ((!(domain->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT)) || - (!(ldb_msg_find_uint(msg, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED))) { + (!(ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED))) { ldb_msg_remove_attr(msg, "sambaPassword"); } } /* don't touch it if a value is set. It could be an incoming samsync */ - if (ldb_msg_find_uint64(msg, "pwdLastSet", 0) == 0) { + if (ldb_msg_find_attr_as_uint64(msg, "pwdLastSet", 0) == 0) { if (set_pwdLastSet(ac->module, msg, 0) != LDB_SUCCESS) { return LDB_ERR_OPERATIONS_ERROR; } @@ -996,8 +996,8 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) { /* now add krb5 keys based on unicode password */ ret = add_krb5_keys_from_password(ac->module, msg, smb_krb5_context, domain, - ldb_msg_find_string(ac->search_res->message, "samAccountName", NULL), - ldb_msg_find_string(ac->search_res->message, "userPrincipalName", NULL), + ldb_msg_find_attr_as_string(ac->search_res->message, "samAccountName", NULL), + ldb_msg_find_attr_as_string(ac->search_res->message, "userPrincipalName", NULL), ldb_msg_check_string_attribute(ac->search_res->message, "objectClass", "computer")); if (ret != LDB_SUCCESS) { @@ -1007,7 +1007,7 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) { /* if the domain properties or the user account controls do not permit * clear text passwords then wipe out the sambaPassword */ if ((!(domain->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT)) || - (!(ldb_msg_find_uint(ac->search_res->message, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED))) { + (!(ldb_msg_find_attr_as_uint(ac->search_res->message, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED))) { ldb_msg_remove_attr(msg, "sambaPassword"); } @@ -1043,7 +1043,7 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) { if (!ldb_msg_find_element(ac->orig_req->op.mod.message, "msDS-KeyVersionNumber")) { if (add_keyVersionNumber(ac->module, msg, - ldb_msg_find_uint(ac->search_res->message, + ldb_msg_find_attr_as_uint(ac->search_res->message, "msDS-KeyVersionNumber", 0) ) != LDB_SUCCESS) { return LDB_ERR_OPERATIONS_ERROR; -- cgit From b21b119cbcff175453173d7061e3be3888dc8ec3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 25 Aug 2006 07:32:18 +0000 Subject: r17824: add a wrapper for the common partitions_basedn calculation (This used to be commit 09007b0907662a0d147e8eb21d5bdfc90dbffefc) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 273cc60c30..e8b9307cf5 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -489,7 +489,7 @@ static int build_domain_data_request(struct ph_context *ac) return LDB_ERR_OPERATIONS_ERROR; } ac->dom_req->operation = LDB_SEARCH; - ac->dom_req->op.search.base = samdb_base_dn(ac); + ac->dom_req->op.search.base = ldb_auto_basedn(ac->module->ldb); ac->dom_req->op.search.scope = LDB_SCOPE_SUBTREE; filter = talloc_asprintf(ac->dom_req, "(&(objectSid=%s)(|(objectClass=domain)(objectClass=builtinDomain)))", -- cgit From 88b04ab6e65137079b2dad76d1cea07e7ea9ab80 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 25 Aug 2006 12:59:03 +0000 Subject: r17830: Set the default_basedn (hey, it comes from the "default" naming contex :-) once at connection time, after modules have been loaded. Introduce a function to retrieve the value where needed. (This used to be commit 0caf6a44e03393c645030a9288e7dfd31e97c98b) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index e8b9307cf5..2fcfdff997 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -489,7 +489,7 @@ static int build_domain_data_request(struct ph_context *ac) return LDB_ERR_OPERATIONS_ERROR; } ac->dom_req->operation = LDB_SEARCH; - ac->dom_req->op.search.base = ldb_auto_basedn(ac->module->ldb); + ac->dom_req->op.search.base = ldb_get_default_basedn(ac->module->ldb); ac->dom_req->op.search.scope = LDB_SCOPE_SUBTREE; filter = talloc_asprintf(ac->dom_req, "(&(objectSid=%s)(|(objectClass=domain)(objectClass=builtinDomain)))", -- cgit From 0329d755a7611ba3897fc1ee9bdce410cc33d7f8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 30 Aug 2006 11:29:34 +0000 Subject: r17930: Merge noinclude branch: * Move dlinklist.h, smb.h to subsystem-specific directories * Clean up ads.h and move what is left of it to dsdb/ (only place where it's used) (This used to be commit f7afa1cb77f3cfa7020b57de12e6003db7cfcc42) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 2fcfdff997..dbe307fc03 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -42,7 +42,7 @@ #include "auth/kerberos/kerberos.h" #include "system/time.h" #include "dsdb/samdb/samdb.h" -#include "ads.h" +#include "dsdb/common/flags.h" #include "hdb.h" #include "dsdb/samdb/ldb_modules/password_modules.h" -- cgit From 25f9e52a5d7a7dce7c98a1f27c9b38ada650d343 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 31 Aug 2006 08:17:09 +0000 Subject: r17955: Don't search for the dnsDomain attribute, it is invented (not in the AD schema). Andrew Bartlett (This used to be commit fac27e4dddc98288dc765e135db6b168fbec760c) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 30 ++++++++++++++++++++------ 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index dbe307fc03..9bdb9aa0cc 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -90,7 +90,7 @@ struct ph_context { struct domain_data { uint_t pwdProperties; uint_t pwdHistoryLength; - char *dnsDomain; + char *dns_domain; char *realm; }; @@ -165,7 +165,7 @@ static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_mes if (name[strlen(name)-1] == '$') { name[strlen(name)-1] = '\0'; } - saltbody = talloc_asprintf(msg, "%s.%s", name, domain->dnsDomain); + saltbody = talloc_asprintf(msg, "%s.%s", name, domain->dns_domain); krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, &salt_principal, @@ -480,7 +480,7 @@ static int build_domain_data_request(struct ph_context *ac) /* attrs[] is returned from this function in ac->dom_req->op.search.attrs, so it must be static, as otherwise the compiler can put it on the stack */ - static const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", "dnsDomain", NULL }; + static const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", NULL }; char *filter; ac->dom_req = talloc_zero(ac, struct ldb_request); @@ -520,7 +520,8 @@ static struct domain_data *get_domain_data(struct ldb_module *module, void *ctx, struct domain_data *data; const char *tmp; struct ph_context *ac; - + char *p; + ac = talloc_get_type(ctx, struct ph_context); data = talloc_zero(ac, struct domain_data); @@ -536,11 +537,26 @@ static struct domain_data *get_domain_data(struct ldb_module *module, void *ctx, data->pwdProperties = samdb_result_uint(res->message, "pwdProperties", 0); data->pwdHistoryLength = samdb_result_uint(res->message, "pwdHistoryLength", 0); - tmp = ldb_msg_find_attr_as_string(res->message, "dnsDomain", NULL); + + /* For a domain DN, this puts things in dotted notation */ + /* For builtin domains, this will give details for the host, + * but that doesn't really matter, as it's just used for salt + * and kerberos principals, which don't exist here */ + + tmp = ldb_dn_canonical_string(ctx, res->message->dn); + if (!tmp) { + return NULL; + } + + /* But it puts a trailing (or just before 'builtin') / on things, so kill that */ + p = strchr(tmp, '/'); + if (p) { + p[0] = '\0'; + } if (tmp != NULL) { - data->dnsDomain = talloc_strdup(data, tmp); - if (data->dnsDomain == NULL) { + data->dns_domain = strlower_talloc(data, tmp); + if (data->dns_domain == NULL) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n"); return NULL; } -- cgit From 704327044d6f54129cef4706b572f1f4dc3ad36f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 8 Sep 2006 00:23:21 +0000 Subject: r18240: Make it clearer when we store the plaintext password. Store the plaintext password in userPassword in the LDAP backend so that the OpenLDAP server can use DIGEST-MD5. Andrew Bartlett (This used to be commit 1b02c604b2c55e1c9e15ac1f266e7df74d619dbd) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 9bdb9aa0cc..d8ef9176fd 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -88,6 +88,7 @@ struct ph_context { }; struct domain_data { + BOOL store_cleartext; uint_t pwdProperties; uint_t pwdHistoryLength; char *dns_domain; @@ -535,7 +536,8 @@ static struct domain_data *get_domain_data(struct ldb_module *module, void *ctx, return NULL; } - data->pwdProperties = samdb_result_uint(res->message, "pwdProperties", 0); + data->pwdProperties= samdb_result_uint(res->message, "pwdProperties", 0); + data->store_cleartext = data->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT; data->pwdHistoryLength = samdb_result_uint(res->message, "pwdHistoryLength", 0); /* For a domain DN, this puts things in dotted notation */ @@ -692,6 +694,7 @@ static int password_hash_add_do_add(struct ldb_handle *h) { /* if we have sambaPassword in the original message add the operatio on it here */ sambaAttr = ldb_msg_find_element(msg, "sambaPassword"); if (sambaAttr) { + unsigned int user_account_control; ret = add_password_hashes(ac->module, msg, 0); /* we can compute new password hashes from the unicode password */ if (ret != LDB_SUCCESS) { @@ -715,8 +718,10 @@ static int password_hash_add_do_add(struct ldb_handle *h) { /* if both the domain properties and the user account controls do not permit * clear text passwords then wipe out the sambaPassword */ - if ((!(domain->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT)) || - (!(ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED))) { + user_account_control = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0); + if (domain->store_cleartext && (user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { + /* Keep sambaPassword attribute */ + } else { ldb_msg_remove_attr(msg, "sambaPassword"); } } @@ -1022,8 +1027,10 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) { /* if the domain properties or the user account controls do not permit * clear text passwords then wipe out the sambaPassword */ - if ((!(domain->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT)) || - (!(ldb_msg_find_attr_as_uint(ac->search_res->message, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED))) { + if (domain->store_cleartext && + (ldb_msg_find_attr_as_uint(ac->search_res->message, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { + /* Keep sambaPassword attribute */ + } else { ldb_msg_remove_attr(msg, "sambaPassword"); } -- cgit From 379e6598e128e5e63a10bd6a81ede01d3965a8be Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 16 Oct 2006 01:19:01 +0000 Subject: r19308: Merge samsync fixes from SAMBA_4_0_RELEASE Andrew Bartlett (This used to be commit 331003239972d80864211377e864f7e469bd3d77) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index d8ef9176fd..6f24c7fa4c 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -102,7 +102,7 @@ static int add_password_hashes(struct ldb_module *module, struct ldb_message *ms sambaPassword = ldb_msg_find_attr_as_string(msg, "sambaPassword", NULL); if (sambaPassword == NULL) { /* impossible, what happened ?! */ - return LDB_ERR_OPERATIONS_ERROR; + return LDB_ERR_CONSTRAINT_VIOLATION; } if (is_mod) { @@ -634,6 +634,20 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_CONSTRAINT_VIOLATION; } + if (sambaAttr && sambaAttr->num_values == 0) { + ldb_set_errstring(module->ldb, "sambaPassword must have a value!\n"); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + + if (ntAttr && (ntAttr->num_values == 0)) { + ldb_set_errstring(module->ldb, "lmPwdHash must have a value!\n"); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + if (lmAttr && (lmAttr->num_values == 0)) { + ldb_set_errstring(module->ldb, "lmPwdHash must have a value!\n"); + return LDB_ERR_CONSTRAINT_VIOLATION; + } + h = ph_init_handle(req, module, PH_ADD); if (!h) { return LDB_ERR_OPERATIONS_ERROR; -- cgit From bd8f63a61747d91452dadaa1667bc30a708fa4d4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 16 Oct 2006 07:32:22 +0000 Subject: r19321: Merge from release branch: Always set the krb5key from the ntPwdHash, even if we don't have the cleartext password in sambaPassword. This fixes kerberos after a vampire. Andrew Bartlett (This used to be commit 1d4d2271c9b944db3a9a2eba971aec5bcd9cf100) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 6f24c7fa4c..a4862f3820 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -724,12 +724,6 @@ static int password_hash_add_do_add(struct ldb_handle *h) { return ret; } - /* add also kr5 keys based on NT the hash */ - ret = add_krb5_keys_from_NThash(ac->module, msg, smb_krb5_context); - if (ret != LDB_SUCCESS) { - return ret; - } - /* if both the domain properties and the user account controls do not permit * clear text passwords then wipe out the sambaPassword */ user_account_control = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0); @@ -740,6 +734,12 @@ static int password_hash_add_do_add(struct ldb_handle *h) { } } + /* add also krb5 keys based on NT the hash (we might have ntPwdHash, but not the cleartext */ + ret = add_krb5_keys_from_NThash(ac->module, msg, smb_krb5_context); + if (ret != LDB_SUCCESS) { + return ret; + } + /* don't touch it if a value is set. It could be an incoming samsync */ if (ldb_msg_find_attr_as_uint64(msg, "pwdLastSet", 0) == 0) { if (set_pwdLastSet(ac->module, msg, 0) != LDB_SUCCESS) { -- cgit From 8b60b7fa2ad0f707cad5af63566f4dd931a7a6b9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 16 Oct 2006 11:23:40 +0000 Subject: r19329: fixed a leak in the password hash module (This used to be commit 3f48bcb0585684686ba7601eb7614589a1bc2f5d) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index a4862f3820..8bfd46e641 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -501,7 +501,7 @@ static int build_domain_data_request(struct ph_context *ac) return LDB_ERR_OPERATIONS_ERROR; } - ac->dom_req->op.search.tree = ldb_parse_tree(ac->module->ldb, filter); + ac->dom_req->op.search.tree = ldb_parse_tree(ac->dom_req, filter); if (ac->dom_req->op.search.tree == NULL) { ldb_set_errstring(ac->module->ldb, "Invalid search filter"); talloc_free(ac->dom_req); -- cgit From 549dd10f0f4bbc15c47a6da885db5d802b0a9a24 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 16 Oct 2006 12:03:55 +0000 Subject: r19332: ldb_parse_tree leaks (This used to be commit 3e0e2787c1da1c3831e21b163e1370001d725a3d) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 8bfd46e641..9ba7bc44c4 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -924,7 +924,7 @@ static int password_hash_mod_search_self(struct ldb_handle *h) { ac->search_req->operation = LDB_SEARCH; ac->search_req->op.search.base = ac->orig_req->op.mod.message->dn; ac->search_req->op.search.scope = LDB_SCOPE_BASE; - ac->search_req->op.search.tree = ldb_parse_tree(ac->module->ldb, NULL); + ac->search_req->op.search.tree = ldb_parse_tree(ac->search_req, NULL); if (ac->search_req->op.search.tree == NULL) { ldb_set_errstring(ac->module->ldb, "Invalid search filter"); return LDB_ERR_OPERATIONS_ERROR; -- cgit From 7f833458ca0083654e34cbfde1c6c6510cab1826 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 25 Oct 2006 01:42:59 +0000 Subject: r19489: Change ldb_msg_add_value and ldb_msg_add_empty to take a foruth argument. This is a pointer to an element pointer. If it is not null it will be filled with the pointer of the manipulated element. Will avoid double searches on the elements list in some cases. (This used to be commit 0fa5d4bc225b83e9f63ac6d75bffc4c08eb6b620) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 9ba7bc44c4..1b35ec3e8c 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -106,10 +106,10 @@ static int add_password_hashes(struct ldb_module *module, struct ldb_message *ms } if (is_mod) { - if (ldb_msg_add_empty(msg, "ntPwdHash", LDB_FLAG_MOD_REPLACE) != 0) { + if (ldb_msg_add_empty(msg, "ntPwdHash", LDB_FLAG_MOD_REPLACE, NULL) != 0) { return LDB_ERR_OPERATIONS_ERROR; } - if (ldb_msg_add_empty(msg, "lmPwdHash", LDB_FLAG_MOD_REPLACE) != 0) { + if (ldb_msg_add_empty(msg, "lmPwdHash", LDB_FLAG_MOD_REPLACE, NULL) != 0) { return LDB_ERR_OPERATIONS_ERROR; } } @@ -250,7 +250,7 @@ static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_mes hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); return LDB_ERR_OPERATIONS_ERROR; } - ret = ldb_msg_add_value(msg, "krb5Key", &val); + ret = ldb_msg_add_value(msg, "krb5Key", &val, NULL); if (ret != LDB_SUCCESS) { hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); return ret; @@ -301,7 +301,7 @@ static int add_krb5_keys_from_NThash(struct ldb_module *module, struct ldb_messa if (!val.data) { return LDB_ERR_OPERATIONS_ERROR; } - if (ldb_msg_add_value(msg, "krb5Key", &val) != 0) { + if (ldb_msg_add_value(msg, "krb5Key", &val, NULL) != 0) { return LDB_ERR_OPERATIONS_ERROR; } @@ -319,12 +319,12 @@ static int set_pwdLastSet(struct ldb_module *module, struct ldb_message *msg, in /* be sure there isn't a 0 value set (eg. coming from the template) */ ldb_msg_remove_attr(msg, "pwdLastSet"); /* add */ - if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_ADD) != 0) { + if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_ADD, NULL) != 0) { return LDB_ERR_OPERATIONS_ERROR; } } else { /* replace */ - if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE) != 0) { + if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE, NULL) != 0) { return LDB_ERR_OPERATIONS_ERROR; } } @@ -339,7 +339,7 @@ static int set_pwdLastSet(struct ldb_module *module, struct ldb_message *msg, in static int add_keyVersionNumber(struct ldb_module *module, struct ldb_message *msg, int previous) { /* replace or add */ - if (ldb_msg_add_empty(msg, "msDS-KeyVersionNumber", LDB_FLAG_MOD_REPLACE) != 0) { + if (ldb_msg_add_empty(msg, "msDS-KeyVersionNumber", LDB_FLAG_MOD_REPLACE, NULL) != 0) { return LDB_ERR_OPERATIONS_ERROR; } @@ -385,7 +385,7 @@ static int setPwdHistory(struct ldb_module *module, struct ldb_message *msg, str } else { ZERO_STRUCT(new_nt_history[0]); } - if (ldb_msg_add_empty(msg, "sambaNTPwdHistory", LDB_FLAG_MOD_REPLACE) != LDB_SUCCESS) { + if (ldb_msg_add_empty(msg, "sambaNTPwdHistory", LDB_FLAG_MOD_REPLACE, NULL) != LDB_SUCCESS) { return LDB_ERR_OPERATIONS_ERROR; } if (samdb_msg_add_hashes(msg, msg, "sambaNTPwdHistory", new_nt_history, nt_hist_len) != LDB_SUCCESS) { @@ -408,7 +408,7 @@ static int setPwdHistory(struct ldb_module *module, struct ldb_message *msg, str } else { ZERO_STRUCT(new_lm_history[0]); } - if (ldb_msg_add_empty(msg, "sambaLMPwdHistory", LDB_FLAG_MOD_REPLACE) != LDB_SUCCESS) { + if (ldb_msg_add_empty(msg, "sambaLMPwdHistory", LDB_FLAG_MOD_REPLACE, NULL) != LDB_SUCCESS) { return LDB_ERR_OPERATIONS_ERROR; } if (samdb_msg_add_hashes(msg, msg, "sambaLMPwdHistory", new_lm_history, lm_hist_len) != LDB_SUCCESS) { @@ -1005,7 +1005,7 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) { } /* we are going to replace the existing krb5key or delete it */ - if (ldb_msg_add_empty(msg, "krb5key", LDB_FLAG_MOD_REPLACE) != 0) { + if (ldb_msg_add_empty(msg, "krb5key", LDB_FLAG_MOD_REPLACE, NULL) != 0) { return LDB_ERR_OPERATIONS_ERROR; } -- cgit From 4889eb9f7aae9349e426d0f6d2217adff67eaebd Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 22 Nov 2006 00:59:34 +0000 Subject: r19831: Big ldb_dn optimization and interfaces enhancement patch This patch changes a lot of the code in ldb_dn.c, and also removes and add a number of manipulation functions around. The aim is to avoid validating a dn if not necessary as the validation code is necessarily slow. This is mainly to speed up internal operations where input is not user generated and so we can assume the DNs need no validation. The code is designed to keep the data as a string if possible. The code is not yet 100% perfect, but pass all the tests so far. A memleak is certainly present, I'll work on that next. Simo. (This used to be commit a580c871d3784602a9cce32d33419e63c8236e63) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 1b35ec3e8c..b25beb7a8f 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -588,8 +588,7 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) } /* If the caller is manipulating the local passwords directly, let them pass */ - if (ldb_dn_compare_base(module->ldb, - ldb_dn_explode(req, LOCAL_BASE), + if (ldb_dn_compare_base(ldb_dn_new(req, module->ldb, LOCAL_BASE), req->op.add.message->dn) == 0) { return ldb_next_request(module, req); } @@ -783,8 +782,7 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r } /* If the caller is manipulating the local passwords directly, let them pass */ - if (ldb_dn_compare_base(module->ldb, - ldb_dn_explode(req, LOCAL_BASE), + if (ldb_dn_compare_base(ldb_dn_new(req, module->ldb, LOCAL_BASE), req->op.mod.message->dn) == 0) { return ldb_next_request(module, req); } -- cgit From a9e31b33b55a873c2f01db5e348560176adf863d Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 22 Nov 2006 02:05:19 +0000 Subject: r19832: better prototypes for the linearization functions: - ldb_dn_get_linearized returns a const string - ldb_dn_alloc_linearized allocs astring with the linearized dn (This used to be commit 3929c086d5d0b3f08b1c4f2f3f9602c3f4a9a4bd) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index b25beb7a8f..38a44bdae2 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -160,7 +160,7 @@ static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_mes ldb_asprintf_errstring(module->ldb, "password_hash_handle: " "generation of new kerberos keys failed: %s is a computer without a samAccountName", - ldb_dn_linearize(msg, msg->dn)); + ldb_dn_get_linearized(msg->dn)); return LDB_ERR_OPERATIONS_ERROR; } if (name[strlen(name)-1] == '$') { @@ -191,7 +191,7 @@ static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_mes ldb_asprintf_errstring(module->ldb, "password_hash_handle: " "generation of new kerberos keys failed: %s has no samAccountName", - ldb_dn_linearize(msg, msg->dn)); + ldb_dn_get_linearized(msg->dn)); return LDB_ERR_OPERATIONS_ERROR; } krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, -- cgit From c2e492ece3e5dd39c3c113dfe7f745fc900a5dc0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 19 Jan 2007 13:36:15 +0000 Subject: r20902: don't crash if the object isn't there yet metze (This used to be commit 4588e2522b11f707e608488c782f6988fd97628a) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 38a44bdae2..9a72643ec9 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1192,6 +1192,10 @@ static int ph_wait(struct ldb_handle *handle) { return LDB_SUCCESS; } + if (ac->search_res == NULL) { + return LDB_ERR_NO_SUCH_OBJECT; + } + /* self search done, go on */ return password_hash_mod_search_dom(handle); -- cgit From 3b14713f6d583a33fc2b2bb8c2c3aab6f5928630 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Feb 2007 12:54:58 +0000 Subject: r21362: rename: "ntPwdHash" => "unicodePwd" "lmPwdHash" => "dBCSPwd" "sambaLMPwdHistory" => "lmPwdHistory" "sambaNTPwdHistory" => "ntPwdHistory" Note: you need to reprovision after this change! metze (This used to be commit dc4242c09c0402cbfdba912f82892df3153456ad) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 56 +++++++++++++------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 9a72643ec9..201a5d295a 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -106,22 +106,22 @@ static int add_password_hashes(struct ldb_module *module, struct ldb_message *ms } if (is_mod) { - if (ldb_msg_add_empty(msg, "ntPwdHash", LDB_FLAG_MOD_REPLACE, NULL) != 0) { + if (ldb_msg_add_empty(msg, "unicodePwd", LDB_FLAG_MOD_REPLACE, NULL) != 0) { return LDB_ERR_OPERATIONS_ERROR; } - if (ldb_msg_add_empty(msg, "lmPwdHash", LDB_FLAG_MOD_REPLACE, NULL) != 0) { + if (ldb_msg_add_empty(msg, "dBCSPwd", LDB_FLAG_MOD_REPLACE, NULL) != 0) { return LDB_ERR_OPERATIONS_ERROR; } } /* compute the new nt and lm hashes */ E_md4hash(sambaPassword, tmp_hash.hash); - if (samdb_msg_add_hash(module->ldb, msg, msg, "ntPwdHash", &tmp_hash) != 0) { + if (samdb_msg_add_hash(module->ldb, msg, msg, "unicodePwd", &tmp_hash) != 0) { return LDB_ERR_OPERATIONS_ERROR; } if (E_deshash(sambaPassword, tmp_hash.hash)) { - if (samdb_msg_add_hash(module->ldb, msg, msg, "lmPwdHash", &tmp_hash) != 0) { + if (samdb_msg_add_hash(module->ldb, msg, msg, "dBCSPwd", &tmp_hash) != 0) { return LDB_ERR_OPERATIONS_ERROR; } } @@ -276,7 +276,7 @@ static int add_krb5_keys_from_NThash(struct ldb_module *module, struct ldb_messa key.mkvno = 0; key.salt = NULL; /* No salt for this enc type */ - ntPwdHash = samdb_result_hash(msg, msg, "ntPwdHash"); + ntPwdHash = samdb_result_hash(msg, msg, "unicodePwd"); if (ntPwdHash == NULL) { /* what happened ?! */ return LDB_ERR_OPERATIONS_ERROR; } @@ -362,14 +362,14 @@ static int setPwdHistory(struct ldb_module *module, struct ldb_message *msg, str int lm_hist_len; int i; - nt_hash = samdb_result_hash(msg, old_msg, "ntPwdHash"); - lm_hash = samdb_result_hash(msg, old_msg, "lmPwdHash"); + nt_hash = samdb_result_hash(msg, old_msg, "unicodePwd"); + lm_hash = samdb_result_hash(msg, old_msg, "dBCSPwd"); /* if no previous passwords just return */ if (nt_hash == NULL && lm_hash == NULL) return LDB_SUCCESS; - nt_hist_len = samdb_result_hashes(msg, old_msg, "sambaNTPwdHistory", &nt_history); - lm_hist_len = samdb_result_hashes(msg, old_msg, "sambaLMPwdHistory", &lm_history); + nt_hist_len = samdb_result_hashes(msg, old_msg, "ntPwdHistory", &nt_history); + lm_hist_len = samdb_result_hashes(msg, old_msg, "lmPwdHistory", &lm_history); /* We might not have an old NT password */ new_nt_history = talloc_array(msg, struct samr_Password, hlen); @@ -385,10 +385,10 @@ static int setPwdHistory(struct ldb_module *module, struct ldb_message *msg, str } else { ZERO_STRUCT(new_nt_history[0]); } - if (ldb_msg_add_empty(msg, "sambaNTPwdHistory", LDB_FLAG_MOD_REPLACE, NULL) != LDB_SUCCESS) { + if (ldb_msg_add_empty(msg, "ntPwdHistory", LDB_FLAG_MOD_REPLACE, NULL) != LDB_SUCCESS) { return LDB_ERR_OPERATIONS_ERROR; } - if (samdb_msg_add_hashes(msg, msg, "sambaNTPwdHistory", new_nt_history, nt_hist_len) != LDB_SUCCESS) { + if (samdb_msg_add_hashes(msg, msg, "ntPwdHistory", new_nt_history, nt_hist_len) != LDB_SUCCESS) { return LDB_ERR_OPERATIONS_ERROR; } @@ -408,10 +408,10 @@ static int setPwdHistory(struct ldb_module *module, struct ldb_message *msg, str } else { ZERO_STRUCT(new_lm_history[0]); } - if (ldb_msg_add_empty(msg, "sambaLMPwdHistory", LDB_FLAG_MOD_REPLACE, NULL) != LDB_SUCCESS) { + if (ldb_msg_add_empty(msg, "lmPwdHistory", LDB_FLAG_MOD_REPLACE, NULL) != LDB_SUCCESS) { return LDB_ERR_OPERATIONS_ERROR; } - if (samdb_msg_add_hashes(msg, msg, "sambaLMPwdHistory", new_lm_history, lm_hist_len) != LDB_SUCCESS) { + if (samdb_msg_add_hashes(msg, msg, "lmPwdHistory", new_lm_history, lm_hist_len) != LDB_SUCCESS) { return LDB_ERR_OPERATIONS_ERROR; } @@ -594,8 +594,8 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) } /* nobody must touch password Histories */ - if (ldb_msg_find_element(req->op.add.message, "sambaNTPwdHistory") || - ldb_msg_find_element(req->op.add.message, "sambaLMPwdHistory")) { + if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory") || + ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) { return LDB_ERR_UNWILLING_TO_PERFORM; } @@ -603,8 +603,8 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) * or LM hashes, then we don't need to make any changes. */ sambaAttr = ldb_msg_find_element(req->op.mod.message, "sambaPassword"); - ntAttr = ldb_msg_find_element(req->op.mod.message, "ntPwdHash"); - lmAttr = ldb_msg_find_element(req->op.mod.message, "lmPwdHash"); + ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd"); + lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd"); if ((!sambaAttr) && (!ntAttr) && (!lmAttr)) { return ldb_next_request(module, req); @@ -788,14 +788,14 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r } /* nobody must touch password Histories */ - if (ldb_msg_find_element(req->op.mod.message, "sambaNTPwdHistory") || - ldb_msg_find_element(req->op.mod.message, "sambaLMPwdHistory")) { + if (ldb_msg_find_element(req->op.mod.message, "ntPwdHistory") || + ldb_msg_find_element(req->op.mod.message, "lmPwdHistory")) { return LDB_ERR_UNWILLING_TO_PERFORM; } sambaAttr = ldb_msg_find_element(req->op.mod.message, "sambaPassword"); - ntAttr = ldb_msg_find_element(req->op.mod.message, "ntPwdHash"); - lmAttr = ldb_msg_find_element(req->op.mod.message, "lmPwdHash"); + ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd"); + lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd"); /* check passwords are single valued here */ /* TODO: remove this when passwords will be single valued in schema */ @@ -844,8 +844,8 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r /* - remove any imodification to the password from the first commit * we will make the real modification later */ if (sambaAttr) ldb_msg_remove_attr(msg, "sambaPassword"); - if (ntAttr) ldb_msg_remove_attr(msg, "ntPwdHash"); - if (lmAttr) ldb_msg_remove_attr(msg, "lmPwdHash"); + if (ntAttr) ldb_msg_remove_attr(msg, "unicodePwd"); + if (lmAttr) ldb_msg_remove_attr(msg, "dBCSPwd"); /* if there was nothing else to be modify skip to next step */ if (msg->num_elements == 0) { @@ -902,12 +902,12 @@ static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_ static int password_hash_mod_search_self(struct ldb_handle *h) { struct ph_context *ac; - static const char * const attrs[] = { "userAccountControl", "sambaLMPwdHistory", - "sambaNTPwdHistory", + static const char * const attrs[] = { "userAccountControl", "lmPwdHistory", + "ntPwdHistory", "objectSid", "msDS-KeyVersionNumber", "objectClass", "userPrincipalName", "samAccountName", - "lmPwdHash", "ntPwdHash", + "dBCSPwd", "unicodePwd", NULL }; ac = talloc_get_type(h->private_data, struct ph_context); @@ -1053,12 +1053,12 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) { if (!added_hashes) { struct ldb_message_element *el; - el = ldb_msg_find_element(ac->orig_req->op.mod.message, "ntPwdHash"); + el = ldb_msg_find_element(ac->orig_req->op.mod.message, "unicodePwd"); if (ldb_msg_add(msg, el, el->flags) != 0) { return LDB_ERR_OPERATIONS_ERROR; } - el = ldb_msg_find_element(ac->orig_req->op.mod.message, "lmPwdHash"); + el = ldb_msg_find_element(ac->orig_req->op.mod.message, "dBCSPwd"); if (ldb_msg_add(msg, el, el->flags) != 0) { return LDB_ERR_OPERATIONS_ERROR; } -- cgit From 9a9b1978560b9758d69fbcd7028d098e363f7e8f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Feb 2007 13:01:18 +0000 Subject: r21364: cosmetic change: it's nicer to use the KEYTYPE_ macro for the keytype field... metze (This used to be commit e96aa8980097712d7666a85f17c7214486d99618) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 201a5d295a..58a408a3d9 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -231,7 +231,7 @@ static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_mes struct ldb_val val; int ret; - if (keys[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { + if (keys[i].key.keytype == KEYTYPE_ARCFOUR) { /* We might end up doing this below: * This ensures we get the unicode * conversion right. This should also @@ -282,7 +282,7 @@ static int add_krb5_keys_from_NThash(struct ldb_module *module, struct ldb_messa } krb5_ret = krb5_keyblock_init(smb_krb5_context->krb5_context, - ETYPE_ARCFOUR_HMAC_MD5, + KEYTYPE_ARCFOUR, ntPwdHash->hash, sizeof(ntPwdHash->hash), &key.key); if (krb5_ret) { -- cgit From 8a9a68b707963f071480e79618d33e858154263f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 16 Feb 2007 17:36:58 +0000 Subject: r21395: fix comments metze (This used to be commit 97fc985bd062b6ad5a58dd6ce883a637043283a1) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 58a408a3d9..a2fe2a85db 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -56,7 +56,7 @@ * Once this is done (which could update anything at all), we * calculate the password hashes. * - * This function must not only update the ntPwdHash, lmPwdHash and + * This function must not only update the unicodePwd, dBCSPwd and * krb5Key fields, it must also atomicly increment the * msDS-KeyVersionNumber. We should be in a transaction, so all this * should be quite safe... @@ -625,11 +625,11 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) } if (ntAttr && (ntAttr->num_values > 1)) { - ldb_set_errstring(module->ldb, "mupltiple values for lmPwdHash not allowed!\n"); + ldb_set_errstring(module->ldb, "mupltiple values for unicodePwd not allowed!\n"); return LDB_ERR_CONSTRAINT_VIOLATION; } if (lmAttr && (lmAttr->num_values > 1)) { - ldb_set_errstring(module->ldb, "mupltiple values for lmPwdHash not allowed!\n"); + ldb_set_errstring(module->ldb, "mupltiple values for dBCSPwd not allowed!\n"); return LDB_ERR_CONSTRAINT_VIOLATION; } @@ -639,11 +639,11 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) } if (ntAttr && (ntAttr->num_values == 0)) { - ldb_set_errstring(module->ldb, "lmPwdHash must have a value!\n"); + ldb_set_errstring(module->ldb, "unicodePwd must have a value!\n"); return LDB_ERR_CONSTRAINT_VIOLATION; } if (lmAttr && (lmAttr->num_values == 0)) { - ldb_set_errstring(module->ldb, "lmPwdHash must have a value!\n"); + ldb_set_errstring(module->ldb, "dBCSPwd must have a value!\n"); return LDB_ERR_CONSTRAINT_VIOLATION; } @@ -733,7 +733,7 @@ static int password_hash_add_do_add(struct ldb_handle *h) { } } - /* add also krb5 keys based on NT the hash (we might have ntPwdHash, but not the cleartext */ + /* add also krb5 keys based on NT the hash (we might have unicodePwd, but not the cleartext */ ret = add_krb5_keys_from_NThash(ac->module, msg, smb_krb5_context); if (ret != LDB_SUCCESS) { return ret; @@ -809,7 +809,7 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r return LDB_ERR_CONSTRAINT_VIOLATION; } - /* If no part of this touches the sambaPassword OR ntPwdHash and/or lmPwdHash, then we don't + /* If no part of this touches the sambaPassword OR unicodePwd and/or dBCSPwd, then we don't * need to make any changes. For password changes/set there should * be a 'delete' or a 'modify' on this attribute. */ /* If the only operation is the deletion of the passwords then go on */ -- cgit From 6e2d85e38baa2221c2d31d2246567e7523e00fd6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 18 Feb 2007 22:01:02 +0000 Subject: r21434: - get rid of "krb5Key" - use "sambaPassword" only as virtual attribute for passing the cleartext password (in unix charset) into the ldb layer - store des-cbc-crc, des-cbc-md5 keys in the Primary:Kerberos blob to match w2k and w2k3 - aes key support is disabled by default, as we don't know exacly how longhorn stores them. use password_hash:create_aes_key=yes to force creation of them. - store the cleartext password in the Primary:CLEARTEXT blob if configured TODO: - find out how longhorn stores aes keys - find out how the Primary:WDigest blob needs to be constructed (not supported by w2k) metze (This used to be commit e20b53f6feaaca2cc81ee7d296ca3ff757ee3953) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 1088 ++++++++++++++++-------- 1 file changed, 731 insertions(+), 357 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index a2fe2a85db..a31486fdda 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -45,6 +45,8 @@ #include "dsdb/common/flags.h" #include "hdb.h" #include "dsdb/samdb/ldb_modules/password_modules.h" +#include "librpc/ndr/libndr.h" +#include "librpc/gen_ndr/ndr_drsblobs.h" /* If we have decided there is reason to work on this request, then * setup all the password hash types correctly. @@ -57,7 +59,7 @@ * calculate the password hashes. * * This function must not only update the unicodePwd, dBCSPwd and - * krb5Key fields, it must also atomicly increment the + * supplementalCredentials fields, it must also atomicly increment the * msDS-KeyVersionNumber. We should be in a transaction, so all this * should be quite safe... * @@ -95,324 +97,660 @@ struct domain_data { char *realm; }; -static int add_password_hashes(struct ldb_module *module, struct ldb_message *msg, int is_mod) +struct setup_password_fields_io { + struct ph_context *ac; + struct domain_data *domain; + struct smb_krb5_context *smb_krb5_context; + + /* infos about the user account */ + struct { + uint32_t user_account_control; + const char *sAMAccountName; + const char *user_principal_name; + bool is_computer; + } u; + + /* new credentials */ + struct { + const char *cleartext; + struct samr_Password *nt_hash; + struct samr_Password *lm_hash; + } n; + + /* old credentials */ + struct { + uint32_t nt_history_len; + struct samr_Password *nt_history; + uint32_t lm_history_len; + struct samr_Password *lm_history; + const struct ldb_val *supplemental; + struct supplementalCredentialsBlob scb; + uint32_t kvno; + } o; + + /* generated credentials */ + struct { + struct samr_Password *nt_hash; + struct samr_Password *lm_hash; + uint32_t nt_history_len; + struct samr_Password *nt_history; + uint32_t lm_history_len; + struct samr_Password *lm_history; + struct ldb_val supplemental; + NTTIME last_set; + uint32_t kvno; + } g; +}; + +static int setup_nt_fields(struct setup_password_fields_io *io) { - const char *sambaPassword; - struct samr_Password tmp_hash; - - sambaPassword = ldb_msg_find_attr_as_string(msg, "sambaPassword", NULL); - if (sambaPassword == NULL) { /* impossible, what happened ?! */ - return LDB_ERR_CONSTRAINT_VIOLATION; + uint32_t i; + + io->g.nt_hash = io->n.nt_hash; + + if (io->domain->pwdHistoryLength == 0) { + return LDB_SUCCESS; } - if (is_mod) { - if (ldb_msg_add_empty(msg, "unicodePwd", LDB_FLAG_MOD_REPLACE, NULL) != 0) { - return LDB_ERR_OPERATIONS_ERROR; - } - if (ldb_msg_add_empty(msg, "dBCSPwd", LDB_FLAG_MOD_REPLACE, NULL) != 0) { - return LDB_ERR_OPERATIONS_ERROR; - } - } + /* We might not have an old NT password */ + io->g.nt_history = talloc_array(io->ac, + struct samr_Password, + io->domain->pwdHistoryLength); + if (!io->g.nt_history) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + for (i = 0; i < MIN(io->domain->pwdHistoryLength-1, io->o.nt_history_len); i++) { + io->g.nt_history[i+1] = io->o.nt_history[i]; + } + io->g.nt_history_len = i + 1; - /* compute the new nt and lm hashes */ - E_md4hash(sambaPassword, tmp_hash.hash); - if (samdb_msg_add_hash(module->ldb, msg, msg, "unicodePwd", &tmp_hash) != 0) { + if (io->g.nt_hash) { + io->g.nt_history[0] = *io->g.nt_hash; + } else { + /* + * TODO: is this correct? + * the simular behavior is correct for the lm history case + */ + E_md4hash("", io->g.nt_history[0].hash); + } + + return LDB_SUCCESS; +} + +static int setup_lm_fields(struct setup_password_fields_io *io) +{ + uint32_t i; + + io->g.lm_hash = io->n.lm_hash; + + if (io->domain->pwdHistoryLength == 0) { + return LDB_SUCCESS; + } + + /* We might not have an old NT password */ + io->g.lm_history = talloc_array(io->ac, + struct samr_Password, + io->domain->pwdHistoryLength); + if (!io->g.lm_history) { + ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - if (E_deshash(sambaPassword, tmp_hash.hash)) { - if (samdb_msg_add_hash(module->ldb, msg, msg, "dBCSPwd", &tmp_hash) != 0) { - return LDB_ERR_OPERATIONS_ERROR; - } + for (i = 0; i < MIN(io->domain->pwdHistoryLength-1, io->o.lm_history_len); i++) { + io->g.lm_history[i+1] = io->o.lm_history[i]; + } + io->g.lm_history_len = i + 1; + + if (io->g.lm_hash) { + io->g.lm_history[0] = *io->g.lm_hash; + } else { + E_deshash("", io->g.lm_history[0].hash); } return LDB_SUCCESS; } -static int add_krb5_keys_from_password(struct ldb_module *module, struct ldb_message *msg, - struct smb_krb5_context *smb_krb5_context, - struct domain_data *domain, - const char *samAccountName, - const char *user_principal_name, - int is_computer) +static int setup_primary_kerberos(struct setup_password_fields_io *io, + const struct supplementalCredentialsBlob *old_scb, + struct package_PrimaryKerberosBlob *pkb) { - const char *sambaPassword; - Principal *salt_principal; krb5_error_code krb5_ret; - size_t num_keys; - Key *keys; - int i; + Principal *salt_principal; + krb5_salt salt; + krb5_keyblock key; + uint32_t k=0; + struct supplementalCredentialsPackage *old_scp = NULL; + struct package_PrimaryKerberosBlob _old_pkb; + struct package_PrimaryKerberosBlob *old_pkb = NULL; + uint32_t i; + NTSTATUS status; /* Many, many thanks to lukeh@padl.com for this * algorithm, described in his Nov 10 2004 mail to * samba-technical@samba.org */ - sambaPassword = ldb_msg_find_attr_as_string(msg, "sambaPassword", NULL); - if (sambaPassword == NULL) { /* impossible, what happened ?! */ - return LDB_ERR_OPERATIONS_ERROR; - } - - if (is_computer) { - /* Determine a salting principal */ - char *name = talloc_strdup(msg, samAccountName); + /* + * Determine a salting principal + */ + if (io->u.is_computer) { + char *name; char *saltbody; - if (name == NULL) { - ldb_asprintf_errstring(module->ldb, - "password_hash_handle: " - "generation of new kerberos keys failed: %s is a computer without a samAccountName", - ldb_dn_get_linearized(msg->dn)); + + name = talloc_strdup(io->ac, io->u.sAMAccountName); + if (!name) { + ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } + if (name[strlen(name)-1] == '$') { name[strlen(name)-1] = '\0'; } - saltbody = talloc_asprintf(msg, "%s.%s", name, domain->dns_domain); + + saltbody = talloc_asprintf(io->ac, "%s.%s", name, io->domain->dns_domain); + if (!saltbody) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } - krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, - &salt_principal, - domain->realm, "host", - saltbody, NULL); - } else if (user_principal_name) { + krb5_ret = krb5_make_principal(io->smb_krb5_context->krb5_context, + &salt_principal, + io->domain->realm, "host", + saltbody, NULL); + } else if (io->u.user_principal_name) { + char *user_principal_name; char *p; - user_principal_name = talloc_strdup(msg, user_principal_name); - if (user_principal_name == NULL) { - return LDB_ERR_OPERATIONS_ERROR; - } else { - p = strchr(user_principal_name, '@'); - if (p) { - p[0] = '\0'; - } - krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, - &salt_principal, - domain->realm, user_principal_name, NULL); - } - } else { - if (!samAccountName) { - ldb_asprintf_errstring(module->ldb, - "password_hash_handle: " - "generation of new kerberos keys failed: %s has no samAccountName", - ldb_dn_get_linearized(msg->dn)); + + user_principal_name = talloc_strdup(io->ac, io->u.user_principal_name); + if (!user_principal_name) { + ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - krb5_ret = krb5_make_principal(smb_krb5_context->krb5_context, - &salt_principal, - domain->realm, samAccountName, - NULL); + + p = strchr(user_principal_name, '@'); + if (p) { + p[0] = '\0'; + } + + krb5_ret = krb5_make_principal(io->smb_krb5_context->krb5_context, + &salt_principal, + io->domain->realm, user_principal_name, + NULL); + } else { + krb5_ret = krb5_make_principal(io->smb_krb5_context->krb5_context, + &salt_principal, + io->domain->realm, io->u.sAMAccountName, + NULL); + } + if (krb5_ret) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_primary_kerberos: " + "generation of a salting principal failed: %s", + smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); + return LDB_ERR_OPERATIONS_ERROR; } + /* + * create salt from salt_principal + */ + krb5_ret = krb5_get_pw_salt(io->smb_krb5_context->krb5_context, + salt_principal, &salt); + krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal); if (krb5_ret) { - ldb_asprintf_errstring(module->ldb, - "password_hash_handle: " - "generation of a saltking principal failed: %s", - smb_get_krb5_error_message(smb_krb5_context->krb5_context, krb5_ret, msg)); + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_primary_kerberos: " + "generation of krb5_salt failed: %s", + smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); + return LDB_ERR_OPERATIONS_ERROR; + } + /* create a talloc copy */ + pkb->salt.string = talloc_strndup(io->ac, + salt.saltvalue.data, + salt.saltvalue.length); + krb5_free_salt(io->smb_krb5_context->krb5_context, salt); + if (!pkb->salt.string) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + salt.saltvalue.data = discard_const(pkb->salt.string); + salt.saltvalue.length = strlen(pkb->salt.string); + + /* + * prepare generation of keys + * + * ENCTYPE_AES256_CTS_HMAC_SHA1_96 (disabled by default) + * ENCTYPE_DES_CBC_MD5 + * ENCTYPE_DES_CBC_CRC + * + * NOTE: update num_keys1 when you add another enctype! + */ + pkb->num_keys1 = 0; + pkb->keys1 = talloc_array(io->ac, struct package_PrimaryKerberosKey, 3); + if (!pkb->keys1) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + pkb->unknown3_1 = talloc_zero_array(io->ac, uint64_t, pkb->num_keys1); + if (!pkb->unknown3_1) { + ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - /* TODO: We may wish to control the encryption types chosen in future */ - krb5_ret = hdb_generate_key_set_password(smb_krb5_context->krb5_context, - salt_principal, sambaPassword, &keys, &num_keys); - krb5_free_principal(smb_krb5_context->krb5_context, salt_principal); +if (lp_parm_bool(-1, "password_hash", "create_aes_key", false)) { +/* + * TODO: + * + * w2k and w2k3 doesn't support AES, so we'll not include + * the AES key here yet. + * + * Also we don't have an example supplementalCredentials blob + * from Windows Longhorn Server with AES support + * + */ + /* + * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of + * the salt and the cleartext password + */ + krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + io->n.cleartext, + salt, + &key); + pkb->keys1[k].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; + pkb->keys1[k].value = talloc(pkb->keys1, DATA_BLOB); + if (!pkb->keys1[k].value) { + krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + *pkb->keys1[k].value = data_blob_talloc(pkb->keys1[k].value, + key.keyvalue.data, + key.keyvalue.length); + krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); + if (!pkb->keys1[k].value->data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + k++; +} - if (krb5_ret) { - ldb_asprintf_errstring(module->ldb, - "password_hash_handle: " - "generation of new kerberos keys failed: %s", - smb_get_krb5_error_message(smb_krb5_context->krb5_context, krb5_ret, msg)); + /* + * create ENCTYPE_DES_CBC_MD5 key out of + * the salt and the cleartext password + */ + krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, + ENCTYPE_DES_CBC_MD5, + io->n.cleartext, + salt, + &key); + pkb->keys1[k].keytype = ENCTYPE_DES_CBC_MD5; + pkb->keys1[k].value = talloc(pkb->keys1, DATA_BLOB); + if (!pkb->keys1[k].value) { + krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + *pkb->keys1[k].value = data_blob_talloc(pkb->keys1[k].value, + key.keyvalue.data, + key.keyvalue.length); + krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); + if (!pkb->keys1[k].value->data) { + ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } + k++; - /* Walking all the key types generated, transform each - * key into an ASN.1 blob + /* + * create ENCTYPE_DES_CBC_CRC key out of + * the salt and the cleartext password */ - for (i=0; i < num_keys; i++) { - unsigned char *buf; - size_t buf_size; - size_t len; - struct ldb_val val; - int ret; - - if (keys[i].key.keytype == KEYTYPE_ARCFOUR) { - /* We might end up doing this below: - * This ensures we get the unicode - * conversion right. This should also - * be fixed in the Heimdal libs */ + krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, + ENCTYPE_DES_CBC_CRC, + io->n.cleartext, + salt, + &key); + pkb->keys1[k].keytype = ENCTYPE_DES_CBC_CRC; + pkb->keys1[k].value = talloc(pkb->keys1, DATA_BLOB); + if (!pkb->keys1[k].value) { + krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + *pkb->keys1[k].value = data_blob_talloc(pkb->keys1[k].value, + key.keyvalue.data, + key.keyvalue.length); + krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); + if (!pkb->keys1[k].value->data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + k++; + + /* fix up key number */ + pkb->num_keys1 = k; + + /* initialize the old keys to zero */ + pkb->num_keys2 = 0; + pkb->keys2 = NULL; + pkb->unknown3_2 = NULL; + + /* if there're no old keys, then we're done */ + if (!old_scb) { + return LDB_SUCCESS; + } + + for (i=0; i < old_scb->sub.num_packages; i++) { + if (old_scb->sub.packages[i].unknown1 != 0x00000001) { continue; } - ASN1_MALLOC_ENCODE(Key, buf, buf_size, &keys[i], &len, krb5_ret); - if (krb5_ret) { - return LDB_ERR_OPERATIONS_ERROR; + + if (strcmp("Primary:Kerberos", old_scb->sub.packages[i].name) != 0) { + continue; } - - val.data = talloc_memdup(msg, buf, len); - val.length = len; - free(buf); - if (!val.data || krb5_ret) { - hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); + + if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) { + continue; + } + + old_scp = &old_scb->sub.packages[i]; + break; + } + /* Primary:Kerberos element of supplementalCredentials */ + if (old_scp) { + DATA_BLOB blob; + + blob = strhex_to_data_blob(old_scp->data); + if (!blob.data) { + ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - ret = ldb_msg_add_value(msg, "krb5Key", &val, NULL); - if (ret != LDB_SUCCESS) { - hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); - return ret; + talloc_steal(io->ac, blob.data); + + /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */ + status = ndr_pull_struct_blob(&blob, io->ac, &_old_pkb, + (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob); + if (!NT_STATUS_IS_OK(status)) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_primary_kerberos: " + "failed to pull old package_PrimaryKerberosBlob: %s", + nt_errstr(status)); + return LDB_ERR_OPERATIONS_ERROR; } + old_pkb = &_old_pkb; } - - hdb_free_keys (smb_krb5_context->krb5_context, num_keys, keys); + + /* if we didn't found the old keys we're done */ + if (!old_pkb) { + return LDB_SUCCESS; + } + + /* fill in the old keys */ + pkb->num_keys2 = old_pkb->num_keys1; + pkb->keys2 = old_pkb->keys1; + pkb->unknown3_2 = old_pkb->unknown3_1; return LDB_SUCCESS; } -static int add_krb5_keys_from_NThash(struct ldb_module *module, struct ldb_message *msg, - struct smb_krb5_context *smb_krb5_context) +static int setup_supplemental_field(struct setup_password_fields_io *io) { - struct samr_Password *ntPwdHash; - krb5_error_code krb5_ret; - unsigned char *buf; - size_t buf_size; - size_t len; - struct ldb_val val; - Key key; - - key.mkvno = 0; - key.salt = NULL; /* No salt for this enc type */ + struct supplementalCredentialsBlob scb; + struct supplementalCredentialsBlob _old_scb; + struct supplementalCredentialsBlob *old_scb = NULL; + /* Packages + (Kerberos and maybe CLEARTEXT) */ + uint32_t num_packages = 1 + 1; + struct supplementalCredentialsPackage packages[1+2]; + struct supplementalCredentialsPackage *pp = &packages[0]; + struct supplementalCredentialsPackage *pk = &packages[1]; + struct supplementalCredentialsPackage *pc = NULL; + struct package_PackagesBlob pb; + DATA_BLOB pb_blob; + char *pb_hexstr; + struct package_PrimaryKerberosBlob pkb; + DATA_BLOB pkb_blob; + char *pkb_hexstr; + struct package_PrimaryCLEARTEXTBlob pcb; + DATA_BLOB pcb_blob; + char *pcb_hexstr; + int ret; + NTSTATUS status; + uint8_t zero16[16]; + + ZERO_STRUCT(zero16); + + if (!io->n.cleartext) { + /* + * when we don't have a cleartext password + * we can't setup a supplementalCredential value + */ + return LDB_SUCCESS; + } + + /* if there's an old supplementaCredentials blob then parse it */ + if (io->o.supplemental) { + status = ndr_pull_struct_blob_all(io->o.supplemental, io->ac, &_old_scb, + (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob); + if (!NT_STATUS_IS_OK(status)) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_supplemental_field: " + "failed to pull old supplementalCredentialsBlob: %s", + nt_errstr(status)); + return LDB_ERR_OPERATIONS_ERROR; + } - ntPwdHash = samdb_result_hash(msg, msg, "unicodePwd"); - if (ntPwdHash == NULL) { /* what happened ?! */ - return LDB_ERR_OPERATIONS_ERROR; + old_scb = &_old_scb; } - krb5_ret = krb5_keyblock_init(smb_krb5_context->krb5_context, - KEYTYPE_ARCFOUR, - ntPwdHash->hash, sizeof(ntPwdHash->hash), - &key.key); - if (krb5_ret) { - return LDB_ERR_OPERATIONS_ERROR; + if (io->domain->store_cleartext && + (io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { + pc = &packages[2]; + num_packages++; } - ASN1_MALLOC_ENCODE(Key, buf, buf_size, &key, &len, krb5_ret); - if (krb5_ret) { + + /* Kerberos, CLEARTEXT and termination(counted by the Packages element) */ + pb.names = talloc_zero_array(io->ac, const char *, num_packages); + + /* + * setup 'Primary:Kerberos' element + */ + pb.names[0] = "Kerberos"; + + ret = setup_primary_kerberos(io, old_scb, &pkb); + if (ret != LDB_SUCCESS) { + return ret; + } + + status = ndr_push_struct_blob(&pkb_blob, io->ac, &pkb, + (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob); + if (!NT_STATUS_IS_OK(status)) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_supplemental_field: " + "failed to push package_PrimaryKerberosBlob: %s", + nt_errstr(status)); return LDB_ERR_OPERATIONS_ERROR; } - krb5_free_keyblock_contents(smb_krb5_context->krb5_context, - &key.key); - - val.data = talloc_memdup(msg, buf, len); - val.length = len; - free(buf); - if (!val.data) { + /* + * TODO: + * + * This is ugly, but we want to generate the same blob as + * w2k and w2k3...we should handle this in the idl + */ + status = data_blob_append(io->ac, &pkb_blob, zero16, sizeof(zero16)); + if (!NT_STATUS_IS_OK(status)) { + ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - if (ldb_msg_add_value(msg, "krb5Key", &val, NULL) != 0) { + pkb_hexstr = data_blob_hex_string(io->ac, &pkb_blob); + if (!pkb_hexstr) { + ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } + pk->name = "Primary:Kerberos"; + pk->unknown1 = 1; + pk->data = pkb_hexstr; - return LDB_SUCCESS; -} - -static int set_pwdLastSet(struct ldb_module *module, struct ldb_message *msg, int is_mod) -{ - NTTIME now_nt; - - /* set it as now */ - unix_to_nt_time(&now_nt, time(NULL)); - - if (!is_mod) { - /* be sure there isn't a 0 value set (eg. coming from the template) */ - ldb_msg_remove_attr(msg, "pwdLastSet"); - /* add */ - if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_ADD, NULL) != 0) { + /* + * setup 'Primary:CLEARTEXT' element + */ + if (pc) { + pb.names[1] = "CLEARTEXT"; + + pcb.cleartext = io->n.cleartext; + + status = ndr_push_struct_blob(&pcb_blob, io->ac, &pcb, + (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob); + if (!NT_STATUS_IS_OK(status)) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_supplemental_field: " + "failed to push package_PrimaryCLEARTEXTBlob: %s", + nt_errstr(status)); return LDB_ERR_OPERATIONS_ERROR; } - } else { - /* replace */ - if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE, NULL) != 0) { + pcb_hexstr = data_blob_hex_string(io->ac, &pcb_blob); + if (!pcb_hexstr) { + ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } + pc->name = "Primary:CLEARTEXT"; + pc->unknown1 = 1; + pc->data = pcb_hexstr; } - if (samdb_msg_add_uint64(module->ldb, msg, msg, "pwdLastSet", now_nt) != 0) { + /* + * setup 'Packages' element + */ + status = ndr_push_struct_blob(&pb_blob, io->ac, &pb, + (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob); + if (!NT_STATUS_IS_OK(status)) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_supplemental_field: " + "failed to push package_PackagesBlob: %s", + nt_errstr(status)); return LDB_ERR_OPERATIONS_ERROR; } - - return LDB_SUCCESS; -} - -static int add_keyVersionNumber(struct ldb_module *module, struct ldb_message *msg, int previous) -{ - /* replace or add */ - if (ldb_msg_add_empty(msg, "msDS-KeyVersionNumber", LDB_FLAG_MOD_REPLACE, NULL) != 0) { + pb_hexstr = data_blob_hex_string(io->ac, &pb_blob); + if (!pb_hexstr) { + ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } + pp->name = "Packages"; + pp->unknown1 = 2; + pp->data = pb_hexstr; - if (samdb_msg_add_uint(module->ldb, msg, msg, "msDS-KeyVersionNumber", previous+1) != 0) { + /* + * setup 'supplementalCredentials' value + */ + scb.sub.num_packages = num_packages; + scb.sub.packages = packages; + + status = ndr_push_struct_blob(&io->g.supplemental, io->ac, &scb, + (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob); + if (!NT_STATUS_IS_OK(status)) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_supplemental_field: " + "failed to push supplementalCredentialsBlob: %s", + nt_errstr(status)); return LDB_ERR_OPERATIONS_ERROR; } return LDB_SUCCESS; } -static int setPwdHistory(struct ldb_module *module, struct ldb_message *msg, struct ldb_message *old_msg, int hlen) +static int setup_last_set_field(struct setup_password_fields_io *io) { - struct samr_Password *nt_hash; - struct samr_Password *lm_hash; - struct samr_Password *nt_history; - struct samr_Password *lm_history; - struct samr_Password *new_nt_history; - struct samr_Password *new_lm_history; - int nt_hist_len; - int lm_hist_len; - int i; + /* set it as now */ + unix_to_nt_time(&io->g.last_set, time(NULL)); - nt_hash = samdb_result_hash(msg, old_msg, "unicodePwd"); - lm_hash = samdb_result_hash(msg, old_msg, "dBCSPwd"); + return LDB_SUCCESS; +} - /* if no previous passwords just return */ - if (nt_hash == NULL && lm_hash == NULL) return LDB_SUCCESS; +static int setup_kvno_field(struct setup_password_fields_io *io) +{ + /* increment by one */ + io->g.kvno = io->o.kvno + 1; - nt_hist_len = samdb_result_hashes(msg, old_msg, "ntPwdHistory", &nt_history); - lm_hist_len = samdb_result_hashes(msg, old_msg, "lmPwdHistory", &lm_history); + return LDB_SUCCESS; +} - /* We might not have an old NT password */ - new_nt_history = talloc_array(msg, struct samr_Password, hlen); - if (new_nt_history == NULL) { - return LDB_ERR_OPERATIONS_ERROR; - } - for (i = 0; i < MIN(hlen-1, nt_hist_len); i++) { - new_nt_history[i+1] = nt_history[i]; - } - nt_hist_len = i + 1; - if (nt_hash) { - new_nt_history[0] = *nt_hash; - } else { - ZERO_STRUCT(new_nt_history[0]); +static int setup_password_fields(struct setup_password_fields_io *io) +{ + bool ok; + int ret; + + /* + * refuse the change if someone want to change the cleartext + * and supply his own hashes at the same time... + */ + if (io->n.cleartext && (io->n.nt_hash || io->n.lm_hash)) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_password_fields: " + "it's only allowed to set the cleartext password or the password hashes"); + return LDB_ERR_UNWILLING_TO_PERFORM; } - if (ldb_msg_add_empty(msg, "ntPwdHistory", LDB_FLAG_MOD_REPLACE, NULL) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + + if (io->n.cleartext && !io->n.nt_hash) { + struct samr_Password *hash; + + hash = talloc(io->ac, struct samr_Password); + if (!hash) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* compute the new nt hash */ + ok = E_md4hash(io->n.cleartext, hash->hash); + if (ok) { + io->n.nt_hash = hash; + } else { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_password_fields: " + "failed to generate nthash from cleartext password"); + return LDB_ERR_OPERATIONS_ERROR; + } } - if (samdb_msg_add_hashes(msg, msg, "ntPwdHistory", new_nt_history, nt_hist_len) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + + if (io->n.cleartext && !io->n.lm_hash) { + struct samr_Password *hash; + + hash = talloc(io->ac, struct samr_Password); + if (!hash) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* compute the new lm hash */ + ok = E_deshash(io->n.cleartext, hash->hash); + if (ok) { + io->n.lm_hash = hash; + } else { + talloc_free(hash->hash); + } } - - /* Don't store 'long' passwords in the LM history, - but make sure to 'expire' one password off the other end */ - new_lm_history = talloc_array(msg, struct samr_Password, hlen); - if (new_lm_history == NULL) { - return LDB_ERR_OPERATIONS_ERROR; + ret = setup_nt_fields(io); + if (ret != 0) { + return ret; } - for (i = 0; i < MIN(hlen-1, lm_hist_len); i++) { - new_lm_history[i+1] = lm_history[i]; + + ret = setup_lm_fields(io); + if (ret != 0) { + return ret; } - lm_hist_len = i + 1; - if (lm_hash) { - new_lm_history[0] = *lm_hash; - } else { - ZERO_STRUCT(new_lm_history[0]); + + ret = setup_supplemental_field(io); + if (ret != 0) { + return ret; } - if (ldb_msg_add_empty(msg, "lmPwdHistory", LDB_FLAG_MOD_REPLACE, NULL) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + + ret = setup_last_set_field(io); + if (ret != 0) { + return ret; } - if (samdb_msg_add_hashes(msg, msg, "lmPwdHistory", new_lm_history, lm_hist_len) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + + ret = setup_kvno_field(io); + if (ret != 0) { + return ret; } return LDB_SUCCESS; @@ -593,9 +931,14 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } - /* nobody must touch password Histories */ - if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory") || - ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) { + /* nobody must touch this fields */ + if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) { return LDB_ERR_UNWILLING_TO_PERFORM; } @@ -677,8 +1020,8 @@ static int password_hash_add_do_add(struct ldb_handle *h) { struct ph_context *ac; struct domain_data *domain; struct smb_krb5_context *smb_krb5_context; - struct ldb_message_element *sambaAttr; struct ldb_message *msg; + struct setup_password_fields_io io; int ret; ac = talloc_get_type(h->private_data, struct ph_context); @@ -704,54 +1047,84 @@ static int password_hash_add_do_add(struct ldb_handle *h) { return LDB_ERR_OPERATIONS_ERROR; } - /* if we have sambaPassword in the original message add the operatio on it here */ - sambaAttr = ldb_msg_find_element(msg, "sambaPassword"); - if (sambaAttr) { - unsigned int user_account_control; - ret = add_password_hashes(ac->module, msg, 0); - /* we can compute new password hashes from the unicode password */ + ZERO_STRUCT(io); + io.ac = ac; + io.domain = domain; + io.smb_krb5_context = smb_krb5_context; + + io.u.user_account_control = samdb_result_uint(msg, "userAccountControl", 0); + io.u.sAMAccountName = samdb_result_string(msg, "samAccountName", NULL); + io.u.user_principal_name = samdb_result_string(msg, "userPrincipalName", NULL); + io.u.is_computer = ldb_msg_check_string_attribute(msg, "objectClass", "computer"); + + io.n.cleartext = samdb_result_string(msg, "sambaPassword", NULL); + io.n.nt_hash = samdb_result_hash(io.ac, msg, "unicodePwd"); + io.n.lm_hash = samdb_result_hash(io.ac, msg, "dBCSPwd"); + + /* remove attributes */ + if (io.n.cleartext) ldb_msg_remove_attr(msg, "sambaPassword"); + if (io.n.nt_hash) ldb_msg_remove_attr(msg, "unicodePwd"); + if (io.n.lm_hash) ldb_msg_remove_attr(msg, "dBCSPwd"); + ldb_msg_remove_attr(msg, "pwdLastSet"); + io.o.kvno = samdb_result_uint(msg, "msDs-KeyVersionNumber", 1) - 1; + ldb_msg_remove_attr(msg, "msDs-KeyVersionNumber"); + + ret = setup_password_fields(&io); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (io.g.nt_hash) { + ret = samdb_msg_add_hash(ac->module->ldb, ac, msg, + "unicodePwd", io.g.nt_hash); if (ret != LDB_SUCCESS) { return ret; } - - /* now add krb5 keys based on unicode password */ - ret = add_krb5_keys_from_password(ac->module, msg, smb_krb5_context, domain, - ldb_msg_find_attr_as_string(msg, "samAccountName", NULL), - ldb_msg_find_attr_as_string(msg, "userPrincipalName", NULL), - ldb_msg_check_string_attribute(msg, "objectClass", "computer")); + } + if (io.g.lm_hash) { + ret = samdb_msg_add_hash(ac->module->ldb, ac, msg, + "dBCSPwd", io.g.lm_hash); if (ret != LDB_SUCCESS) { return ret; } - - /* if both the domain properties and the user account controls do not permit - * clear text passwords then wipe out the sambaPassword */ - user_account_control = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0); - if (domain->store_cleartext && (user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { - /* Keep sambaPassword attribute */ - } else { - ldb_msg_remove_attr(msg, "sambaPassword"); - } } - - /* add also krb5 keys based on NT the hash (we might have unicodePwd, but not the cleartext */ - ret = add_krb5_keys_from_NThash(ac->module, msg, smb_krb5_context); - if (ret != LDB_SUCCESS) { - return ret; + if (io.g.nt_history_len > 0) { + ret = samdb_msg_add_hashes(ac, msg, + "ntPwdHistory", + io.g.nt_history, + io.g.nt_history_len); + if (ret != LDB_SUCCESS) { + return ret; + } } - - /* don't touch it if a value is set. It could be an incoming samsync */ - if (ldb_msg_find_attr_as_uint64(msg, "pwdLastSet", 0) == 0) { - if (set_pwdLastSet(ac->module, msg, 0) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + if (io.g.lm_history_len > 0) { + ret = samdb_msg_add_hashes(ac, msg, + "lmPwdHistory", + io.g.lm_history, + io.g.lm_history_len); + if (ret != LDB_SUCCESS) { + return ret; } } - - /* don't touch it if a value is set. It could be an incoming samsync */ - if (!ldb_msg_find_element(msg, "msDS-KeyVersionNumber")) { - if (add_keyVersionNumber(ac->module, msg, 0) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + if (io.g.supplemental.length > 0) { + ret = ldb_msg_add_value(msg, "supplementalCredentials", + &io.g.supplemental, NULL); + if (ret != LDB_SUCCESS) { + return ret; } } + ret = samdb_msg_add_uint64(ac->module->ldb, ac, msg, + "pwdLastSet", + io.g.last_set); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = samdb_msg_add_uint(ac->module->ldb, ac, msg, + "msDs-KeyVersionNumber", + io.g.kvno); + if (ret != LDB_SUCCESS) { + return ret; + } h->state = LDB_ASYNC_INIT; h->status = LDB_SUCCESS; @@ -788,8 +1161,13 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r } /* nobody must touch password Histories */ - if (ldb_msg_find_element(req->op.mod.message, "ntPwdHistory") || - ldb_msg_find_element(req->op.mod.message, "lmPwdHistory")) { + if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } + if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) { return LDB_ERR_UNWILLING_TO_PERFORM; } @@ -797,6 +1175,13 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd"); lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd"); + /* If no part of this touches the sambaPassword OR unicodePwd and/or dBCSPwd, then we don't + * need to make any changes. For password changes/set there should + * be a 'delete' or a 'modify' on this attribute. */ + if ((!sambaAttr) && (!ntAttr) && (!lmAttr)) { + return ldb_next_request(module, req); + } + /* check passwords are single valued here */ /* TODO: remove this when passwords will be single valued in schema */ if (sambaAttr && (sambaAttr->num_values > 1)) { @@ -809,17 +1194,6 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r return LDB_ERR_CONSTRAINT_VIOLATION; } - /* If no part of this touches the sambaPassword OR unicodePwd and/or dBCSPwd, then we don't - * need to make any changes. For password changes/set there should - * be a 'delete' or a 'modify' on this attribute. */ - /* If the only operation is the deletion of the passwords then go on */ - if ( ((!sambaAttr) || ((sambaAttr->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_DELETE)) - && ((!ntAttr) || ((ntAttr->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_DELETE)) - && ((!lmAttr) || ((lmAttr->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_DELETE)) ) { - - return ldb_next_request(module, req); - } - h = ph_init_handle(req, module, PH_MOD); if (!h) { return LDB_ERR_OPERATIONS_ERROR; @@ -906,8 +1280,9 @@ static int password_hash_mod_search_self(struct ldb_handle *h) { "ntPwdHistory", "objectSid", "msDS-KeyVersionNumber", "objectClass", "userPrincipalName", - "samAccountName", + "sAMAccountName", "dBCSPwd", "unicodePwd", + "supplementalCredentials", NULL }; ac = talloc_get_type(h->private_data, struct ph_context); @@ -968,11 +1343,11 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) { struct ph_context *ac; struct domain_data *domain; struct smb_krb5_context *smb_krb5_context; - struct ldb_message_element *sambaAttr; struct ldb_message *msg; - int phlen; + struct ldb_message *orig_msg; + struct ldb_message *searched_msg; + struct setup_password_fields_io io; int ret; - BOOL added_hashes = False; ac = talloc_get_type(h->private_data, struct ph_context); @@ -1002,94 +1377,93 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) { return LDB_ERR_OPERATIONS_ERROR; } - /* we are going to replace the existing krb5key or delete it */ - if (ldb_msg_add_empty(msg, "krb5key", LDB_FLAG_MOD_REPLACE, NULL) != 0) { - return LDB_ERR_OPERATIONS_ERROR; - } + orig_msg = discard_const(ac->orig_req->op.mod.message); + searched_msg = ac->search_res->message; - /* if we have sambaPassword in the original message add the operation on it here */ - sambaAttr = ldb_msg_find_element(ac->orig_req->op.mod.message, "sambaPassword"); - if (sambaAttr) { + ZERO_STRUCT(io); + io.ac = ac; + io.domain = domain; + io.smb_krb5_context = smb_krb5_context; - if (ldb_msg_add(msg, sambaAttr, sambaAttr->flags) != 0) { - return LDB_ERR_OPERATIONS_ERROR; - } + io.u.user_account_control = samdb_result_uint(searched_msg, "userAccountControl", 0); + io.u.sAMAccountName = samdb_result_string(searched_msg, "samAccountName", NULL); + io.u.user_principal_name = samdb_result_string(searched_msg, "userPrincipalName", NULL); + io.u.is_computer = ldb_msg_check_string_attribute(searched_msg, "objectClass", "computer"); - /* if we are actually settting a new unicode password, - * use it to generate the password hashes */ - if (((sambaAttr->flags & LDB_FLAG_MOD_MASK) != LDB_FLAG_MOD_DELETE) - && (sambaAttr->num_values == 1)) { - /* we can compute new password hashes from the unicode password */ - ret = add_password_hashes(ac->module, msg, 1); - if (ret != LDB_SUCCESS) { - return ret; - } - - added_hashes = True; - - /* now add krb5 keys based on unicode password */ - ret = add_krb5_keys_from_password(ac->module, msg, smb_krb5_context, domain, - ldb_msg_find_attr_as_string(ac->search_res->message, "samAccountName", NULL), - ldb_msg_find_attr_as_string(ac->search_res->message, "userPrincipalName", NULL), - ldb_msg_check_string_attribute(ac->search_res->message, "objectClass", "computer")); - - if (ret != LDB_SUCCESS) { - return ret; - } - - /* if the domain properties or the user account controls do not permit - * clear text passwords then wipe out the sambaPassword */ - if (domain->store_cleartext && - (ldb_msg_find_attr_as_uint(ac->search_res->message, "userAccountControl", 0) & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { - /* Keep sambaPassword attribute */ - } else { - ldb_msg_remove_attr(msg, "sambaPassword"); - } + io.n.cleartext = samdb_result_string(orig_msg, "sambaPassword", NULL); + io.n.nt_hash = samdb_result_hash(io.ac, orig_msg, "unicodePwd"); + io.n.lm_hash = samdb_result_hash(io.ac, orig_msg, "dBCSPwd"); - } + io.o.kvno = samdb_result_uint(searched_msg, "msDs-KeyVersionNumber", 0); + io.o.nt_history_len = samdb_result_hashes(io.ac, searched_msg, "ntPwdHistory", &io.o.nt_history); + io.o.lm_history_len = samdb_result_hashes(io.ac, searched_msg, "lmPwdHistory", &io.o.lm_history); + io.o.supplemental = ldb_msg_find_ldb_val(searched_msg, "supplementalCredentials"); + + ret = setup_password_fields(&io); + if (ret != LDB_SUCCESS) { + return ret; } - /* if we didn't create the hashes above, try using values supplied directly */ - if (!added_hashes) { - struct ldb_message_element *el; - - el = ldb_msg_find_element(ac->orig_req->op.mod.message, "unicodePwd"); - if (ldb_msg_add(msg, el, el->flags) != 0) { - return LDB_ERR_OPERATIONS_ERROR; - } - - el = ldb_msg_find_element(ac->orig_req->op.mod.message, "dBCSPwd"); - if (ldb_msg_add(msg, el, el->flags) != 0) { - return LDB_ERR_OPERATIONS_ERROR; + /* make sure we replace all the old attributes */ + ret = ldb_msg_add_empty(msg, "unicodePwd", LDB_FLAG_MOD_REPLACE, NULL); + ret = ldb_msg_add_empty(msg, "dBCSPwd", LDB_FLAG_MOD_REPLACE, NULL); + ret = ldb_msg_add_empty(msg, "ntPwdHistory", LDB_FLAG_MOD_REPLACE, NULL); + ret = ldb_msg_add_empty(msg, "lmPwdHistory", LDB_FLAG_MOD_REPLACE, NULL); + ret = ldb_msg_add_empty(msg, "supplementalCredentials", LDB_FLAG_MOD_REPLACE, NULL); + ret = ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE, NULL); + ret = ldb_msg_add_empty(msg, "msDs-KeyVersionNumber", LDB_FLAG_MOD_REPLACE, NULL); + + if (io.g.nt_hash) { + ret = samdb_msg_add_hash(ac->module->ldb, ac, msg, + "unicodePwd", io.g.nt_hash); + if (ret != LDB_SUCCESS) { + return ret; } } - - /* add also krb5 keys based on NT the hash */ - if (add_krb5_keys_from_NThash(ac->module, msg, smb_krb5_context) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + if (io.g.lm_hash) { + ret = samdb_msg_add_hash(ac->module->ldb, ac, msg, + "dBCSPwd", io.g.lm_hash); + if (ret != LDB_SUCCESS) { + return ret; + } } - - /* set change time */ - if (set_pwdLastSet(ac->module, msg, 1) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + if (io.g.nt_history_len > 0) { + ret = samdb_msg_add_hashes(ac, msg, + "ntPwdHistory", + io.g.nt_history, + io.g.nt_history_len); + if (ret != LDB_SUCCESS) { + return ret; + } } - - /* don't touch it if a value is set. It could be an incoming samsync */ - if (!ldb_msg_find_element(ac->orig_req->op.mod.message, - "msDS-KeyVersionNumber")) { - if (add_keyVersionNumber(ac->module, msg, - ldb_msg_find_attr_as_uint(ac->search_res->message, - "msDS-KeyVersionNumber", 0) - ) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + if (io.g.lm_history_len > 0) { + ret = samdb_msg_add_hashes(ac, msg, + "lmPwdHistory", + io.g.lm_history, + io.g.lm_history_len); + if (ret != LDB_SUCCESS) { + return ret; } } - - if ((phlen = samdb_result_uint(ac->dom_res->message, "pwdHistoryLength", 0)) > 0) { - if (setPwdHistory(ac->module, msg, ac->search_res->message, phlen) != LDB_SUCCESS) { - return LDB_ERR_OPERATIONS_ERROR; + if (io.g.supplemental.length > 0) { + ret = ldb_msg_add_value(msg, "supplementalCredentials", + &io.g.supplemental, NULL); + if (ret != LDB_SUCCESS) { + return ret; } } + ret = samdb_msg_add_uint64(ac->module->ldb, ac, msg, + "pwdLastSet", + io.g.last_set); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = samdb_msg_add_uint(ac->module->ldb, ac, msg, + "msDs-KeyVersionNumber", + io.g.kvno); + if (ret != LDB_SUCCESS) { + return ret; + } h->state = LDB_ASYNC_INIT; h->status = LDB_SUCCESS; -- cgit From ad7e7249b6d6e2e37868ff13236a60cfbadb7ef0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Feb 2007 00:28:11 +0000 Subject: r21441: create a union for the PrimaryKerberosBlob content so that ndr_pull will fail if version isn't 3 and we notice if the format changes... metze (This used to be commit 91f7a094cfd04405c224b9579146d814cba507b3) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 80 +++++++++++++++----------- 1 file changed, 45 insertions(+), 35 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index a31486fdda..861e17e4d0 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -221,9 +221,10 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, krb5_salt salt; krb5_keyblock key; uint32_t k=0; + struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3; struct supplementalCredentialsPackage *old_scp = NULL; struct package_PrimaryKerberosBlob _old_pkb; - struct package_PrimaryKerberosBlob *old_pkb = NULL; + struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL; uint32_t i; NTSTATUS status; @@ -305,16 +306,16 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, return LDB_ERR_OPERATIONS_ERROR; } /* create a talloc copy */ - pkb->salt.string = talloc_strndup(io->ac, + pkb3->salt.string = talloc_strndup(io->ac, salt.saltvalue.data, salt.saltvalue.length); krb5_free_salt(io->smb_krb5_context->krb5_context, salt); - if (!pkb->salt.string) { + if (!pkb3->salt.string) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - salt.saltvalue.data = discard_const(pkb->salt.string); - salt.saltvalue.length = strlen(pkb->salt.string); + salt.saltvalue.data = discard_const(pkb3->salt.string); + salt.saltvalue.length = strlen(pkb3->salt.string); /* * prepare generation of keys @@ -323,16 +324,16 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, * ENCTYPE_DES_CBC_MD5 * ENCTYPE_DES_CBC_CRC * - * NOTE: update num_keys1 when you add another enctype! + * NOTE: update num_keys when you add another enctype! */ - pkb->num_keys1 = 0; - pkb->keys1 = talloc_array(io->ac, struct package_PrimaryKerberosKey, 3); - if (!pkb->keys1) { + pkb3->num_keys = 3; + pkb3->keys = talloc_array(io->ac, struct package_PrimaryKerberosKey, pkb3->num_keys); + if (!pkb3->keys) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - pkb->unknown3_1 = talloc_zero_array(io->ac, uint64_t, pkb->num_keys1); - if (!pkb->unknown3_1) { + pkb3->unknown3 = talloc_zero_array(io->ac, uint64_t, pkb3->num_keys); + if (!pkb3->unknown3) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } @@ -357,18 +358,18 @@ if (lp_parm_bool(-1, "password_hash", "create_aes_key", false)) { io->n.cleartext, salt, &key); - pkb->keys1[k].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; - pkb->keys1[k].value = talloc(pkb->keys1, DATA_BLOB); - if (!pkb->keys1[k].value) { + pkb3->keys[k].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; + pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB); + if (!pkb3->keys[k].value) { krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - *pkb->keys1[k].value = data_blob_talloc(pkb->keys1[k].value, + *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value, key.keyvalue.data, key.keyvalue.length); krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - if (!pkb->keys1[k].value->data) { + if (!pkb3->keys[k].value->data) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } @@ -384,18 +385,18 @@ if (lp_parm_bool(-1, "password_hash", "create_aes_key", false)) { io->n.cleartext, salt, &key); - pkb->keys1[k].keytype = ENCTYPE_DES_CBC_MD5; - pkb->keys1[k].value = talloc(pkb->keys1, DATA_BLOB); - if (!pkb->keys1[k].value) { + pkb3->keys[k].keytype = ENCTYPE_DES_CBC_MD5; + pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB); + if (!pkb3->keys[k].value) { krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - *pkb->keys1[k].value = data_blob_talloc(pkb->keys1[k].value, + *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value, key.keyvalue.data, key.keyvalue.length); krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - if (!pkb->keys1[k].value->data) { + if (!pkb3->keys[k].value->data) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } @@ -410,30 +411,30 @@ if (lp_parm_bool(-1, "password_hash", "create_aes_key", false)) { io->n.cleartext, salt, &key); - pkb->keys1[k].keytype = ENCTYPE_DES_CBC_CRC; - pkb->keys1[k].value = talloc(pkb->keys1, DATA_BLOB); - if (!pkb->keys1[k].value) { + pkb3->keys[k].keytype = ENCTYPE_DES_CBC_CRC; + pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB); + if (!pkb3->keys[k].value) { krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - *pkb->keys1[k].value = data_blob_talloc(pkb->keys1[k].value, + *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value, key.keyvalue.data, key.keyvalue.length); krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - if (!pkb->keys1[k].value->data) { + if (!pkb3->keys[k].value->data) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } k++; /* fix up key number */ - pkb->num_keys1 = k; + pkb3->num_keys = k; /* initialize the old keys to zero */ - pkb->num_keys2 = 0; - pkb->keys2 = NULL; - pkb->unknown3_2 = NULL; + pkb3->num_old_keys = 0; + pkb3->old_keys = NULL; + pkb3->unknown3_old = NULL; /* if there're no old keys, then we're done */ if (!old_scb) { @@ -477,18 +478,27 @@ if (lp_parm_bool(-1, "password_hash", "create_aes_key", false)) { nt_errstr(status)); return LDB_ERR_OPERATIONS_ERROR; } - old_pkb = &_old_pkb; + + if (_old_pkb.version != 3) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_primary_kerberos: " + "package_PrimaryKerberosBlob version[%u] expected[3]", + _old_pkb.version); + return LDB_ERR_OPERATIONS_ERROR; + } + + old_pkb3 = &_old_pkb.ctr.ctr3; } /* if we didn't found the old keys we're done */ - if (!old_pkb) { + if (!old_pkb3) { return LDB_SUCCESS; } /* fill in the old keys */ - pkb->num_keys2 = old_pkb->num_keys1; - pkb->keys2 = old_pkb->keys1; - pkb->unknown3_2 = old_pkb->unknown3_1; + pkb3->num_old_keys = old_pkb3->num_keys; + pkb3->old_keys = old_pkb3->keys; + pkb3->unknown3_old = old_pkb3->unknown3; return LDB_SUCCESS; } -- cgit From b3ef5c0b92dc86aadd3d81e981edc17559ce0026 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 20 Feb 2007 16:22:50 +0000 Subject: r21470: generate Primary:WDigest blob with precalculated digest-md5 hashes: see http://technet2.microsoft.com/WindowsServer/en/library/717b450c-f4a0-4cc9-86f4-cc0633aae5f91033.mspx?mfr=true for how the hashes are supposed to be (but w2k3 doesn't to some correctly...) this is a verify nice tool to test the hash genaration, but you need to add support for "" realm strings... http://fresh.t-systems-sfr.com/unix/src/www/httpauth-0.6.tar.gz:a/httpauth-0.6/tools/mkha1.c metze (This used to be commit 26d51741b6aa54c47ee039ac14390f1f0ee51e30) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 389 ++++++++++++++++++++++++- 1 file changed, 383 insertions(+), 6 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 861e17e4d0..780dc69b23 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -4,6 +4,7 @@ Copyright (C) Simo Sorce 2004-2006 Copyright (C) Andrew Bartlett 2005-2006 Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2007 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 @@ -28,6 +29,7 @@ * Description: correctly update hash values based on changes to sambaPassword and friends * * Author: Andrew Bartlett + * Author: Stefan Metzmacher */ #include "includes.h" @@ -47,6 +49,7 @@ #include "dsdb/samdb/ldb_modules/password_modules.h" #include "librpc/ndr/libndr.h" #include "librpc/gen_ndr/ndr_drsblobs.h" +#include "lib/crypto/crypto.h" /* If we have decided there is reason to work on this request, then * setup all the password hash types correctly. @@ -93,6 +96,7 @@ struct domain_data { BOOL store_cleartext; uint_t pwdProperties; uint_t pwdHistoryLength; + char *netbios_domain; char *dns_domain; char *realm; }; @@ -503,16 +507,349 @@ if (lp_parm_bool(-1, "password_hash", "create_aes_key", false)) { return LDB_SUCCESS; } +static int setup_primary_wdigest(struct setup_password_fields_io *io, + const struct supplementalCredentialsBlob *old_scb, + struct package_PrimaryWDigestBlob *pdb) +{ + DATA_BLOB sAMAccountName; + DATA_BLOB sAMAccountName_l; + DATA_BLOB sAMAccountName_u; + const char *user_principal_name = io->u.user_principal_name; + DATA_BLOB userPrincipalName; + DATA_BLOB userPrincipalName_l; + DATA_BLOB userPrincipalName_u; + DATA_BLOB netbios_domain; + DATA_BLOB netbios_domain_l; + DATA_BLOB netbios_domain_u; + DATA_BLOB dns_domain; + DATA_BLOB dns_domain_l; + DATA_BLOB dns_domain_u; + DATA_BLOB cleartext; + DATA_BLOB digest; + DATA_BLOB delim; + DATA_BLOB backslash; + uint8_t i; + struct { + DATA_BLOB *user; + DATA_BLOB *realm; + DATA_BLOB *nt4dom; + } wdigest[] = { + /* + * See + * http://technet2.microsoft.com/WindowsServer/en/library/717b450c-f4a0-4cc9-86f4-cc0633aae5f91033.mspx?mfr=true + * for what precalculated hashes are supposed to be stored... + * + * I can't reproduce all values which should contain "Digest" as realm, + * am I doing something wrong or is w2k3 just broken...? + * + * W2K3 fills in following for a user: + * + * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base + * sAMAccountName: NewUser2Sam + * userPrincipalName: NewUser2Princ@sub1.w2k3.vmnet1.vm.base + * + * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007 + * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007 + * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007 + * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007 + * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007 + * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007 + * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007 + * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007 + * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007 + * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007 + * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007 + * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007 + * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007 + * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007 + * 221c55284451ae9b3aacaa2a3c86f10f => NewUser2Princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007 + * 74e1be668853d4324d38c07e2acfb8ea => (w2k3 has a bug here!) newuser2princ@sub1.w2k3.vmnet1.vm.base::TestPwd2007 + * e1e244ab7f098e3ae1761be7f9229bbb => NEWUSER2PRINC@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007 + * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007 + * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007 + * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007 + * 31dc704d3640335b2123d4ee28aa1f11 => ??? changes with NewUser2Sam => NewUser1Sam + * 36349f5cecd07320fb3bb0e119230c43 => ??? changes with NewUser2Sam => NewUser1Sam + * 12adf019d037fb535c01fd0608e78d9d => ??? changes with NewUser2Sam => NewUser1Sam + * 6feecf8e724906f3ee1105819c5105a1 => ??? changes with NewUser2Princ => NewUser1Princ + * 6c6911f3de6333422640221b9c51ff1f => ??? changes with NewUser2Princ => NewUser1Princ + * 4b279877e742895f9348ac67a8de2f69 => ??? changes with NewUser2Princ => NewUser1Princ + * db0c6bff069513e3ebb9870d29b57490 => ??? changes with NewUser2Sam => NewUser1Sam + * 45072621e56b1c113a4e04a8ff68cd0e => ??? changes with NewUser2Sam => NewUser1Sam + * 11d1220abc44a9c10cf91ef4a9c1de02 => ??? changes with NewUser2Sam => NewUser1Sam + * + * dn: CN=NewUser,OU=newtop,DC=sub1,DC=w2k3,DC=vmnet1,DC=vm,DC=base + * sAMAccountName: NewUser2Sam + * + * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007 + * b7ec9da91062199aee7d121e6710fe23 => newuser2sam:sub1:TestPwd2007 + * 17d290bc5c9f463fac54c37a8cea134d => NEWUSER2SAM:SUB1:TestPwd2007 + * 4279815024bda54fc074a5f8bd0a6e6f => NewUser2Sam:SUB1:TestPwd2007 + * 5d57e7823938348127322e08cd81bcb5 => NewUser2Sam:sub1:TestPwd2007 + * 07dd701bf8a011ece585de3d47237140 => NEWUSER2SAM:sub1:TestPwd2007 + * e14fb0eb401498d2cb33c9aae1cc7f37 => newuser2sam:SUB1:TestPwd2007 + * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007 + * f52da1266a6bdd290ffd48b2c823dda7 => newuser2sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007 + * d2b42f171248cec37a3c5c6b55404062 => NEWUSER2SAM:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007 + * fff8d790ff6c152aaeb6ebe17b4021de => NewUser2Sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007 + * 8dadc90250f873d8b883f79d890bef82 => NewUser2Sam:sub1.w2k3.vmnet1.vm.base:TestPwd2007 + * 2a7563c3715bc418d626dabef378c008 => NEWUSER2SAM:sub1.w2k3.vmnet1.vm.base:TestPwd2007 + * c8e9557a87cd4200fda0c11d2fa03f96 => newuser2sam:SUB1.W2K3.VMNET1.VM.BASE:TestPwd2007 + * 8a140d30b6f0a5912735dc1e3bc993b4 => NewUser2Sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007 + * 86d95b2faae6cae4ec261e7fbaccf093 => (here w2k3 is correct) newuser2sam@sub1.w2k3.vmnet1.vm.base::TestPwd2007 + * dfeff1493110220efcdfc6362e5f5450 => NEWUSER2SAM@SUB1.W2K3.VMNET1.VM.BASE::TestPwd2007 + * 86db637df42513039920e605499c3af6 => SUB1\NewUser2Sam::TestPwd2007 + * f5e43474dfaf067fee8197a253debaa2 => sub1\newuser2sam::TestPwd2007 + * 2ecaa8382e2518e4b77a52422b279467 => SUB1\NEWUSER2SAM::TestPwd2007 + * 31dc704d3640335b2123d4ee28aa1f11 => ???M1 changes with NewUser2Sam => NewUser1Sam + * 36349f5cecd07320fb3bb0e119230c43 => ???M1.L changes with newuser2sam => newuser1sam + * 12adf019d037fb535c01fd0608e78d9d => ???M1.U changes with NEWUSER2SAM => NEWUSER1SAM + * 569b4533f2d9e580211dd040e5e360a8 => ???M2 changes with NewUser2Princ => NewUser1Princ + * 52528bddf310a587c5d7e6a9ae2cbb20 => ???M2.L changes with newuser2princ => newuser1princ + * 4f629a4f0361289ca4255ab0f658fcd5 => ???M3 changes with NewUser2Princ => NewUser1Princ (doesn't depend on case of userPrincipal ) + * db0c6bff069513e3ebb9870d29b57490 => ???M4 changes with NewUser2Sam => NewUser1Sam + * 45072621e56b1c113a4e04a8ff68cd0e => ???M5 changes with NewUser2Sam => NewUser1Sam (doesn't depend on case of sAMAccountName) + * 11d1220abc44a9c10cf91ef4a9c1de02 => ???M4.U changes with NEWUSER2SAM => NEWUSER1SAM + */ + + /* + * sAMAccountName, netbios_domain + */ + { + .user = &sAMAccountName, + .realm = &netbios_domain, + }, + { + .user = &sAMAccountName_l, + .realm = &netbios_domain_l, + }, + { + .user = &sAMAccountName_u, + .realm = &netbios_domain_u, + }, + { + .user = &sAMAccountName, + .realm = &netbios_domain_u, + }, + { + .user = &sAMAccountName, + .realm = &netbios_domain_l, + }, + { + .user = &sAMAccountName_u, + .realm = &netbios_domain_l, + }, + { + .user = &sAMAccountName_l, + .realm = &netbios_domain_u, + }, + /* + * sAMAccountName, dns_domain + */ + { + .user = &sAMAccountName, + .realm = &dns_domain, + }, + { + .user = &sAMAccountName_l, + .realm = &dns_domain_l, + }, + { + .user = &sAMAccountName_u, + .realm = &dns_domain_u, + }, + { + .user = &sAMAccountName, + .realm = &dns_domain_u, + }, + { + .user = &sAMAccountName, + .realm = &dns_domain_l, + }, + { + .user = &sAMAccountName_u, + .realm = &dns_domain_l, + }, + { + .user = &sAMAccountName_l, + .realm = &dns_domain_u, + }, + /* + * userPrincipalName, no realm + */ + { + .user = &userPrincipalName, + }, + { + /* + * NOTE: w2k3 messes this up, if the user has a real userPrincipalName, + * the fallback to the sAMAccountName based userPrincipalName is correct + */ + .user = &userPrincipalName_l, + }, + { + .user = &userPrincipalName_u, + }, + /* + * nt4dom\sAMAccountName, no realm + */ + { + .user = &sAMAccountName, + .nt4dom = &netbios_domain + }, + { + .user = &sAMAccountName_l, + .nt4dom = &netbios_domain_l + }, + { + .user = &sAMAccountName_u, + .nt4dom = &netbios_domain_u + }, + + /* + * the following ones are guessed depending on the technet2 article + * but not reproducable on a w2k3 server + */ + /* sAMAccountName with "Digest" realm */ + { + .user = &sAMAccountName, + .realm = &digest + }, + { + .user = &sAMAccountName_l, + .realm = &digest + }, + { + .user = &sAMAccountName_u, + .realm = &digest + }, + /* userPrincipalName with "Digest" realm */ + { + .user = &userPrincipalName, + .realm = &digest + }, + { + .user = &userPrincipalName_l, + .realm = &digest + }, + { + .user = &userPrincipalName_u, + .realm = &digest + }, + /* nt4dom\\sAMAccountName with "Digest" realm */ + { + .user = &sAMAccountName, + .nt4dom = &netbios_domain, + .realm = &digest + }, + { + .user = &sAMAccountName_l, + .nt4dom = &netbios_domain_l, + .realm = &digest + }, + { + .user = &sAMAccountName_u, + .nt4dom = &netbios_domain_u, + .realm = &digest + }, + }; + + /* prepare DATA_BLOB's used in the combinations array */ + sAMAccountName = data_blob_string_const(io->u.sAMAccountName); + sAMAccountName_l = data_blob_string_const(strlower_talloc(io->ac, io->u.sAMAccountName)); + if (!sAMAccountName_l.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + sAMAccountName_u = data_blob_string_const(strupper_talloc(io->ac, io->u.sAMAccountName)); + if (!sAMAccountName_u.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* if the user doesn't have a userPrincipalName, create one (with lower case realm) */ + if (!user_principal_name) { + user_principal_name = talloc_asprintf(io->ac, "%s@%s", + io->u.sAMAccountName, + io->domain->dns_domain); + if (!user_principal_name) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + } + userPrincipalName = data_blob_string_const(user_principal_name); + userPrincipalName_l = data_blob_string_const(strlower_talloc(io->ac, user_principal_name)); + if (!userPrincipalName_l.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + userPrincipalName_u = data_blob_string_const(strupper_talloc(io->ac, user_principal_name)); + if (!userPrincipalName_u.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + netbios_domain = data_blob_string_const(io->domain->netbios_domain); + netbios_domain_l = data_blob_string_const(strlower_talloc(io->ac, io->domain->netbios_domain)); + if (!netbios_domain_l.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + netbios_domain_u = data_blob_string_const(strupper_talloc(io->ac, io->domain->netbios_domain)); + if (!netbios_domain_u.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + dns_domain = data_blob_string_const(io->domain->dns_domain); + dns_domain_l = data_blob_string_const(io->domain->dns_domain); + dns_domain_u = data_blob_string_const(io->domain->realm); + + cleartext = data_blob_string_const(io->n.cleartext); + + digest = data_blob_string_const("Digest"); + + delim = data_blob_string_const(":"); + backslash = data_blob_string_const("\\"); + + pdb->num_hashes = ARRAY_SIZE(wdigest); + pdb->hashes = talloc_array(io->ac, struct package_PrimaryWDigestHash, pdb->num_hashes); + if (!pdb->hashes) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + for (i=0; i < ARRAY_SIZE(wdigest); i++) { + struct MD5Context md5; + MD5Init(&md5); + if (wdigest[i].nt4dom) { + MD5Update(&md5, wdigest[i].nt4dom->data, wdigest[i].nt4dom->length); + MD5Update(&md5, backslash.data, backslash.length); + } + MD5Update(&md5, wdigest[i].user->data, wdigest[i].user->length); + MD5Update(&md5, delim.data, delim.length); + if (wdigest[i].realm) { + MD5Update(&md5, wdigest[i].realm->data, wdigest[i].realm->length); + } + MD5Update(&md5, delim.data, delim.length); + MD5Update(&md5, cleartext.data, cleartext.length); + MD5Final(pdb->hashes[i].hash, &md5); + } + + return LDB_SUCCESS; +} + static int setup_supplemental_field(struct setup_password_fields_io *io) { struct supplementalCredentialsBlob scb; struct supplementalCredentialsBlob _old_scb; struct supplementalCredentialsBlob *old_scb = NULL; - /* Packages + (Kerberos and maybe CLEARTEXT) */ - uint32_t num_packages = 1 + 1; - struct supplementalCredentialsPackage packages[1+2]; + /* Packages + (Kerberos, WDigest and maybe CLEARTEXT) */ + uint32_t num_packages = 1 + 2; + struct supplementalCredentialsPackage packages[1+3]; struct supplementalCredentialsPackage *pp = &packages[0]; struct supplementalCredentialsPackage *pk = &packages[1]; + struct supplementalCredentialsPackage *pd = &packages[2]; struct supplementalCredentialsPackage *pc = NULL; struct package_PackagesBlob pb; DATA_BLOB pb_blob; @@ -520,6 +857,9 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) struct package_PrimaryKerberosBlob pkb; DATA_BLOB pkb_blob; char *pkb_hexstr; + struct package_PrimaryWDigestBlob pdb; + DATA_BLOB pdb_blob; + char *pdb_hexstr; struct package_PrimaryCLEARTEXTBlob pcb; DATA_BLOB pcb_blob; char *pcb_hexstr; @@ -554,11 +894,11 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) if (io->domain->store_cleartext && (io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { - pc = &packages[2]; + pc = &packages[3]; num_packages++; } - /* Kerberos, CLEARTEXT and termination(counted by the Packages element) */ + /* Kerberos, WDigest, CLEARTEXT and termination(counted by the Packages element) */ pb.names = talloc_zero_array(io->ac, const char *, num_packages); /* @@ -600,11 +940,39 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) pk->unknown1 = 1; pk->data = pkb_hexstr; + /* + * setup 'Primary:WDigest' element + */ + pb.names[1] = "WDigest"; + + ret = setup_primary_wdigest(io, old_scb, &pdb); + if (ret != LDB_SUCCESS) { + return ret; + } + + status = ndr_push_struct_blob(&pdb_blob, io->ac, &pdb, + (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob); + if (!NT_STATUS_IS_OK(status)) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_supplemental_field: " + "failed to push package_PrimaryWDigestBlob: %s", + nt_errstr(status)); + return LDB_ERR_OPERATIONS_ERROR; + } + pdb_hexstr = data_blob_hex_string(io->ac, &pdb_blob); + if (!pdb_hexstr) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + pd->name = "Primary:WDigest"; + pd->unknown1 = 1; + pd->data = pdb_hexstr; + /* * setup 'Primary:CLEARTEXT' element */ if (pc) { - pb.names[1] = "CLEARTEXT"; + pb.names[2] = "CLEARTEXT"; pcb.cleartext = io->n.cleartext; @@ -915,6 +1283,15 @@ static struct domain_data *get_domain_data(struct ldb_module *module, void *ctx, ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n"); return NULL; } + p = strchr(tmp, '.'); + if (p) { + p[0] = '\0'; + } + data->netbios_domain = strupper_talloc(data, tmp); + if (data->netbios_domain == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n"); + return NULL; + } } return data; -- cgit From c42219d7352bd2e7a6413f7ae1cd0fd5cded1d95 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 17 May 2007 08:47:04 +0000 Subject: r22969: fix some more places where we could end up with more than one event context. We now have an event context on the torture_context, and we can also get one from the cli_credentials structure (This used to be commit c0f65eb6562e13530337c23e3447a6aa6eb8fc17) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 780dc69b23..2db76f8439 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1430,7 +1430,9 @@ static int password_hash_add_do_add(struct ldb_handle *h) { } /* Some operations below require kerberos contexts */ - if (smb_krb5_init_context(ac->down_req, &smb_krb5_context) != 0) { + if (smb_krb5_init_context(ac->down_req, + ldb_get_opaque(h->module->ldb, "EventContext"), + &smb_krb5_context) != 0) { return LDB_ERR_OPERATIONS_ERROR; } @@ -1760,7 +1762,9 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) { msg->dn = ac->orig_req->op.mod.message->dn; /* Some operations below require kerberos contexts */ - if (smb_krb5_init_context(ac->mod_req, &smb_krb5_context) != 0) { + if (smb_krb5_init_context(ac->mod_req, + ldb_get_opaque(h->module->ldb, "EventContext"), + &smb_krb5_context) != 0) { return LDB_ERR_OPERATIONS_ERROR; } -- cgit From d43cb597ba110c837ff836804252a31bc5dac138 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 11 Jun 2007 03:45:56 +0000 Subject: r23412: We don't need hdb.h here any more (This used to be commit 1abda90f15bcfb56ac56b01fd2b7343fade3843c) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 2db76f8439..5a5099c22e 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -45,7 +45,6 @@ #include "system/time.h" #include "dsdb/samdb/samdb.h" #include "dsdb/common/flags.h" -#include "hdb.h" #include "dsdb/samdb/ldb_modules/password_modules.h" #include "librpc/ndr/libndr.h" #include "librpc/gen_ndr/ndr_drsblobs.h" -- cgit From 0479a2f1cbae51fcd8dbdc3c148c808421fb4d25 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 02:07:03 +0000 Subject: r23792: convert Samba4 to GPLv3 There are still a few tidyups of old FSF addresses to come (in both s3 and s4). More commits soon. (This used to be commit fcf38a38ac691abd0fa51b89dc951a08e89fdafa) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 5a5099c22e..718e0480af 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -8,7 +8,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, @@ -17,8 +17,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 . */ /* -- cgit From 714c5c92ef8e80b3510e222ce621401e55d05d7e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 28 Aug 2007 05:43:26 +0000 Subject: r24731: Remove unused code - if we hit these error conditions, then we are dead anyway, and a segfault would leave us with more infomation. Andrew Bartlett (This used to be commit 62320616ff8795ff18c8f49029d81f12558c10ed) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 718e0480af..61e9002439 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1168,11 +1168,6 @@ static int get_domain_data_callback(struct ldb_context *ldb, void *context, stru { struct ph_context *ac; - if (!context || !ares) { - ldb_set_errstring(ldb, "NULL Context or Result in callback"); - return LDB_ERR_OPERATIONS_ERROR; - } - ac = talloc_get_type(context, struct ph_context); /* we are interested only in the single reply (base search) we receive here */ @@ -1629,11 +1624,6 @@ static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_ { struct ph_context *ac; - if (!context || !ares) { - ldb_set_errstring(ldb, "NULL Context or Result in callback"); - return LDB_ERR_OPERATIONS_ERROR; - } - ac = talloc_get_type(context, struct ph_context); /* we are interested only in the single reply (base search) we receive here */ -- cgit From 0b91f3916430d0271eab867675d44c5439de40c2 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 29 Aug 2007 13:07:03 +0000 Subject: r24780: More work allowing libutil to be used by external users. (This used to be commit 31993cf67b816a184a4a4e92ef8ca2532c797190) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 61e9002439..98061570c8 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -924,8 +924,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) * This is ugly, but we want to generate the same blob as * w2k and w2k3...we should handle this in the idl */ - status = data_blob_append(io->ac, &pkb_blob, zero16, sizeof(zero16)); - if (!NT_STATUS_IS_OK(status)) { + if (!data_blob_append(io->ac, &pkb_blob, zero16, sizeof(zero16))) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } -- cgit From 959915a8cbea0c598ef1f29ce666329a521ef2f6 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 7 Sep 2007 15:35:18 +0000 Subject: r25001: Fix more C++ and other warnings, fix some of the indentation with ts=4 lines that I accidently added earlier. (This used to be commit 0bcb21ed740fcec0f48ad36bbc2deee2948e8fc7) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 98061570c8..a275810b12 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -340,17 +340,17 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, return LDB_ERR_OPERATIONS_ERROR; } -if (lp_parm_bool(-1, "password_hash", "create_aes_key", false)) { -/* - * TODO: - * - * w2k and w2k3 doesn't support AES, so we'll not include - * the AES key here yet. - * - * Also we don't have an example supplementalCredentials blob - * from Windows Longhorn Server with AES support - * - */ + if (lp_parm_bool(-1, "password_hash", "create_aes_key", false)) { + /* + * TODO: + * + * w2k and w2k3 doesn't support AES, so we'll not include + * the AES key here yet. + * + * Also we don't have an example supplementalCredentials blob + * from Windows Longhorn Server with AES support + * + */ /* * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of * the salt and the cleartext password -- cgit From ffeee68e4b72dd94fee57366bd8d38b8c284c3d4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 8 Sep 2007 12:42:09 +0000 Subject: r25026: Move param/param.h out of includes.h (This used to be commit abe8349f9b4387961ff3665d8c589d61cd2edf31) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index a275810b12..22d04a5519 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -48,6 +48,7 @@ #include "librpc/ndr/libndr.h" #include "librpc/gen_ndr/ndr_drsblobs.h" #include "lib/crypto/crypto.h" +#include "param/param.h" /* If we have decided there is reason to work on this request, then * setup all the password hash types correctly. -- cgit From 98b57d5eb61094a9c88e2f7d90d3e21b7e74e9d8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 8 Sep 2007 16:46:30 +0000 Subject: r25035: Fix some more warnings, use service pointer rather than service number in more places. (This used to be commit df9cebcb97e20564359097148665bd519f31bc6f) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 22d04a5519..5f4317a646 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -341,7 +341,7 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, return LDB_ERR_OPERATIONS_ERROR; } - if (lp_parm_bool(-1, "password_hash", "create_aes_key", false)) { + if (lp_parm_bool(NULL, "password_hash", "create_aes_key", false)) { /* * TODO: * -- cgit From 60a1046c5c5783799bd64fe18e03534670f83d82 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 29 Sep 2007 18:00:19 +0000 Subject: r25430: Add the loadparm context to all parametric options. (This used to be commit fd697d77c9fe67a00939a1f04b35c451316fff58) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 5f4317a646..646aab9c94 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -341,7 +341,7 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, return LDB_ERR_OPERATIONS_ERROR; } - if (lp_parm_bool(NULL, "password_hash", "create_aes_key", false)) { + if (lp_parm_bool(global_loadparm, NULL, "password_hash", "create_aes_key", false)) { /* * TODO: * -- cgit From 05e7c481465e3065effaf21b43636d6605d7c313 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 6 Oct 2007 22:25:41 +0000 Subject: r25553: Convert to standard bool type. (This used to be commit b7371f1a191fb86834c0d586d094f39f0b04544b) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 646aab9c94..090cce2719 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -92,7 +92,7 @@ struct ph_context { }; struct domain_data { - BOOL store_cleartext; + bool store_cleartext; uint_t pwdProperties; uint_t pwdHistoryLength; char *netbios_domain; -- cgit From 529763a9aa192a6785ba878aceeb1683c2510913 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Nov 2007 19:24:51 +0100 Subject: r25920: ndr: change NTSTAUS into enum ndr_err_code (samba4 callers) lib/messaging/ lib/registry/ lib/ldb-samba/ librpc/rpc/ auth/auth_winbind.c auth/gensec/ auth/kerberos/ dsdb/repl/ dsdb/samdb/ dsdb/schema/ torture/ cluster/ctdb/ kdc/ ntvfs/ipc/ torture/rap/ ntvfs/ utils/getntacl.c ntptr/ smb_server/ libcli/wrepl/ wrepl_server/ libcli/cldap/ libcli/dgram/ libcli/ldap/ libcli/raw/ libcli/nbt/ libnet/ winbind/ rpc_server/ metze (This used to be commit 6223c7fddc972687eb577e04fc1c8e0604c35435) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 53 +++++++++++++++----------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 090cce2719..d0afae5395 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -229,7 +229,7 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, struct package_PrimaryKerberosBlob _old_pkb; struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL; uint32_t i; - NTSTATUS status; + enum ndr_err_code ndr_err; /* Many, many thanks to lukeh@padl.com for this * algorithm, described in his Nov 10 2004 mail to @@ -472,9 +472,10 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, talloc_steal(io->ac, blob.data); /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */ - status = ndr_pull_struct_blob(&blob, io->ac, &_old_pkb, - (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob); - if (!NT_STATUS_IS_OK(status)) { + ndr_err = ndr_pull_struct_blob(&blob, io->ac, &_old_pkb, + (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); ldb_asprintf_errstring(io->ac->module->ldb, "setup_primary_kerberos: " "failed to pull old package_PrimaryKerberosBlob: %s", @@ -863,7 +864,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) DATA_BLOB pcb_blob; char *pcb_hexstr; int ret; - NTSTATUS status; + enum ndr_err_code ndr_err; uint8_t zero16[16]; ZERO_STRUCT(zero16); @@ -878,9 +879,10 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* if there's an old supplementaCredentials blob then parse it */ if (io->o.supplemental) { - status = ndr_pull_struct_blob_all(io->o.supplemental, io->ac, &_old_scb, - (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob); - if (!NT_STATUS_IS_OK(status)) { + ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac, &_old_scb, + (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); ldb_asprintf_errstring(io->ac->module->ldb, "setup_supplemental_field: " "failed to pull old supplementalCredentialsBlob: %s", @@ -910,9 +912,10 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return ret; } - status = ndr_push_struct_blob(&pkb_blob, io->ac, &pkb, - (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob); - if (!NT_STATUS_IS_OK(status)) { + ndr_err = ndr_push_struct_blob(&pkb_blob, io->ac, &pkb, + (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); ldb_asprintf_errstring(io->ac->module->ldb, "setup_supplemental_field: " "failed to push package_PrimaryKerberosBlob: %s", @@ -948,9 +951,10 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return ret; } - status = ndr_push_struct_blob(&pdb_blob, io->ac, &pdb, - (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob); - if (!NT_STATUS_IS_OK(status)) { + ndr_err = ndr_push_struct_blob(&pdb_blob, io->ac, &pdb, + (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); ldb_asprintf_errstring(io->ac->module->ldb, "setup_supplemental_field: " "failed to push package_PrimaryWDigestBlob: %s", @@ -974,9 +978,10 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) pcb.cleartext = io->n.cleartext; - status = ndr_push_struct_blob(&pcb_blob, io->ac, &pcb, - (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob); - if (!NT_STATUS_IS_OK(status)) { + ndr_err = ndr_push_struct_blob(&pcb_blob, io->ac, &pcb, + (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); ldb_asprintf_errstring(io->ac->module->ldb, "setup_supplemental_field: " "failed to push package_PrimaryCLEARTEXTBlob: %s", @@ -996,9 +1001,10 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* * setup 'Packages' element */ - status = ndr_push_struct_blob(&pb_blob, io->ac, &pb, - (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob); - if (!NT_STATUS_IS_OK(status)) { + ndr_err = ndr_push_struct_blob(&pb_blob, io->ac, &pb, + (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); ldb_asprintf_errstring(io->ac->module->ldb, "setup_supplemental_field: " "failed to push package_PackagesBlob: %s", @@ -1020,9 +1026,10 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) scb.sub.num_packages = num_packages; scb.sub.packages = packages; - status = ndr_push_struct_blob(&io->g.supplemental, io->ac, &scb, - (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob); - if (!NT_STATUS_IS_OK(status)) { + ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac, &scb, + (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); ldb_asprintf_errstring(io->ac->module->ldb, "setup_supplemental_field: " "failed to push supplementalCredentialsBlob: %s", -- cgit From cc04f143dcd35fb67884e385ffd3e6ed2d32a4c2 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Dec 2007 19:04:33 +0100 Subject: r26229: Set loadparm context as opaque pointer in ldb, remove more uses of global_loadparm. (This used to be commit 37d05fdc7b0e6b3211ba6ae56b1b5da30a6a392a) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index d0afae5395..eecec6a55b 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -341,7 +341,7 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, return LDB_ERR_OPERATIONS_ERROR; } - if (lp_parm_bool(global_loadparm, NULL, "password_hash", "create_aes_key", false)) { + if (lp_parm_bool(ldb_get_opaque(io->ac->module->ldb, "loadparm"), NULL, "password_hash", "create_aes_key", false)) { /* * TODO: * -- cgit From 120ecdb5cb7dbd7c650f3e9fbcefb925f695e0f2 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Dec 2007 20:56:26 +0100 Subject: r26233: Pass loadparm context when creating krb5 contexts. (This used to be commit 7780bf285fdfc30f89409d0436bad0d4b6de5cd4) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index eecec6a55b..529b1aa96f 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1432,6 +1432,7 @@ static int password_hash_add_do_add(struct ldb_handle *h) { /* Some operations below require kerberos contexts */ if (smb_krb5_init_context(ac->down_req, ldb_get_opaque(h->module->ldb, "EventContext"), + (struct loadparm_context *)ldb_get_opaque(h->module->ldb, "loadparm"), &smb_krb5_context) != 0) { return LDB_ERR_OPERATIONS_ERROR; } @@ -1759,6 +1760,7 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) { /* Some operations below require kerberos contexts */ if (smb_krb5_init_context(ac->mod_req, ldb_get_opaque(h->module->ldb, "EventContext"), + (struct loadparm_context *)ldb_get_opaque(h->module->ldb, "loadparm"), &smb_krb5_context) != 0) { return LDB_ERR_OPERATIONS_ERROR; } -- cgit From 41db2ab12cea20b271d690be554ab8e6095c2b4e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 6 Dec 2007 21:39:49 +0100 Subject: r26319: Split encoding functions out of libcli_ldap. (This used to be commit 95a6ef7fc8757ccfd90dbf0d6c9b5098f10b10b6) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 529b1aa96f..d139cc23a4 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -32,8 +32,9 @@ */ #include "includes.h" -#include "libcli/ldap/ldap.h" +#include "libcli/ldap/ldap_ndr.h" #include "ldb/include/ldb_errors.h" +#include "ldb/include/ldb.h" #include "ldb/include/ldb_private.h" #include "librpc/gen_ndr/misc.h" #include "librpc/gen_ndr/samr.h" -- cgit From 3e75f222bcdf114238cc4f2bcc61332dc059135f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 19 Dec 2007 23:27:42 +0100 Subject: r26539: Remove unnecessary statics. (This used to be commit e53e79eebef3ece6978f0a2b4a1ee0a0814bb5d2) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index d139cc23a4..03c2bbc7ae 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1198,7 +1198,7 @@ static int build_domain_data_request(struct ph_context *ac) /* attrs[] is returned from this function in ac->dom_req->op.search.attrs, so it must be static, as otherwise the compiler can put it on the stack */ - static const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", NULL }; + const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", NULL }; char *filter; ac->dom_req = talloc_zero(ac, struct ldb_request); @@ -1662,7 +1662,7 @@ static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_ static int password_hash_mod_search_self(struct ldb_handle *h) { struct ph_context *ac; - static const char * const attrs[] = { "userAccountControl", "lmPwdHistory", + const char * const attrs[] = { "userAccountControl", "lmPwdHistory", "ntPwdHistory", "objectSid", "msDS-KeyVersionNumber", "objectClass", "userPrincipalName", -- cgit From 0500b87092540d300b4e021a0fb95ce16a44fbd2 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 20 Dec 2007 00:02:15 +0100 Subject: r26540: Revert my previous commit after concerns raised by Andrew. (This used to be commit 6ac86f8be7d9a8c5ab396a93e6d1e6819e11f173) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 03c2bbc7ae..d139cc23a4 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1198,7 +1198,7 @@ static int build_domain_data_request(struct ph_context *ac) /* attrs[] is returned from this function in ac->dom_req->op.search.attrs, so it must be static, as otherwise the compiler can put it on the stack */ - const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", NULL }; + static const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", NULL }; char *filter; ac->dom_req = talloc_zero(ac, struct ldb_request); @@ -1662,7 +1662,7 @@ static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_ static int password_hash_mod_search_self(struct ldb_handle *h) { struct ph_context *ac; - const char * const attrs[] = { "userAccountControl", "lmPwdHistory", + static const char * const attrs[] = { "userAccountControl", "lmPwdHistory", "ntPwdHistory", "objectSid", "msDS-KeyVersionNumber", "objectClass", "userPrincipalName", -- cgit From 86dc05e99f124db47f2743d1fc23117a7f5145ab Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 1 Jan 2008 22:05:05 -0600 Subject: r26638: libndr: Require explicitly specifying iconv_convenience for ndr_struct_push_blob(). (This used to be commit 61ad78ac98937ef7a9aa32075a91a1c95b7606b3) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index d139cc23a4..a69459cfef 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -913,7 +913,9 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return ret; } - ndr_err = ndr_push_struct_blob(&pkb_blob, io->ac, &pkb, + ndr_err = ndr_push_struct_blob(&pkb_blob, io->ac, + lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), + &pkb, (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); @@ -952,7 +954,9 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return ret; } - ndr_err = ndr_push_struct_blob(&pdb_blob, io->ac, &pdb, + ndr_err = ndr_push_struct_blob(&pdb_blob, io->ac, + lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), + &pdb, (ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); @@ -979,7 +983,9 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) pcb.cleartext = io->n.cleartext; - ndr_err = ndr_push_struct_blob(&pcb_blob, io->ac, &pcb, + ndr_err = ndr_push_struct_blob(&pcb_blob, io->ac, + lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), + &pcb, (ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); @@ -1002,7 +1008,9 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* * setup 'Packages' element */ - ndr_err = ndr_push_struct_blob(&pb_blob, io->ac, &pb, + ndr_err = ndr_push_struct_blob(&pb_blob, io->ac, + lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), + &pb, (ndr_push_flags_fn_t)ndr_push_package_PackagesBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); @@ -1027,7 +1035,9 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) scb.sub.num_packages = num_packages; scb.sub.packages = packages; - ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac, &scb, + ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac, + lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), + &scb, (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); -- cgit From 7d5f0e0893d42b56145a3ffa34e3b4b9906cbd91 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 1 Jan 2008 22:05:13 -0600 Subject: r26639: librpc: Pass iconv convenience on from RPC connection to NDR library, so it can be overridden by OpenChange. (This used to be commit 2f29f80e07adef1f020173f2cd6d947d0ef505ce) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index a69459cfef..61bd391d67 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -473,7 +473,7 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, talloc_steal(io->ac, blob.data); /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */ - ndr_err = ndr_pull_struct_blob(&blob, io->ac, &_old_pkb, + ndr_err = ndr_pull_struct_blob(&blob, io->ac, lp_iconv_convenience(global_loadparm), &_old_pkb, (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); @@ -880,7 +880,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* if there's an old supplementaCredentials blob then parse it */ if (io->o.supplemental) { - ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac, &_old_scb, + ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), &_old_scb, (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); -- cgit From 9d136bc0a323171b13ec047816033ae4fac9e9d4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 2 Jan 2008 01:52:18 -0600 Subject: r26640: Janitorial: Remove some more uses of global_loadparm. (This used to be commit c863f4ebde8efa1a695b4469142d6719e30bc419) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 61bd391d67..57c053d961 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -473,7 +473,7 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, talloc_steal(io->ac, blob.data); /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */ - ndr_err = ndr_pull_struct_blob(&blob, io->ac, lp_iconv_convenience(global_loadparm), &_old_pkb, + ndr_err = ndr_pull_struct_blob(&blob, io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), &_old_pkb, (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); -- cgit From 16109a40c0abd8c30a5eb9bf9ef692bfae9dfc7d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 20 Feb 2008 01:54:32 +0100 Subject: Use struct-based rather than function-based initialization for ldb modules everywhere. (This used to be commit 85c96a325867f7bcdb412ebc53f8a47dbf7cd89b) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 57c053d961..380045c1cf 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -2044,15 +2044,9 @@ static int password_hash_wait(struct ldb_handle *handle, enum ldb_wait_type type } } -static const struct ldb_module_ops password_hash_ops = { +const struct ldb_module_ops ldb_password_hash_module_ops = { .name = "password_hash", .add = password_hash_add, .modify = password_hash_modify, .wait = password_hash_wait }; - - -int password_hash_module_init(void) -{ - return ldb_register_module(&password_hash_ops); -} -- cgit From 39a817d310964f8e9a63cfb096b3ad24fa03bd5e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 20 Feb 2008 04:33:43 +0100 Subject: Fix use of some modules (needed _PUBLIC_). (This used to be commit ce332130ea77159832da23bab760fa26921719e2) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 380045c1cf..aa64700f2f 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -2044,7 +2044,7 @@ static int password_hash_wait(struct ldb_handle *handle, enum ldb_wait_type type } } -const struct ldb_module_ops ldb_password_hash_module_ops = { +_PUBLIC_ const struct ldb_module_ops ldb_password_hash_module_ops = { .name = "password_hash", .add = password_hash_add, .modify = password_hash_modify, -- cgit From 0c882402360a10b19a038bce9f87e241051c9ba8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 13 Mar 2008 11:36:58 +1100 Subject: Rework to have member server 'domains' be CN=NETBIOSNAME This reworks quite a few parts of our provision system to use CN=NETBIOSNAME as the domain for member servers. This makes it clear that these domains are not in the DNS structure, while complying with our own schema (found by OpenLDAP's schema validation). Andrew Bartlett (This used to be commit bda6a38b055fed2394e65cdc0b308a1442116402) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index aa64700f2f..ec19e0d49e 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1220,7 +1220,7 @@ static int build_domain_data_request(struct ph_context *ac) ac->dom_req->op.search.base = ldb_get_default_basedn(ac->module->ldb); ac->dom_req->op.search.scope = LDB_SCOPE_SUBTREE; - filter = talloc_asprintf(ac->dom_req, "(&(objectSid=%s)(|(objectClass=domain)(objectClass=builtinDomain)))", + filter = talloc_asprintf(ac->dom_req, "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))", ldap_encode_ndr_dom_sid(ac->dom_req, ac->domain_sid)); if (filter == NULL) { ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n"); -- cgit From 79a25a648debf0aba77185a5b2b1ee979210359c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 19 Mar 2008 12:06:37 +1100 Subject: Indent Andrew Bartlett (This used to be commit d2b5f40d80008ca3269118915409333755b6eac3) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index ec19e0d49e..1d2bdd988e 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1220,7 +1220,8 @@ static int build_domain_data_request(struct ph_context *ac) ac->dom_req->op.search.base = ldb_get_default_basedn(ac->module->ldb); ac->dom_req->op.search.scope = LDB_SCOPE_SUBTREE; - filter = talloc_asprintf(ac->dom_req, "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))", + filter = talloc_asprintf(ac->dom_req, + "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))", ldap_encode_ndr_dom_sid(ac->dom_req, ac->domain_sid)); if (filter == NULL) { ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n"); -- cgit From 44ea6a26fd088f0f8c86817510ebe5a6cddf9158 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 12 Jul 2008 15:26:42 +1000 Subject: rename sambaPassword -> userPassword. This attribute is used in a very similar way (virtual attribute updating the password) in AD on Win2003, so eliminate the difference. This should not cause a problem for on-disk passwords, as by default we do not store the plaintext at all. Andrew Bartlett (This used to be commit 1cf0d751493b709ef6b2234ec8847a7499f48ab3) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 1d2bdd988e..3e442b6341 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -25,7 +25,7 @@ * * Component: ldb password_hash module * - * Description: correctly update hash values based on changes to sambaPassword and friends + * Description: correctly update hash values based on changes to userPassword and friends * * Author: Andrew Bartlett * Author: Stefan Metzmacher @@ -54,7 +54,7 @@ /* If we have decided there is reason to work on this request, then * setup all the password hash types correctly. * - * If the administrator doesn't want the sambaPassword stored (set in the + * If the administrator doesn't want the userPassword stored (set in the * domain and per-account policies) then we must strip that out before * we do the first operation. * @@ -1341,10 +1341,10 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_UNWILLING_TO_PERFORM; } - /* If no part of this ADD touches the sambaPassword, or the NT + /* If no part of this ADD touches the userPassword, or the NT * or LM hashes, then we don't need to make any changes. */ - sambaAttr = ldb_msg_find_element(req->op.mod.message, "sambaPassword"); + sambaAttr = ldb_msg_find_element(req->op.mod.message, "userPassword"); ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd"); lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd"); @@ -1353,16 +1353,16 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) } /* if it is not an entry of type person its an error */ - /* TODO: remove this when sambaPassword will be in schema */ + /* TODO: remove this when userPassword will be in schema */ if (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "person")) { ldb_set_errstring(module->ldb, "Cannot set a password on entry that does not have objectClass 'person'"); return LDB_ERR_OBJECT_CLASS_VIOLATION; } - /* check sambaPassword is single valued here */ - /* TODO: remove this when sambaPassword will be single valued in schema */ + /* check userPassword is single valued here */ + /* TODO: remove this when userPassword will be single valued in schema */ if (sambaAttr && sambaAttr->num_values > 1) { - ldb_set_errstring(module->ldb, "mupltiple values for sambaPassword not allowed!\n"); + ldb_set_errstring(module->ldb, "mupltiple values for userPassword not allowed!\n"); return LDB_ERR_CONSTRAINT_VIOLATION; } @@ -1376,7 +1376,7 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req) } if (sambaAttr && sambaAttr->num_values == 0) { - ldb_set_errstring(module->ldb, "sambaPassword must have a value!\n"); + ldb_set_errstring(module->ldb, "userPassword must have a value!\n"); return LDB_ERR_CONSTRAINT_VIOLATION; } @@ -1459,12 +1459,12 @@ static int password_hash_add_do_add(struct ldb_handle *h) { io.u.user_principal_name = samdb_result_string(msg, "userPrincipalName", NULL); io.u.is_computer = ldb_msg_check_string_attribute(msg, "objectClass", "computer"); - io.n.cleartext = samdb_result_string(msg, "sambaPassword", NULL); + io.n.cleartext = samdb_result_string(msg, "userPassword", NULL); io.n.nt_hash = samdb_result_hash(io.ac, msg, "unicodePwd"); io.n.lm_hash = samdb_result_hash(io.ac, msg, "dBCSPwd"); /* remove attributes */ - if (io.n.cleartext) ldb_msg_remove_attr(msg, "sambaPassword"); + if (io.n.cleartext) ldb_msg_remove_attr(msg, "userPassword"); if (io.n.nt_hash) ldb_msg_remove_attr(msg, "unicodePwd"); if (io.n.lm_hash) ldb_msg_remove_attr(msg, "dBCSPwd"); ldb_msg_remove_attr(msg, "pwdLastSet"); @@ -1573,11 +1573,11 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r return LDB_ERR_UNWILLING_TO_PERFORM; } - sambaAttr = ldb_msg_find_element(req->op.mod.message, "sambaPassword"); + sambaAttr = ldb_msg_find_element(req->op.mod.message, "userPassword"); ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd"); lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd"); - /* If no part of this touches the sambaPassword OR unicodePwd and/or dBCSPwd, then we don't + /* If no part of this touches the userPassword OR unicodePwd and/or dBCSPwd, then we don't * need to make any changes. For password changes/set there should * be a 'delete' or a 'modify' on this attribute. */ if ((!sambaAttr) && (!ntAttr) && (!lmAttr)) { @@ -1619,7 +1619,7 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r /* - remove any imodification to the password from the first commit * we will make the real modification later */ - if (sambaAttr) ldb_msg_remove_attr(msg, "sambaPassword"); + if (sambaAttr) ldb_msg_remove_attr(msg, "userPassword"); if (ntAttr) ldb_msg_remove_attr(msg, "unicodePwd"); if (lmAttr) ldb_msg_remove_attr(msg, "dBCSPwd"); @@ -1655,7 +1655,7 @@ static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_ } /* if it is not an entry of type person this is an error */ - /* TODO: remove this when sambaPassword will be in schema */ + /* TODO: remove this when userPassword will be in schema */ if (!ldb_msg_check_string_attribute(ares->message, "objectClass", "person")) { ldb_set_errstring(ldb, "Object class violation"); talloc_free(ares); @@ -1790,7 +1790,7 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) { io.u.user_principal_name = samdb_result_string(searched_msg, "userPrincipalName", NULL); io.u.is_computer = ldb_msg_check_string_attribute(searched_msg, "objectClass", "computer"); - io.n.cleartext = samdb_result_string(orig_msg, "sambaPassword", NULL); + io.n.cleartext = samdb_result_string(orig_msg, "userPassword", NULL); io.n.nt_hash = samdb_result_hash(io.ac, orig_msg, "unicodePwd"); io.n.lm_hash = samdb_result_hash(io.ac, orig_msg, "dBCSPwd"); -- cgit From bcb0db3634680fdaf1d037545fafe7509ed72ad9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 18:31:45 +0200 Subject: password_hash: don't add zero padding as w2k8 also don't add it metze (This used to be commit 26e9169d454349795ad0bc64d7f65059541ab89e) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 3e442b6341..2dddb26550 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -925,16 +925,6 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) nt_errstr(status)); return LDB_ERR_OPERATIONS_ERROR; } - /* - * TODO: - * - * This is ugly, but we want to generate the same blob as - * w2k and w2k3...we should handle this in the idl - */ - if (!data_blob_append(io->ac, &pkb_blob, zero16, sizeof(zero16))) { - ldb_oom(io->ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } pkb_hexstr = data_blob_hex_string(io->ac, &pkb_blob); if (!pkb_hexstr) { ldb_oom(io->ac->module->ldb); -- cgit From 69d3f0e602893875118878a4b11c2a65f9d4090c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 12:00:42 +0200 Subject: password_hash: ignore reserved value, but still set it like windows does metze (This used to be commit 5b860572686167d0291161f6597f143e538e2f3a) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 2dddb26550..e149009948 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -446,10 +446,6 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, } for (i=0; i < old_scb->sub.num_packages; i++) { - if (old_scb->sub.packages[i].unknown1 != 0x00000001) { - continue; - } - if (strcmp("Primary:Kerberos", old_scb->sub.packages[i].name) != 0) { continue; } @@ -931,7 +927,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return LDB_ERR_OPERATIONS_ERROR; } pk->name = "Primary:Kerberos"; - pk->unknown1 = 1; + pk->reserved = 1; pk->data = pkb_hexstr; /* @@ -962,7 +958,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return LDB_ERR_OPERATIONS_ERROR; } pd->name = "Primary:WDigest"; - pd->unknown1 = 1; + pd->reserved = 1; pd->data = pdb_hexstr; /* @@ -991,7 +987,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return LDB_ERR_OPERATIONS_ERROR; } pc->name = "Primary:CLEARTEXT"; - pc->unknown1 = 1; + pc->reserved = 1; pc->data = pcb_hexstr; } @@ -1016,7 +1012,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return LDB_ERR_OPERATIONS_ERROR; } pp->name = "Packages"; - pp->unknown1 = 2; + pp->reserved = 2; pp->data = pb_hexstr; /* -- cgit From fbea02accfa8f92d84d0f2cb17847dac1519aa87 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 13:31:14 +0200 Subject: password_hash: check the SUPPLEMENTAL_CREDENTIALS_SIGNATURE metze (This used to be commit 19b8c8e37bafab050ab61266c35006efada2947c) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index e149009948..59ec18e546 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -876,7 +876,9 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* if there's an old supplementaCredentials blob then parse it */ if (io->o.supplemental) { - ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), &_old_scb, + ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac, + lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), + &_old_scb, (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); @@ -887,7 +889,14 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return LDB_ERR_OPERATIONS_ERROR; } - old_scb = &_old_scb; + if (_old_scb.sub.signature == SUPPLEMENTAL_CREDENTIALS_SIGNATURE) { + old_scb = &_old_scb; + } else { + ldb_debug(io->ac->module->ldb, LDB_DEBUG_ERROR, + "setup_supplemental_field: " + "supplementalCredentialsBlob signature[0x%04X] expected[0x%04X]", + _old_scb.sub.signature, SUPPLEMENTAL_CREDENTIALS_SIGNATURE); + } } if (io->domain->store_cleartext && -- cgit From e0f04e36ad415d7396fea7d43eb1d0db53d53a69 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 10:05:43 +0200 Subject: password_hash: fix callers after idl change for package_PrimaryKerberos metze (This used to be commit 1bf552856f3a930c4716ceb73d9ba9adf7502d3d) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 59ec18e546..5bbae2c164 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -336,11 +336,6 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - pkb3->unknown3 = talloc_zero_array(io->ac, uint64_t, pkb3->num_keys); - if (!pkb3->unknown3) { - ldb_oom(io->ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } if (lp_parm_bool(ldb_get_opaque(io->ac->module->ldb, "loadparm"), NULL, "password_hash", "create_aes_key", false)) { /* @@ -438,7 +433,6 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, /* initialize the old keys to zero */ pkb3->num_old_keys = 0; pkb3->old_keys = NULL; - pkb3->unknown3_old = NULL; /* if there're no old keys, then we're done */ if (!old_scb) { @@ -499,7 +493,6 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, /* fill in the old keys */ pkb3->num_old_keys = old_pkb3->num_keys; pkb3->old_keys = old_pkb3->keys; - pkb3->unknown3_old = old_pkb3->unknown3; return LDB_SUCCESS; } -- cgit From b783b28d70d787d7524e8afd54c24ef6f3f8bf54 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 18:32:49 +0200 Subject: password_hash: simplify the logic if we have cleartext we always generate the hashes metze (This used to be commit 5edff84429ef0d03b47a438e18861d26c97e17b6) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 5bbae2c164..8dd4e1e76b 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1071,7 +1071,7 @@ static int setup_password_fields(struct setup_password_fields_io *io) return LDB_ERR_UNWILLING_TO_PERFORM; } - if (io->n.cleartext && !io->n.nt_hash) { + if (io->n.cleartext) { struct samr_Password *hash; hash = talloc(io->ac, struct samr_Password); @@ -1092,7 +1092,7 @@ static int setup_password_fields(struct setup_password_fields_io *io) } } - if (io->n.cleartext && !io->n.lm_hash) { + if (io->n.cleartext) { struct samr_Password *hash; hash = talloc(io->ac, struct samr_Password); -- cgit From 12ac4c5666d56dc806a613584fa72e7c2f29c34e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 18:27:36 +0200 Subject: password_hash: split the generation of krb5 keys into a different function metze (This used to be commit 4ad73a0bf8952783d3d9a7339c0c4fd8ca28981a) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 161 +++++++++++-------------- 1 file changed, 69 insertions(+), 92 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 8dd4e1e76b..9996e89cc6 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -140,6 +140,9 @@ struct setup_password_fields_io { struct samr_Password *nt_history; uint32_t lm_history_len; struct samr_Password *lm_history; + const char *salt; + DATA_BLOB des_md5; + DATA_BLOB des_crc; struct ldb_val supplemental; NTTIME last_set; uint32_t kvno; @@ -216,21 +219,12 @@ static int setup_lm_fields(struct setup_password_fields_io *io) return LDB_SUCCESS; } -static int setup_primary_kerberos(struct setup_password_fields_io *io, - const struct supplementalCredentialsBlob *old_scb, - struct package_PrimaryKerberosBlob *pkb) +static int setup_kerberos_keys(struct setup_password_fields_io *io) { krb5_error_code krb5_ret; Principal *salt_principal; krb5_salt salt; krb5_keyblock key; - uint32_t k=0; - struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3; - struct supplementalCredentialsPackage *old_scp = NULL; - struct package_PrimaryKerberosBlob _old_pkb; - struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL; - uint32_t i; - enum ndr_err_code ndr_err; /* Many, many thanks to lukeh@padl.com for this * algorithm, described in his Nov 10 2004 mail to @@ -290,7 +284,7 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, } if (krb5_ret) { ldb_asprintf_errstring(io->ac->module->ldb, - "setup_primary_kerberos: " + "setup_kerberos_keys: " "generation of a salting principal failed: %s", smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); return LDB_ERR_OPERATIONS_ERROR; @@ -304,131 +298,107 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal); if (krb5_ret) { ldb_asprintf_errstring(io->ac->module->ldb, - "setup_primary_kerberos: " + "setup_kerberos_keys: " "generation of krb5_salt failed: %s", smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); return LDB_ERR_OPERATIONS_ERROR; } /* create a talloc copy */ - pkb3->salt.string = talloc_strndup(io->ac, - salt.saltvalue.data, - salt.saltvalue.length); + io->g.salt = talloc_strndup(io->ac, + salt.saltvalue.data, + salt.saltvalue.length); krb5_free_salt(io->smb_krb5_context->krb5_context, salt); - if (!pkb3->salt.string) { - ldb_oom(io->ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - salt.saltvalue.data = discard_const(pkb3->salt.string); - salt.saltvalue.length = strlen(pkb3->salt.string); - - /* - * prepare generation of keys - * - * ENCTYPE_AES256_CTS_HMAC_SHA1_96 (disabled by default) - * ENCTYPE_DES_CBC_MD5 - * ENCTYPE_DES_CBC_CRC - * - * NOTE: update num_keys when you add another enctype! - */ - pkb3->num_keys = 3; - pkb3->keys = talloc_array(io->ac, struct package_PrimaryKerberosKey, pkb3->num_keys); - if (!pkb3->keys) { + if (!io->g.salt) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } + salt.saltvalue.data = discard_const(io->g.salt); + salt.saltvalue.length = strlen(io->g.salt); - if (lp_parm_bool(ldb_get_opaque(io->ac->module->ldb, "loadparm"), NULL, "password_hash", "create_aes_key", false)) { - /* - * TODO: - * - * w2k and w2k3 doesn't support AES, so we'll not include - * the AES key here yet. - * - * Also we don't have an example supplementalCredentials blob - * from Windows Longhorn Server with AES support - * - */ /* - * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of + * create ENCTYPE_DES_CBC_MD5 key out of * the salt and the cleartext password */ krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, - ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_DES_CBC_MD5, io->n.cleartext, salt, &key); - pkb3->keys[k].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; - pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB); - if (!pkb3->keys[k].value) { - krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - ldb_oom(io->ac->module->ldb); + if (krb5_ret) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_kerberos_keys: " + "generation of a des-cbc-md5 key failed: %s", + smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); return LDB_ERR_OPERATIONS_ERROR; } - *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value, - key.keyvalue.data, - key.keyvalue.length); + io->g.des_md5 = data_blob_talloc(io->ac, + key.keyvalue.data, + key.keyvalue.length); krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - if (!pkb3->keys[k].value->data) { + if (!io->g.des_md5.data) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - k++; -} /* - * create ENCTYPE_DES_CBC_MD5 key out of + * create ENCTYPE_DES_CBC_CRC key out of * the salt and the cleartext password */ krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, - ENCTYPE_DES_CBC_MD5, + ENCTYPE_DES_CBC_CRC, io->n.cleartext, salt, &key); - pkb3->keys[k].keytype = ENCTYPE_DES_CBC_MD5; - pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB); - if (!pkb3->keys[k].value) { - krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - ldb_oom(io->ac->module->ldb); + if (krb5_ret) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_kerberos_keys: " + "generation of a des-cbc-crc key failed: %s", + smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); return LDB_ERR_OPERATIONS_ERROR; } - *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value, - key.keyvalue.data, - key.keyvalue.length); + io->g.des_crc = data_blob_talloc(io->ac, + key.keyvalue.data, + key.keyvalue.length); krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - if (!pkb3->keys[k].value->data) { + if (!io->g.des_crc.data) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - k++; + + return LDB_SUCCESS; +} + +static int setup_primary_kerberos(struct setup_password_fields_io *io, + const struct supplementalCredentialsBlob *old_scb, + struct package_PrimaryKerberosBlob *pkb) +{ + struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3; + struct supplementalCredentialsPackage *old_scp = NULL; + struct package_PrimaryKerberosBlob _old_pkb; + struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL; + uint32_t i; + enum ndr_err_code ndr_err; /* - * create ENCTYPE_DES_CBC_CRC key out of - * the salt and the cleartext password + * prepare generation of keys + * + * ENCTYPE_DES_CBC_MD5 + * ENCTYPE_DES_CBC_CRC */ - krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, - ENCTYPE_DES_CBC_CRC, - io->n.cleartext, - salt, - &key); - pkb3->keys[k].keytype = ENCTYPE_DES_CBC_CRC; - pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB); - if (!pkb3->keys[k].value) { - krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - ldb_oom(io->ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value, - key.keyvalue.data, - key.keyvalue.length); - krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - if (!pkb3->keys[k].value->data) { + pkb3->salt.string = io->g.salt; + pkb3->num_keys = 2; + pkb3->keys = talloc_array(io->ac, + struct package_PrimaryKerberosKey, + pkb3->num_keys); + if (!pkb3->keys) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - k++; - /* fix up key number */ - pkb3->num_keys = k; + pkb3->keys[0].keytype = ENCTYPE_DES_CBC_MD5; + pkb3->keys[0].value = &io->g.des_md5; + pkb3->keys[1].keytype = ENCTYPE_DES_CBC_CRC; + pkb3->keys[1].value = &io->g.des_crc; /* initialize the old keys to zero */ pkb3->num_old_keys = 0; @@ -1110,6 +1080,13 @@ static int setup_password_fields(struct setup_password_fields_io *io) } } + if (io->n.cleartext) { + ret = setup_kerberos_keys(io); + if (ret != 0) { + return ret; + } + } + ret = setup_nt_fields(io); if (ret != 0) { return ret; -- cgit From b3d6c5ee31bed1a921ddb3387892d7e82808592d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 18:54:21 +0200 Subject: password_hash: order the supplementalCredentials Packages in the same order like windows metze (This used to be commit ca9cd81a1798fb15195566422b3cad7c282fce89) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 68 +++++++++++++++++++++----- 1 file changed, 55 insertions(+), 13 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 9996e89cc6..8d63aed0f5 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -804,30 +804,41 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) struct supplementalCredentialsBlob scb; struct supplementalCredentialsBlob _old_scb; struct supplementalCredentialsBlob *old_scb = NULL; - /* Packages + (Kerberos, WDigest and maybe CLEARTEXT) */ - uint32_t num_packages = 1 + 2; + /* Packages + (Kerberos, WDigest and CLEARTEXT) */ + uint32_t num_names = 0; + const char *names[1+3]; + uint32_t num_packages = 0; struct supplementalCredentialsPackage packages[1+3]; - struct supplementalCredentialsPackage *pp = &packages[0]; - struct supplementalCredentialsPackage *pk = &packages[1]; - struct supplementalCredentialsPackage *pd = &packages[2]; - struct supplementalCredentialsPackage *pc = NULL; + /* Packages */ + struct supplementalCredentialsPackage *pp = NULL; struct package_PackagesBlob pb; DATA_BLOB pb_blob; char *pb_hexstr; + /* Primary:Kerberos */ + const char **nk = NULL; + struct supplementalCredentialsPackage *pk = NULL; struct package_PrimaryKerberosBlob pkb; DATA_BLOB pkb_blob; char *pkb_hexstr; + /* Primary:WDigest */ + const char **nd = NULL; + struct supplementalCredentialsPackage *pd = NULL; struct package_PrimaryWDigestBlob pdb; DATA_BLOB pdb_blob; char *pdb_hexstr; + /* Primary:CLEARTEXT */ + const char **nc = NULL; + struct supplementalCredentialsPackage *pc = NULL; struct package_PrimaryCLEARTEXTBlob pcb; DATA_BLOB pcb_blob; char *pcb_hexstr; int ret; enum ndr_err_code ndr_err; uint8_t zero16[16]; + bool do_cleartext = false; ZERO_STRUCT(zero16); + ZERO_STRUCT(names); if (!io->n.cleartext) { /* @@ -864,17 +875,46 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) if (io->domain->store_cleartext && (io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { - pc = &packages[3]; - num_packages++; + do_cleartext = true; } - /* Kerberos, WDigest, CLEARTEXT and termination(counted by the Packages element) */ - pb.names = talloc_zero_array(io->ac, const char *, num_packages); + /* + * The ordering is this + * + * Primary:Kerberos + * Primary:WDigest + * Primary:CLEARTEXT (optional) + * + * And the 'Packages' package is insert before the last + * other package. + */ + + /* Primary:Kerberos */ + nk = &names[num_names++]; + pk = &packages[num_packages++]; + + if (!do_cleartext) { + /* Packages */ + pp = &packages[num_packages++]; + } + + /* Primary:WDigest */ + nd = &names[num_names++]; + pd = &packages[num_packages++]; + + if (do_cleartext) { + /* Packages */ + pp = &packages[num_packages++]; + + /* Primary:CLEARTEXT */ + nc = &names[num_names++]; + pc = &packages[num_packages++]; + } /* * setup 'Primary:Kerberos' element */ - pb.names[0] = "Kerberos"; + *nk = "Kerberos"; ret = setup_primary_kerberos(io, old_scb, &pkb); if (ret != LDB_SUCCESS) { @@ -905,7 +945,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* * setup 'Primary:WDigest' element */ - pb.names[1] = "WDigest"; + *nd = "WDigest"; ret = setup_primary_wdigest(io, old_scb, &pdb); if (ret != LDB_SUCCESS) { @@ -937,7 +977,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) * setup 'Primary:CLEARTEXT' element */ if (pc) { - pb.names[2] = "CLEARTEXT"; + *nc = "CLEARTEXT"; pcb.cleartext = io->n.cleartext; @@ -966,6 +1006,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* * setup 'Packages' element */ + pb.names = names; ndr_err = ndr_push_struct_blob(&pb_blob, io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), &pb, @@ -990,6 +1031,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* * setup 'supplementalCredentials' value */ + ZERO_STRUCT(scb); scb.sub.num_packages = num_packages; scb.sub.packages = packages; -- cgit From 34b10077f9ca742b72ad37c86357d0f16ed68ee7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 09:35:19 +0200 Subject: password_hash: add generation of the Primary:Kerberos-Newer-Keys blob But it's still of by default until we now what triggers this generation. It could be that the value is always generated but the KDC only uses it when in a specific funtional level, but it could also be that it's only generated in a specific functional level. metze (This used to be commit 08618bbd508ede0bb9e1922fae562cffdca41cbd) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 219 ++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 3 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 8d63aed0f5..413ec12479 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -141,6 +141,8 @@ struct setup_password_fields_io { uint32_t lm_history_len; struct samr_Password *lm_history; const char *salt; + DATA_BLOB aes_256; + DATA_BLOB aes_128; DATA_BLOB des_md5; DATA_BLOB des_crc; struct ldb_val supplemental; @@ -315,6 +317,56 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io) salt.saltvalue.data = discard_const(io->g.salt); salt.saltvalue.length = strlen(io->g.salt); + /* + * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of + * the salt and the cleartext password + */ + krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + io->n.cleartext, + salt, + &key); + if (krb5_ret) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_kerberos_keys: " + "generation of a aes256-cts-hmac-sha1-96 key failed: %s", + smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); + return LDB_ERR_OPERATIONS_ERROR; + } + io->g.aes_256 = data_blob_talloc(io->ac, + key.keyvalue.data, + key.keyvalue.length); + krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); + if (!io->g.aes_256.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * create ENCTYPE_AES128_CTS_HMAC_SHA1_96 key out of + * the salt and the cleartext password + */ + krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + io->n.cleartext, + salt, + &key); + if (krb5_ret) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_kerberos_keys: " + "generation of a aes128-cts-hmac-sha1-96 key failed: %s", + smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); + return LDB_ERR_OPERATIONS_ERROR; + } + io->g.aes_128 = data_blob_talloc(io->ac, + key.keyvalue.data, + key.keyvalue.length); + krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); + if (!io->g.aes_128.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + /* * create ENCTYPE_DES_CBC_MD5 key out of * the salt and the cleartext password @@ -467,6 +519,117 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, return LDB_SUCCESS; } +static int setup_primary_kerberos_newer(struct setup_password_fields_io *io, + const struct supplementalCredentialsBlob *old_scb, + struct package_PrimaryKerberosNewerBlob *pkb) +{ + struct package_PrimaryKerberosNewerCtr4 *pkb4 = &pkb->ctr.ctr4; + struct supplementalCredentialsPackage *old_scp = NULL; + struct package_PrimaryKerberosNewerBlob _old_pkb; + struct package_PrimaryKerberosNewerCtr4 *old_pkb4 = NULL; + uint32_t i; + enum ndr_err_code ndr_err; + + /* + * prepare generation of keys + * + * ENCTYPE_AES256_CTS_HMAC_SHA1_96 + * ENCTYPE_AES128_CTS_HMAC_SHA1_96 + * ENCTYPE_DES_CBC_MD5 + * ENCTYPE_DES_CBC_CRC + */ + pkb4->salt.string = io->g.salt; + pkb4->num_keys = 4; + pkb4->keys = talloc_array(io->ac, + struct package_PrimaryKerberosNewerKey, + pkb4->num_keys); + if (!pkb4->keys) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + pkb4->keys[0].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; + pkb4->keys[0].value = &io->g.aes_256; + pkb4->keys[1].keytype = ENCTYPE_AES128_CTS_HMAC_SHA1_96; + pkb4->keys[1].value = &io->g.aes_128; + pkb4->keys[2].keytype = ENCTYPE_DES_CBC_MD5; + pkb4->keys[2].value = &io->g.des_md5; + pkb4->keys[3].keytype = ENCTYPE_DES_CBC_CRC; + pkb4->keys[3].value = &io->g.des_crc; + + /* initialize the old keys to zero */ + pkb4->num_old_keys1 = 0; + pkb4->old_keys1 = NULL; + pkb4->num_old_keys2 = 0; + pkb4->old_keys2 = NULL; + + /* if there're no old keys, then we're done */ + if (!old_scb) { + return LDB_SUCCESS; + } + + for (i=0; i < old_scb->sub.num_packages; i++) { + if (strcmp("Primary:Kerberos-Newer-Keys", old_scb->sub.packages[i].name) != 0) { + continue; + } + + if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) { + continue; + } + + old_scp = &old_scb->sub.packages[i]; + break; + } + /* Primary:Kerberos element of supplementalCredentials */ + if (old_scp) { + DATA_BLOB blob; + + blob = strhex_to_data_blob(old_scp->data); + if (!blob.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + talloc_steal(io->ac, blob.data); + + /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */ + ndr_err = ndr_pull_struct_blob(&blob, io->ac, + lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), + &_old_pkb, + (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosNewerBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_primary_kerberos_newer: " + "failed to pull old package_PrimaryKerberosNewerBlob: %s", + nt_errstr(status)); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (_old_pkb.version != 4) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_primary_kerberos: " + "package_PrimaryKerberosNewerBlob version[%u] expected[4]", + _old_pkb.version); + return LDB_ERR_OPERATIONS_ERROR; + } + + old_pkb4 = &_old_pkb.ctr.ctr4; + } + + /* if we didn't found the old keys we're done */ + if (!old_pkb4) { + return LDB_SUCCESS; + } + + /* fill in the old keys */ + pkb4->num_old_keys1 = old_pkb4->num_keys; + pkb4->old_keys1 = old_pkb4->keys; + pkb4->num_old_keys2 = old_pkb4->num_old_keys1; + pkb4->old_keys2 = old_pkb4->old_keys1; + + return LDB_SUCCESS; +} + static int setup_primary_wdigest(struct setup_password_fields_io *io, const struct supplementalCredentialsBlob *old_scb, struct package_PrimaryWDigestBlob *pdb) @@ -804,16 +967,22 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) struct supplementalCredentialsBlob scb; struct supplementalCredentialsBlob _old_scb; struct supplementalCredentialsBlob *old_scb = NULL; - /* Packages + (Kerberos, WDigest and CLEARTEXT) */ + /* Packages + (Kerberos-Newer-Keys, Kerberos, WDigest and CLEARTEXT) */ uint32_t num_names = 0; - const char *names[1+3]; + const char *names[1+4]; uint32_t num_packages = 0; - struct supplementalCredentialsPackage packages[1+3]; + struct supplementalCredentialsPackage packages[1+4]; /* Packages */ struct supplementalCredentialsPackage *pp = NULL; struct package_PackagesBlob pb; DATA_BLOB pb_blob; char *pb_hexstr; + /* Primary:Kerberos-Newer-Keys */ + const char **nkn = NULL; + struct supplementalCredentialsPackage *pkn = NULL; + struct package_PrimaryKerberosNewerBlob pknb; + DATA_BLOB pknb_blob; + char *pknb_hexstr; /* Primary:Kerberos */ const char **nk = NULL; struct supplementalCredentialsPackage *pk = NULL; @@ -835,6 +1004,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) int ret; enum ndr_err_code ndr_err; uint8_t zero16[16]; + bool do_newer_keys = false; bool do_cleartext = false; ZERO_STRUCT(zero16); @@ -873,6 +1043,10 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) } } + /* TODO: do the correct check for this, it maybe depends on the functional level? */ + do_newer_keys = lp_parm_bool(ldb_get_opaque(io->ac->module->ldb, "loadparm"), + NULL, "password_hash", "create_aes_key", false); + if (io->domain->store_cleartext && (io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { do_cleartext = true; @@ -881,6 +1055,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* * The ordering is this * + * Primary:Kerberos-Newer-Keys (optional) * Primary:Kerberos * Primary:WDigest * Primary:CLEARTEXT (optional) @@ -888,6 +1063,11 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) * And the 'Packages' package is insert before the last * other package. */ + if (do_newer_keys) { + /* Primary:Kerberos-Newer-Keys */ + nkn = &names[num_names++]; + pkn = &packages[num_packages++]; + } /* Primary:Kerberos */ nk = &names[num_names++]; @@ -911,6 +1091,39 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) pc = &packages[num_packages++]; } + if (pkn) { + /* + * setup 'Primary:Kerberos-Newer-Keys' element + */ + *nkn = "Kerberos-Newer-Keys"; + + ret = setup_primary_kerberos_newer(io, old_scb, &pknb); + if (ret != LDB_SUCCESS) { + return ret; + } + + ndr_err = ndr_push_struct_blob(&pknb_blob, io->ac, + lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), + &pknb, + (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosNewerBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_supplemental_field: " + "failed to push package_PrimaryKerberosNeverBlob: %s", + nt_errstr(status)); + return LDB_ERR_OPERATIONS_ERROR; + } + pknb_hexstr = data_blob_hex_string(io->ac, &pknb_blob); + if (!pknb_hexstr) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + pkn->name = "Primary:Kerberos-Newer-Keys"; + pkn->reserved = 1; + pkn->data = pknb_hexstr; + } + /* * setup 'Primary:Kerberos' element */ -- cgit From 0c8fb9361e524639cc35efda2f6a4d48098c76a7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 24 Jul 2008 08:22:23 +0200 Subject: password_hash: fix the callers after drsblobs.idl changes metze (This used to be commit fac7c79afae05a88ecc2a63c8eb9f2fd53ab7ce6) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 74 ++++++++++++++------------ 1 file changed, 41 insertions(+), 33 deletions(-) (limited to 'source4/dsdb/samdb/ldb_modules/password_hash.c') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 413ec12479..69783aefa8 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -437,10 +437,11 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, * ENCTYPE_DES_CBC_MD5 * ENCTYPE_DES_CBC_CRC */ + pkb->version = 3; pkb3->salt.string = io->g.salt; pkb3->num_keys = 2; pkb3->keys = talloc_array(io->ac, - struct package_PrimaryKerberosKey, + struct package_PrimaryKerberosKey3, pkb3->num_keys); if (!pkb3->keys) { ldb_oom(io->ac->module->ldb); @@ -521,12 +522,12 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, static int setup_primary_kerberos_newer(struct setup_password_fields_io *io, const struct supplementalCredentialsBlob *old_scb, - struct package_PrimaryKerberosNewerBlob *pkb) + struct package_PrimaryKerberosBlob *pkb) { - struct package_PrimaryKerberosNewerCtr4 *pkb4 = &pkb->ctr.ctr4; + struct package_PrimaryKerberosCtr4 *pkb4 = &pkb->ctr.ctr4; struct supplementalCredentialsPackage *old_scp = NULL; - struct package_PrimaryKerberosNewerBlob _old_pkb; - struct package_PrimaryKerberosNewerCtr4 *old_pkb4 = NULL; + struct package_PrimaryKerberosBlob _old_pkb; + struct package_PrimaryKerberosCtr4 *old_pkb4 = NULL; uint32_t i; enum ndr_err_code ndr_err; @@ -538,30 +539,37 @@ static int setup_primary_kerberos_newer(struct setup_password_fields_io *io, * ENCTYPE_DES_CBC_MD5 * ENCTYPE_DES_CBC_CRC */ - pkb4->salt.string = io->g.salt; - pkb4->num_keys = 4; - pkb4->keys = talloc_array(io->ac, - struct package_PrimaryKerberosNewerKey, - pkb4->num_keys); + pkb->version = 4; + pkb4->salt.string = io->g.salt; + pkb4->default_iteration_count = 4096; + pkb4->num_keys = 4; + + pkb4->keys = talloc_array(io->ac, + struct package_PrimaryKerberosKey4, + pkb4->num_keys); if (!pkb4->keys) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - pkb4->keys[0].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; - pkb4->keys[0].value = &io->g.aes_256; - pkb4->keys[1].keytype = ENCTYPE_AES128_CTS_HMAC_SHA1_96; - pkb4->keys[1].value = &io->g.aes_128; - pkb4->keys[2].keytype = ENCTYPE_DES_CBC_MD5; - pkb4->keys[2].value = &io->g.des_md5; - pkb4->keys[3].keytype = ENCTYPE_DES_CBC_CRC; - pkb4->keys[3].value = &io->g.des_crc; + pkb4->keys[0].iteration_count = 4096; + pkb4->keys[0].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; + pkb4->keys[0].value = &io->g.aes_256; + pkb4->keys[1].iteration_count = 4096; + pkb4->keys[1].keytype = ENCTYPE_AES128_CTS_HMAC_SHA1_96; + pkb4->keys[1].value = &io->g.aes_128; + pkb4->keys[2].iteration_count = 4096; + pkb4->keys[2].keytype = ENCTYPE_DES_CBC_MD5; + pkb4->keys[2].value = &io->g.des_md5; + pkb4->keys[3].iteration_count = 4096; + pkb4->keys[3].keytype = ENCTYPE_DES_CBC_CRC; + pkb4->keys[3].value = &io->g.des_crc; /* initialize the old keys to zero */ - pkb4->num_old_keys1 = 0; - pkb4->old_keys1 = NULL; - pkb4->num_old_keys2 = 0; - pkb4->old_keys2 = NULL; + pkb4->num_old_keys = 0; + pkb4->old_keys = NULL; + pkb4->num_older_keys = 0; + pkb4->older_keys = NULL; /* if there're no old keys, then we're done */ if (!old_scb) { @@ -580,7 +588,7 @@ static int setup_primary_kerberos_newer(struct setup_password_fields_io *io, old_scp = &old_scb->sub.packages[i]; break; } - /* Primary:Kerberos element of supplementalCredentials */ + /* Primary:Kerberos-Newer-Keys element of supplementalCredentials */ if (old_scp) { DATA_BLOB blob; @@ -595,20 +603,20 @@ static int setup_primary_kerberos_newer(struct setup_password_fields_io *io, ndr_err = ndr_pull_struct_blob(&blob, io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), &_old_pkb, - (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosNewerBlob); + (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); ldb_asprintf_errstring(io->ac->module->ldb, "setup_primary_kerberos_newer: " - "failed to pull old package_PrimaryKerberosNewerBlob: %s", + "failed to pull old package_PrimaryKerberosBlob: %s", nt_errstr(status)); return LDB_ERR_OPERATIONS_ERROR; } if (_old_pkb.version != 4) { ldb_asprintf_errstring(io->ac->module->ldb, - "setup_primary_kerberos: " - "package_PrimaryKerberosNewerBlob version[%u] expected[4]", + "setup_primary_kerberos_newer: " + "package_PrimaryKerberosBlob version[%u] expected[4]", _old_pkb.version); return LDB_ERR_OPERATIONS_ERROR; } @@ -622,10 +630,10 @@ static int setup_primary_kerberos_newer(struct setup_password_fields_io *io, } /* fill in the old keys */ - pkb4->num_old_keys1 = old_pkb4->num_keys; - pkb4->old_keys1 = old_pkb4->keys; - pkb4->num_old_keys2 = old_pkb4->num_old_keys1; - pkb4->old_keys2 = old_pkb4->old_keys1; + pkb4->num_old_keys = old_pkb4->num_keys; + pkb4->old_keys = old_pkb4->keys; + pkb4->num_older_keys = old_pkb4->num_old_keys; + pkb4->older_keys = old_pkb4->old_keys; return LDB_SUCCESS; } @@ -980,7 +988,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* Primary:Kerberos-Newer-Keys */ const char **nkn = NULL; struct supplementalCredentialsPackage *pkn = NULL; - struct package_PrimaryKerberosNewerBlob pknb; + struct package_PrimaryKerberosBlob pknb; DATA_BLOB pknb_blob; char *pknb_hexstr; /* Primary:Kerberos */ @@ -1105,7 +1113,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) ndr_err = ndr_push_struct_blob(&pknb_blob, io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), &pknb, - (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosNewerBlob); + (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); ldb_asprintf_errstring(io->ac->module->ldb, -- cgit