2009-07-10 18:28:03

by Tom Haynes

[permalink] [raw]
Subject: Security negotiation

During a NFSv3 mount request, the server returns an array of supported
security flavors.

With a Linux server, exports(5) states:

For the purposes of security flavor negotiation, order counts:
preferred flavors should be listed first.

And the Solaris client states in mount_nfs(1M):

NFS Version 3 mounts negotiate a security mode when the server
returns an array of security modes. The
client picks the first mode in the array that is supported on the
client. In negotiations, an NFS Version 3 client
is limited to the security flavors listed in /etc/nfssec.conf.

The Linux nfs(5) states:

If the sec option is not specified, or if sec=sys is specified, the
NFS client uses the AUTH_SYS
security flavor for all NFS requests on this mount point.

So, I'm trying to understand what the Linux client would do if the
export does not support AUTH_SYS and
there is no sec= supplied.

Does the Linux client traverse the array in order until it finds a match
or does it consider which flavor is strongest?



2009-07-13 17:41:39

by J. Bruce Fields

[permalink] [raw]
Subject: Re: Security negotiation

On Fri, Jul 10, 2009 at 03:55:58PM -0500, Tom Haynes wrote:
> Chuck Lever wrote:
>>
>>>
>>> If mountd does not provide AUTH_SYS a mount request with no sec= will
>>> fail. Should it try the first one in the list instead? What if the
>>> first one is AUTH_NULL?
>>
>> In other words, I'm not sure what is the right behavior here. What it
>> does now is probably suboptimal. I've browsed 2623 a bit, but it's
>> not hitting me.
>>
>
> So we (OpenSolaris) changed our behavior inadvertently to do the
> list in order. Which means we are trying AUTH_NONE against
> a Linux server. (Bug is here:
> http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6834430)

Yeah, that was a linux mountd bug. Fixed by the below. And note the
rfc language it mentions:

"For this reason, a NFS client SHOULD use the first flavor in the
list that it supports, on the assumption that the best access is
provided by the first flavor. NFS servers that support the
ability to export file systems with multiple security flavors
SHOULD either present the best accessing flavor first to the
client, or leave the order under the control of the system
administrator."

Of course we may still be stuck with buggy servers, so perhaps a careful
client will still want to handle auth_null at least specially....

--b.

commit 3c1bb23c0379864722e79d19f74c180edcf2c36e
Author: bc Wong <[email protected]>
Date: Tue Mar 18 09:30:44 2008 -0400

There were 2 things wrong with auth flavour ordering:
- Mountd used to advertise AUTH_NULL as the first flavour on
the list, which means that it prefers AUTH_NULL to anything
else (as per RFC 2623 section 2.7).
- Mount.nfs used to scan the returned list in reverse order,
and stopping at the first AUTH_NULL or AUTH_SYS encountered.
If a server advertises (AUTH_SYS, AUTH_NULL), it will by
default choose AUTH_NULL and have degraded access.

I've fixed mount.nfs to scan from the beginning. For mountd,
it does not advertise AUTH_NULL anymore. This is necessary
to avoid backward compatibility issue. If AUTH_NULL appears
in the list, either the new or the old client will choose
that over AUTH_SYS.

Tested the server/client combination against the previous
versions, as well as Solaris and FreeBSD.

Signed-off-by: bc Wong <[email protected]>
Signed-off-by: Steve Dickson <[email protected]>

