NFS: Use the authentication flavor list returned by mountd
Commit a14017db
added support in the kernel's NFS mount client to
decode the authentication flavor list returned by mountd.
The NFS client can now use this list to determine whether the
authentication flavor requested by the user is actually supported
by the server.
Note we don't actually negotiate the security flavor if none was
specified by the user. Instead, we try to use AUTH_SYS, and fail if
the server does not support it. This prevents us from negotiating
an inappropriate security flavor (some servers list AUTH_NULL first).
If the server does not support AUTH_SYS, the user must provide an
appropriate security flavor by specifying the "sec=" mount option.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
059f90b323
commit
ec88f28d1e
1 changed files with 51 additions and 7 deletions
|
@ -1436,6 +1436,42 @@ static int nfs_parse_mount_options(char *raw,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Match the requested auth flavors with the list returned by
|
||||||
|
* the server. Returns zero and sets the mount's authentication
|
||||||
|
* flavor on success; returns -EACCES if server does not support
|
||||||
|
* the requested flavor.
|
||||||
|
*/
|
||||||
|
static int nfs_walk_authlist(struct nfs_parsed_mount_data *args,
|
||||||
|
struct nfs_mount_request *request)
|
||||||
|
{
|
||||||
|
unsigned int i, j, server_authlist_len = *(request->auth_flav_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We avoid sophisticated negotiating here, as there are
|
||||||
|
* plenty of cases where we can get it wrong, providing
|
||||||
|
* either too little or too much security.
|
||||||
|
*
|
||||||
|
* RFC 2623, section 2.7 suggests we SHOULD prefer the
|
||||||
|
* flavor listed first. However, some servers list
|
||||||
|
* AUTH_NULL first. Our caller plants AUTH_SYS, the
|
||||||
|
* preferred default, in args->auth_flavors[0] if user
|
||||||
|
* didn't specify sec= mount option.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < args->auth_flavor_len; i++)
|
||||||
|
for (j = 0; j < server_authlist_len; j++)
|
||||||
|
if (args->auth_flavors[i] == request->auth_flavs[j]) {
|
||||||
|
dfprintk(MOUNT, "NFS: using auth flavor %d\n",
|
||||||
|
request->auth_flavs[j]);
|
||||||
|
args->auth_flavors[0] = request->auth_flavs[j];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dfprintk(MOUNT, "NFS: server does not support requested auth flavor\n");
|
||||||
|
nfs_umount(request);
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use the remote server's MOUNT service to request the NFS file handle
|
* Use the remote server's MOUNT service to request the NFS file handle
|
||||||
* corresponding to the provided path.
|
* corresponding to the provided path.
|
||||||
|
@ -1443,7 +1479,8 @@ static int nfs_parse_mount_options(char *raw,
|
||||||
static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
||||||
struct nfs_fh *root_fh)
|
struct nfs_fh *root_fh)
|
||||||
{
|
{
|
||||||
unsigned int auth_flavor_len = 0;
|
rpc_authflavor_t server_authlist[NFS_MAX_SECFLAVORS];
|
||||||
|
unsigned int server_authlist_len = ARRAY_SIZE(server_authlist);
|
||||||
struct nfs_mount_request request = {
|
struct nfs_mount_request request = {
|
||||||
.sap = (struct sockaddr *)
|
.sap = (struct sockaddr *)
|
||||||
&args->mount_server.address,
|
&args->mount_server.address,
|
||||||
|
@ -1451,7 +1488,8 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
||||||
.protocol = args->mount_server.protocol,
|
.protocol = args->mount_server.protocol,
|
||||||
.fh = root_fh,
|
.fh = root_fh,
|
||||||
.noresvport = args->flags & NFS_MOUNT_NORESVPORT,
|
.noresvport = args->flags & NFS_MOUNT_NORESVPORT,
|
||||||
.auth_flav_len = &auth_flavor_len,
|
.auth_flav_len = &server_authlist_len,
|
||||||
|
.auth_flavs = server_authlist,
|
||||||
};
|
};
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
@ -1488,12 +1526,18 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
||||||
* to a file handle.
|
* to a file handle.
|
||||||
*/
|
*/
|
||||||
status = nfs_mount(&request);
|
status = nfs_mount(&request);
|
||||||
if (status == 0)
|
if (status != 0) {
|
||||||
return 0;
|
dfprintk(MOUNT, "NFS: unable to mount server %s, error %d\n",
|
||||||
|
request.hostname, status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
dfprintk(MOUNT, "NFS: unable to mount server %s, error %d\n",
|
/*
|
||||||
request.hostname, status);
|
* MNTv1 (NFSv2) does not support auth flavor negotiation.
|
||||||
return status;
|
*/
|
||||||
|
if (args->mount_server.version != NFS_MNT3_VERSION)
|
||||||
|
return 0;
|
||||||
|
return nfs_walk_authlist(args, &request);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nfs_parse_simple_hostname(const char *dev_name,
|
static int nfs_parse_simple_hostname(const char *dev_name,
|
||||||
|
|
Loading…
Reference in a new issue