From: Andy Adamson Date: Fri, 18 May 2007 16:52:43 -0400 NFSv4: Try each security flavor in WRONGSEC list Main function for NFS4ERR_WRONGSEC handling. Success returns zero with ex_cred set and ready for exception retry. Use a private rpc_clnt to obtain credentials for a flavor in the list. An rpc_clnt and not an rpc_auth is created and destroyed upon each attempt to get a credential due to the RPC_AUTH_GSS upcall pipe creation/destruction and rpc.gssd notification. NOTE: We could update rpc.gssd to do the right thing when the pipe file goes away, and then we could keep the ex_clnt around and get creds with new rpc_auth's. Signed-off-by: Trond Myklebust --- fs/nfs/client.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 50 insertions(+), 0 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index ec7290c..187e66b 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -1152,6 +1152,56 @@ static int nfs4_set_ex_cred(struct nfs4_exception *exc, rpc_authflavor_t flavor) return error; } +/* + * Shutdown WRONGSEC exception handling + */ +void nfs4_shutdown_wrongsec(struct nfs4_exception *exc) +{ + kfree(exc->ex_list); + if (!IS_ERR(exc->ex_clnt)) + rpc_shutdown_client(exc->ex_clnt); +} + +/* + * Try the next security flavor. + */ +int nfs4_clnt_try_next_flavor(struct nfs_server *server, + struct nfs4_exception *exc) +{ + rpc_authflavor_t ret, cur_flavor = server->client->cl_auth->au_flavor; + int error; + + dprintk("--> nfs4_clnt_try_next_flavor() current flavor %d\n", cur_flavor); + +retry: + if (exc->ex_clnt) + rpc_shutdown_client(exc->ex_clnt); + + exc->ex_clnt = rpc_clone_client(clp->cl_rpcclient); + if (IS_ERR(exc->ex_clnt)) { + error = PTR_ERR(exc->ex_clnt); + goto out_free; + } + ret = nfs4_next_flavor(exc, cur_flavor); + if (ret == RPC_AUTH_MAXFLAVOR) { + dprintk("%s Tried all flavors\n", __FUNCTION__); + error = -EACCES; + goto out_free; + } + + error = nfs4_set_ex_cred(exc, ret); + if (error < 0) { + dprintk("%s No creds for flavor %d\n", __FUNCTION__, ret); + goto retry; + } +out: + dprintk("<-- nfs4_clnt_try_next_flavor() error %d\n", error); + return error; +out_free: + nfs4_shutdown_wrongsec(exc); + goto out; +} + #endif /* CONFIG_NFS_V4 */ /*