diff --git a/utils/mount/nfsmount.c b/utils/mount/nfsmount.c
index d1d43c6..ff0ff93 100644
--- a/utils/mount/nfsmount.c
+++ b/utils/mount/nfsmount.c
@@ -738,7 +738,7 @@ nfsmount(const char *spec, const char *node, int flags,
#if NFS_MOUNT_VERSION >= 4
mountres3_ok *mountres;
fhandle3 *fhandle;
- int i, *flavor, yum = 0;
+ int i, n_flavors, *flavor, yum = 0;
if (mntres.nfsv3.fhs_status != 0) {
nfs_error(_("%s: %s:%s failed, reason given by server: %s"),
progname, hostname, dirname,
@@ -747,13 +747,16 @@ nfsmount(const char *spec, const char *node, int flags,
}
#if NFS_MOUNT_VERSION >= 5
mountres = &mntres.nfsv3.mountres3_u.mountinfo;
- i = mountres->auth_flavors.auth_flavors_len;
- if (i <= 0)
+ n_flavors = mountres->auth_flavors.auth_flavors_len;
+ if (n_flavors <= 0)
goto noauth_flavors;

flavor = mountres->auth_flavors.auth_flavors_val;
- while (--i >= 0) {
- /* If no flavour requested, use first simple
+ for (i = 0; i < n_flavors; ++i) {
+ /*
+ * Per RFC2623, section 2.7, we should prefer the
+ * flavour listed first.
+ * If no flavour requested, use the first simple
* flavour that is offered.
*/
if (! (data.flags & NFS_MOUNT_SECFLAVOUR) &&
diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
index 63d5ce1..8137f7f 100644
--- a/utils/mountd/mountd.c
+++ b/utils/mountd/mountd.c
@@ -342,7 +342,14 @@ mount_mnt_3_svc(struct svc_req *rqstp, dirpath *path, mountres3 *res)
#define AUTH_GSS_KRB5 390003
#define AUTH_GSS_KRB5I 390004
#define AUTH_GSS_KRB5P 390005
- static int flavors[] = { AUTH_NULL, AUTH_UNIX, AUTH_GSS_KRB5, AUTH_GSS_KRB5I, AUTH_GSS_KRB5P};
+ static int flavors[] = { AUTH_UNIX, AUTH_GSS_KRB5, AUTH_GSS_KRB5I, AUTH_GSS_KRB5P};
+ /*
+ * We should advertise the preferred flavours first. (See RFC 2623
+ * section 2.7.) AUTH_UNIX is arbitrarily ranked over the GSS's.
+ * AUTH_NULL is dropped from the list to avoid backward compatibility
+ * issue with older Linux clients, who inspect the list in reversed
+ * order.
+ */
struct nfs_fh_len *fh;

xlog(D_CALL, "MNT3(%s) called", *path);

2009-07-10 20:56:11

by Tom Haynes

[permalink] [raw]
Subject: Re: Security negotiation

Chuck Lever wrote:
>
>>
>> If mountd does not provide AUTH_SYS a mount request with no sec= will
>> fail. Should it try the first one in the list instead? What if the
>> first one is AUTH_NULL?
>
> In other words, I'm not sure what is the right behavior here. What it
> does now is probably suboptimal. I've browsed 2623 a bit, but it's
> not hitting me.
>

So we (OpenSolaris) changed our behavior inadvertently to do the
list in order. Which means we are trying AUTH_NONE against
a Linux server. (Bug is here:
http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6834430)

We are considering two changes:

1) Use our default flavor (user configurable)
2) Order the list by strength based on the flavors we support.

The first option would get us to where you are going to be. AUTH_SYS will
probably be the default.

The second option would push AUTH_NONE to the end of the list, which
corresponds to my thinking of it as a wild card.

But it also means that if AUTH_SYS is not our default, then we might try
Kerberized access first. I think that is a surprise.

Also, if the server has already ordered the list based on the preference it
would like the client to try, then the client should honor that list if no
specific flavor is used.

So, I would say algorithmically:

1) If the client specifies a flavor, it uses that if the server supports
it. If the
server does not, the mount fails.

2) If the client has a default, it tries that first if the server
supports it. If the
server does not, then:

3) The client walks the array of flavors and uses the first that it supports
and the server supports.


2009-07-14 18:24:30

by Tom Haynes

[permalink] [raw]
Subject: Re: Security negotiation

J. Bruce Fields wrote:
> Yeah, that was a linux mountd bug. Fixed by the below. And note the
> rfc language it mentions:
>
> "For this reason, a NFS client SHOULD use the first flavor in the
> list that it supports, on the assumption that the best access is
> provided by the first flavor. NFS servers that support the
> ability to export file systems with multiple security flavors
> SHOULD either present the best accessing flavor first to the
> client, or leave the order under the control of the system
> administrator."
>
> Of course we may still be stuck with buggy servers, so perhaps a careful
> client will still want to handle auth_null at least specially....
>
>

Hey Chuck and Bruce,

Thanks for the discussion on this subject, it really helped us by
understanding what the
Linux client and server was doing.

Tom

2009-07-10 18:57:29

by Chuck Lever

[permalink] [raw]
Subject: Re: Security negotiation


On Jul 10, 2009, at 2:07 PM, Tom Haynes wrote:

