diff mbox

[09/11] cifs: allow mixed secTypes on a socket

Message ID 1272110272-20686-10-git-send-email-jlayton@redhat.com
State New
Headers show

Commit Message

Jeff Layton April 24, 2010, 11:57 a.m. UTC
Allow secType to be set on a per-session basis. This allows us to mix
secTypes on a single socket. Also, add a "sign" bool to cifsSesInfo
and determine whether signing should be enabled at session setup
time.

Try to clarify the code that makes decisions about what sectype to
use by using a securityEnum in the volume info instead of a set of
flags.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifsglob.h  |   12 ++-
 fs/cifs/cifspdu.h   |    2 +
 fs/cifs/cifssmb.c   |  127 ++------------------------------
 fs/cifs/connect.c   |  202 ++++++++++++++++++++++++++++++++++++++++++++-------
 fs/cifs/file.c      |   12 +--
 fs/cifs/misc.c      |    6 +-
 fs/cifs/sess.c      |   34 +++++----
 fs/cifs/transport.c |   12 +--
 8 files changed, 218 insertions(+), 189 deletions(-)

Comments

Steve French May 6, 2010, 10:29 p.m. UTC | #1
On Sat, Apr 24, 2010 at 6:57 AM, Jeff Layton <jlayton@redhat.com> wrote:

> Allow secType to be set on a per-session basis. This allows us to mix
> secTypes on a single socket. Also, add a "sign" bool to cifsSesInfo
> and determine whether signing should be enabled at session setup
> time.
>
>  enum securityEnum {
> -       PLAINTXT = 0,           /* Legacy with Plaintext passwords */
> +       Undefined = 0,          /* Uninitialized */
> +       Anonymous,              /* Anonymous login */
> +       Plaintext,              /* Legacy with plaintext passwords */
>        LANMAN,                 /* Legacy LANMAN auth */
>        NTLM,                   /* Legacy NTLM012 auth with NTLM hash */
>        NTLMv2,                 /* Legacy NTLM auth with NTLMv2 hash */
> -       RawNTLMSSP,             /* NTLMSSP without SPNEGO, NTLMv2 hash */
> -/*     NTLMSSP, */ /* can use rawNTLMSSP instead of NTLMSSP via SPNEGO */
> +       NTLMSSP,                /* NTLMSSP, NTLMv1 hash */
>        Kerberos,               /* Kerberos via SPNEGO */
>  };
>
>
I like how this adds anonymous, and starts that with 1 rather than 0 - makes
sense.

