summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2014-12-16 13:58:11 +0000
committerStefan Metzmacher <metze@samba.org>2014-12-19 13:15:13 +0100
commit826b0f761e07987fbe067badde665c3d1c99e821 (patch)
treea936bc9caae2fe182c84a984a5a5f174ebe828dd
parent153938a1f2a06fec5b2f7daef12200a504fb92f4 (diff)
downloadsamba-826b0f761e07987fbe067badde665c3d1c99e821.tar.gz
auth/credentials: add cli_credentials_set_utf16_password()
We need a way to initialize the cli_credentials from the raw utf16 blob, which might not be completely valid utf16, which means the conversion from CH_UTF16MUNGED to CH_UTF8 might loose information. This would result in an invalid nt_hash, when we convert back from CH_UTF8 to CH_UTF16LE. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11016 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
-rw-r--r--auth/credentials/credentials.c13
-rw-r--r--auth/credentials/credentials.h3
-rw-r--r--auth/credentials/credentials_ntlm.c55
3 files changed, 65 insertions, 6 deletions
diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c
index 78b59556eae..a9e4fc864d4 100644
--- a/auth/credentials/credentials.c
+++ b/auth/credentials/credentials.c
@@ -496,24 +496,27 @@ _PUBLIC_ bool cli_credentials_set_old_password(struct cli_credentials *cred,
_PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred,
TALLOC_CTX *mem_ctx)
{
- const char *password = cli_credentials_get_password(cred);
+ const char *password = NULL;
- if (password) {
+ if (cred->nt_hash != NULL) {
struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
if (!nt_hash) {
return NULL;
}
- E_md4hash(password, nt_hash->hash);
+ *nt_hash = *cred->nt_hash;
return nt_hash;
- } else if (cred->nt_hash != NULL) {
+ }
+
+ password = cli_credentials_get_password(cred);
+ if (password) {
struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
if (!nt_hash) {
return NULL;
}
- *nt_hash = *cred->nt_hash;
+ E_md4hash(password, nt_hash->hash);
return nt_hash;
}
diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h
index 2da47d2cac3..814f01648b0 100644
--- a/auth/credentials/credentials.h
+++ b/auth/credentials/credentials.h
@@ -191,6 +191,9 @@ enum netr_SchannelType cli_credentials_get_secure_channel_type(struct cli_creden
time_t cli_credentials_get_password_last_changed_time(struct cli_credentials *cred);
void cli_credentials_set_kvno(struct cli_credentials *cred,
int kvno);
+bool cli_credentials_set_utf16_password(struct cli_credentials *cred,
+ const DATA_BLOB *password_utf16,
+ enum credentials_obtained obtained);
bool cli_credentials_set_nt_hash(struct cli_credentials *cred,
const struct samr_Password *nt_hash,
enum credentials_obtained obtained);
diff --git a/auth/credentials/credentials_ntlm.c b/auth/credentials/credentials_ntlm.c
index 8c6be395226..5e9aeeda954 100644
--- a/auth/credentials/credentials_ntlm.c
+++ b/auth/credentials/credentials_ntlm.c
@@ -214,7 +214,60 @@ _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred
}
return NT_STATUS_OK;
}
-
+
+/*
+ * Set a utf16 password on the credentials context, including an indication
+ * of 'how' the password was obtained
+ *
+ * This is required because the nt_hash is calculated over the raw utf16 blob,
+ * which might not be completely valid utf16, which means the conversion
+ * from CH_UTF16MUNGED to CH_UTF8 might loose information.
+ */
+_PUBLIC_ bool cli_credentials_set_utf16_password(struct cli_credentials *cred,
+ const DATA_BLOB *password_utf16,
+ enum credentials_obtained obtained)
+{
+ if (password_utf16 == NULL) {
+ return cli_credentials_set_password(cred, NULL, obtained);
+ }
+
+ if (obtained >= cred->password_obtained) {
+ struct samr_Password *nt_hash = NULL;
+ char *password_talloc = NULL;
+ size_t password_len = 0;
+ bool ok;
+
+ nt_hash = talloc(cred, struct samr_Password);
+ if (nt_hash == NULL) {
+ return false;
+ }
+
+ ok = convert_string_talloc(cred,
+ CH_UTF16MUNGED, CH_UTF8,
+ password_utf16->data,
+ password_utf16->length,
+ (void *)&password_talloc,
+ &password_len);
+ if (!ok) {
+ TALLOC_FREE(nt_hash);
+ return false;
+ }
+
+ ok = cli_credentials_set_password(cred, password_talloc, obtained);
+ TALLOC_FREE(password_talloc);
+ if (!ok) {
+ TALLOC_FREE(nt_hash);
+ return false;
+ }
+
+ mdfour(nt_hash->hash, password_utf16->data, password_utf16->length);
+ cred->nt_hash = nt_hash;
+ return true;
+ }
+
+ return false;
+}
+
_PUBLIC_ bool cli_credentials_set_nt_hash(struct cli_credentials *cred,
const struct samr_Password *nt_hash,
enum credentials_obtained obtained)