diff mbox

cifs: ignore everything in SPNEGO blob after mechTypes

Message ID 1363009939-2264-1-git-send-email-jlayton@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jeff Layton March 11, 2013, 1:52 p.m. UTC
We've had several reports of people attempting to mount Windows 8 shares
and getting failures with a return code of -EINVAL. The default sec=
mode changed recently to sec=ntlmssp. With that, we expect and parse a
SPNEGO blob from the server in the NEGOTIATE reply.

The current decode_negTokenInit function first parses all of the
mechTypes and then tries to parse the rest of the negTokenInit reply.
The parser however currently expects a mechListMIC or nothing to follow the
mechTypes, but Windows 8 puts a mechToken field there instead to carry
some info for the new NegoEx stuff.

In practice, we don't do anything with the fields after the mechTypes
anyway so I don't see any real benefit in continuing to parse them.
This patch just has the kernel ignore the fields after the mechTypes.
We'll probably need to reinstate some of this if we ever want to support
NegoEx.

Reported-by: Jason Burgess <jason@jacknife2.dns2go.com>
Reported-by: Yan Li <elliot.li.tech@gmail.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/asn1.c | 53 +++++------------------------------------------------
 1 file changed, 5 insertions(+), 48 deletions(-)

Comments

Yan Li March 12, 2013, 6:27 p.m. UTC | #1
Yes, this patch fixed the problem in the current kernel we encountered when trying to mount a directory shared from a Windows 8 Pro system.

Yan Li

On Mar 11, 2013, at 6:52 AM, Jeff Layton <jlayton@redhat.com> wrote:

> We've had several reports of people attempting to mount Windows 8 shares
> and getting failures with a return code of -EINVAL. The default sec=
> mode changed recently to sec=ntlmssp. With that, we expect and parse a
> SPNEGO blob from the server in the NEGOTIATE reply.
> 
> The current decode_negTokenInit function first parses all of the
> mechTypes and then tries to parse the rest of the negTokenInit reply.
> The parser however currently expects a mechListMIC or nothing to follow the
> mechTypes, but Windows 8 puts a mechToken field there instead to carry
> some info for the new NegoEx stuff.
> 
> In practice, we don't do anything with the fields after the mechTypes
> anyway so I don't see any real benefit in continuing to parse them.
> This patch just has the kernel ignore the fields after the mechTypes.
> We'll probably need to reinstate some of this if we ever want to support
> NegoEx.
> 
> Reported-by: Jason Burgess <jason@jacknife2.dns2go.com>
> Reported-by: Yan Li <elliot.li.tech@gmail.com>
> Signed-off-by: Jeff Layton <jlayton@redhat.com>
> ---
> fs/cifs/asn1.c | 53 +++++------------------------------------------------
> 1 file changed, 5 insertions(+), 48 deletions(-)
> 
> diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
> index cfd1ce3..1d36db1 100644
> --- a/fs/cifs/asn1.c
> +++ b/fs/cifs/asn1.c
> @@ -614,53 +614,10 @@ decode_negTokenInit(unsigned char *security_blob, int length,
> 		}
> 	}
> 
> -	/* mechlistMIC */
> -	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> -		/* Check if we have reached the end of the blob, but with
> -		   no mechListMic (e.g. NTLMSSP instead of KRB5) */
> -		if (ctx.error == ASN1_ERR_DEC_EMPTY)
> -			goto decode_negtoken_exit;
> -		cFYI(1, "Error decoding last part negTokenInit exit3");
> -		return 0;
> -	} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
> -		/* tag = 3 indicating mechListMIC */
> -		cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
> -			cls, con, tag, end, *end);
> -		return 0;
> -	}
> -
> -	/* sequence */
> -	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> -		cFYI(1, "Error decoding last part negTokenInit exit5");
> -		return 0;
> -	} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
> -		   || (tag != ASN1_SEQ)) {
> -		cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)",
> -			cls, con, tag, end, *end);
> -	}
> -
> -	/* sequence of */
> -	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> -		cFYI(1, "Error decoding last part negTokenInit exit 7");
> -		return 0;
> -	} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
> -		cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
> -			cls, con, tag, end, *end);
> -		return 0;
> -	}
> -
> -	/* general string */
> -	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> -		cFYI(1, "Error decoding last part negTokenInit exit9");
> -		return 0;
> -	} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
> -		   || (tag != ASN1_GENSTR)) {
> -		cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)",
> -			cls, con, tag, end, *end);
> -		return 0;
> -	}
> -	cFYI(1, "Need to call asn1_octets_decode() function for %s",
> -		ctx.pointer);	/* is this UTF-8 or ASCII? */
> -decode_negtoken_exit:
> +	/*
> +	 * We currently ignore anything at the end of the SPNEGO blob after
> +	 * the mechTypes have been parsed, since none of that info is
> +	 * used at the moment.
> +	 */
> 	return 1;
> }
> -- 
> 1.7.11.7
> 

