diff mbox

[07/19] cifs: break out decoding of security blob into separate function

Message ID 1369321563-16893-8-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
...cleanup.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifspdu.h |   4 +-
 fs/cifs/cifssmb.c | 109 ++++++++++++++++++++++++++++++------------------------
 2 files changed, 62 insertions(+), 51 deletions(-)

Comments

Pavel Shilovsky May 24, 2013, 12:24 p.m. UTC | #1
2013/5/23 Jeff Layton <jlayton@redhat.com>:
> ...cleanup.
>
> Signed-off-by: Jeff Layton <jlayton@redhat.com>
> ---
>  fs/cifs/cifspdu.h |   4 +-
>  fs/cifs/cifssmb.c | 109 ++++++++++++++++++++++++++++++------------------------
>  2 files changed, 62 insertions(+), 51 deletions(-)
>
> diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
> index e996ff6..4e6135a 100644
> --- a/fs/cifs/cifspdu.h
> +++ b/fs/cifs/cifspdu.h
> @@ -531,7 +531,7 @@ typedef struct lanman_neg_rsp {
>  #define READ_RAW_ENABLE 1
>  #define WRITE_RAW_ENABLE 2
>  #define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)
> -
> +#define SMB1_CLIENT_GUID_SIZE (16)
>  typedef struct negotiate_rsp {
>         struct smb_hdr hdr;     /* wct = 17 */
>         __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
> @@ -553,7 +553,7 @@ typedef struct negotiate_rsp {
>                 /* followed by 16 bytes of server GUID */
>                 /* then security blob if cap_extended_security negotiated */
>                 struct {
> -                       unsigned char GUID[16];
> +                       unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
>                         unsigned char SecurityBlob[1];
>                 } __attribute__((packed)) extended_response;
>         } __attribute__((packed)) u;
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index c1c2006..9b4aea8 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -367,6 +367,56 @@ vt2_err:
>         return -EINVAL;
>  }
>
> +static int
> +decode_ext_sec_blob(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
> +{
> +       int     rc = 0;
> +       u16     count;
> +       char    *guid = pSMBr->u.extended_response.GUID;
> +
> +       count = get_bcc(&pSMBr->hdr);
> +       if (count < SMB1_CLIENT_GUID_SIZE)
> +               return -EIO;
> +
> +       spin_lock(&cifs_tcp_ses_lock);
> +       if (server->srv_count > 1) {
> +               spin_unlock(&cifs_tcp_ses_lock);
> +               if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
> +                       cifs_dbg(FYI, "server UID changed\n");
> +                       memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
> +               }
> +       } else {
> +               spin_unlock(&cifs_tcp_ses_lock);
> +               memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
> +       }
> +
> +       if (count == SMB1_CLIENT_GUID_SIZE) {
> +               server->secType = RawNTLMSSP;
> +       } else {
> +               count -= SMB1_CLIENT_GUID_SIZE;
> +               rc = decode_negTokenInit(
> +                       pSMBr->u.extended_response.SecurityBlob, count, server);
> +               if (rc != 1)
> +                       return -EINVAL;
> +
> +               /* Make sure server supports what we want to use */
> +               switch(server->secType) {
> +               case Kerberos:
> +                       if (!server->sec_kerberos && !server->sec_mskerberos)
> +                               return -EOPNOTSUPP;
> +                       break;
> +               case RawNTLMSSP:
> +                       if (!server->sec_ntlmssp)
> +                               return -EOPNOTSUPP;
> +                       break;
> +               default:
> +                       return -EOPNOTSUPP;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
>  int
>  CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
>  {
> @@ -568,61 +618,22 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
>         server->capabilities = le32_to_cpu(pSMBr->Capabilities);
>         server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
>         server->timeAdj *= 60;
> -       if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
> +
> +       if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE)
>                 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
>                        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) &&
> -                               (pSMBr->EncryptionKeyLength == 0)) {
> -               /* decode security blob */
> -               count = get_bcc(&pSMBr->hdr);
> -               if (count < 16) {
> -                       rc = -EIO;
> -                       goto neg_err_exit;
> -               }
> -               spin_lock(&cifs_tcp_ses_lock);
> -               if (server->srv_count > 1) {
> -                       spin_unlock(&cifs_tcp_ses_lock);
> -                       if (memcmp(server->server_GUID,
> -                                  pSMBr->u.extended_response.
> -                                  GUID, 16) != 0) {
> -                               cifs_dbg(FYI, "server UID changed\n");
> -                               memcpy(server->server_GUID,
> -                                       pSMBr->u.extended_response.GUID,
> -                                       16);
> -                       }
> -               } else {
> -                       spin_unlock(&cifs_tcp_ses_lock);
> -                       memcpy(server->server_GUID,
> -                              pSMBr->u.extended_response.GUID, 16);
> -               }
> -
> -               if (count == 16) {
> -                       server->secType = RawNTLMSSP;
> -               } else {
> -                       rc = decode_negTokenInit(pSMBr->u.extended_response.
> -                                                SecurityBlob, count - 16,
> -                                                server);
> -                       if (rc == 1)
> -                               rc = 0;
> -                       else
> -                               rc = -EINVAL;
> -                       if (server->secType == Kerberos) {
> -                               if (!server->sec_kerberos &&
> -                                               !server->sec_mskerberos)
> -                                       rc = -EOPNOTSUPP;
> -                       } else if (server->secType == RawNTLMSSP) {
> -                               if (!server->sec_ntlmssp)
> -                                       rc = -EOPNOTSUPP;
> -                       } else
> -                                       rc = -EOPNOTSUPP;
> -               }
> -       } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
> +                               (pSMBr->EncryptionKeyLength == 0))
> +               rc = decode_ext_sec_blob(server, pSMBr);
> +       else if (server->sec_mode & SECMODE_PW_ENCRYPT)
>                 rc = -EIO; /* no crypt key only if plain text pwd */
> -               goto neg_err_exit;
> -       } else
> +       else
>                 server->capabilities &= ~CAP_EXTENDED_SECURITY;
>
> +       if (rc)
> +               goto neg_err_exit;
> +
>  #ifdef CONFIG_CIFS_WEAK_PW_HASH
>  signing_check:
>  #endif
> --
> 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

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/cifspdu.h b/fs/cifs/cifspdu.h
index e996ff6..4e6135a 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -531,7 +531,7 @@  typedef struct lanman_neg_rsp {
 #define READ_RAW_ENABLE 1
 #define WRITE_RAW_ENABLE 2
 #define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)
-
+#define SMB1_CLIENT_GUID_SIZE (16)
 typedef struct negotiate_rsp {
 	struct smb_hdr hdr;	/* wct = 17 */
 	__le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
@@ -553,7 +553,7 @@  typedef struct negotiate_rsp {
 		/* followed by 16 bytes of server GUID */
 		/* then security blob if cap_extended_security negotiated */
 		struct {
-			unsigned char GUID[16];
+			unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
 			unsigned char SecurityBlob[1];
 		} __attribute__((packed)) extended_response;
 	} __attribute__((packed)) u;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index c1c2006..9b4aea8 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -367,6 +367,56 @@  vt2_err:
 	return -EINVAL;
 }
 
+static int
+decode_ext_sec_blob(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
+{
+	int	rc = 0;
+	u16	count;
+	char	*guid = pSMBr->u.extended_response.GUID;
+
+	count = get_bcc(&pSMBr->hdr);
+	if (count < SMB1_CLIENT_GUID_SIZE)
+		return -EIO;
+
+	spin_lock(&cifs_tcp_ses_lock);
+	if (server->srv_count > 1) {
+		spin_unlock(&cifs_tcp_ses_lock);
+		if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
+			cifs_dbg(FYI, "server UID changed\n");
+			memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
+		}
+	} else {
+		spin_unlock(&cifs_tcp_ses_lock);
+		memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
+	}
+
+	if (count == SMB1_CLIENT_GUID_SIZE) {
+		server->secType = RawNTLMSSP;
+	} else {
+		count -= SMB1_CLIENT_GUID_SIZE;
+		rc = decode_negTokenInit(
+			pSMBr->u.extended_response.SecurityBlob, count, server);
+		if (rc != 1)
+			return -EINVAL;
+
+		/* Make sure server supports what we want to use */
+		switch(server->secType) {
+		case Kerberos:
+			if (!server->sec_kerberos && !server->sec_mskerberos)
+				return -EOPNOTSUPP;
+			break;
+		case RawNTLMSSP:
+			if (!server->sec_ntlmssp)
+				return -EOPNOTSUPP;
+			break;
+		default:
+			return -EOPNOTSUPP;
+		}
+	}
+
+	return 0;
+}
+
 int
 CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 {
@@ -568,61 +618,22 @@  CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
 	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
 	server->timeAdj *= 60;
-	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
+
+	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE)
 		memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
 		       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) &&