> @@ -978,42 +978,39 @@ cifs_parse_mount_options(char *options, const char
> *devname,
>                                cERROR(1, "no security value specified");
>                                continue;
>                        } else if (strnicmp(value, "krb5i", 5) == 0) {
> -                               vol->secFlg |= CIFSSEC_MAY_KRB5 |
> -                                       CIFSSEC_MUST_SIGN;
> +                               vol->sectype = Kerberos;
> +                               vol->sign = true;
>                        } else if (strnicmp(value, "krb5p", 5) == 0) {
> -                               /* vol->secFlg |= CIFSSEC_MUST_SEAL |
> -                                       CIFSSEC_MAY_KRB5; */
>                                cERROR(1, "Krb5 cifs privacy not
> supported");
>                                return 1;
>                        } else if (strnicmp(value, "krb5", 4) == 0) {
> -                               vol->secFlg |= CIFSSEC_MAY_KRB5;
> +                               vol->sectype = Kerberos;
>


Doesn't this change behavior a lot - user can no longer pass in a list of
more than one acceptable security options as before (e.g. sec=krb5,
sec=ntlmv2i)
and can only specify one (but doesn't know ahead of time which the server
supports).

Also curious if it changed how plaintext was handled (if build with weak
password support allowed, which I don't want to encourage) - IIRC we sent
this via the older (LANMAN only) style session setup.
Jeff Layton May 7, 2010, 7:31 a.m. UTC | #2
On Thu, 6 May 2010 17:29:17 -0500
Steve French <smfrench@gmail.com> wrote:

> On Sat, Apr 24, 2010 at 6:57 AM, Jeff Layton <jlayton@redhat.com> wrote:
> 
> > Allow secType to be set on a per-session basis. This allows us to mix
> > secTypes on a single socket. Also, add a "sign" bool to cifsSesInfo
> > and determine whether signing should be enabled at session setup
> > time.
> >
> >  enum securityEnum {
> > -       PLAINTXT = 0,           /* Legacy with Plaintext passwords */
> > +       Undefined = 0,          /* Uninitialized */
> > +       Anonymous,              /* Anonymous login */
> > +       Plaintext,              /* Legacy with plaintext passwords */
> >        LANMAN,                 /* Legacy LANMAN auth */
> >        NTLM,                   /* Legacy NTLM012 auth with NTLM hash */
> >        NTLMv2,                 /* Legacy NTLM auth with NTLMv2 hash */
> > -       RawNTLMSSP,             /* NTLMSSP without SPNEGO, NTLMv2 hash */
> > -/*     NTLMSSP, */ /* can use rawNTLMSSP instead of NTLMSSP via SPNEGO */
> > +       NTLMSSP,                /* NTLMSSP, NTLMv1 hash */
> >        Kerberos,               /* Kerberos via SPNEGO */
> >  };
> >
> >
> I like how this adds anonymous, and starts that with 1 rather than 0 - makes
> sense.
> 
> > @@ -978,42 +978,39 @@ cifs_parse_mount_options(char *options, const char
> > *devname,
> >                                cERROR(1, "no security value specified");
> >                                continue;
> >                        } else if (strnicmp(value, "krb5i", 5) == 0) {
> > -                               vol->secFlg |= CIFSSEC_MAY_KRB5 |
> > -                                       CIFSSEC_MUST_SIGN;
> > +                               vol->sectype = Kerberos;
> > +                               vol->sign = true;
> >                        } else if (strnicmp(value, "krb5p", 5) == 0) {
> > -                               /* vol->secFlg |= CIFSSEC_MUST_SEAL |
> > -                                       CIFSSEC_MAY_KRB5; */
> >                                cERROR(1, "Krb5 cifs privacy not
> > supported");
> >                                return 1;
> >                        } else if (strnicmp(value, "krb5", 4) == 0) {
> > -                               vol->secFlg |= CIFSSEC_MAY_KRB5;
> > +                               vol->sectype = Kerberos;
> >
> 
> 
> Doesn't this change behavior a lot - user can no longer pass in a list of
> more than one acceptable security options as before (e.g. sec=krb5,
> sec=ntlmv2i)
> and can only specify one (but doesn't know ahead of time which the server
> supports).
> 
> Also curious if it changed how plaintext was handled (if build with weak
> password support allowed, which I don't want to encourage) - IIRC we sent
> this via the older (LANMAN only) style session setup.
> 
> 

It does change that behavior. I didn't realize that was a use case we
were interested in supporting.

Note that the existing code:

1) doesn't take the order of sec= options into account to indicate the
preference (this one will, with the well-established behavior that last
option specified wins)

2) doesn't try multiple auth types in turn. It's going to pick one and
go with it.

If it is important to allow specification of multiple sec= options,
could you clarify what should the behavior be when someone does this?
Steve French May 7, 2010, 7:51 a.m. UTC | #3
On Fri, May 7, 2010 at 2:31 AM, Jeff Layton <jlayton@redhat.com> wrote:
>> > @@ -978,42 +978,39 @@ cifs_parse_mount_options(char *options, const char
>> > *devname,
>> >                                cERROR(1, "no security value specified");
>> >                                continue;
>> >                        } else if (strnicmp(value, "krb5i", 5) == 0) {
>> > -                               vol->secFlg |= CIFSSEC_MAY_KRB5 |
>> > -                                       CIFSSEC_MUST_SIGN;
>> > +                               vol->sectype = Kerberos;
>> > +                               vol->sign = true;
>> >                        } else if (strnicmp(value, "krb5p", 5) == 0) {
>> > -                               /* vol->secFlg |= CIFSSEC_MUST_SEAL |
>> > -                                       CIFSSEC_MAY_KRB5; */
>> >                                cERROR(1, "Krb5 cifs privacy not
>> > supported");
>> >                                return 1;
>> >                        } else if (strnicmp(value, "krb5", 4) == 0) {
>> > -                               vol->secFlg |= CIFSSEC_MAY_KRB5;
>> > +                               vol->sectype = Kerberos;
>> >
>>
>>
>> Doesn't this change behavior a lot - user can no longer pass in a list of
>> more than one acceptable security options as before (e.g. sec=krb5,
>> sec=ntlmv2i)
>> and can only specify one (but doesn't know ahead of time which the server
>> supports).
>>
>> Also curious if it changed how plaintext was handled (if build with weak
>> password support allowed, which I don't want to encourage) - IIRC we sent
>> this via the older (LANMAN only) style session setup.
>>
>>
>
> It does change that behavior. I didn't realize that was a use case we
> were interested in supporting.
>
> Note that the existing code:
>
> 1) doesn't take the order of sec= options into account to indicate the
> preference (this one will, with the well-established behavior that last
> option specified wins)
>
> 2) doesn't try multiple auth types in turn. It's going to pick one and
> go with it.
>
> If it is important to allow specification of multiple sec= options,
> could you clarify what should the behavior be when someone does this

1) If no sec options specified on mount, it chooses among the available
mechanisms (configurable globally in /proc/fs/cifs - a distro could
populate this pseudofile at boot time from a configuration file, if
they want to
restrict or expand the available mechanisms) and picks from among
those the server supports.

2) If one sec option is specified on mount, that mechanism is used
if the server supports it, otherwise fails

3) If more than one sec option is specified, the behavior should
be similar to temporarily setting the available mechanisms
in /proc/fs/cifs  (cifs.ko picks among those based on
what the server would support).   General idea with specifying
multiple sec options - the user says which mechanisms
are acceptable to it, and as long as the server supports them,
the user lets cifs.ko decide which is "best"

2) If sec options
Shirish Pargaonkar May 7, 2010, 8:31 a.m. UTC | #4
On Fri, May 7, 2010 at 2:51 AM, Steve French <smfrench@gmail.com> wrote:
> On Fri, May 7, 2010 at 2:31 AM, Jeff Layton <jlayton@redhat.com> wrote:
>>> > @@ -978,42 +978,39 @@ cifs_parse_mount_options(char *options, const char
>>> > *devname,
>>> >                                cERROR(1, "no security value specified");
>>> >                                continue;
>>> >                        } else if (strnicmp(value, "krb5i", 5) == 0) {
>>> > -                               vol->secFlg |= CIFSSEC_MAY_KRB5 |
>>> > -                                       CIFSSEC_MUST_SIGN;
>>> > +                               vol->sectype = Kerberos;
>>> > +                               vol->sign = true;
>>> >                        } else if (strnicmp(value, "krb5p", 5) == 0) {
>>> > -                               /* vol->secFlg |= CIFSSEC_MUST_SEAL |
>>> > -                                       CIFSSEC_MAY_KRB5; */
>>> >                                cERROR(1, "Krb5 cifs privacy not
>>> > supported");
>>> >                                return 1;
>>> >                        } else if (strnicmp(value, "krb5", 4) == 0) {
>>> > -                               vol->secFlg |= CIFSSEC_MAY_KRB5;
>>> > +                               vol->sectype = Kerberos;
>>> >
>>>
>>>
>>> Doesn't this change behavior a lot - user can no longer pass in a list of
>>> more than one acceptable security options as before (e.g. sec=krb5,
>>> sec=ntlmv2i)
>>> and can only specify one (but doesn't know ahead of time which the server
>>> supports).
>>>
>>> Also curious if it changed how plaintext was handled (if build with weak
>>> password support allowed, which I don't want to encourage) - IIRC we sent
>>> this via the older (LANMAN only) style session setup.
>>>
>>>
>>
>> It does change that behavior. I didn't realize that was a use case we
>> were interested in supporting.
>>
>> Note that the existing code:
>>
>> 1) doesn't take the order of sec= options into account to indicate the
>> preference (this one will, with the well-established behavior that last
>> option specified wins)
>>
>> 2) doesn't try multiple auth types in turn. It's going to pick one and
>> go with it.
>>
>> If it is important to allow specification of multiple sec= options,
>> could you clarify what should the behavior be when someone does this
>
> 1) If no sec options specified on mount, it chooses among the available
> mechanisms (configurable globally in /proc/fs/cifs - a distro could
> populate this pseudofile at boot time from a configuration file, if
> they want to
> restrict or expand the available mechanisms) and picks from among
> those the server supports.
>
> 2) If one sec option is specified on mount, that mechanism is used
> if the server supports it, otherwise fails
>
> 3) If more than one sec option is specified, the behavior should
> be similar to temporarily setting the available mechanisms
> in /proc/fs/cifs  (cifs.ko picks among those based on
> what the server would support).   General idea with specifying
> multiple sec options - the user says which mechanisms
> are acceptable to it, and as long as the server supports them,
> the user lets cifs.ko decide which is "best"
>
> 2) If sec options
>
>
>
> --
> Thanks,
>
> Steve
> _______________________________________________
> linux-cifs-client mailing list
> linux-cifs-client@lists.samba.org
> https://lists.samba.org/mailman/listinfo/linux-cifs-client
>

