|
@@ -1436,6 +1436,42 @@ out_security_failure:
|
|
|
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
|
|
|
* corresponding to the provided path.
|
|
@@ -1443,7 +1479,8 @@ out_security_failure:
|
|
|
static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
|
|
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 = {
|
|
|
.sap = (struct sockaddr *)
|
|
|
&args->mount_server.address,
|
|
@@ -1451,7 +1488,8 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
|
|
.protocol = args->mount_server.protocol,
|
|
|
.fh = root_fh,
|
|
|
.noresvport = args->flags & NFS_MOUNT_NORESVPORT,
|
|
|
- .auth_flav_len = &auth_flavor_len,
|
|
|
+ .auth_flav_len = &server_authlist_len,
|
|
|
+ .auth_flavs = server_authlist,
|
|
|
};
|
|
|
int status;
|
|
|
|
|
@@ -1488,12 +1526,18 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
|
|
* to a file handle.
|
|
|
*/
|
|
|
status = nfs_mount(&request);
|
|
|
- if (status == 0)
|
|
|
- return 0;
|
|
|
+ if (status != 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);
|
|
|
- return status;
|
|
|
+ /*
|
|
|
+ * MNTv1 (NFSv2) does not support auth flavor negotiation.
|
|
|
+ */
|
|
|
+ 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,
|