aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Seiderer <ps.report@gmx.net>2015-09-17 15:40:12 -0400
committerSteve French <smfrench@gmail.com>2015-09-22 16:24:02 -0400
commit98ce94c8df762d413b3ecb849e2b966b21606d04 (patch)
treeb10f39ddff5668d7c125de9afb0ae0b2b966987f
parente0ddde9d44e37fbc21ce893553094ecf1a633ab5 (diff)
cifs: use server timestamp for ntlmv2 authentication
Linux cifs mount with ntlmssp against an Mac OS X (Yosemite 10.10.5) share fails in case the clocks differ more than +/-2h: digest-service: digest-request: od failed with 2 proto=ntlmv2 digest-service: digest-request: kdc failed with -1561745592 proto=ntlmv2 Fix this by (re-)using the given server timestamp for the ntlmv2 authentication (as Windows 7 does). A related problem was also reported earlier by Namjae Jaen (see below): Windows machine has extended security feature which refuse to allow authentication when there is time difference between server time and client time when ntlmv2 negotiation is used. This problem is prevalent in embedded enviornment where system time is set to default 1970. Modern servers send the server timestamp in the TargetInfo Av_Pair structure in the challenge message [see MS-NLMP 2.2.2.1] In [MS-NLMP 3.1.5.1.2] it is explicitly mentioned that the client must use the server provided timestamp if present OR current time if it is not Reported-by: Namjae Jeon <namjae.jeon@samsung.com> Signed-off-by: Peter Seiderer <ps.report@gmx.net> Signed-off-by: Steve French <smfrench@gmail.com> CC: Stable <stable@vger.kernel.org>
-rw-r--r--fs/cifs/cifsencrypt.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index aa0dc2573374..afa09fce8151 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -444,6 +444,48 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
444 return 0; 444 return 0;
445} 445}
446 446
447/* Server has provided av pairs/target info in the type 2 challenge
448 * packet and we have plucked it and stored within smb session.
449 * We parse that blob here to find the server given timestamp
450 * as part of ntlmv2 authentication (or local current time as
451 * default in case of failure)
452 */
453static __le64
454find_timestamp(struct cifs_ses *ses)
455{
456 unsigned int attrsize;
457 unsigned int type;
458 unsigned int onesize = sizeof(struct ntlmssp2_name);
459 unsigned char *blobptr;
460 unsigned char *blobend;
461 struct ntlmssp2_name *attrptr;
462
463 if (!ses->auth_key.len || !ses->auth_key.response)
464 return 0;
465
466 blobptr = ses->auth_key.response;
467 blobend = blobptr + ses->auth_key.len;
468
469 while (blobptr + onesize < blobend) {
470 attrptr = (struct ntlmssp2_name *) blobptr;
471 type = le16_to_cpu(attrptr->type);
472 if (type == NTLMSSP_AV_EOL)
473 break;
474 blobptr += 2; /* advance attr type */
475 attrsize = le16_to_cpu(attrptr->length);
476 blobptr += 2; /* advance attr size */
477 if (blobptr + attrsize > blobend)
478 break;
479 if (type == NTLMSSP_AV_TIMESTAMP) {
480 if (attrsize == sizeof(u64))
481 return *((__le64 *)blobptr);
482 }
483 blobptr += attrsize; /* advance attr value */
484 }
485
486 return cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
487}
488
447static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, 489static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
448 const struct nls_table *nls_cp) 490 const struct nls_table *nls_cp)
449{ 491{
@@ -641,6 +683,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
641 struct ntlmv2_resp *ntlmv2; 683 struct ntlmv2_resp *ntlmv2;
642 char ntlmv2_hash[16]; 684 char ntlmv2_hash[16];
643 unsigned char *tiblob = NULL; /* target info blob */ 685 unsigned char *tiblob = NULL; /* target info blob */
686 __le64 rsp_timestamp;
644 687
645 if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) { 688 if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
646 if (!ses->domainName) { 689 if (!ses->domainName) {
@@ -659,6 +702,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
659 } 702 }
660 } 703 }
661 704
705 /* Must be within 5 minutes of the server (or in range +/-2h
706 * in case of Mac OS X), so simply carry over server timestamp
707 * (as Windows 7 does)
708 */
709 rsp_timestamp = find_timestamp(ses);
710
662 baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp); 711 baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
663 tilen = ses->auth_key.len; 712 tilen = ses->auth_key.len;
664 tiblob = ses->auth_key.response; 713 tiblob = ses->auth_key.response;
@@ -675,8 +724,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
675 (ses->auth_key.response + CIFS_SESS_KEY_SIZE); 724 (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
676 ntlmv2->blob_signature = cpu_to_le32(0x00000101); 725 ntlmv2->blob_signature = cpu_to_le32(0x00000101);
677 ntlmv2->reserved = 0; 726 ntlmv2->reserved = 0;
678 /* Must be within 5 minutes of the server */ 727 ntlmv2->time = rsp_timestamp;
679 ntlmv2->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 728
680 get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal)); 729 get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
681 ntlmv2->reserved2 = 0; 730 ntlmv2->reserved2 = 0;
682 731