-				(pSMBr->EncryptionKeyLength == 0)) {
-		/* decode security blob */
-		count = get_bcc(&pSMBr->hdr);
-		if (count < 16) {
-			rc = -EIO;
-			goto neg_err_exit;
-		}
-		spin_lock(&cifs_tcp_ses_lock);
-		if (server->srv_count > 1) {
-			spin_unlock(&cifs_tcp_ses_lock);
-			if (memcmp(server->server_GUID,
-				   pSMBr->u.extended_response.
-				   GUID, 16) != 0) {
-				cifs_dbg(FYI, "server UID changed\n");
-				memcpy(server->server_GUID,
-					pSMBr->u.extended_response.GUID,
-					16);
-			}
-		} else {
-			spin_unlock(&cifs_tcp_ses_lock);
-			memcpy(server->server_GUID,
-			       pSMBr->u.extended_response.GUID, 16);
-		}
-
-		if (count == 16) {
-			server->secType = RawNTLMSSP;
-		} else {
-			rc = decode_negTokenInit(pSMBr->u.extended_response.
-						 SecurityBlob, count - 16,
-						 server);
-			if (rc == 1)
-				rc = 0;
-			else
-				rc = -EINVAL;
-			if (server->secType == Kerberos) {
-				if (!server->sec_kerberos &&
-						!server->sec_mskerberos)
-					rc = -EOPNOTSUPP;
-			} else if (server->secType == RawNTLMSSP) {
-				if (!server->sec_ntlmssp)
-					rc = -EOPNOTSUPP;
-			} else
-					rc = -EOPNOTSUPP;
-		}
-	} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
+				(pSMBr->EncryptionKeyLength == 0))
+		rc = decode_ext_sec_blob(server, pSMBr);
+	else if (server->sec_mode & SECMODE_PW_ENCRYPT)
 		rc = -EIO; /* no crypt key only if plain text pwd */
-		goto neg_err_exit;
-	} else
+	else
 		server->capabilities &= ~CAP_EXTENDED_SECURITY;
 
+	if (rc)
+		goto neg_err_exit;
+
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 signing_check:
 #endif