Commit 622954af authored by Pavel Shilovsky's avatar Pavel Shilovsky

Update 3.12 sources from stable (v3.12.51)

parent 6c5601b5
...@@ -441,6 +441,48 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp) ...@@ -441,6 +441,48 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
return 0; 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, static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
const struct nls_table *nls_cp) const struct nls_table *nls_cp)
{ {
...@@ -630,6 +672,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) ...@@ -630,6 +672,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
struct ntlmv2_resp *buf; struct ntlmv2_resp *buf;
char ntlmv2_hash[16]; char ntlmv2_hash[16];
unsigned char *tiblob = NULL; /* target info blob */ unsigned char *tiblob = NULL; /* target info blob */
__le64 rsp_timestamp;
if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) { if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
if (!ses->domainName) { if (!ses->domainName) {
...@@ -648,6 +691,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) ...@@ -648,6 +691,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); baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
tilen = ses->auth_key.len; tilen = ses->auth_key.len;
tiblob = ses->auth_key.response; tiblob = ses->auth_key.response;
...@@ -664,7 +713,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) ...@@ -664,7 +713,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
(ses->auth_key.response + CIFS_SESS_KEY_SIZE); (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
buf->blob_signature = cpu_to_le32(0x00000101); buf->blob_signature = cpu_to_le32(0x00000101);
buf->reserved = 0; 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)); get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
buf->reserved2 = 0; buf->reserved2 = 0;
......
...@@ -629,9 +629,8 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) ...@@ -629,9 +629,8 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
server->negflavor = CIFS_NEGFLAVOR_UNENCAP; server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey, memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
CIFS_CRYPTO_KEY_SIZE); CIFS_CRYPTO_KEY_SIZE);
} else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC || } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
server->capabilities & CAP_EXTENDED_SECURITY) && server->capabilities & CAP_EXTENDED_SECURITY) {
(pSMBr->EncryptionKeyLength == 0)) {
server->negflavor = CIFS_NEGFLAVOR_EXTENDED; server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
rc = decode_ext_sec_blob(ses, pSMBr); rc = decode_ext_sec_blob(ses, pSMBr);
} else if (server->sec_mode & SECMODE_PW_ENCRYPT) { } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
......
...@@ -2250,6 +2250,8 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol) ...@@ -2250,6 +2250,8 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
if (ses->status == CifsExiting)
continue;
if (!match_session(ses, vol)) if (!match_session(ses, vol))
continue; continue;
++ses->ses_count; ++ses->ses_count;
...@@ -2263,24 +2265,37 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol) ...@@ -2263,24 +2265,37 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
static void static void
cifs_put_smb_ses(struct cifs_ses *ses) cifs_put_smb_ses(struct cifs_ses *ses)
{ {
unsigned int xid; unsigned int rc, xid;
struct TCP_Server_Info *server = ses->server; struct TCP_Server_Info *server = ses->server;
cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count); cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
if (ses->status == CifsExiting) {
spin_unlock(&cifs_tcp_ses_lock);
return;
}
if (--ses->ses_count > 0) { if (--ses->ses_count > 0) {
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
return; return;
} }
if (ses->status == CifsGood)
list_del_init(&ses->smb_ses_list); ses->status = CifsExiting;
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
if (ses->status == CifsGood && server->ops->logoff) { if (ses->status == CifsExiting && server->ops->logoff) {
xid = get_xid(); xid = get_xid();
server->ops->logoff(xid, ses); rc = server->ops->logoff(xid, ses);
if (rc)
cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
__func__, rc);
_free_xid(xid); _free_xid(xid);
} }
spin_lock(&cifs_tcp_ses_lock);
list_del_init(&ses->smb_ses_list);
spin_unlock(&cifs_tcp_ses_lock);
sesInfoFree(ses); sesInfoFree(ses);
cifs_put_tcp_session(server); cifs_put_tcp_session(server);
} }
......
...@@ -49,9 +49,13 @@ change_conf(struct TCP_Server_Info *server) ...@@ -49,9 +49,13 @@ change_conf(struct TCP_Server_Info *server)
break; break;
default: default:
server->echoes = true; server->echoes = true;
if (enable_oplocks) {
server->oplocks = true; server->oplocks = true;
server->echo_credits = 1;
server->oplock_credits = 1; server->oplock_credits = 1;
} else
server->oplocks = false;
server->echo_credits = 1;
} }
server->credits -= server->echo_credits + server->oplock_credits; server->credits -= server->echo_credits + server->oplock_credits;
return 0; return 0;
......
...@@ -516,13 +516,19 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf, ...@@ -516,13 +516,19 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
return -EAGAIN; return -EAGAIN;
} }
if (ses->status != CifsGood) { if (ses->status == CifsNew) {
/* check if SMB2 session is bad because we are setting it up */
if ((buf->Command != SMB2_SESSION_SETUP) && if ((buf->Command != SMB2_SESSION_SETUP) &&
(buf->Command != SMB2_NEGOTIATE)) (buf->Command != SMB2_NEGOTIATE))
return -EAGAIN; return -EAGAIN;
/* else ok - we are setting up session */ /* else ok - we are setting up session */
} }
if (ses->status == CifsExiting) {
if (buf->Command != SMB2_LOGOFF)
return -EAGAIN;
/* else ok - we are shutting down the session */
}
*mid = smb2_mid_entry_alloc(buf, ses->server); *mid = smb2_mid_entry_alloc(buf, ses->server);
if (*mid == NULL) if (*mid == NULL)
return -ENOMEM; return -ENOMEM;
......
...@@ -431,13 +431,20 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, ...@@ -431,13 +431,20 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
return -EAGAIN; return -EAGAIN;
} }
if (ses->status != CifsGood) { if (ses->status == CifsNew) {
/* check if SMB session is bad because we are setting it up */
if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
(in_buf->Command != SMB_COM_NEGOTIATE)) (in_buf->Command != SMB_COM_NEGOTIATE))
return -EAGAIN; return -EAGAIN;
/* else ok - we are setting up session */ /* else ok - we are setting up session */
} }
if (ses->status == CifsExiting) {
/* check if SMB session is bad because we are setting it up */
if (in_buf->Command != SMB_COM_LOGOFF_ANDX)
return -EAGAIN;
/* else ok - we are shutting down session */
}
*ppmidQ = AllocMidQEntry(in_buf, ses->server); *ppmidQ = AllocMidQEntry(in_buf, ses->server);
if (*ppmidQ == NULL) if (*ppmidQ == NULL)
return -ENOMEM; return -ENOMEM;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment