summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/auth/ntlm_check.c167
-rwxr-xr-xsource4/script/tests/test_rpc.sh6
-rw-r--r--source4/torture/rpc/samlogon.c62
3 files changed, 178 insertions, 57 deletions
diff --git a/source4/auth/ntlm_check.c b/source4/auth/ntlm_check.c
index 474742bee0..b308741970 100644
--- a/source4/auth/ntlm_check.c
+++ b/source4/auth/ntlm_check.c
@@ -58,11 +58,6 @@ static BOOL smb_pwd_check_ntlmv1(TALLOC_CTX *mem_ctx,
}
SMBOWFencrypt(part_passwd, sec_blob->data, p24);
- if (user_sess_key != NULL) {
- *user_sess_key = data_blob_talloc(mem_ctx, NULL, 16);
- SMBsesskeygen_ntv1(part_passwd, user_sess_key->data);
- }
-
#if DEBUG_PASSWORD
DEBUG(100,("Part password (P16) was |\n"));
@@ -74,7 +69,14 @@ static BOOL smb_pwd_check_ntlmv1(TALLOC_CTX *mem_ctx,
DEBUGADD(100,("Value from encryption was |\n"));
dump_data(100, p24, 24);
#endif
- return (memcmp(p24, nt_response->data, 24) == 0);
+ if (memcmp(p24, nt_response->data, 24) == 0) {
+ if (user_sess_key != NULL) {
+ *user_sess_key = data_blob_talloc(mem_ctx, NULL, 16);
+ SMBsesskeygen_ntv1(part_passwd, user_sess_key->data);
+ }
+ return True;
+ }
+ return False;
}
/****************************************************************************
@@ -93,7 +95,6 @@ static BOOL smb_pwd_check_ntlmv2(TALLOC_CTX *mem_ctx,
/* Finish the encryption of part_passwd. */
uint8_t kr[16];
uint8_t value_from_encryption[16];
- uint8_t client_response[16];
DATA_BLOB client_key_data;
if (part_passwd == NULL) {
@@ -123,17 +124,11 @@ static BOOL smb_pwd_check_ntlmv2(TALLOC_CTX *mem_ctx,
but for NTLMv2 it is meant to contain the current time etc.
*/
- memcpy(client_response, ntv2_response->data, sizeof(client_response));
-
if (!ntv2_owf_gen(part_passwd, user, domain, upper_case_domain, kr)) {
return False;
}
SMBOWFencrypt_ntv2(kr, sec_blob, &client_key_data, value_from_encryption);
- if (user_sess_key != NULL) {
- *user_sess_key = data_blob_talloc(mem_ctx, NULL, 16);
- SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key->data);
- }
#if DEBUG_PASSWORD
DEBUG(100,("Part password (P16) was |\n"));
@@ -148,7 +143,65 @@ static BOOL smb_pwd_check_ntlmv2(TALLOC_CTX *mem_ctx,
dump_data(100, value_from_encryption, 16);
#endif
data_blob_clear_free(&client_key_data);
- return (memcmp(value_from_encryption, client_response, 16) == 0);
+ if (memcmp(value_from_encryption, ntv2_response->data, 16) == 0) {
+ if (user_sess_key != NULL) {
+ *user_sess_key = data_blob_talloc(mem_ctx, NULL, 16);
+ SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key->data);
+ }
+ return True;
+ }
+ return False;
+}
+
+/****************************************************************************
+ Core of smb password checking routine. (NTLMv2, LMv2)
+ Note: The same code works with both NTLMv2 and LMv2.
+****************************************************************************/
+
+static BOOL smb_sess_key_ntlmv2(TALLOC_CTX *mem_ctx,
+ const DATA_BLOB *ntv2_response,
+ const uint8_t *part_passwd,
+ const DATA_BLOB *sec_blob,
+ const char *user, const char *domain,
+ BOOL upper_case_domain, /* should the domain be transformed into upper case? */
+ DATA_BLOB *user_sess_key)
+{
+ /* Finish the encryption of part_passwd. */
+ uint8_t kr[16];
+ uint8_t value_from_encryption[16];
+ DATA_BLOB client_key_data;
+
+ if (part_passwd == NULL) {
+ DEBUG(10,("No password set - DISALLOWING access\n"));
+ /* No password set - always False */
+ return False;
+ }
+
+ if (sec_blob->length != 8) {
+ DEBUG(0, ("smb_sess_key_ntlmv2: incorrect challenge size (%lu)\n",
+ (unsigned long)sec_blob->length));
+ return False;
+ }
+
+ if (ntv2_response->length < 24) {
+ /* We MUST have more than 16 bytes, or the stuff below will go
+ crazy. No known implementation sends less than the 24 bytes
+ for LMv2, let alone NTLMv2. */
+ DEBUG(0, ("smb_sess_key_ntlmv2: incorrect password length (%lu)\n",
+ (unsigned long)ntv2_response->length));
+ return False;
+ }
+
+ client_key_data = data_blob_talloc(mem_ctx, ntv2_response->data+16, ntv2_response->length-16);
+
+ if (!ntv2_owf_gen(part_passwd, user, domain, upper_case_domain, kr)) {
+ return False;
+ }
+
+ SMBOWFencrypt_ntv2(kr, sec_blob, &client_key_data, value_from_encryption);
+ *user_sess_key = data_blob_talloc(mem_ctx, NULL, 16);
+ SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key->data);
+ return True;
}
/**
@@ -182,6 +235,8 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
DATA_BLOB *lm_sess_key)
{
static const uint8_t zeros[8];
+ DATA_BLOB tmp_sess_key;
+
if (nt_pw == NULL) {
DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n",
username));
@@ -299,7 +354,9 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
user_sess_key)) {
if (lm_sess_key) {
*lm_sess_key = *user_sess_key;
- lm_sess_key->length = 8;
+ if (user_sess_key->length) {
+ lm_sess_key->length = 8;
+ }
}
return NT_STATUS_OK;
}
@@ -314,7 +371,9 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
user_sess_key)) {
if (lm_sess_key) {
*lm_sess_key = *user_sess_key;
- lm_sess_key->length = 8;
+ if (user_sess_key->length) {
+ lm_sess_key->length = 8;
+ }
}
return NT_STATUS_OK;
}
@@ -329,7 +388,9 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
user_sess_key)) {
if (lm_sess_key) {
*lm_sess_key = *user_sess_key;
- lm_sess_key->length = 8;
+ if (user_sess_key->length) {
+ lm_sess_key->length = 8;
+ }
}
return NT_STATUS_OK;
} else {
@@ -418,10 +479,28 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
client_username,
client_domain,
False,
- user_sess_key)) {
- if (lm_sess_key) {
+ &tmp_sess_key)) {
+ if (nt_response->length > 24) {
+ /* If NTLMv2 authentication has preceeded us
+ * (even if it failed), then use the session
+ * key from that. See the RPC-SAMLOGON
+ * torture test */
+ smb_sess_key_ntlmv2(mem_ctx,
+ nt_response,
+ nt_pw, challenge,
+ client_username,
+ client_domain,
+ False,
+ user_sess_key);
+ } else if (user_sess_key) {
+ /* Otherwise, use the LMv2 session key */
+ *user_sess_key = tmp_sess_key;
+ }
+ if (user_sess_key && lm_sess_key) {
*lm_sess_key = *user_sess_key;
- lm_sess_key->length = 8;
+ if (user_sess_key->length) {
+ lm_sess_key->length = 8;
+ }
}
return NT_STATUS_OK;
}
@@ -433,10 +512,28 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
client_username,
client_domain,
True,
- user_sess_key)) {
- if (lm_sess_key) {
+ &tmp_sess_key)) {
+ if (nt_response->length > 24) {
+ /* If NTLMv2 authentication has preceeded us
+ * (even if it failed), then use the session
+ * key from that. See the RPC-SAMLOGON
+ * torture test */
+ smb_sess_key_ntlmv2(mem_ctx,
+ nt_response,
+ nt_pw, challenge,
+ client_username,
+ client_domain,
+ True,
+ user_sess_key);
+ } else if (user_sess_key) {
+ /* Otherwise, use the LMv2 session key */
+ *user_sess_key = tmp_sess_key;
+ }
+ if (user_sess_key && lm_sess_key) {
*lm_sess_key = *user_sess_key;
- lm_sess_key->length = 8;
+ if (user_sess_key->length) {
+ lm_sess_key->length = 8;
+ }
}
return NT_STATUS_OK;
}
@@ -448,10 +545,28 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
client_username,
"",
False,
- user_sess_key)) {
- if (lm_sess_key) {
+ &tmp_sess_key)) {
+ if (nt_response->length > 24) {
+ /* If NTLMv2 authentication has preceeded us
+ * (even if it failed), then use the session
+ * key from that. See the RPC-SAMLOGON
+ * torture test */
+ smb_sess_key_ntlmv2(mem_ctx,
+ nt_response,
+ nt_pw, challenge,
+ client_username,
+ "",
+ False,
+ user_sess_key);
+ } else if (user_sess_key) {
+ /* Otherwise, use the LMv2 session key */
+ *user_sess_key = tmp_sess_key;
+ }
+ if (user_sess_key && lm_sess_key) {
*lm_sess_key = *user_sess_key;
- lm_sess_key->length = 8;
+ if (user_sess_key->length) {
+ lm_sess_key->length = 8;
+ }
}
return NT_STATUS_OK;
}
diff --git a/source4/script/tests/test_rpc.sh b/source4/script/tests/test_rpc.sh
index a1181cab42..c15ce87b05 100755
--- a/source4/script/tests/test_rpc.sh
+++ b/source4/script/tests/test_rpc.sh
@@ -2,9 +2,9 @@
# add tests to this list as they start passing, so we test
# that they stay passing
-ncacn_np_tests="RPC-SCHANNEL RPC-ECHO RPC-DSSETUP"
-ncalrpc_tests="RPC-SCHANNEL RPC-ECHO RPC-DSSETUP"
-ncacn_ip_tcp_tests="RPC-SCHANNEL RPC-ECHO"
+ncacn_np_tests="RPC-SCHANNEL RPC-ECHO RPC-DSSETUP RPC-SAMLOGON"
+ncalrpc_tests="RPC-SCHANNEL RPC-ECHO RPC-DSSETUP RPC-SAMLOGON"
+ncacn_ip_tcp_tests="RPC-SCHANNEL RPC-ECHO RPC-SAMLOGON"
if [ $# -lt 4 ]; then
cat <<EOF
diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c
index 0c5afd44fe..7e5579b213 100644
--- a/source4/torture/rpc/samlogon.c
+++ b/source4/torture/rpc/samlogon.c
@@ -582,7 +582,7 @@ static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum
switch (break_which) {
case NO_NT:
- if (memcmp(lmv2_session_key.data, user_session_key,
+ if (memcmp(lmv2_session_key.data, user_session_key,
sizeof(user_session_key)) != 0) {
printf("USER (LMv2) Session Key does not match expectations!\n");
printf("user_session_key:\n");
@@ -604,21 +604,42 @@ static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum
default:
if (memcmp(ntlmv2_session_key.data, user_session_key,
sizeof(user_session_key)) != 0) {
- printf("USER (NTLMv2) Session Key does not match expectations!\n");
- printf("user_session_key:\n");
- dump_data(1, user_session_key, 16);
- printf("expected:\n");
- dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
- pass = False;
+ if (memcmp(lmv2_session_key.data, user_session_key,
+ sizeof(user_session_key)) == 0) {
+ printf("USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
+ printf("user_session_key:\n");
+ dump_data(1, user_session_key, 16);
+ printf("expected:\n");
+ dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
+ pass = False;
+
+ } else {
+ printf("USER (NTLMv2) Session Key does not match expectations!\n");
+ printf("user_session_key:\n");
+ dump_data(1, user_session_key, 16);
+ printf("expected:\n");
+ dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
+ pass = False;
+ }
}
if (memcmp(ntlmv2_session_key.data, lm_session_key,
sizeof(lm_session_key)) != 0) {
- printf("LM (NTLMv2) Session Key does not match expectations!\n");
- printf("lm_session_key:\n");
- dump_data(1, lm_session_key, 8);
- printf("expected:\n");
- dump_data(1, ntlmv2_session_key.data, 8);
- pass = False;
+ if (memcmp(lmv2_session_key.data, lm_session_key,
+ sizeof(lm_session_key)) == 0) {
+ printf("LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
+ printf("user_session_key:\n");
+ dump_data(1, lm_session_key, 8);
+ printf("expected:\n");
+ dump_data(1, ntlmv2_session_key.data, 8);
+ pass = False;
+ } else {
+ printf("LM (NTLMv2) Session Key does not match expectations!\n");
+ printf("lm_session_key:\n");
+ dump_data(1, lm_session_key, 8);
+ printf("expected:\n");
+ dump_data(1, ntlmv2_session_key.data, 8);
+ pass = False;
+ }
}
}
@@ -1267,21 +1288,6 @@ BOOL torture_rpc_samlogon(void)
}
}
- for (i=0; i < 32; i++) {
- if (!test_SetupCredentials2(p, mem_ctx, 1 << i,
- TEST_MACHINE_NAME, machine_password, creds)) {
- return False;
- }
-
- if (!test_InteractiveLogon(p, mem_ctx, creds)) {
- ret = False;
- }
-
- if (!test_SamLogon(p, mem_ctx, creds)) {
- ret = False;
- }
- }
-
failed:
talloc_destroy(mem_ctx);