--
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
Jeff Layton March 14, 2013, 11:41 a.m. UTC | #2
On Tue, 12 Mar 2013 11:27:54 -0700
Yan Li <elliot.li.tech@gmail.com> wrote:

> Yes, this patch fixed the problem in the current kernel we encountered when trying to mount a directory shared from a Windows 8 Pro system.
> 
> Yan Li
> 
> On Mar 11, 2013, at 6:52 AM, Jeff Layton <jlayton@redhat.com> wrote:
> 
> > We've had several reports of people attempting to mount Windows 8 shares
> > and getting failures with a return code of -EINVAL. The default sec=
> > mode changed recently to sec=ntlmssp. With that, we expect and parse a
> > SPNEGO blob from the server in the NEGOTIATE reply.
> > 
> > The current decode_negTokenInit function first parses all of the
> > mechTypes and then tries to parse the rest of the negTokenInit reply.
> > The parser however currently expects a mechListMIC or nothing to follow the
> > mechTypes, but Windows 8 puts a mechToken field there instead to carry
> > some info for the new NegoEx stuff.
> > 
> > In practice, we don't do anything with the fields after the mechTypes
> > anyway so I don't see any real benefit in continuing to parse them.
> > This patch just has the kernel ignore the fields after the mechTypes.
> > We'll probably need to reinstate some of this if we ever want to support
> > NegoEx.
> > 
> > Reported-by: Jason Burgess <jason@jacknife2.dns2go.com>
> > Reported-by: Yan Li <elliot.li.tech@gmail.com>
> > Signed-off-by: Jeff Layton <jlayton@redhat.com>
> > ---
> > fs/cifs/asn1.c | 53 +++++------------------------------------------------
> > 1 file changed, 5 insertions(+), 48 deletions(-)
> > 
> > diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
> > index cfd1ce3..1d36db1 100644
> > --- a/fs/cifs/asn1.c
> > +++ b/fs/cifs/asn1.c
> > @@ -614,53 +614,10 @@ decode_negTokenInit(unsigned char *security_blob, int length,
> > 		}
> > 	}
> > 
> > -	/* mechlistMIC */
> > -	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> > -		/* Check if we have reached the end of the blob, but with
> > -		   no mechListMic (e.g. NTLMSSP instead of KRB5) */
> > -		if (ctx.error == ASN1_ERR_DEC_EMPTY)
> > -			goto decode_negtoken_exit;
> > -		cFYI(1, "Error decoding last part negTokenInit exit3");
> > -		return 0;
> > -	} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
> > -		/* tag = 3 indicating mechListMIC */
> > -		cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
> > -			cls, con, tag, end, *end);
> > -		return 0;
> > -	}
> > -
> > -	/* sequence */
> > -	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> > -		cFYI(1, "Error decoding last part negTokenInit exit5");
> > -		return 0;
> > -	} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
> > -		   || (tag != ASN1_SEQ)) {
> > -		cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)",
> > -			cls, con, tag, end, *end);
> > -	}
> > -
> > -	/* sequence of */
> > -	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> > -		cFYI(1, "Error decoding last part negTokenInit exit 7");
> > -		return 0;
> > -	} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
> > -		cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
> > -			cls, con, tag, end, *end);
> > -		return 0;
> > -	}
> > -
> > -	/* general string */
> > -	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> > -		cFYI(1, "Error decoding last part negTokenInit exit9");
> > -		return 0;
> > -	} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
> > -		   || (tag != ASN1_GENSTR)) {
> > -		cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)",
> > -			cls, con, tag, end, *end);
> > -		return 0;
> > -	}
> > -	cFYI(1, "Need to call asn1_octets_decode() function for %s",
> > -		ctx.pointer);	/* is this UTF-8 or ASCII? */
> > -decode_negtoken_exit:
> > +	/*
> > +	 * We currently ignore anything at the end of the SPNEGO blob after
> > +	 * the mechTypes have been parsed, since none of that info is
> > +	 * used at the moment.
> > +	 */
> > 	return 1;
> > }
> > -- 
> > 1.7.11.7
> > 
> 
> --
> 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


