From 4edaa308888b4bd629fa025cc6d5b2bf1a2a51db Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sat, 16 Mar 2013 15:56:20 -0400 Subject: NFS: Use "krb5i" to establish NFSv4 state whenever possible Currently our client uses AUTH_UNIX for state management on Kerberos NFS mounts in some cases. For example, if the first mount of a server specifies "sec=sys," the SETCLIENTID operation is performed with AUTH_UNIX. Subsequent mounts using stronger security flavors can not change the flavor used for lease establishment. This might be less security than an administrator was expecting. Dave Noveck's migration issues draft recommends the use of an integrity-protecting security flavor for the SETCLIENTID operation. Let's ignore the mount's sec= setting and use krb5i as the default security flavor for SETCLIENTID. If our client can't establish a GSS context (eg. because it doesn't have a keytab or the server doesn't support Kerberos) we fall back to using AUTH_NULL. For an operation that requires a machine credential (which never represents a particular user) AUTH_NULL is as secure as AUTH_UNIX. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/nfs/nfs4state.c | 37 +++++-------------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) (limited to 'fs/nfs/nfs4state.c') diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index b924bdd69494..a30f51eb048f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1866,26 +1866,13 @@ int nfs4_discover_server_trunking(struct nfs_client *clp, { const struct nfs4_state_recovery_ops *ops = clp->cl_mvops->reboot_recovery_ops; - rpc_authflavor_t *flavors, flav, save; struct rpc_clnt *clnt; struct rpc_cred *cred; - int i, len, status; + int i, status; dprintk("NFS: %s: testing '%s'\n", __func__, clp->cl_hostname); - len = NFS_MAX_SECFLAVORS; - flavors = kcalloc(len, sizeof(*flavors), GFP_KERNEL); - if (flavors == NULL) { - status = -ENOMEM; - goto out; - } - len = rpcauth_list_flavors(flavors, len); - if (len < 0) { - status = len; - goto out_free; - } clnt = clp->cl_rpcclient; - save = clnt->cl_auth->au_flavor; i = 0; mutex_lock(&nfs_clid_init_mutex); @@ -1900,12 +1887,6 @@ again: switch (status) { case 0: break; - - case -EACCES: - if (clp->cl_machine_cred == NULL) - break; - /* Handle case where the user hasn't set up machine creds */ - nfs4_clear_machine_cred(clp); case -NFS4ERR_DELAY: case -ETIMEDOUT: case -EAGAIN: @@ -1914,17 +1895,12 @@ again: dprintk("NFS: %s after status %d, retrying\n", __func__, status); goto again; - + case -EACCES: + if (i++) + break; case -NFS4ERR_CLID_INUSE: case -NFS4ERR_WRONGSEC: - status = -EPERM; - if (i >= len) - break; - - flav = flavors[i++]; - if (flav == save) - flav = flavors[i++]; - clnt = rpc_clone_client_set_auth(clnt, flav); + clnt = rpc_clone_client_set_auth(clnt, RPC_AUTH_NULL); if (IS_ERR(clnt)) { status = PTR_ERR(clnt); break; @@ -1944,9 +1920,6 @@ again: out_unlock: mutex_unlock(&nfs_clid_init_mutex); -out_free: - kfree(flavors); -out: dprintk("NFS: %s: status = %d\n", __func__, status); return status; } -- cgit v1.2.1 From ea33e6c3e79d23ef693b7ed3171ef90dddfbfc15 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 5 Apr 2013 13:22:50 -0400 Subject: NFSv4: Fix issues in nfs4_discover_server_trunking - Ensure that we exit with ENOENT if the call to ops->get_clid_cred() fails. - Handle the case where ops->detect_trunking() exits with an unexpected error, and return EIO. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4state.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'fs/nfs/nfs4state.c') diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index a30f51eb048f..209df6976a5b 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1876,8 +1876,8 @@ int nfs4_discover_server_trunking(struct nfs_client *clp, i = 0; mutex_lock(&nfs_clid_init_mutex); - status = -ENOENT; again: + status = -ENOENT; cred = ops->get_clid_cred(clp); if (cred == NULL) goto out_unlock; @@ -1916,6 +1916,11 @@ again: case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery * in nfs4_exchange_id */ status = -EKEYEXPIRED; + break; + default: + pr_warn("NFS: %s unhandled error %d. Exiting with error EIO\n", + __func__, status); + status = -EIO; } out_unlock: -- cgit v1.2.1 From 845cbceb22c67030df76552892ad4935669bf2e5 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 5 Apr 2013 15:37:04 -0400 Subject: NFSv4: Don't clear the machine cred when client establish returns EACCES The expected behaviour is that the client will decide at mount time whether or not to use a krb5i machine cred, or AUTH_NULL. Signed-off-by: Trond Myklebust Cc: Chuck Lever Cc: Bryan Schumaker --- fs/nfs/nfs4state.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'fs/nfs/nfs4state.c') diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 209df6976a5b..c54600962bc6 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -154,18 +154,6 @@ struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp) return cred; } -static void nfs4_clear_machine_cred(struct nfs_client *clp) -{ - struct rpc_cred *cred; - - spin_lock(&clp->cl_lock); - cred = clp->cl_machine_cred; - clp->cl_machine_cred = NULL; - spin_unlock(&clp->cl_lock); - if (cred != NULL) - put_rpccred(cred); -} - static struct rpc_cred * nfs4_get_renew_cred_server_locked(struct nfs_server *server) { @@ -1768,10 +1756,6 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); return -EPERM; case -EACCES: - if (clp->cl_machine_cred == NULL) - return -EACCES; - /* Handle case where the user hasn't set up machine creds */ - nfs4_clear_machine_cred(clp); case -NFS4ERR_DELAY: case -ETIMEDOUT: case -EAGAIN: -- cgit v1.2.1 From 79d852bf5e7691dc78cc6322ecd1860c50940785 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 22 Apr 2013 15:42:48 -0400 Subject: NFS: Retry SETCLIENTID with AUTH_SYS instead of AUTH_NONE Recently I changed the SETCLIENTID code to use AUTH_GSS(krb5i), and then retry with AUTH_NONE if that didn't work. This was to enable Kerberos NFS mounts to work without forcing Linux NFS clients to have a keytab on hand. Rick Macklem reports that the FreeBSD server accepts AUTH_NONE only for NULL operations (thus certainly not for SETCLIENTID). Falling back to AUTH_NONE means our proposed 3.10 NFS client will not interoperate with FreeBSD servers over NFSv4 unless Kerberos is fully configured on both ends. If the Linux client falls back to using AUTH_SYS instead for SETCLIENTID, all should work fine as long as the NFS server is configured to allow AUTH_SYS for SETCLIENTID. This may still prevent access to Kerberos-only FreeBSD servers by Linux clients with no keytab. Rick is of the opinion that the security settings the server applies to its pseudo-fs should also apply to the SETCLIENTID operation. Linux and Solaris NFS servers do not place that limitation on SETCLIENTID. The security settings for the server's pseudo-fs are determined automatically as the union of security flavors allowed on real exports, as recommended by RFC 3530bis; and the flavors allowed for SETCLIENTID are all flavors supported by the respective server implementation. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/nfs/nfs4state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/nfs/nfs4state.c') diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index c54600962bc6..a75e712490f4 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1884,7 +1884,7 @@ again: break; case -NFS4ERR_CLID_INUSE: case -NFS4ERR_WRONGSEC: - clnt = rpc_clone_client_set_auth(clnt, RPC_AUTH_NULL); + clnt = rpc_clone_client_set_auth(clnt, RPC_AUTH_UNIX); if (IS_ERR(clnt)) { status = PTR_ERR(clnt); break; -- cgit v1.2.1