diff mbox

[RFC,1/2] CIFS: Fix signing for SMB2/3

Message ID 20180604202935.4872-2-aaptel@suse.com (mailing list archive)
State New, archived
Headers show

Commit Message

Aurélien Aptel June 4, 2018, 8:29 p.m. UTC
It seems Ronnie's preamble removal broke signing.

the signing functions are called when:

A) we send a request (to sign it)
B) when we recv a response (to check the signature).

On code path A, the smb2 header is in iov[1] but on code path B, the
smb2 header is in iov[0] (and there's only one vector).

So we have different iov indexes for the smb2 header but the signing
function always use index 1. Fix this by checking the nb of io vectors
in the signing function as a hint.

Signed-off-by: Aurelien Aptel <aaptel@suse.com>
---
 fs/cifs/cifsencrypt.c   |  8 +++-----
 fs/cifs/cifsproto.h     |  2 +-
 fs/cifs/smb2transport.c | 12 ++++++++----
 3 files changed, 12 insertions(+), 10 deletions(-)

Comments

ronnie sahlberg June 4, 2018, 11:17 p.m. UTC | #1
Thanks.

I think it was patch #8 that broke it.  It would have been unbroken
again in one of the later patches in 9-14 when we add the plumbing to
push the
NBSS generation further down the stack. I.e. Delay generating the NBSS
4 byte length until just immediately writing the vectors to the
socket.

This is good enough for now. I will rebase the remaining patches ontop
of for-next and this patch test and resend later this week.
(Optionally, Steve, you could fold Aurelien's patch into patch #8 you
merged into for-next.)


On Tue, Jun 5, 2018 at 6:29 AM, Aurelien Aptel <aaptel@suse.com> wrote:
> It seems Ronnie's preamble removal broke signing.
>
> the signing functions are called when:
>
> A) we send a request (to sign it)
> B) when we recv a response (to check the signature).
>
> On code path A, the smb2 header is in iov[1] but on code path B, the
> smb2 header is in iov[0] (and there's only one vector).
>
> So we have different iov indexes for the smb2 header but the signing
> function always use index 1. Fix this by checking the nb of io vectors
> in the signing function as a hint.
>
> Signed-off-by: Aurelien Aptel <aaptel@suse.com>
> ---
>  fs/cifs/cifsencrypt.c   |  8 +++-----
>  fs/cifs/cifsproto.h     |  2 +-
>  fs/cifs/smb2transport.c | 12 ++++++++----
>  3 files changed, 12 insertions(+), 10 deletions(-)
>
> diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
> index a6ef088e057b..d3e14d1fc0b5 100644
> --- a/fs/cifs/cifsencrypt.c
> +++ b/fs/cifs/cifsencrypt.c
> @@ -37,6 +37,7 @@
>  #include <crypto/aead.h>
>
>  int __cifs_calc_signature(struct smb_rqst *rqst,
> +                       int start,
>                         struct TCP_Server_Info *server, char *signature,
>                         struct shash_desc *shash)
>  {
> @@ -45,10 +46,7 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
>         struct kvec *iov = rqst->rq_iov;
>         int n_vec = rqst->rq_nvec;
>
> -       if (n_vec < 2 || iov[0].iov_len != 4)
> -               return -EIO;
> -
> -       for (i = 1; i < n_vec; i++) {
> +       for (i = start; i < n_vec; i++) {
>                 if (iov[i].iov_len == 0)
>                         continue;
>                 if (iov[i].iov_base == NULL) {
> @@ -119,7 +117,7 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
>                 return rc;
>         }
>
> -       return __cifs_calc_signature(rqst, server, signature,
> +       return __cifs_calc_signature(rqst, 1, server, signature,
>                                      &server->secmech.sdescmd5->shash);
>  }
>
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index 7933c5f9c076..7f0c773d5f6b 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -544,7 +544,7 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
>                            struct cifs_sb_info *cifs_sb,
>                            const unsigned char *path, char *pbuf,
>                            unsigned int *pbytes_written);
> -int __cifs_calc_signature(struct smb_rqst *rqst,
> +int __cifs_calc_signature(struct smb_rqst *rqst, int start,
>                         struct TCP_Server_Info *server, char *signature,
>                         struct shash_desc *shash);
>  enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
> diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
> index 2c671123a6bf..349d5ccf854c 100644
> --- a/fs/cifs/smb2transport.c
> +++ b/fs/cifs/smb2transport.c
> @@ -171,7 +171,9 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
>         unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
>         unsigned char *sigptr = smb2_signature;
>         struct kvec *iov = rqst->rq_iov;
> -       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
> +       int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0;
> +       struct smb2_sync_hdr *shdr =
> +               (struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
>         struct cifs_ses *ses;
>
>         ses = smb2_find_smb_ses(server, shdr->SessionId);
> @@ -202,7 +204,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
>                 return rc;
>         }
>
> -       rc = __cifs_calc_signature(rqst, server, sigptr,
> +       rc = __cifs_calc_signature(rqst, iov_hdr_index,  server, sigptr,
>                 &server->secmech.sdeschmacsha256->shash);
>
>         if (!rc)
> @@ -412,7 +414,9 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
>         unsigned char smb3_signature[SMB2_CMACAES_SIZE];
>         unsigned char *sigptr = smb3_signature;
>         struct kvec *iov = rqst->rq_iov;
> -       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
> +       int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0;
> +       struct smb2_sync_hdr *shdr =
> +               (struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
>         struct cifs_ses *ses;
>
>         ses = smb2_find_smb_ses(server, shdr->SessionId);
> @@ -443,7 +447,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
>                 return rc;
>         }
>
> -       rc = __cifs_calc_signature(rqst, server, sigptr,
> +       rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr,
>                                    &server->secmech.sdesccmacaes->shash);
>
>         if (!rc)
> --
> 2.13.6
>
> --
> 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
--
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
Steve French June 4, 2018, 11:54 p.m. UTC | #2
I will merge this one ASAP into for-next

On Mon, Jun 4, 2018 at 6:17 PM, ronnie sahlberg
<ronniesahlberg@gmail.com> wrote:
> Thanks.
>
> I think it was patch #8 that broke it.  It would have been unbroken
> again in one of the later patches in 9-14 when we add the plumbing to
> push the
> NBSS generation further down the stack. I.e. Delay generating the NBSS
> 4 byte length until just immediately writing the vectors to the
> socket.
>
> This is good enough for now. I will rebase the remaining patches ontop
> of for-next and this patch test and resend later this week.
> (Optionally, Steve, you could fold Aurelien's patch into patch #8 you
> merged into for-next.)
>
>
> On Tue, Jun 5, 2018 at 6:29 AM, Aurelien Aptel <aaptel@suse.com> wrote:
>> It seems Ronnie's preamble removal broke signing.
>>
>> the signing functions are called when:
>>
>> A) we send a request (to sign it)
>> B) when we recv a response (to check the signature).
>>
>> On code path A, the smb2 header is in iov[1] but on code path B, the
>> smb2 header is in iov[0] (and there's only one vector).
>>
>> So we have different iov indexes for the smb2 header but the signing
>> function always use index 1. Fix this by checking the nb of io vectors
>> in the signing function as a hint.
>>
>> Signed-off-by: Aurelien Aptel <aaptel@suse.com>
>> ---
>>  fs/cifs/cifsencrypt.c   |  8 +++-----
>>  fs/cifs/cifsproto.h     |  2 +-
>>  fs/cifs/smb2transport.c | 12 ++++++++----
>>  3 files changed, 12 insertions(+), 10 deletions(-)
>>
>> diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
>> index a6ef088e057b..d3e14d1fc0b5 100644
>> --- a/fs/cifs/cifsencrypt.c
>> +++ b/fs/cifs/cifsencrypt.c
>> @@ -37,6 +37,7 @@
>>  #include <crypto/aead.h>
>>
>>  int __cifs_calc_signature(struct smb_rqst *rqst,
>> +                       int start,
>>                         struct TCP_Server_Info *server, char *signature,
>>                         struct shash_desc *shash)
>>  {
>> @@ -45,10 +46,7 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
>>         struct kvec *iov = rqst->rq_iov;
>>         int n_vec = rqst->rq_nvec;
>>
>> -       if (n_vec < 2 || iov[0].iov_len != 4)
>> -               return -EIO;
>> -
>> -       for (i = 1; i < n_vec; i++) {
>> +       for (i = start; i < n_vec; i++) {
>>                 if (iov[i].iov_len == 0)
>>                         continue;
>>                 if (iov[i].iov_base == NULL) {
>> @@ -119,7 +117,7 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
>>                 return rc;
>>         }
>>
>> -       return __cifs_calc_signature(rqst, server, signature,
>> +       return __cifs_calc_signature(rqst, 1, server, signature,
>>                                      &server->secmech.sdescmd5->shash);
>>  }
>>
>> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
>> index 7933c5f9c076..7f0c773d5f6b 100644
>> --- a/fs/cifs/cifsproto.h
>> +++ b/fs/cifs/cifsproto.h
>> @@ -544,7 +544,7 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
>>                            struct cifs_sb_info *cifs_sb,
>>                            const unsigned char *path, char *pbuf,
>>                            unsigned int *pbytes_written);
>> -int __cifs_calc_signature(struct smb_rqst *rqst,
>> +int __cifs_calc_signature(struct smb_rqst *rqst, int start,
>>                         struct TCP_Server_Info *server, char *signature,
>>                         struct shash_desc *shash);
>>  enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
>> diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
>> index 2c671123a6bf..349d5ccf854c 100644
>> --- a/fs/cifs/smb2transport.c
>> +++ b/fs/cifs/smb2transport.c
>> @@ -171,7 +171,9 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
>>         unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
>>         unsigned char *sigptr = smb2_signature;
>>         struct kvec *iov = rqst->rq_iov;
>> -       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
>> +       int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0;
>> +       struct smb2_sync_hdr *shdr =
>> +               (struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
>>         struct cifs_ses *ses;
>>
>>         ses = smb2_find_smb_ses(server, shdr->SessionId);
>> @@ -202,7 +204,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
>>                 return rc;
>>         }
>>
>> -       rc = __cifs_calc_signature(rqst, server, sigptr,
>> +       rc = __cifs_calc_signature(rqst, iov_hdr_index,  server, sigptr,
>>                 &server->secmech.sdeschmacsha256->shash);
>>
>>         if (!rc)
>> @@ -412,7 +414,9 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
>>         unsigned char smb3_signature[SMB2_CMACAES_SIZE];
>>         unsigned char *sigptr = smb3_signature;
>>         struct kvec *iov = rqst->rq_iov;
>> -       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
>> +       int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0;
>> +       struct smb2_sync_hdr *shdr =
>> +               (struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
>>         struct cifs_ses *ses;
>>
>>         ses = smb2_find_smb_ses(server, shdr->SessionId);
>> @@ -443,7 +447,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
>>                 return rc;
>>         }
>>
>> -       rc = __cifs_calc_signature(rqst, server, sigptr,
>> +       rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr,
>>                                    &server->secmech.sdesccmacaes->shash);
>>
>>         if (!rc)
>> --
>> 2.13.6
>>
>> --
>> 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/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index a6ef088e057b..d3e14d1fc0b5 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -37,6 +37,7 @@ 
 #include <crypto/aead.h>
 
 int __cifs_calc_signature(struct smb_rqst *rqst,
+			int start,
 			struct TCP_Server_Info *server, char *signature,
 			struct shash_desc *shash)
 {
@@ -45,10 +46,7 @@  int __cifs_calc_signature(struct smb_rqst *rqst,
 	struct kvec *iov = rqst->rq_iov;
 	int n_vec = rqst->rq_nvec;
 
-	if (n_vec < 2 || iov[0].iov_len != 4)
-		return -EIO;
-
-	for (i = 1; i < n_vec; i++) {
+	for (i = start; i < n_vec; i++) {
 		if (iov[i].iov_len == 0)
 			continue;
 		if (iov[i].iov_base == NULL) {
@@ -119,7 +117,7 @@  static int cifs_calc_signature(struct smb_rqst *rqst,
 		return rc;
 	}
 
-	return __cifs_calc_signature(rqst, server, signature,
+	return __cifs_calc_signature(rqst, 1, server, signature,
 				     &server->secmech.sdescmd5->shash);
 }
 
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 7933c5f9c076..7f0c773d5f6b 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -544,7 +544,7 @@  int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
 			   struct cifs_sb_info *cifs_sb,
 			   const unsigned char *path, char *pbuf,
 			   unsigned int *pbytes_written);
-int __cifs_calc_signature(struct smb_rqst *rqst,
+int __cifs_calc_signature(struct smb_rqst *rqst, int start,
 			struct TCP_Server_Info *server, char *signature,
 			struct shash_desc *shash);
 enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 2c671123a6bf..349d5ccf854c 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -171,7 +171,9 @@  smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 	unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
 	unsigned char *sigptr = smb2_signature;
 	struct kvec *iov = rqst->rq_iov;
-	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
+	int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0;
+	struct smb2_sync_hdr *shdr =
+		(struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
 	struct cifs_ses *ses;
 
 	ses = smb2_find_smb_ses(server, shdr->SessionId);
@@ -202,7 +204,7 @@  smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 		return rc;
 	}
 
-	rc = __cifs_calc_signature(rqst, server, sigptr,
+	rc = __cifs_calc_signature(rqst, iov_hdr_index,  server, sigptr,
 		&server->secmech.sdeschmacsha256->shash);
 
 	if (!rc)
@@ -412,7 +414,9 @@  smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 	unsigned char smb3_signature[SMB2_CMACAES_SIZE];
 	unsigned char *sigptr = smb3_signature;
 	struct kvec *iov = rqst->rq_iov;
-	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
+	int iov_hdr_index = rqst->rq_nvec > 1 ? 1 : 0;
+	struct smb2_sync_hdr *shdr =
+		(struct smb2_sync_hdr *)iov[iov_hdr_index].iov_base;
 	struct cifs_ses *ses;
 
 	ses = smb2_find_smb_ses(server, shdr->SessionId);
@@ -443,7 +447,7 @@  smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
 		return rc;
 	}
 
-	rc = __cifs_calc_signature(rqst, server, sigptr,
+	rc = __cifs_calc_signature(rqst, iov_hdr_index, server, sigptr,
 				   &server->secmech.sdesccmacaes->shash);
 
 	if (!rc)