summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/auth/ntlm/auth_sam.c2
-rw-r--r--source4/dsdb/common/util.c88
-rw-r--r--source4/dsdb/samdb/ldb_modules/objectclass.c12
-rw-r--r--source4/dsdb/samdb/ldb_modules/password_hash.c195
-rw-r--r--source4/kdc/kpasswdd.c37
-rw-r--r--source4/libcli/auth/smbencrypt.c33
-rw-r--r--source4/librpc/idl/drsblobs.idl2
-rw-r--r--source4/rpc_server/lsa/dcesrv_lsa.c21
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c27
-rw-r--r--source4/rpc_server/samr/samr_password.c88
10 files changed, 322 insertions, 183 deletions
diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c
index ac36d4f1ef..78429106f6 100644
--- a/source4/auth/ntlm/auth_sam.c
+++ b/source4/auth/ntlm/auth_sam.c
@@ -248,7 +248,7 @@ static NTSTATUS authsam_authenticate(struct auth_context *auth_context,
}
}
- nt_status = samdb_result_passwords(mem_ctx, msgs[0], &lm_pwd, &nt_pwd);
+ nt_status = samdb_result_passwords(mem_ctx, auth_context->lp_ctx, msgs[0], &lm_pwd, &nt_pwd);
NT_STATUS_NOT_OK_RETURN(nt_status);
nt_status = authsam_password_ok(auth_context, mem_ctx,
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,
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c
index e610c358f6..7d00851792 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass.c
@@ -382,11 +382,17 @@ static int fix_attributes(struct ldb_context *ldb, const struct dsdb_schema *sch
int i;
for (i=0; i < msg->num_elements; i++) {
const struct dsdb_attribute *attribute = dsdb_attribute_by_lDAPDisplayName(schema, msg->elements[i].name);
+ /* Add in a very special case for 'clearTextPassword',
+ * which is used for internal processing only, and is
+ * not presented in the schema */
if (!attribute) {
- ldb_asprintf_errstring(ldb, "attribute %s is not a valid attribute in schema", msg->elements[i].name);
- return LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE;
+ if (strcasecmp(msg->elements[i].name, "clearTextPassword") != 0) {
+ ldb_asprintf_errstring(ldb, "attribute %s is not a valid attribute in schema", msg->elements[i].name);
+ return LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE;
+ }
+ } else {
+ msg->elements[i].name = attribute->lDAPDisplayName;
}
- msg->elements[i].name = attribute->lDAPDisplayName;
}
return LDB_SUCCESS;
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index e36de3c5c4..c4451d1355 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -109,7 +109,8 @@ struct setup_password_fields_io {
/* new credentials */
struct {
- const char *cleartext;
+ const struct ldb_val *cleartext_utf8;
+ const struct ldb_val *cleartext_utf16;
struct samr_Password *nt_hash;
struct samr_Password *lm_hash;
} n;
@@ -144,6 +145,9 @@ struct setup_password_fields_io {
} g;
};
+/* Get the NT hash, and fill it in as an entry in the password history,
+ and specify it into io->g.nt_hash */
+
static int setup_nt_fields(struct setup_password_fields_io *io)
{
uint32_t i;
@@ -181,6 +185,9 @@ static int setup_nt_fields(struct setup_password_fields_io *io)
return LDB_SUCCESS;
}
+/* Get the LANMAN hash, and fill it in as an entry in the password history,
+ and specify it into io->g.lm_hash */
+
static int setup_lm_fields(struct setup_password_fields_io *io)
{
uint32_t i;
@@ -220,6 +227,10 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
Principal *salt_principal;
krb5_salt salt;
krb5_keyblock key;
+ krb5_data cleartext_data;
+
+ cleartext_data.data = io->n.cleartext_utf8->data;
+ cleartext_data.length = io->n.cleartext_utf8->length;
/* Many, many thanks to lukeh@padl.com for this
* algorithm, described in his Nov 10 2004 mail to
@@ -314,11 +325,11 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
* 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);
+ krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context,
+ ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+ cleartext_data,
+ salt,
+ &key);
if (krb5_ret) {
ldb_asprintf_errstring(io->ac->module->ldb,
"setup_kerberos_keys: "
@@ -339,11 +350,11 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
* 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);
+ krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context,
+ ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+ cleartext_data,
+ salt,
+ &key);
if (krb5_ret) {
ldb_asprintf_errstring(io->ac->module->ldb,
"setup_kerberos_keys: "
@@ -364,11 +375,11 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
* 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);
+ krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context,
+ ENCTYPE_DES_CBC_MD5,
+ cleartext_data,
+ salt,
+ &key);
if (krb5_ret) {
ldb_asprintf_errstring(io->ac->module->ldb,
"setup_kerberos_keys: "
@@ -389,11 +400,11 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
* 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_CRC,
- io->n.cleartext,
- salt,
- &key);
+ krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context,
+ ENCTYPE_DES_CBC_CRC,
+ cleartext_data,
+ salt,
+ &key);
if (krb5_ret) {
ldb_asprintf_errstring(io->ac->module->ldb,
"setup_kerberos_keys: "
@@ -648,7 +659,6 @@ static int setup_primary_wdigest(struct setup_password_fields_io *io,
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;
@@ -929,8 +939,6 @@ static int setup_primary_wdigest(struct setup_password_fields_io *io,
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(":");
@@ -956,7 +964,7 @@ static int setup_primary_wdigest(struct setup_password_fields_io *io,
MD5Update(&md5, wdigest[i].realm->data, wdigest[i].realm->length);
}
MD5Update(&md5, delim.data, delim.length);
- MD5Update(&md5, cleartext.data, cleartext.length);
+ MD5Update(&md5, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length);
MD5Final(pdb->hashes[i].hash, &md5);
}
@@ -1011,7 +1019,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io)
ZERO_STRUCT(zero16);
ZERO_STRUCT(names);
- if (!io->n.cleartext) {
+ if (!io->n.cleartext_utf8) {
/*
* when we don't have a cleartext password
* we can't setup a supplementalCredential value
@@ -1193,7 +1201,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io)
if (pc) {
*nc = "CLEARTEXT";
- pcb.cleartext = io->n.cleartext;
+ pcb.cleartext = *io->n.cleartext_utf16;
ndr_err = ndr_push_struct_blob(&pcb_blob, io->ac,
lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")),
@@ -1285,58 +1293,97 @@ static int setup_password_fields(struct setup_password_fields_io *io)
{
bool ok;
int ret;
-
+ ssize_t converted_pw_len;
+
/*
* 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)) {
+ if ((io->n.cleartext_utf8 || io->n.cleartext_utf16) && (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 (io->n.cleartext) {
- struct samr_Password *hash;
-
- hash = talloc(io->ac, struct samr_Password);
- if (!hash) {
+
+ if (io->n.cleartext_utf8 && io->n.cleartext_utf16) {
+ ldb_asprintf_errstring(io->ac->module->ldb,
+ "setup_password_fields: "
+ "it's only allowed to set the cleartext password as userPassword or clearTextPasssword, not both at once");
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
+ if (io->n.cleartext_utf8) {
+ char **cleartext_utf16_str;
+ struct ldb_val *cleartext_utf16_blob;
+ io->n.cleartext_utf16 = cleartext_utf16_blob = talloc(io->ac, struct ldb_val);
+ if (!io->n.cleartext_utf16) {
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 {
+ converted_pw_len = convert_string_talloc(io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")),
+ CH_UTF8, CH_UTF16, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length,
+ (void **)&cleartext_utf16_str);
+ if (converted_pw_len == -1) {
ldb_asprintf_errstring(io->ac->module->ldb,
"setup_password_fields: "
- "failed to generate nthash from cleartext password");
+ "failed to generate UTF16 password from cleartext UTF8 password");
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ *cleartext_utf16_blob = data_blob_const(cleartext_utf16_str, converted_pw_len);
+ } else if (io->n.cleartext_utf16) {
+ char *cleartext_utf8_str;
+ struct ldb_val *cleartext_utf8_blob;
+ io->n.cleartext_utf8 = cleartext_utf8_blob = talloc(io->ac, struct ldb_val);
+ if (!io->n.cleartext_utf8) {
+ ldb_oom(io->ac->module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
+ converted_pw_len = convert_string_talloc(io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")),
+ CH_UTF16, CH_UTF8, io->n.cleartext_utf16->data, io->n.cleartext_utf16->length,
+ (void **)&cleartext_utf8_str);
+ if (converted_pw_len == -1) {
+ /* We can't bail out entirely, as these unconvertable passwords are frustratingly valid */
+ io->n.cleartext_utf8 = NULL;
+ talloc_free(cleartext_utf8_blob);
+ }
+ *cleartext_utf8_blob = data_blob_const(cleartext_utf8_str, converted_pw_len);
}
-
- if (io->n.cleartext) {
- struct samr_Password *hash;
-
- hash = talloc(io->ac, struct samr_Password);
- if (!hash) {
+ if (io->n.cleartext_utf16) {
+ struct samr_Password *nt_hash;
+ nt_hash = talloc(io->ac, struct samr_Password);
+ if (!nt_hash) {
ldb_oom(io->ac->module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
+ io->n.nt_hash = nt_hash;
- /* 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);
- }
+ /* compute the new nt hash */
+ mdfour(nt_hash->hash, io->n.cleartext_utf16->data, io->n.cleartext_utf16->length);
}
- if (io->n.cleartext) {
+ if (io->n.cleartext_utf8) {
+ struct samr_Password *lm_hash;
+ char *cleartext_unix;
+ converted_pw_len = convert_string_talloc(io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")),
+ CH_UTF8, CH_UNIX, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length,
+ (void **)&cleartext_unix);
+ if (converted_pw_len != -1) {
+ lm_hash = talloc(io->ac, struct samr_Password);
+ if (!lm_hash) {
+ ldb_oom(io->ac->module->ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* compute the new lm hash. */
+ ok = E_deshash((char *)cleartext_unix, lm_hash->hash);
+ if (ok) {
+ io->n.lm_hash = lm_hash;
+ } else {
+ talloc_free(lm_hash->hash);
+ }
+ }
+
ret = setup_kerberos_keys(io);
if (ret != 0) {
return ret;
@@ -1560,6 +1607,7 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
{
struct ph_context *ac;
struct ldb_message_element *sambaAttr;
+ struct ldb_message_element *clearTextPasswordAttr;
struct ldb_message_element *ntAttr;
struct ldb_message_element *lmAttr;
int ret;
@@ -1591,6 +1639,7 @@ 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, "userPassword");
+ clearTextPasswordAttr = ldb_msg_find_element(req->op.mod.message, "clearTextPassword");
ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd");
lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd");
@@ -1611,6 +1660,10 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
ldb_set_errstring(module->ldb, "mupltiple values for userPassword not allowed!\n");
return LDB_ERR_CONSTRAINT_VIOLATION;
}
+ if (clearTextPasswordAttr && clearTextPasswordAttr->num_values > 1) {
+ ldb_set_errstring(module->ldb, "mupltiple values for clearTextPassword not allowed!\n");
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
if (ntAttr && (ntAttr->num_values > 1)) {
ldb_set_errstring(module->ldb, "mupltiple values for unicodePwd not allowed!\n");
@@ -1626,6 +1679,11 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
return LDB_ERR_CONSTRAINT_VIOLATION;
}
+ if (clearTextPasswordAttr && clearTextPasswordAttr->num_values == 0) {
+ ldb_set_errstring(module->ldb, "clearTextPassword must have a value!\n");
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
if (ntAttr && (ntAttr->num_values == 0)) {
ldb_set_errstring(module->ldb, "unicodePwd must have a value!\n");
return LDB_ERR_CONSTRAINT_VIOLATION;
@@ -1687,12 +1745,14 @@ static int password_hash_add_do_add(struct ph_context *ac) {
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, "userPassword", NULL);
+ io.n.cleartext_utf8 = ldb_msg_find_ldb_val(msg, "userPassword");
+ io.n.cleartext_utf16 = ldb_msg_find_ldb_val(msg, "clearTextPassword");
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, "userPassword");
+ if (io.n.cleartext_utf8) ldb_msg_remove_attr(msg, "userPassword");
+ if (io.n.cleartext_utf16) ldb_msg_remove_attr(msg, "clearTextPassword");
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");
@@ -1772,6 +1832,7 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r
{
struct ph_context *ac;
struct ldb_message_element *sambaAttr;
+ struct ldb_message_element *clearTextAttr;
struct ldb_message_element *ntAttr;
struct ldb_message_element *lmAttr;
struct ldb_message *msg;
@@ -1802,13 +1863,16 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r
}
sambaAttr = ldb_msg_find_element(req->op.mod.message, "userPassword");
+ clearTextAttr = ldb_msg_find_element(req->op.mod.message, "clearTextPassword");
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 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)) {
+ /* If no part of this touches the userPassword OR
+ * clearTextPassword 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) && (!clearTextAttr) && (!ntAttr) && (!lmAttr)) {
return ldb_next_request(module, req);
}
@@ -1817,6 +1881,9 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r
if (sambaAttr && (sambaAttr->num_values > 1)) {
return LDB_ERR_CONSTRAINT_VIOLATION;
}
+ if (clearTextAttr && (clearTextAttr->num_values > 1)) {
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
if (ntAttr && (ntAttr->num_values > 1)) {
return LDB_ERR_CONSTRAINT_VIOLATION;
}
@@ -1839,6 +1906,7 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r
/* - remove any modification to the password from the first commit
* we will make the real modification later */
if (sambaAttr) ldb_msg_remove_attr(msg, "userPassword");
+ if (clearTextAttr) ldb_msg_remove_attr(msg, "clearTextPassword");
if (ntAttr) ldb_msg_remove_attr(msg, "unicodePwd");
if (lmAttr) ldb_msg_remove_attr(msg, "dBCSPwd");
@@ -2028,7 +2096,8 @@ static int password_hash_mod_do_mod(struct ph_context *ac) {
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, "userPassword", NULL);
+ io.n.cleartext_utf8 = ldb_msg_find_ldb_val(orig_msg, "userPassword");
+ io.n.cleartext_utf16 = ldb_msg_find_ldb_val(orig_msg, "clearTextPassword");
io.n.nt_hash = samdb_result_hash(io.ac, orig_msg, "unicodePwd");
io.n.lm_hash = samdb_result_hash(io.ac, orig_msg, "dBCSPwd");
diff --git a/source4/kdc/kpasswdd.c b/source4/kdc/kpasswdd.c
index d662844c4e..1336b0157e 100644
--- a/source4/kdc/kpasswdd.c
+++ b/source4/kdc/kpasswdd.c
@@ -175,7 +175,7 @@ static bool kpasswd_make_pwchange_reply(struct kdc_server *kdc,
static bool kpasswdd_change_password(struct kdc_server *kdc,
TALLOC_CTX *mem_ctx,
struct auth_session_info *session_info,
- const char *password,
+ const DATA_BLOB *password,
DATA_BLOB *reply)
{
NTSTATUS status;
@@ -219,6 +219,8 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
DATA_BLOB *reply)
{
struct auth_session_info *session_info;
+ ssize_t pw_len;
+
if (!NT_STATUS_IS_OK(gensec_session_info(gensec_security,
&session_info))) {
return kpasswdd_make_error_reply(kdc, mem_ctx,
@@ -230,12 +232,20 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
switch (version) {
case KRB5_KPASSWD_VERS_CHANGEPW:
{
- char *password = talloc_strndup(mem_ctx, (const char *)input->data, input->length);
- if (!password) {
+ DATA_BLOB password;
+ pw_len = convert_string_talloc(mem_ctx, lp_iconv_convenience(kdc->task->lp_ctx),
+ CH_UTF8, CH_UTF16,
+ (const char *)input->data,
+ input->length,
+ (void **)&password.data);
+
+ if (pw_len == -1) {
return false;
}
+ password.length = pw_len;
+
return kpasswdd_change_password(kdc, mem_ctx, session_info,
- password, reply);
+ &password, reply);
break;
}
case KRB5_KPASSWD_VERS_SETPW:
@@ -248,7 +258,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
krb5_context context = kdc->smb_krb5_context->krb5_context;
ChangePasswdDataMS chpw;
- char *password;
+ DATA_BLOB password;
krb5_principal principal;
char *set_password_on_princ;
@@ -271,13 +281,18 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
reply);
}
- password = talloc_strndup(mem_ctx,
- (const char *)chpw.newpasswd.data,
- chpw.newpasswd.length);
- if (!password) {
+ pw_len = convert_string_talloc(mem_ctx, lp_iconv_convenience(kdc->task->lp_ctx),
+ CH_UTF8, CH_UTF16,
+ (const char *)chpw.newpasswd.data,
+ chpw.newpasswd.length,
+ (void **)&password.data);
+ if (pw_len == -1) {
free_ChangePasswdDataMS(&chpw);
return false;
}
+
+ password.length = pw_len;
+
if ((chpw.targname && !chpw.targrealm)
|| (!chpw.targname && chpw.targrealm)) {
return kpasswdd_make_error_reply(kdc, mem_ctx,
@@ -306,7 +321,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
} else {
free_ChangePasswdDataMS(&chpw);
return kpasswdd_change_password(kdc, mem_ctx, session_info,
- password, reply);
+ &password, reply);
}
free_ChangePasswdDataMS(&chpw);
@@ -371,7 +386,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
/* Admin password set */
status = samdb_set_password(samdb, mem_ctx,
set_password_on_dn, NULL,
- msg, password, NULL, NULL,
+ msg, &password, NULL, NULL,
false, /* this is not a user password change */
&reject_reason, &dominfo);
}
diff --git a/source4/libcli/auth/smbencrypt.c b/source4/libcli/auth/smbencrypt.c
index 3af7e45002..6eb8767140 100644
--- a/source4/libcli/auth/smbencrypt.c
+++ b/source4/libcli/auth/smbencrypt.c
@@ -536,9 +536,40 @@ bool decode_pw_buffer(uint8_t in_buffer[516], char *new_pwrd,
#ifdef DEBUG_PASSWORD
DEBUG(100,("decode_pw_buffer: new_pwrd: "));
dump_data(100, (const uint8_t *)new_pwrd, converted_pw_len);
- DEBUG(100,("multibyte len:%d\n", converted_pw_len));
+ DEBUG(100,("multibyte len:%d\n", (int)converted_pw_len));
DEBUG(100,("original char len:%d\n", byte_len/2));
#endif
return true;
}
+
+/***********************************************************
+ decode a password buffer
+ *new_pw_size is the length in bytes of the extracted unicode password
+************************************************************/
+bool extract_pw_from_buffer(TALLOC_CTX *mem_ctx,
+ uint8_t in_buffer[516], DATA_BLOB *new_pass)
+{
+ int byte_len=0;
+
+ /* The length of the new password is in the last 4 bytes of the data buffer. */
+
+ byte_len = IVAL(in_buffer, 512);
+
+#ifdef DEBUG_PASSWORD
+ dump_data(100, in_buffer, 516);
+#endif
+
+ /* Password cannot be longer than the size of the password buffer */
+ if ( (byte_len < 0) || (byte_len > 512)) {
+ return false;
+ }
+
+ *new_pass = data_blob_talloc(mem_ctx, &in_buffer[512 - byte_len], byte_len);
+
+ if (!*new_pass->data) {
+ return false;
+ }
+
+ return true;
+}
diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl
index 4274d2000a..087f0c982d 100644
--- a/source4/librpc/idl/drsblobs.idl
+++ b/source4/librpc/idl/drsblobs.idl
@@ -332,7 +332,7 @@ interface drsblobs {
);
typedef [public] struct {
- [flag(STR_NOTERM|NDR_REMAINING)] string cleartext;
+ [flag(NDR_REMAINING)] DATA_BLOB cleartext;
} package_PrimaryCLEARTEXTBlob;
void decode_PrimaryCLEARTEXT(
diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index 9cda7d0d89..4c596f1f03 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -968,19 +968,14 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc
mem_ctx, msg_user, "unicodePwd",
&auth_struct.incoming.current[i]->AuthInfo.nt4owf.password);
} else if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_CLEAR) {
- struct samr_Password hash;
-/*
- . We cannot do this, as windows chooses to send in random passwords here, that won't convert to UTF8
- samdb_msg_add_string(trusted_domain_state->policy->sam_ldb,
- mem_ctx, msg_user, "userPassword",
- auth_struct.incoming.current->array[i].AuthInfo.clear.password);
-*/
- mdfour(hash.hash, auth_struct.incoming.current[i]->AuthInfo.clear.password,
- auth_struct.incoming.current[i]->AuthInfo.clear.size);
- samdb_msg_add_hash(trusted_domain_state->policy->sam_ldb,
- mem_ctx, msg_user, "unicodePwd",
- &hash);
- }
+ DATA_BLOB new_password = data_blob_const(auth_struct.incoming.current[i]->AuthInfo.clear.password,
+ auth_struct.incoming.current[i]->AuthInfo.clear.size);
+ ret = ldb_msg_add_value(msg_user, "clearTextPassword", &new_password, NULL);
+ if (ret != LDB_SUCCESS) {
+ ldb_transaction_cancel(policy_state->sam_ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
}
}
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 470c27a075..9d4c897892 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -107,7 +107,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
- char *flatname;
+ const char *flatname;
if (!encoded_account) {
return NT_STATUS_NO_MEMORY;
}
@@ -370,7 +370,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call
creds->sid,
NULL, /* Don't have plaintext */
NULL, &r->in.new_password,
- false, /* This is not considered a password change */
+ true, /* Password change */
NULL, NULL);
return nt_status;
}
@@ -385,15 +385,14 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
struct creds_CredentialState *creds;
struct ldb_context *sam_ctx;
NTSTATUS nt_status;
- char new_pass[512];
- bool ret;
+ DATA_BLOB new_password;
struct samr_CryptPassword password_buf;
nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
r->in.computer_name, mem_ctx,
- &r->in.credential, &r->out.return_authenticator,
- &creds);
+ &r->in.credential, &r->out.return_authenticator,
+ &creds);
NT_STATUS_NOT_OK_RETURN(nt_status);
sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
@@ -402,22 +401,20 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
}
memcpy(password_buf.data, r->in.new_password.data, 512);
- SIVAL(password_buf.data,512,r->in.new_password.length);
+ SIVAL(password_buf.data, 512, r->in.new_password.length);
creds_arcfour_crypt(creds, password_buf.data, 516);
- ret = decode_pw_buffer(password_buf.data, new_pass, sizeof(new_pass),
- STR_UNICODE);
- if (!ret) {
- DEBUG(3,("netr_ServerPasswordSet2: failed to decode password buffer\n"));
- return NT_STATUS_ACCESS_DENIED;
+ if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
+ DEBUG(3,("samr: failed to decode password buffer\n"));
+ return NT_STATUS_WRONG_PASSWORD;
}
-
+
/* Using the sid for the account as the key, set the password */
nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
creds->sid,
- new_pass, /* we have plaintext */
+ &new_password, /* we have plaintext */
NULL, NULL,
- false, /* This is not considered a password change */
+ true, /* Password change */
NULL, NULL);
return nt_status;
}
diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c
index 8a855a7bdb..336720ecc7 100644
--- a/source4/rpc_server/samr/samr_password.c
+++ b/source4/rpc_server/samr/samr_password.c
@@ -86,7 +86,8 @@ NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call,
}
msg = res[0];
- status = samdb_result_passwords(mem_ctx, msg, &lm_pwd, &nt_pwd);
+ status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
+ msg, &lm_pwd, &nt_pwd);
if (!NT_STATUS_IS_OK(status) || !lm_pwd || !nt_pwd) {
ldb_transaction_cancel(sam_ctx);
return NT_STATUS_WRONG_PASSWORD;
@@ -183,8 +184,8 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
struct samr_OemChangePasswordUser2 *r)
{
NTSTATUS status;
- char new_pass[512];
- uint32_t new_pass_len;
+ DATA_BLOB new_password;
+ char *new_pass;
struct samr_CryptPassword *pwbuf = r->in.password;
struct ldb_context *sam_ctx;
struct ldb_dn *user_dn;
@@ -231,7 +232,8 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
user_dn = res[0]->dn;
- status = samdb_result_passwords(mem_ctx, res[0], &lm_pwd, NULL);
+ status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
+ res[0], &lm_pwd, NULL);
if (!NT_STATUS_IS_OK(status) || !lm_pwd) {
ldb_transaction_cancel(sam_ctx);
return NT_STATUS_WRONG_PASSWORD;
@@ -242,15 +244,18 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob);
data_blob_free(&lm_pwd_blob);
- if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),
- STR_ASCII)) {
+ if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
ldb_transaction_cancel(sam_ctx);
DEBUG(3,("samr: failed to decode password buffer\n"));
return NT_STATUS_WRONG_PASSWORD;
}
-
- /* check LM verifier */
- if (lm_pwd == NULL) {
+
+ if (convert_string_talloc(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
+ CH_DOS, CH_UNIX,
+ (const char *)new_password.data,
+ new_password.length,
+ (void **)&new_pass) == -1) {
+ DEBUG(3,("samr: failed to convert incoming password buffer to unix charset\n"));
ldb_transaction_cancel(sam_ctx);
return NT_STATUS_WRONG_PASSWORD;
}
@@ -278,7 +283,7 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
* due to password policies */
status = samdb_set_password(sam_ctx, mem_ctx,
user_dn, NULL,
- mod, new_pass,
+ mod, &new_password,
NULL, NULL,
true, /* this is a user password change */
NULL,
@@ -320,7 +325,7 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
struct samr_ChangePasswordUser3 *r)
{
NTSTATUS status;
- char new_pass[512];
+ DATA_BLOB new_password;
struct ldb_context *sam_ctx = NULL;
struct ldb_dn *user_dn;
int ret;
@@ -369,7 +374,8 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
user_dn = res[0]->dn;
- status = samdb_result_passwords(mem_ctx, res[0], &lm_pwd, &nt_pwd);
+ status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
+ res[0], &lm_pwd, &nt_pwd);
if (!NT_STATUS_IS_OK(status) ) {
goto failed;
}
@@ -384,40 +390,49 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob);
data_blob_free(&nt_pwd_blob);
- if (!decode_pw_buffer(r->in.nt_password->data, new_pass, sizeof(new_pass),
- STR_UNICODE)) {
+ if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) {
+ ldb_transaction_cancel(sam_ctx);
DEBUG(3,("samr: failed to decode password buffer\n"));
- status = NT_STATUS_WRONG_PASSWORD;
- goto failed;
+ return NT_STATUS_WRONG_PASSWORD;
}
-
+
if (r->in.nt_verifier == NULL) {
status = NT_STATUS_WRONG_PASSWORD;
goto failed;
}
/* check NT verifier */
- E_md4hash(new_pass, new_nt_hash);
+ mdfour(new_nt_hash, new_password.data, new_password.length);
+
E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash);
if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) {
status = NT_STATUS_WRONG_PASSWORD;
goto failed;
}
- /* check LM verifier */
+ /* check LM verifier (really not needed as we just checked the
+ * much stronger NT hash, but the RPC-SAMR test checks for
+ * this) */
if (lm_pwd && r->in.lm_verifier != NULL) {
- E_deshash(new_pass, new_lm_hash);
- E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);
- if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {
- status = NT_STATUS_WRONG_PASSWORD;
- goto failed;
+ char *new_pass;
+ if (convert_string_talloc(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
+ CH_UTF16, CH_UNIX,
+ (const char *)new_password.data,
+ new_password.length,
+ (void **)&new_pass) != -1) {
+ E_deshash(new_pass, new_lm_hash);
+ E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);
+ if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {
+ status = NT_STATUS_WRONG_PASSWORD;
+ goto failed;
+ }
}
}
-
mod = ldb_msg_new(mem_ctx);
if (mod == NULL) {
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto failed;
}
mod->dn = ldb_dn_copy(mod, user_dn);
@@ -430,7 +445,7 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
* due to password policies */
status = samdb_set_password(sam_ctx, mem_ctx,
user_dn, NULL,
- mod, new_pass,
+ mod, &new_password,
NULL, NULL,
true, /* this is a user password change */
&reason,
@@ -517,7 +532,7 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
struct samr_CryptPassword *pwbuf)
{
NTSTATUS nt_status;
- char new_pass[512];
+ DATA_BLOB new_password;
DATA_BLOB session_key = data_blob(NULL, 0);
nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
@@ -527,17 +542,16 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
arcfour_crypt_blob(pwbuf->data, 516, &session_key);
- if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),
- STR_UNICODE)) {
+ if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
DEBUG(3,("samr: failed to decode password buffer\n"));
return NT_STATUS_WRONG_PASSWORD;
}
-
+
/* set the password - samdb needs to know both the domain and user DNs,
so the domain password policy can be used */
return samdb_set_password(sam_ctx, mem_ctx,
account_dn, domain_dn,
- msg, new_pass,
+ msg, &new_password,
NULL, NULL,
false, /* This is a password set, not change */
NULL, NULL);
@@ -557,8 +571,7 @@ NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
struct samr_CryptPasswordEx *pwbuf)
{
NTSTATUS nt_status;
- char new_pass[512];
- uint32_t new_pass_len;
+ DATA_BLOB new_password;
DATA_BLOB co_session_key;
DATA_BLOB session_key = data_blob(NULL, 0);
struct MD5Context ctx;
@@ -580,17 +593,16 @@ NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
arcfour_crypt_blob(pwbuf->data, 516, &co_session_key);
- if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),
- STR_UNICODE)) {
+ if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
DEBUG(3,("samr: failed to decode password buffer\n"));
return NT_STATUS_WRONG_PASSWORD;
}
-
+
/* set the password - samdb needs to know both the domain and user DNs,
so the domain password policy can be used */
return samdb_set_password(sam_ctx, mem_ctx,
account_dn, domain_dn,
- msg, new_pass,
+ msg, &new_password,
NULL, NULL,
false, /* This is a password set, not change */
NULL, NULL);