Should cifs consider at all security mechanisms a server
provides/supports in neg prot response?
In case of this Win7, I see snmpv2-smi and ntlmssp but no kerberos e.g.
Jeff Layton May 7, 2010, 11:18 a.m. UTC | #5
On Fri, 7 May 2010 02:51:50 -0500
Steve French <smfrench@gmail.com> wrote:

> On Fri, May 7, 2010 at 2:31 AM, Jeff Layton <jlayton@redhat.com> wrote:
> >> > @@ -978,42 +978,39 @@ cifs_parse_mount_options(char *options, const char
> >> > *devname,
> >> >                                cERROR(1, "no security value specified");
> >> >                                continue;
> >> >                        } else if (strnicmp(value, "krb5i", 5) == 0) {
> >> > -                               vol->secFlg |= CIFSSEC_MAY_KRB5 |
> >> > -                                       CIFSSEC_MUST_SIGN;
> >> > +                               vol->sectype = Kerberos;
> >> > +                               vol->sign = true;
> >> >                        } else if (strnicmp(value, "krb5p", 5) == 0) {
> >> > -                               /* vol->secFlg |= CIFSSEC_MUST_SEAL |
> >> > -                                       CIFSSEC_MAY_KRB5; */
> >> >                                cERROR(1, "Krb5 cifs privacy not
> >> > supported");
> >> >                                return 1;
> >> >                        } else if (strnicmp(value, "krb5", 4) == 0) {
> >> > -                               vol->secFlg |= CIFSSEC_MAY_KRB5;
> >> > +                               vol->sectype = Kerberos;
> >> >
> >>
> >>
> >> Doesn't this change behavior a lot - user can no longer pass in a list of
> >> more than one acceptable security options as before (e.g. sec=krb5,
> >> sec=ntlmv2i)
> >> and can only specify one (but doesn't know ahead of time which the server
> >> supports).
> >>
> >> Also curious if it changed how plaintext was handled (if build with weak
> >> password support allowed, which I don't want to encourage) - IIRC we sent
> >> this via the older (LANMAN only) style session setup.
> >>
> >>
> >
> > It does change that behavior. I didn't realize that was a use case we
> > were interested in supporting.
> >
> > Note that the existing code:
> >
> > 1) doesn't take the order of sec= options into account to indicate the
> > preference (this one will, with the well-established behavior that last
> > option specified wins)
> >
> > 2) doesn't try multiple auth types in turn. It's going to pick one and
> > go with it.
> >
> > If it is important to allow specification of multiple sec= options,
> > could you clarify what should the behavior be when someone does this
> 
> 1) If no sec options specified on mount, it chooses among the available
> mechanisms (configurable globally in /proc/fs/cifs - a distro could
> populate this pseudofile at boot time from a configuration file, if
> they want to
> restrict or expand the available mechanisms) and picks from among
> those the server supports.
> 

Right. That behavior should be preserved by this patchset (with some
sensible modifications like auto-enabling signing).

> 2) If one sec option is specified on mount, that mechanism is used
> if the server supports it, otherwise fails
> 

Same with this patch.

> 3) If more than one sec option is specified, the behavior should
> be similar to temporarily setting the available mechanisms
> in /proc/fs/cifs  (cifs.ko picks among those based on
> what the server would support).   General idea with specifying
> multiple sec options - the user says which mechanisms
> are acceptable to it, and as long as the server supports them,
> the user lets cifs.ko decide which is "best"
> 

This tosses out that behavior. Do you feel it's important to preserve
it somehow?
Jeff Layton May 7, 2010, 11:25 a.m. UTC | #6
On Fri, 7 May 2010 13:18:29 +0200
Jeff Layton <jlayton@redhat.com> wrote:

> On Fri, 7 May 2010 02:51:50 -0500
> Steve French <smfrench@gmail.com> wrote:
> 
> > On Fri, May 7, 2010 at 2:31 AM, Jeff Layton <jlayton@redhat.com> wrote:
> > >> > @@ -978,42 +978,39 @@ cifs_parse_mount_options(char *options, const char
> > >> > *devname,
> > >> >                                cERROR(1, "no security value specified");
> > >> >                                continue;
> > >> >                        } else if (strnicmp(value, "krb5i", 5) == 0) {
> > >> > -                               vol->secFlg |= CIFSSEC_MAY_KRB5 |
> > >> > -                                       CIFSSEC_MUST_SIGN;
> > >> > +                               vol->sectype = Kerberos;
> > >> > +                               vol->sign = true;
> > >> >                        } else if (strnicmp(value, "krb5p", 5) == 0) {
> > >> > -                               /* vol->secFlg |= CIFSSEC_MUST_SEAL |
> > >> > -                                       CIFSSEC_MAY_KRB5; */
> > >> >                                cERROR(1, "Krb5 cifs privacy not
> > >> > supported");
> > >> >                                return 1;
> > >> >                        } else if (strnicmp(value, "krb5", 4) == 0) {
> > >> > -                               vol->secFlg |= CIFSSEC_MAY_KRB5;
> > >> > +                               vol->sectype = Kerberos;
> > >> >
> > >>
> > >>
> > >> Doesn't this change behavior a lot - user can no longer pass in a list of
> > >> more than one acceptable security options as before (e.g. sec=krb5,
> > >> sec=ntlmv2i)
> > >> and can only specify one (but doesn't know ahead of time which the server
> > >> supports).
> > >>
> > >> Also curious if it changed how plaintext was handled (if build with weak
> > >> password support allowed, which I don't want to encourage) - IIRC we sent
> > >> this via the older (LANMAN only) style session setup.
> > >>
> > >>
> > >
> > > It does change that behavior. I didn't realize that was a use case we
> > > were interested in supporting.
> > >
> > > Note that the existing code:
> > >
> > > 1) doesn't take the order of sec= options into account to indicate the
> > > preference (this one will, with the well-established behavior that last
> > > option specified wins)
> > >
> > > 2) doesn't try multiple auth types in turn. It's going to pick one and
> > > go with it.
> > >
> > > If it is important to allow specification of multiple sec= options,
> > > could you clarify what should the behavior be when someone does this
> > 
> > 1) If no sec options specified on mount, it chooses among the available
> > mechanisms (configurable globally in /proc/fs/cifs - a distro could
> > populate this pseudofile at boot time from a configuration file, if
> > they want to
> > restrict or expand the available mechanisms) and picks from among
> > those the server supports.
> > 
> 
> Right. That behavior should be preserved by this patchset (with some
> sensible modifications like auto-enabling signing).
> 
> > 2) If one sec option is specified on mount, that mechanism is used
> > if the server supports it, otherwise fails
> > 
> 
> Same with this patch.
> 
> > 3) If more than one sec option is specified, the behavior should
> > be similar to temporarily setting the available mechanisms
> > in /proc/fs/cifs  (cifs.ko picks among those based on
> > what the server would support).   General idea with specifying
> > multiple sec options - the user says which mechanisms
> > are acceptable to it, and as long as the server supports them,
> > the user lets cifs.ko decide which is "best"
> > 
> 
> This tosses out that behavior. Do you feel it's important to preserve
> it somehow?
> 

