Nice catch. Merged into cifs-2.6.git for next > On Sep 17, 2015, at 2:40 PM, Peter Seiderer <ps.report@xxxxxxx> wrote: > > 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). > > Signed-off-by: Peter Seiderer <ps.report@xxxxxxx> > --- > fs/cifs/cifsencrypt.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 51 insertions(+), 2 deletions(-) > > diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c > index aa0dc25..e6bfa92 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) > return 0; > } > > +/* Server has provided av pairs/target info in the type 2 challenge > + * packet and we have plucked it and stored within smb session. > + * We parse that blob here to find the server given timestamp > + * as part of ntlmv2 authentication (or local current time as > + * default in case of failure) > + */ > +static u64 > +find_timestamp(struct cifs_ses *ses) > +{ > + unsigned int attrsize; > + unsigned int type; > + unsigned int onesize = sizeof(struct ntlmssp2_name); > + unsigned char *blobptr; > + unsigned char *blobend; > + struct ntlmssp2_name *attrptr; > + > + if (!ses->auth_key.len || !ses->auth_key.response) > + return 0; > + > + blobptr = ses->auth_key.response; > + blobend = blobptr + ses->auth_key.len; > + > + while (blobptr + onesize < blobend) { > + attrptr = (struct ntlmssp2_name *) blobptr; > + type = le16_to_cpu(attrptr->type); > + if (type == NTLMSSP_AV_EOL) > + break; > + blobptr += 2; /* advance attr type */ > + attrsize = le16_to_cpu(attrptr->length); > + blobptr += 2; /* advance attr size */ > + if (blobptr + attrsize > blobend) > + break; > + if (type == NTLMSSP_AV_TIMESTAMP) { > + if (attrsize == sizeof(u64)) > + return *((u64 *)blobptr); > + } > + blobptr += attrsize; /* advance attr value */ > + } > + > + return cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); > +} > + > static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, > const struct nls_table *nls_cp) > { > @@ -641,6 +683,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) > struct ntlmv2_resp *ntlmv2; > char ntlmv2_hash[16]; > unsigned char *tiblob = NULL; /* target info blob */ > + u64 rsp_timestamp; > > if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) { > if (!ses->domainName) { > @@ -659,6 +702,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) > } > } > > + /* Must be within 5 minutes of the server (or in range +/-2h > + * in case of Mac OS X), so simply carry over server timestamp > + * (as Windows 7 does) > + */ > + rsp_timestamp = find_timestamp(ses); > + > baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp); > tilen = ses->auth_key.len; > tiblob = ses->auth_key.response; > @@ -675,8 +724,8 @@ 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)); > + ntlmv2->time = rsp_timestamp; > + > get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal)); > ntlmv2->reserved2 = 0; > > -- > 2.1.4 > -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html