cifs: Split ntlm and ntlmv2 authentication methods off CIFS_SessSetup()
Signed-off-by: Sachin Prabhu <sprabhu@redhat.com> Reviewed-by: Shirish Pargaonkar <spargaonkar@suse.com> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
parent
80a0e63751
commit
583cf7afc7
290
fs/cifs/sess.c
290
fs/cifs/sess.c
|
@ -754,6 +754,216 @@ sess_auth_lanman(struct sess_data *sess_data)
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sess_establish_session(sess_data);
|
||||||
|
out:
|
||||||
|
sess_data->result = rc;
|
||||||
|
sess_data->func = NULL;
|
||||||
|
sess_free_buffer(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sess_establish_session(sess_data);
|
||||||
|
out:
|
||||||
|
sess_data->result = rc;
|
||||||
|
sess_data->func = NULL;
|
||||||
|
sess_free_buffer(sess_data);
|
||||||
|
kfree(ses->auth_key.response);
|
||||||
|
ses->auth_key.response = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
|
CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
|
||||||
const struct nls_table *nls_cp)
|
const struct nls_table *nls_cp)
|
||||||
|
@ -801,6 +1011,12 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
|
||||||
case LANMAN:
|
case LANMAN:
|
||||||
sess_auth_lanman(sess_data);
|
sess_auth_lanman(sess_data);
|
||||||
goto out;
|
goto out;
|
||||||
|
case NTLM:
|
||||||
|
sess_auth_ntlm(sess_data);
|
||||||
|
goto out;
|
||||||
|
case NTLMv2:
|
||||||
|
sess_auth_ntlmv2(sess_data);
|
||||||
|
goto out;
|
||||||
default:
|
default:
|
||||||
cifs_dbg(FYI, "Continuing with CIFS_SessSetup\n");
|
cifs_dbg(FYI, "Continuing with CIFS_SessSetup\n");
|
||||||
}
|
}
|
||||||
|
@ -820,10 +1036,7 @@ ssetup_ntlmssp_authenticate:
|
||||||
if (phase == NtLmChallenge)
|
if (phase == NtLmChallenge)
|
||||||
phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
|
phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
|
||||||
|
|
||||||
if ((type == NTLM) || (type == NTLMv2)) {
|
/* same size: negotiate or auth, NTLMSSP or extended security */
|
||||||
/* 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;
|
wct = 12;
|
||||||
|
|
||||||
rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
|
rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
|
||||||
|
@ -859,70 +1072,7 @@ ssetup_ntlmssp_authenticate:
|
||||||
iov[1].iov_base = NULL;
|
iov[1].iov_base = NULL;
|
||||||
iov[1].iov_len = 0;
|
iov[1].iov_len = 0;
|
||||||
|
|
||||||
if (type == NTLM) {
|
if (type == Kerberos) {
|
||||||
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) {
|
|
||||||
#ifdef CONFIG_CIFS_UPCALL
|
#ifdef CONFIG_CIFS_UPCALL
|
||||||
struct cifs_spnego_msg *msg;
|
struct cifs_spnego_msg *msg;
|
||||||
|
|
||||||
|
@ -1073,7 +1223,7 @@ ssetup_ntlmssp_authenticate:
|
||||||
if (rc)
|
if (rc)
|
||||||
goto ssetup_exit;
|
goto ssetup_exit;
|
||||||
|
|
||||||
if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
|
if (smb_buf->WordCount != 4) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
|
cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
|
||||||
goto ssetup_exit;
|
goto ssetup_exit;
|
||||||
|
@ -1088,7 +1238,6 @@ ssetup_ntlmssp_authenticate:
|
||||||
bytes_remaining = get_bcc(smb_buf);
|
bytes_remaining = get_bcc(smb_buf);
|
||||||
bcc_ptr = pByteArea(smb_buf);
|
bcc_ptr = pByteArea(smb_buf);
|
||||||
|
|
||||||
if (smb_buf->WordCount == 4) {
|
|
||||||
blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
|
blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
|
||||||
if (blob_len > bytes_remaining) {
|
if (blob_len > bytes_remaining) {
|
||||||
cifs_dbg(VFS, "bad security blob length %d\n",
|
cifs_dbg(VFS, "bad security blob length %d\n",
|
||||||
|
@ -1103,7 +1252,6 @@ ssetup_ntlmssp_authenticate:
|
||||||
}
|
}
|
||||||
bcc_ptr += blob_len;
|
bcc_ptr += blob_len;
|
||||||
bytes_remaining -= blob_len;
|
bytes_remaining -= blob_len;
|
||||||
}
|
|
||||||
|
|
||||||
/* BB check if Unicode and decode strings */
|
/* BB check if Unicode and decode strings */
|
||||||
if (bytes_remaining == 0) {
|
if (bytes_remaining == 0) {
|
||||||
|
|
Loading…
Reference in New Issue