FWIW, I'll also note that the sec= documentation is pretty sparse:

       sec=
           Security mode. Allowed values are: (blah)

...so I'm not sure that we have any sort of "social contract" to
preserve the existing behavior of multiple sec= options.
Steve French May 7, 2010, 11:56 a.m. UTC | #7
On 5/7/10, Jeff Layton <jlayton@samba.org> wrote:
>> > 3) If more than one sec option is specified, the behavior should
>> > be similar to temporarily setting the available mechanisms
>> > in /proc/fs/cifs  (cifs.ko picks among those based on
>> > what the server would support).   General idea with specifying
>> > multiple sec options - the user says which mechanisms
>> > are acceptable to it, and as long as the server supports them,
>> > the user lets cifs.ko decide which is "best"
>> >
>>
>> This tosses out that behavior. Do you feel it's important to preserve
>> it somehow?

Yes - being able to specify the only acceptable mechanisms
(e.g. sec=ntlmv2i,sec=krb5) is required in various cases.
Alternatively you have to flip the global security flags
temporarily which is more awkward and even
dangerous, if different mounts are issued close in time, or
worse, you have to retry the mounts multiple times with different
sec= flags each time (which is hard to do with automated
mounting via fstab).

>
> FWIW, I'll also note that the sec= documentation is pretty sparse:
>
>        sec=
>            Security mode. Allowed values are: (blah)
>
> ...so I'm not sure that we have any sort of "social contract" to
> preserve the existing behavior of multiple sec= options.
Yep.  I agree that we need to add more information to the man page,
and the Users Guide is long overdue for an update.

