diff mbox

[08/19] cifs: break out lanman NEGOTIATE handling into separate function

Message ID 1369321563-16893-9-git-send-email-jlayton@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jeff Layton May 23, 2013, 3:05 p.m. UTC
...this also gets rid of some #ifdef ugliness too.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifssmb.c | 185 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 97 insertions(+), 88 deletions(-)

Comments

Pavel Shilovsky May 24, 2013, 12:31 p.m. UTC | #1
2013/5/23 Jeff Layton <jlayton@redhat.com>:
> ...this also gets rid of some #ifdef ugliness too.
>
> Signed-off-by: Jeff Layton <jlayton@redhat.com>
> ---
>  fs/cifs/cifssmb.c | 185 ++++++++++++++++++++++++++++--------------------------
>  1 file changed, 97 insertions(+), 88 deletions(-)
>
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index 9b4aea8..5dd4f8a 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -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 */
> --
> 1.8.1.4
>
> --
> 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

Good cleanup. Acked-by: Pavel Shilovsky <piastry@etersoft.ru>

--
Best regards,
Pavel Shilovsky.
--
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 mbox

Patch

diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 9b4aea8..5dd4f8a 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -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 */