Thanks for testing it...

Steve, I think this should probably go to stable too since 3.8 moved to
sec=ntlmssp as the default.
Steve French March 17, 2013, 2:37 p.m. UTC | #3
The existing code is trying to dump the "principal" from the
mechListMic (presumably for debugging) in the SMB negotiate response.
In the trace I looked at Samba server set it to "NONE"  - is there a
case where we would ever need that?

On Mon, Mar 11, 2013 at 8:52 AM, Jeff Layton <jlayton@redhat.com> wrote:
> We've had several reports of people attempting to mount Windows 8 shares
> and getting failures with a return code of -EINVAL. The default sec=
> mode changed recently to sec=ntlmssp. With that, we expect and parse a
> SPNEGO blob from the server in the NEGOTIATE reply.
>
> The current decode_negTokenInit function first parses all of the
> mechTypes and then tries to parse the rest of the negTokenInit reply.
> The parser however currently expects a mechListMIC or nothing to follow the
> mechTypes, but Windows 8 puts a mechToken field there instead to carry
> some info for the new NegoEx stuff.
>
> In practice, we don't do anything with the fields after the mechTypes
> anyway so I don't see any real benefit in continuing to parse them.
> This patch just has the kernel ignore the fields after the mechTypes.
> We'll probably need to reinstate some of this if we ever want to support
> NegoEx.
>
> Reported-by: Jason Burgess <jason@jacknife2.dns2go.com>
> Reported-by: Yan Li <elliot.li.tech@gmail.com>
> Signed-off-by: Jeff Layton <jlayton@redhat.com>
> ---
>  fs/cifs/asn1.c | 53 +++++------------------------------------------------
>  1 file changed, 5 insertions(+), 48 deletions(-)
>
> diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
> index cfd1ce3..1d36db1 100644
> --- a/fs/cifs/asn1.c
> +++ b/fs/cifs/asn1.c
> @@ -614,53 +614,10 @@ decode_negTokenInit(unsigned char *security_blob, int length,
>                 }
>         }
>
> -       /* mechlistMIC */
> -       if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> -               /* Check if we have reached the end of the blob, but with
> -                  no mechListMic (e.g. NTLMSSP instead of KRB5) */
> -               if (ctx.error == ASN1_ERR_DEC_EMPTY)
> -                       goto decode_negtoken_exit;
> -               cFYI(1, "Error decoding last part negTokenInit exit3");
> -               return 0;
> -       } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
> -               /* tag = 3 indicating mechListMIC */
> -               cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
> -                       cls, con, tag, end, *end);
> -               return 0;
> -       }
> -
> -       /* sequence */
> -       if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> -               cFYI(1, "Error decoding last part negTokenInit exit5");
> -               return 0;
> -       } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
> -                  || (tag != ASN1_SEQ)) {
> -               cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)",
> -                       cls, con, tag, end, *end);
> -       }
> -
> -       /* sequence of */
> -       if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> -               cFYI(1, "Error decoding last part negTokenInit exit 7");
> -               return 0;
> -       } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
> -               cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
> -                       cls, con, tag, end, *end);
> -               return 0;
> -       }
> -
> -       /* general string */
> -       if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
> -               cFYI(1, "Error decoding last part negTokenInit exit9");
> -               return 0;
> -       } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
> -                  || (tag != ASN1_GENSTR)) {
> -               cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)",
> -                       cls, con, tag, end, *end);
> -               return 0;
> -       }
> -       cFYI(1, "Need to call asn1_octets_decode() function for %s",
> -               ctx.pointer);   /* is this UTF-8 or ASCII? */
> -decode_negtoken_exit:
> +       /*
> +        * We currently ignore anything at the end of the SPNEGO blob after
> +        * the mechTypes have been parsed, since none of that info is
> +        * used at the moment.
> +        */
>         return 1;
>  }
> --
> 1.7.11.7
>
Andrew Bartlett March 17, 2013, 9:14 p.m. UTC | #4
On Sun, 2013-03-17 at 09:37 -0500, Steve French wrote:
> The existing code is trying to dump the "principal" from the
> mechListMic (presumably for debugging) in the SMB negotiate response.
> In the trace I looked at Samba server set it to "NONE"  - is there a
> case where we would ever need that?