> During a NFSv3 mount request, the server returns an array of
> supported security flavors.
>
> With a Linux server, exports(5) states:
>
> For the purposes of security flavor negotiation, order counts:
> preferred flavors should be listed first.
>
> And the Solaris client states in mount_nfs(1M):
>
> NFS Version 3 mounts negotiate a security mode when the server
> returns an array of security modes. The
> client picks the first mode in the array that is supported on the
> client. In negotiations, an NFS Version 3 client
> is limited to the security flavors listed in /etc/nfssec.conf.
>
> The Linux nfs(5) states:
>
> If the sec option is not specified, or if sec=sys is specified,
> the NFS client uses the AUTH_SYS
> security flavor for all NFS requests on this mount point.
>
> So, I'm trying to understand what the Linux client would do if the
> export does not support AUTH_SYS and
> there is no sec= supplied.
>
> Does the Linux client traverse the array in order until it finds a
> match or does it consider which flavor is strongest?

The legacy mount command does this (kernels earlier than 2.6.23) but
the kernel mount client does not yet. I intend to submit patches for
this (today, actually) for 2.6.32.

The patches will walk the auth_list returned by mountd. By default it
will look for AUTH_SYS, otherwise it will look for the flavor
specified by the sec= mount option.

If mountd does not provide AUTH_SYS a mount request with no sec= will
fail. Should it try the first one in the list instead? What if the
first one is AUTH_NULL?

--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com

2009-07-10 20:11:17

by Chuck Lever

[permalink] [raw]
Subject: Re: Security negotiation


On Jul 10, 2009, at 2:57 PM, Chuck Lever wrote:

>
> On Jul 10, 2009, at 2:07 PM, Tom Haynes wrote:
>
>> During a NFSv3 mount request, the server returns an array of
>> supported security flavors.
>>
>> With a Linux server, exports(5) states:
>>
>> For the purposes of security flavor negotiation, order counts:
>> preferred flavors should be listed first.
>>
>> And the Solaris client states in mount_nfs(1M):
>>
>> NFS Version 3 mounts negotiate a security mode when the server
>> returns an array of security modes. The
>> client picks the first mode in the array that is supported on the
>> client. In negotiations, an NFS Version 3 client
>> is limited to the security flavors listed in /etc/nfssec.conf.
>>
>> The Linux nfs(5) states:
>>
>> If the sec option is not specified, or if sec=sys is specified,
>> the NFS client uses the AUTH_SYS
>> security flavor for all NFS requests on this mount point.
>>
>> So, I'm trying to understand what the Linux client would do if the
>> export does not support AUTH_SYS and
>> there is no sec= supplied.
>>
>> Does the Linux client traverse the array in order until it finds a
>> match or does it consider which flavor is strongest?
>
> The legacy mount command does this (kernels earlier than 2.6.23) but
> the kernel mount client does not yet. I intend to submit patches
> for this (today, actually) for 2.6.32.
>
> The patches will walk the auth_list returned by mountd. By default
> it will look for AUTH_SYS, otherwise it will look for the flavor
> specified by the sec= mount option.
>
> If mountd does not provide AUTH_SYS a mount request with no sec=
> will fail. Should it try the first one in the list instead? What
> if the first one is AUTH_NULL?

In other words, I'm not sure what is the right behavior here. What it
does now is probably suboptimal. I've browsed 2623 a bit, but it's
not hitting me.

--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com

2009-07-10 21:37:22

by Chuck Lever

[permalink] [raw]
Subject: Re: Security negotiation

On Jul 10, 2009, at 4:55 PM, Tom Haynes wrote:
> Chuck Lever wrote:
>>
>>> If mountd does not provide AUTH_SYS a mount request with no sec=
>>> will fail. Should it try the first one in the list instead? What
>>> if the first one is AUTH_NULL?
>>
>> In other words, I'm not sure what is the right behavior here. What
>> it does now is probably suboptimal. I've browsed 2623 a bit, but
>> it's not hitting me.
>
> So we (OpenSolaris) changed our behavior inadvertently to do the
> list in order. Which means we are trying AUTH_NONE against
> a Linux server. (Bug is here: http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6834430)
>
> We are considering two changes:
>
> 1) Use our default flavor (user configurable)
> 2) Order the list by strength based on the flavors we support.
>
> The first option would get us to where you are going to be. AUTH_SYS
> will
> probably be the default.

