@@ -671,8 +671,10 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
(ses->auth_key.response + CIFS_SESS_KEY_SIZE);
ntlmv2->blob_signature = cpu_to_le32(0x00000101);
ntlmv2->reserved = 0;
- /* Must be within 5 minutes of the server */
- ntlmv2->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+ if (ses->serverTime)
+ ntlmv2->time = ses->serverTime;
+ else
+ ntlmv2->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
ntlmv2->reserved2 = 0;
@@ -796,6 +796,8 @@ struct cifs_ses {
enum securityEnum sectype; /* what security flavor was specified? */
bool sign; /* is signing required? */
bool need_reconnect:1; /* connection reset, uid now invalid */
+ __u64 serverTime; /* Keeps a track of server time sent by server
+ during NTLM challenge in little endian */
#ifdef CONFIG_CIFS_SMB2
__u16 session_flags;
char smb3signingkey[SMB3_SIGN_KEY_SIZE]; /* for signing smb3 packets */
@@ -277,6 +277,24 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
cifs_dbg(FYI, "ascii: bytes left %d\n", bleft);
}
+static void
+get_ntlmv2_server_time(struct cifs_ses *ses)
+{
+ char *payload = ses->auth_key.response;
+ u16 AvId, AvLen;
+
+ do {
+ AvId = le16_to_cpu(*payload);
+ AvLen = le16_to_cpu(*(payload + sizeof(u16)));
+ payload += AvLen + (2 * sizeof(u16));
+ } while (AvId != NTLMSSP_AV_TIMESTAMP && AvId != NTLMSSP_AV_EOL);
+
+ if (AvId == NTLMSSP_AV_TIMESTAMP)
+ memcpy(&(ses->serverTime), (payload - AvLen), sizeof(__u64));
+ else
+ ses->serverTime = 0;
+}
+
int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
struct cifs_ses *ses)
{
@@ -322,6 +340,7 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
return -ENOMEM;
}
ses->auth_key.len = tilen;
+ get_ntlmv2_server_time(ses);
}
return 0;