No, the "principal" should never be used, and isn't even useful for
debugging as you should just never use it.  It can be set to strange and
invalid values such as NONE and rfc....should_ignore

Andrew Bartlett
Steve French March 17, 2013, 10 p.m. UTC | #5
On Sun, Mar 17, 2013 at 4:14 PM, Andrew Bartlett <abartlet@samba.org> wrote:
> On Sun, 2013-03-17 at 09:37 -0500, Steve French wrote:
>> The existing code is trying to dump the "principal" from the
>> mechListMic (presumably for debugging) in the SMB negotiate response.
>> In the trace I looked at Samba server set it to "NONE"  - is there a
>> case where we would ever need that?
>
> No, the "principal" should never be used, and isn't even useful for
> debugging as you should just never use it.  It can be set to strange and
> invalid values such as NONE and rfc....should_ignore

Thanks - then it makes more sense to do as Jeff suggested and removing
the extra parsing.
diff mbox

Patch

diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index cfd1ce3..1d36db1 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -614,53 +614,10 @@  decode_negTokenInit(unsigned char *security_blob, int length,
 		}
 	}
 
-	/* mechlistMIC */
-	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		/* Check if we have reached the end of the blob, but with
-		   no mechListMic (e.g. NTLMSSP instead of KRB5) */
-		if (ctx.error == ASN1_ERR_DEC_EMPTY)
-			goto decode_negtoken_exit;
-		cFYI(1, "Error decoding last part negTokenInit exit3");
-		return 0;
-	} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
-		/* tag = 3 indicating mechListMIC */
-		cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
-			cls, con, tag, end, *end);
-		return 0;
-	}
-
-	/* sequence */
-	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, "Error decoding last part negTokenInit exit5");
-		return 0;
-	} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
-		   || (tag != ASN1_SEQ)) {
-		cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)",
-			cls, con, tag, end, *end);
-	}
-
-	/* sequence of */
-	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, "Error decoding last part negTokenInit exit 7");
-		return 0;
-	} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
-		cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
-			cls, con, tag, end, *end);
-		return 0;
-	}
-
-	/* general string */
-	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, "Error decoding last part negTokenInit exit9");
-		return 0;
-	} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
-		   || (tag != ASN1_GENSTR)) {
-		cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)",
-			cls, con, tag, end, *end);
-		return 0;
-	}
-	cFYI(1, "Need to call asn1_octets_decode() function for %s",
-		ctx.pointer);	/* is this UTF-8 or ASCII? */
-decode_negtoken_exit:
+	/*
+	 * We currently ignore anything at the end of the SPNEGO blob after
+	 * the mechTypes have been parsed, since none of that info is
+	 * used at the moment.
+	 */
 	return 1;
 }