It's easy to implement, test, and explain in a man page. I think the
first option gives the least surprise (ie a negotiated result that is
not what you expect and thus may expose your data).

> The second option would push AUTH_NONE to the end of the list, which
> corresponds to my thinking of it as a wild card.

The problem with the server's auth list is that it is a list of _all_
flavors that the server supports. That doesn't mean the client
necessarily wants to use any of those by default, especially not
AUTH_NONE. We've hit a number of behavior bugs where the client is
negotiating AUTH_NONE and users can see their files, but not update
them, and no real explanation why. Very confusing.

It might be better to have a subset of flavors that the client can
negotiate, like AUTH_SYS and AUTH_GSS/Krb5. The others are supported,
but can't be used unless the client's administrator has explicitly
asked for them. Having a default of only AUTH_SYS is rather a
degenerate case of this.

> But it also means that if AUTH_SYS is not our default, then we might
> try
> Kerberized access first. I think that is a surprise.
>
> Also, if the server has already ordered the list based on the
> preference it
> would like the client to try, then the client should honor that list
> if no
> specific flavor is used.

I was wondering when a server would not want to order the flavor list
by strongest to weakest. We have the use case of the kerberos 5
pseudoflavors: clients should probably use krb5 over krb5p by
default, as this provides good security without a lot of performance
overhead. But krb5p is stronger security than krb5.

> So, I would say algorithmically:
>
> 1) If the client specifies a flavor, it uses that if the server
> supports it. If the
> server does not, the mount fails.
>
> 2) If the client has a default, it tries that first if the server
> supports it. If the
> server does not, then:
>
> 3) The client walks the array of flavors and uses the first that it
> supports
> and the server supports.


I think it would be polite to display a warning if step 3 gives you
AUTH_NONE.

--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com

2009-07-10 22:38:55

by Tom Haynes

[permalink] [raw]
Subject: Re: Security negotiation

Chuck Lever wrote:
> On Jul 10, 2009, at 4:55 PM, Tom Haynes wrote:
>
>> The second option would push AUTH_NONE to the end of the list, which
>> corresponds to my thinking of it as a wild card.
>
> The problem with the server's auth list is that it is a list of _all_
> flavors that the server supports.

For us it is a list of flavors supported on that export.

Our default export is basically sec=sys,rw.

To get all of the flavors, the admin would have to configure them in.

>
> I was wondering when a server would not want to order the flavor list
> by strongest to weakest. We have the use case of the kerberos 5
> pseudoflavors: clients should probably use krb5 over krb5p by
> default, as this provides good security without a lot of performance
> overhead. But krb5p is stronger security than krb5.

When they have different access lists.

If they have the same access lists, then the server is free to order them...

share -F nfs -o sec=sys:none:krb5,rw /foo
share -F nfs -o sec=sys,ro,sec=krb5p,rw,[email protected],sec=krb5,rw /bar

In the first, we don't care how the server presents them. In the second,
the list would be: sys krb5p krb5.

2009-07-10 22:45:33

by Trond Myklebust

[permalink] [raw]
Subject: Re: Security negotiation

On Fri, 2009-07-10 at 17:38 -0500, Tom Haynes wrote:
> Chuck Lever wrote:
> > On Jul 10, 2009, at 4:55 PM, Tom Haynes wrote:
> >
> >> The second option would push AUTH_NONE to the end of the list, which
> >> corresponds to my thinking of it as a wild card.
> >
> > The problem with the server's auth list is that it is a list of _all_
> > flavors that the server supports.
>
> For us it is a list of flavors supported on that export.
>
> Our default export is basically sec=sys,rw.
>
> To get all of the flavors, the admin would have to configure them in.
>
> >
> > I was wondering when a server would not want to order the flavor list
> > by strongest to weakest. We have the use case of the kerberos 5
> > pseudoflavors: clients should probably use krb5 over krb5p by
> > default, as this provides good security without a lot of performance
> > overhead. But krb5p is stronger security than krb5.
>
> When they have different access lists.
>
> If they have the same access lists, then the server is free to order them...
>
> share -F nfs -o sec=sys:none:krb5,rw /foo
> share -F nfs -o sec=sys,ro,sec=krb5p,rw,[email protected],sec=krb5,rw /bar
>
> In the first, we don't care how the server presents them. In the second,
> the list would be: sys krb5p krb5.

Meaning that the client defaults to read-only access?

Trond