Since this topic (specifying multiple sec= on mount) came up
when this was originally added/discussed and there is a logical
reason for it (I might use this when not on a private network, talking
to a server which I don't know the user configuration for) - we
should probably preserve that behavior.
Jeff Layton May 7, 2010, 12:45 p.m. UTC | #8
On Fri, 7 May 2010 06:56:05 -0500
Steve French <smfrench@gmail.com> wrote:

> On 5/7/10, Jeff Layton <jlayton@samba.org> wrote:
> >> > 3) If more than one sec option is specified, the behavior should
> >> > be similar to temporarily setting the available mechanisms
> >> > in /proc/fs/cifs  (cifs.ko picks among those based on
> >> > what the server would support).   General idea with specifying
> >> > multiple sec options - the user says which mechanisms
> >> > are acceptable to it, and as long as the server supports them,
> >> > the user lets cifs.ko decide which is "best"
> >> >
> >>
> >> This tosses out that behavior. Do you feel it's important to preserve
> >> it somehow?
> 
> Yes - being able to specify the only acceptable mechanisms
> (e.g. sec=ntlmv2i,sec=krb5) is required in various cases.
> Alternatively you have to flip the global security flags
> temporarily which is more awkward and even
> dangerous, if different mounts are issued close in time, or
> worse, you have to retry the mounts multiple times with different
> sec= flags each time (which is hard to do with automated
> mounting via fstab).
> 
> >
> > FWIW, I'll also note that the sec= documentation is pretty sparse:
> >
> >        sec=
> >            Security mode. Allowed values are: (blah)
> >
> > ...so I'm not sure that we have any sort of "social contract" to
> > preserve the existing behavior of multiple sec= options.
> Yep.  I agree that we need to add more information to the man page,
> and the Users Guide is long overdue for an update.
> 
> Since this topic (specifying multiple sec= on mount) came up
> when this was originally added/discussed and there is a logical
> reason for it (I might use this when not on a private network, talking
> to a server which I don't know the user configuration for) - we
> should probably preserve that behavior.
> 

Ok, that'll mean a major rewrite of that patch and the general
approach. I'll see what can be done.
diff mbox

Patch

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 4a99487..1ececf4 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -80,12 +80,13 @@  enum statusEnum {
 };
 
 enum securityEnum {
-	PLAINTXT = 0, 		/* Legacy with Plaintext passwords */
+	Undefined = 0,		/* Uninitialized */
+	Anonymous,		/* Anonymous login */
+	Plaintext, 		/* Legacy with plaintext passwords */
 	LANMAN,			/* Legacy LANMAN auth */
 	NTLM,			/* Legacy NTLM012 auth with NTLM hash */
 	NTLMv2,			/* Legacy NTLM auth with NTLMv2 hash */
-	RawNTLMSSP,		/* NTLMSSP without SPNEGO, NTLMv2 hash */
-/*	NTLMSSP, */ /* can use rawNTLMSSP instead of NTLMSSP via SPNEGO */
+	NTLMSSP,		/* NTLMSSP, NTLMv1 hash */
 	Kerberos,		/* Kerberos via SPNEGO */
 };
 
@@ -160,7 +161,6 @@  struct TCP_Server_Info {
 	struct task_struct *tsk;
 	char server_GUID[16];
 	char secMode;
-	enum securityEnum secType;
 	unsigned int maxReq;	/* Clients should submit no more */
 	/* than maxReq distinct unanswered SMBs to the server when using  */
 	/* multiplexed reads or writes */
@@ -186,6 +186,7 @@  struct TCP_Server_Info {
 	unsigned long lstrp; /* when we got last response from this server */
 	u16 dialect; /* dialect index that server chose */
 	/* extended security flavors that server supports */
+	bool	ext_security;		/* extended security should be used */
 	bool	sec_kerberos;		/* supports plain Kerberos */
 	bool	sec_mskerberos;		/* supports legacy MS Kerberos */
 	bool	sec_kerberosu2u;	/* supports U2U Kerberos */
@@ -218,7 +219,7 @@  struct cifsSesInfo {
 	struct TCP_Server_Info *server;	/* pointer to server info */
 	int ses_count;		/* reference counter */
 	enum statusEnum status;
-	unsigned overrideSecFlg;  /* if non-zero override global sec flags */
+	enum securityEnum secType;
 	__u16 ipc_tid;		/* special tid for connection to IPC share */
 	__u16 flags;
 	__u16 vcnum;
@@ -233,6 +234,7 @@  struct cifsSesInfo {
 	char userName[MAX_USERNAME_SIZE + 1];
 	char *domainName;
 	char *password;
+	bool sign:1;		/* packet signing enabled */
 	bool need_reconnect:1; /* connection reset, uid now invalid */
 };
 /* no more than one of the following three session flags may be set */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 14d036d..d72960c 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -530,6 +530,8 @@  typedef struct negotiate_rsp {
 #define SECMODE_SIGN_ENABLED  0x04	/* SMB security signatures enabled */
 #define SECMODE_SIGN_REQUIRED 0x08	/* SMB security signatures required */
 
+#define SECMODE_SIGN	(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)
+
 /* Negotiate response Capabilities */
 #define CAP_RAW_MODE           0x00000001
 #define CAP_MPX_MODE           0x00000002
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index c65c341..7ba0b1f 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -353,46 +353,18 @@  CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 	int rc = 0;
 	int bytes_returned;
 	int i;
-	struct TCP_Server_Info *server;
+	struct TCP_Server_Info *server = ses->server;
 	u16 count;
-	unsigned int secFlags;
 
-	if (ses->server)
-		server = ses->server;
-	else {
-		rc = -EIO;
-		return rc;
-	}
 	rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
 		      (void **) &pSMB, (void **) &pSMBr);
 	if (rc)
 		return rc;
 
-	/* if any of auth flags (ie not sign or seal) are overriden use them */
-	if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
-		secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
-	else /* if override flags set only sign/seal OR them with global auth */
-		secFlags = global_secflags | ses->overrideSecFlg;
-
-	cFYI(1, "secFlags 0x%x", secFlags);
-
 	pSMB->hdr.Mid = GetNextMid(server);
-	pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
-
-	if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
-		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
-	else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
-		cFYI(1, "Kerberos only mechanism, enable extended security");
+	pSMB->hdr.Flags2 |= SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS;
+	if (server->ext_security)
 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
-	}
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-	else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
-		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
-	else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
-		cFYI(1, "NTLMSSP only mechanism, enable extended security");
-		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
-	}
-#endif
 
 	count = 0;
 	for (i = 0; i < CIFS_NUM_PROT; i++) {
@@ -424,15 +396,6 @@  CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 		__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 {
-			cERROR(1, "mount failed weak security disabled"
-				   " in /proc/fs/cifs/SecurityFlags");
-			rc = -EOPNOTSUPP;
-			goto neg_err_exit;
-		}
 		server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
 		server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
 		server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
@@ -496,7 +459,7 @@  CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 		cFYI(1, "LANMAN negotiated");
 		/* 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;
+		goto neg_err_exit;
 #else /* weak security disabled */
 	} else if (pSMBr->hdr.WordCount == 13) {
 		cERROR(1, "mount failed, cifs module not built "
@@ -514,36 +477,6 @@  CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 	if ((server->secMode & SECMODE_USER) == 0)
 		cFYI(1, "share mode security");
 
-	if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
-#ifdef CONFIG_CIFS_WEAK_PW_HASH
-		if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
-#endif /* CIFS_WEAK_PW_HASH */
-			cERROR(1, "Server requests plain text password"
-				  " but client support disabled");
-
-	if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
-		server->secType = NTLMv2;
-	else if (secFlags & CIFSSEC_MAY_NTLM)
-		server->secType = NTLM;
-	else if (secFlags & CIFSSEC_MAY_NTLMV2)
-		server->secType = NTLMv2;
-	else if (secFlags & CIFSSEC_MAY_KRB5)
-		server->secType = Kerberos;
-	else if (secFlags & CIFSSEC_MAY_NTLMSSP)
-		server->secType = RawNTLMSSP;
-	else if (secFlags & CIFSSEC_MAY_LANMAN)
-		server->secType = LANMAN;
-/* #ifdef CONFIG_CIFS_EXPERIMENTAL
-	else if (secFlags & CIFSSEC_MAY_PLNTXT)
-		server->secType = ??
-#endif */
-	else {
-		rc = -EOPNOTSUPP;
-		cERROR(1, "Invalid security type");
-		goto neg_err_exit;
-	}
-	/* else ... any others ...? */
-
 	/* one byte, so no need to convert this or EncryptionKeyLen from
 	   little endian */
 	server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
@@ -594,7 +527,7 @@  CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 		}
 
 		if (count == 16) {
-			server->secType = RawNTLMSSP;
+			ses->secType = NTLMSSP;
 		} else {
 			rc = decode_negTokenInit(pSMBr->u.extended_response.
 						 SecurityBlob, count - 16,
@@ -603,48 +536,10 @@  CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 				rc = 0;
 			else
 				rc = -EINVAL;
-
-			if (server->sec_kerberos || server->sec_mskerberos)
-				server->secType = Kerberos;
-			else if (server->sec_ntlmssp)
-				server->secType = RawNTLMSSP;
-			else
-				rc = -EOPNOTSUPP;
 		}
 	} else
 		server->capabilities &= ~CAP_EXTENDED_SECURITY;
 
-#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 */
-		cFYI(1, "Signing disabled");
-		if (server->secMode & SECMODE_SIGN_REQUIRED) {
-			cERROR(1, "Server requires "
-				   "packet signing to be enabled in "
-				   "/proc/fs/cifs/SecurityFlags.");
-			rc = -EOPNOTSUPP;
-		}
-		server->secMode &=
-			~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
-	} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
-		/* signing required */
-		cFYI(1, "Must sign - secFlags 0x%x", secFlags);
-		if ((server->secMode &
-			(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
-			cERROR(1, "signing required but server lacks support");
-			rc = -EOPNOTSUPP;
-		} else
-			server->secMode |= SECMODE_SIGN_REQUIRED;
-	} else {
-		/* signing optional ie CIFSSEC_MAY_SIGN */
-		if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
-			server->secMode &=
-				~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
-	}
-
 neg_err_exit:
 	cifs_buf_release(pSMB);
 
@@ -718,9 +613,8 @@  CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
 
 	pSMB->hdr.Mid = GetNextMid(ses->server);
 
-	if (ses->server->secMode &
-		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+	if (ses->sign)
+		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
 	pSMB->hdr.Uid = ses->Suid;
 
@@ -4158,11 +4052,8 @@  getDFSRetry:
 		strncpy(pSMB->RequestFileName, searchName, name_len);
 	}
 
-	if (ses->server) {
-		if (ses->server->secMode &
-		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-	}
+	if (ses->sign)
+		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
 	pSMB->hdr.Uid = ses->Suid;
 
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index fba6b78..c5cbe7d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -70,7 +70,7 @@  struct smb_vol {
 	gid_t linux_gid;
 	mode_t file_mode;
 	mode_t dir_mode;
-	unsigned secFlg;
+	enum securityEnum sectype;
 	bool retry:1;
 	bool intr:1;
 	bool setuids:1;
@@ -87,10 +87,10 @@  struct smb_vol {
 	bool posix_paths:1; /* unset to not ask for posix pathnames. */
 	bool no_linux_ext:1;
 	bool sfu_emul:1;
-	bool nullauth:1;   /* attempt to authenticate with null user */
 	bool nocase:1;     /* request case insensitive filenames */
 	bool nobrl:1;      /* disable sending byte range locks to srv */
 	bool mand_lock:1;  /* send mandatory not posix byte range lock reqs */
+	bool sign:1;
 	bool seal:1;       /* request transport encryption on share */
 	bool nodfs:1;      /* Do not request DFS, even if available */
 	bool local_lease:1; /* check leases only on local system, not remote */
@@ -872,7 +872,7 @@  cifs_parse_mount_options(char *options, const char *devname,
 				return 1;	/* needs_arg; */
 			} else if (!*value) {
 				/* null user, ie anonymous, authentication */
-				vol->nullauth = 1;
+				vol->sectype = Anonymous;
 			}
 			if (strnlen(value, 200) < 200) {
 				vol->username = value;
@@ -978,42 +978,39 @@  cifs_parse_mount_options(char *options, const char *devname,
 				cERROR(1, "no security value specified");
 				continue;
 			} else if (strnicmp(value, "krb5i", 5) == 0) {
-				vol->secFlg |= CIFSSEC_MAY_KRB5 |
-					CIFSSEC_MUST_SIGN;
+				vol->sectype = Kerberos;
+				vol->sign = true;
 			} else if (strnicmp(value, "krb5p", 5) == 0) {
-				/* vol->secFlg |= CIFSSEC_MUST_SEAL |
-					CIFSSEC_MAY_KRB5; */
 				cERROR(1, "Krb5 cifs privacy not supported");
 				return 1;
 			} else if (strnicmp(value, "krb5", 4) == 0) {
-				vol->secFlg |= CIFSSEC_MAY_KRB5;
+				vol->sectype = Kerberos;
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 			} else if (strnicmp(value, "ntlmsspi", 8) == 0) {
-				vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
-					CIFSSEC_MUST_SIGN;
+				vol->sectype = NTLMSSP;
+				vol->sign = true;
 			} else if (strnicmp(value, "ntlmssp", 7) == 0) {
-				vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
+				vol->sectype = NTLMSSP;
 #endif
 			} else if (strnicmp(value, "ntlmv2i", 7) == 0) {
-				vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
-					CIFSSEC_MUST_SIGN;
+				vol->sectype = NTLMv2;
+				vol->sign = true;
 			} else if (strnicmp(value, "ntlmv2", 6) == 0) {
-				vol->secFlg |= CIFSSEC_MAY_NTLMV2;
+				vol->sectype = NTLMv2;
 			} else if (strnicmp(value, "ntlmi", 5) == 0) {
-				vol->secFlg |= CIFSSEC_MAY_NTLM |
-					CIFSSEC_MUST_SIGN;
+				vol->sectype = NTLM;
+				vol->sign = true;
 			} else if (strnicmp(value, "ntlm", 4) == 0) {
-				/* ntlm is default so can be turned off too */
-				vol->secFlg |= CIFSSEC_MAY_NTLM;
+				vol->sectype = NTLM;
 			} else if (strnicmp(value, "nontlm", 6) == 0) {
 				/* BB is there a better way to do this? */
-				vol->secFlg |= CIFSSEC_MAY_NTLMV2;
+				vol->sectype = NTLMv2;
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 			} else if (strnicmp(value, "lanman", 6) == 0) {
-				vol->secFlg |= CIFSSEC_MAY_LANMAN;
+				vol->sectype = LANMAN;
 #endif
 			} else if (strnicmp(value, "none", 4) == 0) {
-				vol->nullauth = 1;
+				vol->sectype = Anonymous;
 			} else {
 				cERROR(1, "bad security option: %s", value);
 				return 1;
@@ -1316,12 +1313,11 @@  cifs_parse_mount_options(char *options, const char *devname,
 			vol->local_lease = 1;
 #endif
 		} else if (strnicmp(data, "sign", 4) == 0) {
-			vol->secFlg |= CIFSSEC_MUST_SIGN;
+			vol->sign = 1;
 		} else if (strnicmp(data, "seal", 4) == 0) {
 			/* we do not do the following in secFlags because seal
 			   is a per tree connection (mount) not a per socket
 			   or per-smb connection option in the protocol */
-			/* vol->secFlg |= CIFSSEC_MUST_SEAL; */
 			vol->seal = 1;
 		} else if (strnicmp(data, "direct", 6) == 0) {
 			vol->direct_io = 1;
@@ -1380,6 +1376,150 @@  cifs_parse_mount_options(char *options, const char *devname,
 	return 0;
 }
 
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+static enum securityEnum
+check_lanman(void)
+{
+	/* only allow if secflags say it's ok */
+	if (global_secflags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT))
+		return LANMAN;
+
+	return Undefined;
+}
+
+static bool
+check_plaintext(struct TCP_Server_Info *server) {
+	if (server->secMode & SECMODE_PW_ENCRYPT)
+		return true;
+	if (global_secflags & CIFSSEC_MAY_PLNTXT)
+		return true;
+	cERROR(1, "Server requested plaintext password, but support is "
+		  "disabled in /proc/fs/cifs/SecurityFlags");
+	return false;
+}
+#else /* CONFIG_CIFS_WEAK_PW_HASH */
+static enum securityEnum
+check_lanman(void)
+{
+	return Undefined;
+}
+
+static bool
+check_plaintext(struct TCP_Server_Info *server) {
+	return false;
+}
+#endif /* CONFIG_CIFS_WEAK_PW_HASH */
+
+static bool
+use_extended_security(struct smb_vol *vol)
+{
+	if (vol->sectype == Kerberos || vol->sectype == NTLMSSP)
+		return true;
+	return false;
+}
+
+/* decide whether session has signing enabled */
+static int
+set_ses_signing(struct cifsSesInfo *ses, struct smb_vol *vol)
+{
+	/* no signing on anonymous login */
+	if (ses->secType == Anonymous) {
+		ses->sign = false;
+	} else if (vol->sign || global_secflags & SECMODE_SIGN_REQUIRED) {
+		if (ses->server->secMode & SECMODE_SIGN) {
+			ses->sign = true;
+		} else {
+			cERROR(1, "mount options specify signing, but server "
+				  "does not support it.");
+			return -EINVAL;
+		}
+	} else if (global_secflags & SECMODE_SIGN) {
+		if (ses->server->secMode & SECMODE_SIGN_REQUIRED)
+			ses->sign = true;
+	} else if (ses->server->secMode & SECMODE_SIGN_REQUIRED) {
+		cERROR(1, "server requires signing, but client has it"
+			  "disabled in /proc/fs/cifs/SecurityFlags");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * determine the security type to use for session
+ *
+ * The decision is based on several inputs:
+ *
+ * 1) the global security flags (/proc/fs/cifs/SecurityFlags)
+ * 2) mount options (vol->sectype)
+ * 3) what the server actually supports (several fields in TCP_Server_Info)
+ *
+ * ...this is far more complicated than it ought to be, but we're saddled
+ * with legacy interfaces (SecurityFlags in particular).
+ */
+static enum securityEnum
+smb_ses_sectype(struct cifsSesInfo *ses, struct smb_vol *vol)
+{
+	struct TCP_Server_Info *server = ses->server;
+	enum securityEnum type;
+
+	/* don't change an existing session */
+	if (ses->secType != Undefined)
+		return ses->secType;
+
+	switch(vol->sectype) {
+	case Undefined:
+		break;
+	case Anonymous:
+	case NTLMSSP:
+	case NTLMv2:
+	case NTLM:
+	case LANMAN:
+		return vol->sectype;
+	case Kerberos:
+		if (server->sec_kerberos || server->sec_mskerberos)
+			return Kerberos;
+		cERROR(1, "Server doesn't support kerberos auth.");
+		return Undefined;
+	default:
+		cERROR(1, "Unknown secType=%d", vol->sectype);
+		return Undefined;
+	}
+
+	/*
+	 * no sec= option, determine based on global_secflags and what the
+	 * server supports.
+	 */
+
+	/*
+	 * extended security requires either krb5 or NTLMSSP. krb5 auth must
+	 * be specified in mount opts. That leaves NTLMSSP if it wasn't.
+	 */
+	if (server->capabilities & CAP_EXTENDED_SECURITY)
+		return NTLMSSP;
+
+	/* check for lanman first if server dialect is ancient */
+	if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT) {
+		type = check_lanman();
+		if (type != Undefined && !check_plaintext(server))
+			return Undefined;
+	}
+
+	if (type != Undefined)
+		return type;
+
+	if ((global_secflags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
+		return NTLMv2;
+	if (global_secflags & CIFSSEC_MAY_NTLM)
+		return NTLM;
+	if (global_secflags & CIFSSEC_MAY_NTLMV2)
+		return NTLMv2;
+	if (global_secflags & CIFSSEC_MAY_LANMAN)
+		return LANMAN;
+
+	return Undefined;
+}
+
 static struct TCP_Server_Info *
 cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port)
 {
@@ -1530,6 +1670,7 @@  cifs_get_tcp_session(struct smb_vol *volume_info)
 	tcp_ses->sequence_number = 0;
 	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
 	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
+	tcp_ses->ext_security = use_extended_security(volume_info);
 
 	/*
 	 * at this point we are the only ones with the pointer
@@ -1707,10 +1848,16 @@  cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
 			strcpy(ses->domainName, volume_info->domainname);
 	}
 	ses->linux_uid = volume_info->linux_uid;
-	ses->overrideSecFlg = volume_info->secFlg;
 
 	mutex_lock(&ses->session_mutex);
 	rc = cifs_negotiate_protocol(xid, ses);
+	if (!rc) {
+		ses->secType = smb_ses_sectype(ses, volume_info);
+		if (ses->secType == Undefined)
+			rc = -EOPNOTSUPP;
+	}
+	if (!rc)
+		rc = set_ses_signing(ses, volume_info);
 	if (!rc)
 		rc = cifs_setup_session(xid, ses, volume_info->local_nls);
 	mutex_unlock(&ses->session_mutex);
@@ -2512,7 +2659,7 @@  try_mount_again:
 		goto out;
 	}
 
-	if (volume_info->nullauth) {
+	if (volume_info->sectype == Anonymous) {
 		cFYI(1, "null user");
 		volume_info->username = "";
 	} else if (volume_info->username) {
@@ -2759,7 +2906,7 @@  CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
 		   NTLMv2 password here) */
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 		if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
-		    (ses->server->secType == LANMAN))
+		    (ses->secType == LANMAN))
 			calc_lanman_hash(tcon->password, ses->server->cryptKey,
 					 ses->server->secMode &
 					    SECMODE_PW_ENCRYPT ? true : false,
@@ -2777,8 +2924,7 @@  CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
 		}
 	}
 
-	if (ses->server->secMode &
-			(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+	if (ses->sign)
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
 	if (ses->capabilities & CAP_STATUS32) {
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5f1f768..c30e8fe 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1132,10 +1132,7 @@  static ssize_t cifs_write(struct file *file, const char *write_data,
 				if (rc != 0)
 					break;
 			}
-			if (experimEnabled || (pTcon->ses->server &&
-				((pTcon->ses->server->secMode &
-				(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-				== 0))) {
+			if (experimEnabled || !pTcon->ses->sign) {
 				struct kvec iov[2];
 				unsigned int len;
 
@@ -1397,11 +1394,8 @@  static int cifs_writepages(struct address_space *mapping,
 	if (cifs_sb->wsize < PAGE_CACHE_SIZE)
 		return generic_writepages(mapping, wbc);
 
-	if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
-		if (cifs_sb->tcon->ses->server->secMode &
-				(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-			if (!experimEnabled)
-				return generic_writepages(mapping, wbc);
+	if (cifs_sb->tcon->ses->sign && !experimEnabled)
+		return generic_writepages(mapping, wbc);
 
 	iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
 	if (iov == NULL)
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 1394aa3..ca58ec1 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -369,10 +369,8 @@  header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
 			buffer->Flags2 |= SMBFLG2_DFS;
 		if (treeCon->nocase)
 			buffer->Flags  |= SMBFLG_CASELESS;
-		if ((treeCon->ses) && (treeCon->ses->server))
-			if (treeCon->ses->server->secMode &
-			  (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-				buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+		if (treeCon->ses->sign)
+			buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 	}
 
 /*  endian conversion of flags is now done just before sending */
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 7707389..fd6921c 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -139,8 +139,7 @@  static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
 	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
 			CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
 
-	if (ses->server->secMode &
-	    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+	if (ses->sign)
 		pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
 	if (ses->capabilities & CAP_UNICODE) {
@@ -222,7 +221,7 @@  static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
 		bcc_ptr++;
 	} */
 	/* copy user */
-	if (ses->userName == NULL) {
+	if (ses->secType == Anonymous) {
 		/* null user mount */
 		*bcc_ptr = 0;
 		*(bcc_ptr+1) = 0;
@@ -426,8 +425,7 @@  static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
 	flags = NTLMSSP_NEGOTIATE_56 |	NTLMSSP_REQUEST_TARGET |
 		NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
 		NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
-	if (ses->server->secMode &
-	   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+	if (ses->sign)
 		flags |= NTLMSSP_NEGOTIATE_SIGN;
 	if (ses->server->secMode & SECMODE_SIGN_REQUIRED)
 		flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
@@ -463,8 +461,7 @@  static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
 		NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
 		NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
 		NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
-	if (ses->server->secMode &
-	   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+	if (ses->sign)
 		flags |= NTLMSSP_NEGOTIATE_SIGN;
 	if (ses->server->secMode & SECMODE_SIGN_REQUIRED)
 		flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
@@ -588,14 +585,15 @@  CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
 	first_time = is_first_ses_reconnect(ses);
 	read_unlock(&cifs_tcp_ses_lock);
 
-	type = ses->server->secType;
+	type = ses->secType;
 
 	cFYI(1, "sess setup type %d", type);
 ssetup_ntlmssp_authenticate:
 	if (phase == NtLmChallenge)
 		phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
 
-	if (type == LANMAN) {
+	switch(type) {
+	case LANMAN:
 #ifndef CONFIG_CIFS_WEAK_PW_HASH
 		/* LANMAN and plaintext are less secure and off by default.
 		So we make this explicitly be turned on in kconfig (in the
@@ -605,11 +603,15 @@  ssetup_ntlmssp_authenticate:
 		return -EOPNOTSUPP;
 #endif
 		wct = 10; /* lanman 2 style sessionsetup */
-	} else if ((type == NTLM) || (type == NTLMv2)) {
-		/* For NTLMv2 failures eventually may need to retry NTLM */
-		wct = 13; /* old style NTLM sessionsetup */
-	} else /* same size: negotiate or auth, NTLMSSP or extended security */
+		break;
+	case NTLM:
+	case NTLMv2:
+	case Anonymous:
+		wct = 13;
+		break;
+	default:
 		wct = 12;
+	}
 
 	rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
 			    (void **)&smb_buf);
@@ -675,7 +677,7 @@  ssetup_ntlmssp_authenticate:
 		/* Unicode not allowed for LANMAN dialects */
 		ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
 #endif
-	} else if (type == NTLM) {
+	} else if (type == NTLM || type == Anonymous) {
 		char ntlm_session_key[CIFS_SESS_KEY_SIZE];
 
 		pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
@@ -809,7 +811,7 @@  ssetup_ntlmssp_authenticate:
 #endif /* CONFIG_CIFS_UPCALL */
 	} else {
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-		if (type == RawNTLMSSP) {
+		if (type == NTLMSSP) {
 			if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
 				cERROR(1, "NTLMSSP requires Unicode support");
 				rc = -ENOSYS;
@@ -874,7 +876,7 @@  ssetup_ntlmssp_authenticate:
 	pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
 	smb_buf = (struct smb_hdr *)iov[0].iov_base;
 
-	if ((type == RawNTLMSSP) && (smb_buf->Status.CifsError ==
+	if ((type == NTLMSSP) && (smb_buf->Status.CifsError ==
 			cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) {
 		if (phase != NtLmNegotiate) {
 			cERROR(1, "Unexpected more processing error");
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 28f563c..8a7a58e 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -540,9 +540,7 @@  SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
 
 		dump_smb(midQ->resp_buf, 80);
 		/* convert the length into a more usable form */
-		if ((receive_len > 24) &&
-		    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
-					     SECMODE_SIGN_ENABLED))) {
+		if (receive_len > 24 && ses->sign) {
 			rc = cifs_verify_signature(midQ->resp_buf,
 						&ses->server->mac_signing_key,
 						midQ->sequence_number+1);
@@ -728,9 +726,7 @@  SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 
 		dump_smb(out_buf, 92);
 		/* convert the length into a more usable form */
-		if ((receive_len > 24) &&
-		    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
-					     SECMODE_SIGN_ENABLED))) {
+		if (receive_len > 24 && ses->sign) {
 			rc = cifs_verify_signature(out_buf,
 						&ses->server->mac_signing_key,
 						midQ->sequence_number+1);
@@ -978,9 +974,7 @@  SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
 
 	dump_smb(out_buf, 92);
 	/* convert the length into a more usable form */
-	if ((receive_len > 24) &&
-	    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
-				     SECMODE_SIGN_ENABLED))) {
+	if (receive_len > 24 && ses->sign) {
 		rc = cifs_verify_signature(out_buf,
 					   &ses->server->mac_signing_key,
 					   midQ->sequence_number+1);