diff options
Diffstat (limited to 'source4/dsdb/common/util.c')
-rw-r--r-- | source4/dsdb/common/util.c | 88 |
1 files changed, 51 insertions, 37 deletions
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index 5b93efb316..0a87c5ffe1 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -26,6 +26,7 @@ #include "ldb.h" #include "ldb_errors.h" #include "../lib/util/util_ldb.h" +#include "../lib/crypto/crypto.h" #include "dsdb/samdb/samdb.h" #include "libcli/security/security.h" #include "librpc/gen_ndr/ndr_security.h" @@ -571,7 +572,7 @@ uint_t samdb_result_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg, return count; } -NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg, +NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct ldb_message *msg, struct samr_Password **lm_pwd, struct samr_Password **nt_pwd) { struct samr_Password *lmPwdHash, *ntPwdHash; @@ -587,14 +588,21 @@ NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg, } } if (lm_pwd) { - int num_lm; - num_lm = samdb_result_hashes(mem_ctx, msg, "dBCSPwd", &lmPwdHash); - if (num_lm == 0) { - *lm_pwd = NULL; - } else if (num_lm > 1) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; + /* Ensure that if we have turned off LM + * authentication, that we never use the LM hash, even + * if we store it */ + if (lp_lanman_auth(lp_ctx)) { + int num_lm; + num_lm = samdb_result_hashes(mem_ctx, msg, "dBCSPwd", &lmPwdHash); + if (num_lm == 0) { + *lm_pwd = NULL; + } else if (num_lm > 1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } else { + *lm_pwd = &lmPwdHash[0]; + } } else { - *lm_pwd = &lmPwdHash[0]; + *lm_pwd = NULL; } } return NT_STATUS_OK; @@ -1531,7 +1539,7 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, struct ldb_dn *user_dn, struct ldb_dn *domain_dn, struct ldb_message *mod, - const char *new_pass, + const DATA_BLOB *new_password, struct samr_Password *lmNewHash, struct samr_Password *ntNewHash, bool user_change, @@ -1632,40 +1640,47 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, *_dominfo = dominfo; } - if (restrictions && new_pass) { - + if (restrictions && new_password) { + char *new_pass; + /* check the various password restrictions */ - if (restrictions && minPwdLength > strlen_m(new_pass)) { + if (restrictions && minPwdLength > utf16_len_n(new_password->data, (new_password->length / 2))) { if (reject_reason) { *reject_reason = SAMR_REJECT_TOO_SHORT; } return NT_STATUS_PASSWORD_RESTRICTION; } + + /* Create the NT hash */ + mdfour(local_ntNewHash.hash, new_password->data, new_password->length); - /* possibly check password complexity */ - if (restrictions && pwdProperties & DOMAIN_PASSWORD_COMPLEX && - !samdb_password_complexity_ok(new_pass)) { - if (reject_reason) { - *reject_reason = SAMR_REJECT_COMPLEXITY; + ntNewHash = &local_ntNewHash; + + /* Only check complexity if we can convert it at all. Assuming unconvertable passwords are 'strong' */ + if (convert_string_talloc(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ctx, "loadparm")), + CH_UTF16, CH_UNIX, + new_password->data, new_password->length, + (void **)&new_pass) != -1) { + + + /* possibly check password complexity */ + if (restrictions && pwdProperties & DOMAIN_PASSWORD_COMPLEX && + !samdb_password_complexity_ok(new_pass)) { + if (reject_reason) { + *reject_reason = SAMR_REJECT_COMPLEXITY; + } + return NT_STATUS_PASSWORD_RESTRICTION; } - return NT_STATUS_PASSWORD_RESTRICTION; - } - - /* compute the new nt and lm hashes */ - if (E_deshash(new_pass, local_lmNewHash.hash)) { - lmNewHash = &local_lmNewHash; - } - if (!E_md4hash(new_pass, local_ntNewHash.hash)) { - /* If we can't convert this password to UCS2, then we should not accept it */ - if (reject_reason) { - *reject_reason = SAMR_REJECT_OTHER; + + /* compute the new lm hashes (for checking history - case insenitivly!) */ + if (E_deshash(new_pass, local_lmNewHash.hash)) { + lmNewHash = &local_lmNewHash; } - return NT_STATUS_PASSWORD_RESTRICTION; + } - ntNewHash = &local_ntNewHash; } - if (user_change) { + if (restrictions && user_change) { /* are all password changes disallowed? */ if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) { if (reject_reason) { @@ -1731,16 +1746,15 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, #define CHECK_RET(x) do { if (x != 0) return NT_STATUS_NO_MEMORY; } while(0) /* the password is acceptable. Start forming the new fields */ - if (new_pass) { - /* if we know the cleartext, then only set it. + if (new_password) { + /* if we know the cleartext UTF16 password, then set it. * Modules in ldb will set all the appropriate * hashes */ - CHECK_RET(samdb_msg_add_string(ctx, mem_ctx, mod, - "userPassword", new_pass)); + CHECK_RET(ldb_msg_add_value(mod, "clearTextPassword", new_password, NULL)); } else { /* We don't have the cleartext, so delete the old one * and set what we have of the hashes */ - CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "userPassword")); + CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "clearTextPassword")); if (lmNewHash) { CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "dBCSPwd", lmNewHash)); @@ -1769,7 +1783,7 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, */ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid, - const char *new_pass, + const DATA_BLOB *new_pass, struct samr_Password *lmNewHash, struct samr_Password *ntNewHash, bool user_change, |