cifs: break out lanman NEGOTIATE handling into separate function
...this also gets rid of some #ifdef ugliness too. Signed-off-by: Jeff Layton <jlayton@redhat.com> Acked-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
31d9e2bd5f
commit
2190eca1d0
1 changed files with 97 additions and 88 deletions
|
@ -417,6 +417,96 @@ decode_ext_sec_blob(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||
static int
|
||||
decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr,
|
||||
unsigned int secFlags)
|
||||
{
|
||||
__s16 tmp;
|
||||
struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
|
||||
|
||||
if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if ((secFlags & CIFSSEC_MAY_LANMAN) || (secFlags & CIFSSEC_MAY_PLNTXT))
|
||||
server->secType = LANMAN;
|
||||
else {
|
||||
cifs_dbg(VFS, "mount failed weak security disabled in /proc/fs/cifs/SecurityFlags\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
server->sec_mode = le16_to_cpu(rsp->SecurityMode);
|
||||
server->maxReq = min_t(unsigned int,
|
||||
le16_to_cpu(rsp->MaxMpxCount),
|
||||
cifs_max_pending);
|
||||
set_credits(server, server->maxReq);
|
||||
server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
|
||||
server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
|
||||
/* even though we do not use raw we might as well set this
|
||||
accurately, in case we ever find a need for it */
|
||||
if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
|
||||
server->max_rw = 0xFF00;
|
||||
server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
|
||||
} else {
|
||||
server->max_rw = 0;/* do not need to use raw anyway */
|
||||
server->capabilities = CAP_MPX_MODE;
|
||||
}
|
||||
tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
|
||||
if (tmp == -1) {
|
||||
/* OS/2 often does not set timezone therefore
|
||||
* we must use server time to calc time zone.
|
||||
* Could deviate slightly from the right zone.
|
||||
* Smallest defined timezone difference is 15 minutes
|
||||
* (i.e. Nepal). Rounding up/down is done to match
|
||||
* this requirement.
|
||||
*/
|
||||
int val, seconds, remain, result;
|
||||
struct timespec ts, utc;
|
||||
utc = CURRENT_TIME;
|
||||
ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
|
||||
rsp->SrvTime.Time, 0);
|
||||
cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n",
|
||||
(int)ts.tv_sec, (int)utc.tv_sec,
|
||||
(int)(utc.tv_sec - ts.tv_sec));
|
||||
val = (int)(utc.tv_sec - ts.tv_sec);
|
||||
seconds = abs(val);
|
||||
result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
|
||||
remain = seconds % MIN_TZ_ADJ;
|
||||
if (remain >= (MIN_TZ_ADJ / 2))
|
||||
result += MIN_TZ_ADJ;
|
||||
if (val < 0)
|
||||
result = -result;
|
||||
server->timeAdj = result;
|
||||
} else {
|
||||
server->timeAdj = (int)tmp;
|
||||
server->timeAdj *= 60; /* also in seconds */
|
||||
}
|
||||
cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj);
|
||||
|
||||
|
||||
/* BB get server time for time conversions and add
|
||||
code to use it and timezone since this is not UTC */
|
||||
|
||||
if (rsp->EncryptionKeyLength ==
|
||||
cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
|
||||
memcpy(server->cryptkey, rsp->EncryptionKey,
|
||||
CIFS_CRYPTO_KEY_SIZE);
|
||||
} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
|
||||
return -EIO; /* need cryptkey unless plain text */
|
||||
}
|
||||
|
||||
cifs_dbg(FYI, "LANMAN negotiated\n");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int
|
||||
decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr,
|
||||
unsigned int secFlags)
|
||||
{
|
||||
cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
|
||||
{
|
||||
|
@ -485,98 +575,19 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
|
|||
could not negotiate a common dialect */
|
||||
rc = -EOPNOTSUPP;
|
||||
goto neg_err_exit;
|
||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||
} else if ((pSMBr->hdr.WordCount == 13)
|
||||
&& ((server->dialect == LANMAN_PROT)
|
||||
|| (server->dialect == LANMAN2_PROT))) {
|
||||
__s16 tmp;
|
||||
struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
|
||||
|
||||
if ((secFlags & CIFSSEC_MAY_LANMAN) ||
|
||||
(secFlags & CIFSSEC_MAY_PLNTXT))
|
||||
server->secType = LANMAN;
|
||||
else {
|
||||
cifs_dbg(VFS, "mount failed weak security disabled in /proc/fs/cifs/SecurityFlags\n");
|
||||
rc = -EOPNOTSUPP;
|
||||
goto neg_err_exit;
|
||||
}
|
||||
server->sec_mode = le16_to_cpu(rsp->SecurityMode);
|
||||
server->maxReq = min_t(unsigned int,
|
||||
le16_to_cpu(rsp->MaxMpxCount),
|
||||
cifs_max_pending);
|
||||
set_credits(server, server->maxReq);
|
||||
server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
|
||||
server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
|
||||
/* even though we do not use raw we might as well set this
|
||||
accurately, in case we ever find a need for it */
|
||||
if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
|
||||
server->max_rw = 0xFF00;
|
||||
server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
|
||||
} else {
|
||||
server->max_rw = 0;/* do not need to use raw anyway */
|
||||
server->capabilities = CAP_MPX_MODE;
|
||||
}
|
||||
tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
|
||||
if (tmp == -1) {
|
||||
/* OS/2 often does not set timezone therefore
|
||||
* we must use server time to calc time zone.
|
||||
* Could deviate slightly from the right zone.
|
||||
* Smallest defined timezone difference is 15 minutes
|
||||
* (i.e. Nepal). Rounding up/down is done to match
|
||||
* this requirement.
|
||||
*/
|
||||
int val, seconds, remain, result;
|
||||
struct timespec ts, utc;
|
||||
utc = CURRENT_TIME;
|
||||
ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
|
||||
rsp->SrvTime.Time, 0);
|
||||
cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n",
|
||||
(int)ts.tv_sec, (int)utc.tv_sec,
|
||||
(int)(utc.tv_sec - ts.tv_sec));
|
||||
val = (int)(utc.tv_sec - ts.tv_sec);
|
||||
seconds = abs(val);
|
||||
result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
|
||||
remain = seconds % MIN_TZ_ADJ;
|
||||
if (remain >= (MIN_TZ_ADJ / 2))
|
||||
result += MIN_TZ_ADJ;
|
||||
if (val < 0)
|
||||
result = -result;
|
||||
server->timeAdj = result;
|
||||
} else {
|
||||
server->timeAdj = (int)tmp;
|
||||
server->timeAdj *= 60; /* also in seconds */
|
||||
}
|
||||
cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj);
|
||||
|
||||
|
||||
/* BB get server time for time conversions and add
|
||||
code to use it and timezone since this is not UTC */
|
||||
|
||||
if (rsp->EncryptionKeyLength ==
|
||||
cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
|
||||
memcpy(ses->server->cryptkey, rsp->EncryptionKey,
|
||||
CIFS_CRYPTO_KEY_SIZE);
|
||||
} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
|
||||
rc = -EIO; /* need cryptkey unless plain text */
|
||||
goto neg_err_exit;
|
||||
}
|
||||
|
||||
cifs_dbg(FYI, "LANMAN negotiated\n");
|
||||
/* we will not end up setting signing flags - as no signing
|
||||
was in LANMAN and server did not return the flags on */
|
||||
goto signing_check;
|
||||
#else /* weak security disabled */
|
||||
} else if (pSMBr->hdr.WordCount == 13) {
|
||||
cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
|
||||
rc = -EOPNOTSUPP;
|
||||
#endif /* WEAK_PW_HASH */
|
||||
goto neg_err_exit;
|
||||
rc = decode_lanman_negprot_rsp(server, pSMBr, secFlags);
|
||||
if (!rc)
|
||||
goto signing_check;
|
||||
else
|
||||
goto neg_err_exit;
|
||||
} else if (pSMBr->hdr.WordCount != 17) {
|
||||
/* unknown wct */
|
||||
rc = -EOPNOTSUPP;
|
||||
goto neg_err_exit;
|
||||
}
|
||||
/* else wct == 17 NTLM */
|
||||
/* else wct == 17, NTLM or better */
|
||||
|
||||
server->sec_mode = pSMBr->SecurityMode;
|
||||
if ((server->sec_mode & SECMODE_USER) == 0)
|
||||
cifs_dbg(FYI, "share mode security\n");
|
||||
|
@ -634,9 +645,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
|
|||
if (rc)
|
||||
goto neg_err_exit;
|
||||
|
||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||
signing_check:
|
||||
#endif
|
||||
if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
|
||||
/* MUST_SIGN already includes the MAY_SIGN FLAG
|
||||
so if this is zero it means that signing is disabled */
|
||||
|
|
Loading…
Reference in a new issue