Message ID | 1398948065-23265-3-git-send-email-sprabhu@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, May 1, 2014 at 7:41 AM, Sachin Prabhu <sprabhu@redhat.com> wrote: > Signed-off-by: Sachin Prabhu <sprabhu@redhat.com> > --- > fs/cifs/sess.c | 318 ++++++++++++++++++++++++++++++++++++++++++--------------- > 1 file changed, 233 insertions(+), 85 deletions(-) > > diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c > index 6559deb..661b67d 100644 > --- a/fs/cifs/sess.c > +++ b/fs/cifs/sess.c > @@ -767,6 +767,216 @@ sess_auth_lanman(struct sess_data *sess_data) > } > #endif > > +static void > +sess_auth_ntlm(struct sess_data *sess_data) > +{ > + int rc = 0; > + struct smb_hdr *smb_buf; > + SESSION_SETUP_ANDX *pSMB; > + char *bcc_ptr; > + struct cifs_ses *ses = sess_data->ses; > + __u32 capabilities; > + __u16 bytes_remaining; > + > + /* old style NTLM sessionsetup */ > + /* wct = 13 */ > + rc = sess_alloc_buffer(sess_data, 13); > + if (rc) > + goto out; > + > + pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; > + bcc_ptr = sess_data->iov[2].iov_base; > + capabilities = cifs_ssetup_hdr(ses, pSMB); > + > + pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); > + pSMB->req_no_secext.CaseInsensitivePasswordLength = > + cpu_to_le16(CIFS_AUTH_RESP_SIZE); > + pSMB->req_no_secext.CaseSensitivePasswordLength = > + cpu_to_le16(CIFS_AUTH_RESP_SIZE); > + > + /* calculate ntlm response and session key */ > + rc = setup_ntlm_response(ses, sess_data->nls_cp); > + if (rc) { > + cifs_dbg(VFS, "Error %d during NTLM authentication\n", > + rc); > + goto out; > + } > + > + /* copy ntlm response */ > + memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, > + CIFS_AUTH_RESP_SIZE); > + bcc_ptr += CIFS_AUTH_RESP_SIZE; > + memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, > + CIFS_AUTH_RESP_SIZE); > + bcc_ptr += CIFS_AUTH_RESP_SIZE; > + > + if (ses->capabilities & CAP_UNICODE) { > + /* unicode strings must be word aligned */ > + if (sess_data->iov[0].iov_len % 2) { > + *bcc_ptr = 0; > + bcc_ptr++; > + } > + unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp); > + } else { > + ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp); > + } > + > + > + sess_data->iov[2].iov_len = (long) bcc_ptr - > + (long) sess_data->iov[2].iov_base; > + > + rc = sess_sendreceive(sess_data); > + if (rc) > + goto out; > + > + pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; > + smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base; > + > + if (smb_buf->WordCount != 3) { > + rc = -EIO; > + cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount); > + goto out; > + } > + > + if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN) > + cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */ > + > + ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */ > + cifs_dbg(FYI, "UID = %llu\n", ses->Suid); > + > + bytes_remaining = get_bcc(smb_buf); > + bcc_ptr = pByteArea(smb_buf); > + > + /* BB check if Unicode and decode strings */ > + if (bytes_remaining == 0) { > + /* no string area to decode, do nothing */ > + } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { > + /* unicode string area must be word-aligned */ > + if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { > + ++bcc_ptr; > + --bytes_remaining; > + } > + decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, > + sess_data->nls_cp); > + } else { > + decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses, > + sess_data->nls_cp); > + } > + > +out: > + sess_data->result = rc; > + sess_data->func = NULL; > + sess_free_buffer(sess_data); > + sess_establish_session(sess_data); > + kfree(ses->auth_key.response); > + ses->auth_key.response = NULL; > +} > + > +static void > +sess_auth_ntlmv2(struct sess_data *sess_data) > +{ > + int rc = 0; > + struct smb_hdr *smb_buf; > + SESSION_SETUP_ANDX *pSMB; > + char *bcc_ptr; > + struct cifs_ses *ses = sess_data->ses; > + __u32 capabilities; > + __u16 bytes_remaining; > + > + /* old style NTLM sessionsetup */ > + /* wct = 13 */ > + rc = sess_alloc_buffer(sess_data, 13); > + if (rc) > + goto out; > + > + pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; > + bcc_ptr = sess_data->iov[2].iov_base; > + capabilities = cifs_ssetup_hdr(ses, pSMB); > + > + pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); > + > + /* LM2 password would be here if we supported it */ > + pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; > + > + /* calculate nlmv2 response and session key */ > + rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp); > + if (rc) { > + cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc); > + goto out; > + } > + > + memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, > + ses->auth_key.len - CIFS_SESS_KEY_SIZE); > + bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE; > + > + /* set case sensitive password length after tilen may get > + * assigned, tilen is 0 otherwise. > + */ > + pSMB->req_no_secext.CaseSensitivePasswordLength = > + cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); > + > + if (ses->capabilities & CAP_UNICODE) { > + if (sess_data->iov[0].iov_len % 2) { > + *bcc_ptr = 0; > + bcc_ptr++; > + } > + unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp); > + } else { > + ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp); > + } > + > + > + sess_data->iov[2].iov_len = (long) bcc_ptr - > + (long) sess_data->iov[2].iov_base; > + > + rc = sess_sendreceive(sess_data); > + if (rc) > + goto out; > + > + pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; > + smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base; > + > + if (smb_buf->WordCount != 3) { > + rc = -EIO; > + cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount); > + goto out; > + } > + > + if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN) > + cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */ > + > + ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */ > + cifs_dbg(FYI, "UID = %llu\n", ses->Suid); > + > + bytes_remaining = get_bcc(smb_buf); > + bcc_ptr = pByteArea(smb_buf); > + > + /* BB check if Unicode and decode strings */ > + if (bytes_remaining == 0) { > + /* no string area to decode, do nothing */ > + } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { > + /* unicode string area must be word-aligned */ > + if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { > + ++bcc_ptr; > + --bytes_remaining; > + } > + decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, > + sess_data->nls_cp); > + } else { > + decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses, > + sess_data->nls_cp); > + } > + > +out: > + sess_data->result = rc; > + sess_data->func = NULL; > + sess_free_buffer(sess_data); > + sess_establish_session(sess_data); > + kfree(ses->auth_key.response); > + ses->auth_key.response = NULL; > +} In all three sess_auth_* functions (ntlm, ntlmv2, and lanman (in previous patch), we will end up calling sess_establish_session() even if there is an error i.e. sess_data->result is not 0. > + > + > int > CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, > const struct nls_table *nls_cp) > @@ -813,6 +1023,12 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, > case LANMAN: > sess_auth_lanman(sess_data); > goto out; > + case NTLM: > + sess_auth_ntlm(sess_data); > + goto out; > + case NTLMv2: > + sess_auth_ntlmv2(sess_data); > + goto out; > default: > /* Continue with the rest of the function */ > break; > @@ -833,11 +1049,8 @@ ssetup_ntlmssp_authenticate: > if (phase == NtLmChallenge) > phase = NtLmAuthenticate; /* if ntlmssp, now final phase */ > > - if ((type == NTLM) || (type == NTLMv2)) { > - /* For NTLMv2 failures eventually may need to retry NTLM */ > - wct = 13; /* old style NTLM sessionsetup */ > - } else /* same size: negotiate or auth, NTLMSSP or extended security */ > - wct = 12; > + /* same size: negotiate or auth, NTLMSSP or extended security */ > + wct = 12; > > rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses, > (void **)&smb_buf); > @@ -872,70 +1085,7 @@ ssetup_ntlmssp_authenticate: > iov[1].iov_base = NULL; > iov[1].iov_len = 0; > > - if (type == NTLM) { > - pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); > - pSMB->req_no_secext.CaseInsensitivePasswordLength = > - cpu_to_le16(CIFS_AUTH_RESP_SIZE); > - pSMB->req_no_secext.CaseSensitivePasswordLength = > - cpu_to_le16(CIFS_AUTH_RESP_SIZE); > - > - /* calculate ntlm response and session key */ > - rc = setup_ntlm_response(ses, nls_cp); > - if (rc) { > - cifs_dbg(VFS, "Error %d during NTLM authentication\n", > - rc); > - goto ssetup_exit; > - } > - > - /* copy ntlm response */ > - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, > - CIFS_AUTH_RESP_SIZE); > - bcc_ptr += CIFS_AUTH_RESP_SIZE; > - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, > - CIFS_AUTH_RESP_SIZE); > - bcc_ptr += CIFS_AUTH_RESP_SIZE; > - > - if (ses->capabilities & CAP_UNICODE) { > - /* unicode strings must be word aligned */ > - if (iov[0].iov_len % 2) { > - *bcc_ptr = 0; > - bcc_ptr++; > - } > - unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); > - } else > - ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); > - } else if (type == NTLMv2) { > - pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); > - > - /* LM2 password would be here if we supported it */ > - pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; > - > - /* calculate nlmv2 response and session key */ > - rc = setup_ntlmv2_rsp(ses, nls_cp); > - if (rc) { > - cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", > - rc); > - goto ssetup_exit; > - } > - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, > - ses->auth_key.len - CIFS_SESS_KEY_SIZE); > - bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE; > - > - /* set case sensitive password length after tilen may get > - * assigned, tilen is 0 otherwise. > - */ > - pSMB->req_no_secext.CaseSensitivePasswordLength = > - cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); > - > - if (ses->capabilities & CAP_UNICODE) { > - if (iov[0].iov_len % 2) { > - *bcc_ptr = 0; > - bcc_ptr++; > - } > - unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); > - } else > - ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); > - } else if (type == Kerberos) { > + if (type == Kerberos) { > #ifdef CONFIG_CIFS_UPCALL > struct cifs_spnego_msg *msg; > > @@ -1086,7 +1236,7 @@ ssetup_ntlmssp_authenticate: > if (rc) > goto ssetup_exit; > > - if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) { > + if (smb_buf->WordCount != 4) { > rc = -EIO; > cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount); > goto ssetup_exit; > @@ -1101,23 +1251,21 @@ ssetup_ntlmssp_authenticate: > bytes_remaining = get_bcc(smb_buf); > bcc_ptr = pByteArea(smb_buf); > > - if (smb_buf->WordCount == 4) { > - blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); > - if (blob_len > bytes_remaining) { > - cifs_dbg(VFS, "bad security blob length %d\n", > - blob_len); > - rc = -EINVAL; > + blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); > + if (blob_len > bytes_remaining) { > + cifs_dbg(VFS, "bad security blob length %d\n", > + blob_len); > + rc = -EINVAL; > + goto ssetup_exit; > + } > + if (phase == NtLmChallenge) { > + rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses); > + /* now goto beginning for ntlmssp authenticate phase */ I think this comment should move to after if statement (it was at wrong place to begin with) i.e. go to authenticate phase only if rc is NULL. > + if (rc) > goto ssetup_exit; > - } > - if (phase == NtLmChallenge) { > - rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses); > - /* now goto beginning for ntlmssp authenticate phase */ > - if (rc) > - goto ssetup_exit; > - } > - bcc_ptr += blob_len; > - bytes_remaining -= blob_len; > } > + bcc_ptr += blob_len; > + bytes_remaining -= blob_len; > > /* BB check if Unicode and decode strings */ > if (bytes_remaining == 0) { > -- > 1.8.4.2 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-cifs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, 2014-05-01 at 10:31 -0500, Shirish Pargaonkar wrote: > > + > > +out: > > + sess_data->result = rc; > > + sess_data->func = NULL; > > + sess_free_buffer(sess_data); > > + sess_establish_session(sess_data); > > + kfree(ses->auth_key.response); > > + ses->auth_key.response = NULL; > > +} > > In all three sess_auth_* functions (ntlm, ntlmv2, and lanman (in > previous patch), > we will end up calling sess_establish_session() even if there is an error i.e. > sess_data->result is not 0. We check for any errors within sess_establish_session() before we attempt to establish session. static int sess_establish_session(struct sess_data *sess_data) { .. if (!sess_data->result) { //Establish Session. } .. } This isn't a technical issue but maybe considered a style issue. > > + if (phase == NtLmChallenge) { > > + rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses); > > + /* now goto beginning for ntlmssp authenticate phase */ > > I think this comment should move to after if statement > (it was at wrong place to begin with) i.e. go to authenticate phase > only if rc is NULL. I agree. The comment is actually not required. Sachin Prabhu -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, May 1, 2014 at 11:26 AM, Sachin Prabhu <sprabhu@redhat.com> wrote: > On Thu, 2014-05-01 at 10:31 -0500, Shirish Pargaonkar wrote: > >> > + >> > +out: >> > + sess_data->result = rc; >> > + sess_data->func = NULL; >> > + sess_free_buffer(sess_data); >> > + sess_establish_session(sess_data); >> > + kfree(ses->auth_key.response); >> > + ses->auth_key.response = NULL; >> > +} >> >> In all three sess_auth_* functions (ntlm, ntlmv2, and lanman (in >> previous patch), >> we will end up calling sess_establish_session() even if there is an error i.e. >> sess_data->result is not 0. > > We check for any errors within sess_establish_session() before we > attempt to establish session. > > static int > sess_establish_session(struct sess_data *sess_data) > { > .. > if (!sess_data->result) { > //Establish Session. > } > .. > } > > This isn't a technical issue but maybe considered a style issue. Sure, would have preferred to call the function before goto lables, but will leave at that. > > >> > + if (phase == NtLmChallenge) { >> > + rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses); >> > + /* now goto beginning for ntlmssp authenticate phase */ >> >> I think this comment should move to after if statement >> (it was at wrong place to begin with) i.e. go to authenticate phase >> only if rc is NULL. > > I agree. The comment is actually not required. > > Sachin Prabhu > -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, 2014-05-01 at 15:01 -0500, Shirish Pargaonkar wrote: > On Thu, May 1, 2014 at 11:26 AM, Sachin Prabhu <sprabhu@redhat.com> wrote: > > On Thu, 2014-05-01 at 10:31 -0500, Shirish Pargaonkar wrote: > > > >> > + > >> > +out: > >> > + sess_data->result = rc; > >> > + sess_data->func = NULL; > >> > + sess_free_buffer(sess_data); > >> > + sess_establish_session(sess_data); > >> > + kfree(ses->auth_key.response); > >> > + ses->auth_key.response = NULL; > >> > +} > >> > >> In all three sess_auth_* functions (ntlm, ntlmv2, and lanman (in > >> previous patch), > >> we will end up calling sess_establish_session() even if there is an error i.e. > >> sess_data->result is not 0. > > > > We check for any errors within sess_establish_session() before we > > attempt to establish session. > > > > static int > > sess_establish_session(struct sess_data *sess_data) > > { > > .. > > if (!sess_data->result) { > > //Establish Session. > > } > > .. > > } > > > > This isn't a technical issue but maybe considered a style issue. > > Sure, would have preferred to call the function before goto lables, but will > leave at that. > Having given it another thought, I agree with you. I've made the required modifications and tested the new patches. I'll send them to the list shortly. Sachin Prabhu > > > > > >> > + if (phase == NtLmChallenge) { > >> > + rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses); > >> > + /* now goto beginning for ntlmssp authenticate phase */ > >> > >> I think this comment should move to after if statement > >> (it was at wrong place to begin with) i.e. go to authenticate phase > >> only if rc is NULL. > > > > I agree. The comment is actually not required. > > > > Sachin Prabhu > > -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 6559deb..661b67d 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -767,6 +767,216 @@ sess_auth_lanman(struct sess_data *sess_data) } #endif +static void +sess_auth_ntlm(struct sess_data *sess_data) +{ + int rc = 0; + struct smb_hdr *smb_buf; + SESSION_SETUP_ANDX *pSMB; + char *bcc_ptr; + struct cifs_ses *ses = sess_data->ses; + __u32 capabilities; + __u16 bytes_remaining; + + /* old style NTLM sessionsetup */ + /* wct = 13 */ + rc = sess_alloc_buffer(sess_data, 13); + if (rc) + goto out; + + pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; + bcc_ptr = sess_data->iov[2].iov_base; + capabilities = cifs_ssetup_hdr(ses, pSMB); + + pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); + pSMB->req_no_secext.CaseInsensitivePasswordLength = + cpu_to_le16(CIFS_AUTH_RESP_SIZE); + pSMB->req_no_secext.CaseSensitivePasswordLength = + cpu_to_le16(CIFS_AUTH_RESP_SIZE); + + /* calculate ntlm response and session key */ + rc = setup_ntlm_response(ses, sess_data->nls_cp); + if (rc) { + cifs_dbg(VFS, "Error %d during NTLM authentication\n", + rc); + goto out; + } + + /* copy ntlm response */ + memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, + CIFS_AUTH_RESP_SIZE); + bcc_ptr += CIFS_AUTH_RESP_SIZE; + memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, + CIFS_AUTH_RESP_SIZE); + bcc_ptr += CIFS_AUTH_RESP_SIZE; + + if (ses->capabilities & CAP_UNICODE) { + /* unicode strings must be word aligned */ + if (sess_data->iov[0].iov_len % 2) { + *bcc_ptr = 0; + bcc_ptr++; + } + unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp); + } else { + ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp); + } + + + sess_data->iov[2].iov_len = (long) bcc_ptr - + (long) sess_data->iov[2].iov_base; + + rc = sess_sendreceive(sess_data); + if (rc) + goto out; + + pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; + smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base; + + if (smb_buf->WordCount != 3) { + rc = -EIO; + cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount); + goto out; + } + + if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN) + cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */ + + ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */ + cifs_dbg(FYI, "UID = %llu\n", ses->Suid); + + bytes_remaining = get_bcc(smb_buf); + bcc_ptr = pByteArea(smb_buf); + + /* BB check if Unicode and decode strings */ + if (bytes_remaining == 0) { + /* no string area to decode, do nothing */ + } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { + /* unicode string area must be word-aligned */ + if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { + ++bcc_ptr; + --bytes_remaining; + } + decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, + sess_data->nls_cp); + } else { + decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses, + sess_data->nls_cp); + } + +out: + sess_data->result = rc; + sess_data->func = NULL; + sess_free_buffer(sess_data); + sess_establish_session(sess_data); + kfree(ses->auth_key.response); + ses->auth_key.response = NULL; +} + +static void +sess_auth_ntlmv2(struct sess_data *sess_data) +{ + int rc = 0; + struct smb_hdr *smb_buf; + SESSION_SETUP_ANDX *pSMB; + char *bcc_ptr; + struct cifs_ses *ses = sess_data->ses; + __u32 capabilities; + __u16 bytes_remaining; + + /* old style NTLM sessionsetup */ + /* wct = 13 */ + rc = sess_alloc_buffer(sess_data, 13); + if (rc) + goto out; + + pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; + bcc_ptr = sess_data->iov[2].iov_base; + capabilities = cifs_ssetup_hdr(ses, pSMB); + + pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); + + /* LM2 password would be here if we supported it */ + pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; + + /* calculate nlmv2 response and session key */ + rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp); + if (rc) { + cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc); + goto out; + } + + memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, + ses->auth_key.len - CIFS_SESS_KEY_SIZE); + bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE; + + /* set case sensitive password length after tilen may get + * assigned, tilen is 0 otherwise. + */ + pSMB->req_no_secext.CaseSensitivePasswordLength = + cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); + + if (ses->capabilities & CAP_UNICODE) { + if (sess_data->iov[0].iov_len % 2) { + *bcc_ptr = 0; + bcc_ptr++; + } + unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp); + } else { + ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp); + } + + + sess_data->iov[2].iov_len = (long) bcc_ptr - + (long) sess_data->iov[2].iov_base; + + rc = sess_sendreceive(sess_data); + if (rc) + goto out; + + pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; + smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base; + + if (smb_buf->WordCount != 3) { + rc = -EIO; + cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount); + goto out; + } + + if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN) + cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */ + + ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */ + cifs_dbg(FYI, "UID = %llu\n", ses->Suid); + + bytes_remaining = get_bcc(smb_buf); + bcc_ptr = pByteArea(smb_buf); + + /* BB check if Unicode and decode strings */ + if (bytes_remaining == 0) { + /* no string area to decode, do nothing */ + } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { + /* unicode string area must be word-aligned */ + if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { + ++bcc_ptr; + --bytes_remaining; + } + decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, + sess_data->nls_cp); + } else { + decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses, + sess_data->nls_cp); + } + +out: + sess_data->result = rc; + sess_data->func = NULL; + sess_free_buffer(sess_data); + sess_establish_session(sess_data); + kfree(ses->auth_key.response); + ses->auth_key.response = NULL; +} + + int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, const struct nls_table *nls_cp) @@ -813,6 +1023,12 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses, case LANMAN: sess_auth_lanman(sess_data); goto out; + case NTLM: + sess_auth_ntlm(sess_data); + goto out; + case NTLMv2: + sess_auth_ntlmv2(sess_data); + goto out; default: /* Continue with the rest of the function */ break; @@ -833,11 +1049,8 @@ ssetup_ntlmssp_authenticate: if (phase == NtLmChallenge) phase = NtLmAuthenticate; /* if ntlmssp, now final phase */ - if ((type == NTLM) || (type == NTLMv2)) { - /* For NTLMv2 failures eventually may need to retry NTLM */ - wct = 13; /* old style NTLM sessionsetup */ - } else /* same size: negotiate or auth, NTLMSSP or extended security */ - wct = 12; + /* same size: negotiate or auth, NTLMSSP or extended security */ + wct = 12; rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses, (void **)&smb_buf); @@ -872,70 +1085,7 @@ ssetup_ntlmssp_authenticate: iov[1].iov_base = NULL; iov[1].iov_len = 0; - if (type == NTLM) { - pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); - pSMB->req_no_secext.CaseInsensitivePasswordLength = - cpu_to_le16(CIFS_AUTH_RESP_SIZE); - pSMB->req_no_secext.CaseSensitivePasswordLength = - cpu_to_le16(CIFS_AUTH_RESP_SIZE); - - /* calculate ntlm response and session key */ - rc = setup_ntlm_response(ses, nls_cp); - if (rc) { - cifs_dbg(VFS, "Error %d during NTLM authentication\n", - rc); - goto ssetup_exit; - } - - /* copy ntlm response */ - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, - CIFS_AUTH_RESP_SIZE); - bcc_ptr += CIFS_AUTH_RESP_SIZE; - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, - CIFS_AUTH_RESP_SIZE); - bcc_ptr += CIFS_AUTH_RESP_SIZE; - - if (ses->capabilities & CAP_UNICODE) { - /* unicode strings must be word aligned */ - if (iov[0].iov_len % 2) { - *bcc_ptr = 0; - bcc_ptr++; - } - unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); - } else - ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); - } else if (type == NTLMv2) { - pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); - - /* LM2 password would be here if we supported it */ - pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; - - /* calculate nlmv2 response and session key */ - rc = setup_ntlmv2_rsp(ses, nls_cp); - if (rc) { - cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", - rc); - goto ssetup_exit; - } - memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE, - ses->auth_key.len - CIFS_SESS_KEY_SIZE); - bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE; - - /* set case sensitive password length after tilen may get - * assigned, tilen is 0 otherwise. - */ - pSMB->req_no_secext.CaseSensitivePasswordLength = - cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE); - - if (ses->capabilities & CAP_UNICODE) { - if (iov[0].iov_len % 2) { - *bcc_ptr = 0; - bcc_ptr++; - } - unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); - } else - ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); - } else if (type == Kerberos) { + if (type == Kerberos) { #ifdef CONFIG_CIFS_UPCALL struct cifs_spnego_msg *msg; @@ -1086,7 +1236,7 @@ ssetup_ntlmssp_authenticate: if (rc) goto ssetup_exit; - if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) { + if (smb_buf->WordCount != 4) { rc = -EIO; cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount); goto ssetup_exit; @@ -1101,23 +1251,21 @@ ssetup_ntlmssp_authenticate: bytes_remaining = get_bcc(smb_buf); bcc_ptr = pByteArea(smb_buf); - if (smb_buf->WordCount == 4) { - blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); - if (blob_len > bytes_remaining) { - cifs_dbg(VFS, "bad security blob length %d\n", - blob_len); - rc = -EINVAL; + blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); + if (blob_len > bytes_remaining) { + cifs_dbg(VFS, "bad security blob length %d\n", + blob_len); + rc = -EINVAL; + goto ssetup_exit; + } + if (phase == NtLmChallenge) { + rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses); + /* now goto beginning for ntlmssp authenticate phase */ + if (rc) goto ssetup_exit; - } - if (phase == NtLmChallenge) { - rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses); - /* now goto beginning for ntlmssp authenticate phase */ - if (rc) - goto ssetup_exit; - } - bcc_ptr += blob_len; - bytes_remaining -= blob_len; } + bcc_ptr += blob_len; + bytes_remaining -= blob_len; /* BB check if Unicode and decode strings */ if (bytes_remaining == 0) {
Signed-off-by: Sachin Prabhu <sprabhu@redhat.com> --- fs/cifs/sess.c | 318 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 233 insertions(+), 85 deletions(-)