lkml.org 
[lkml]   [2016]   [Apr]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.4 60/92] cifs: use server timestamp for ntlmv2 authentication
    Date
    From: Peter Seiderer <ps.report@gmx.net>

    3.4.112-rc1 review patch. If anyone has any objections, please let me know.

    ------------------


    commit 98ce94c8df762d413b3ecb849e2b966b21606d04 upstream.

    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>
    [lizf: Backported to 3.4: adjust context]
    Signed-off-by: Zefan Li <lizefan@huawei.com>
    ---
    fs/cifs/cifsencrypt.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
    1 file changed, 50 insertions(+), 1 deletion(-)

    diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
    index 6dd3b61..8431216 100644
    --- a/fs/cifs/cifsencrypt.c
    +++ b/fs/cifs/cifsencrypt.c
    @@ -388,6 +388,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 __le64
    +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 *((__le64 *)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)
    {
    @@ -549,6 +591,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
    struct ntlmv2_resp *buf;
    char ntlmv2_hash[16];
    unsigned char *tiblob = NULL; /* target info blob */
    + __le64 rsp_timestamp;

    if (ses->server->secType == RawNTLMSSP) {
    if (!ses->domainName) {
    @@ -566,6 +609,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;
    @@ -583,7 +632,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
    (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
    buf->blob_signature = cpu_to_le32(0x00000101);
    buf->reserved = 0;
    - buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
    + buf->time = rsp_timestamp;
    get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
    buf->reserved2 = 0;

    --
    1.9.1
    \
     
     \ /
      Last update: 2016-04-18 13:21    [W:4.044 / U:0.072 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site