@@ -341,6 +341,47 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp)
}
/**
+ * Verify the client and server kerberos and gss configurations by obtaining
+ * a gss_context for UID 0 (current_cred()) prior to use in an RPC call.
+ */
+int nfs_create_gss_rpc_client(struct nfs_client *clp,
+ const struct rpc_timeout *timeparams)
+{
+ struct rpc_cred *cred;
+ int err;
+
+ /* This creates a krb5i rpc_auth if rpc.gssd is running */
+ err = nfs_create_rpc_client(clp, timeparams, RPC_AUTH_GSS_KRB5I);
+ if (err == -EINVAL)
+ return err;
+
+ /* Check that krb5i can be used: cr_init obtains a gss_context */
+ cred = rpcauth_lookupcred(clp->cl_rpcclient->cl_auth, 0);
+ if (IS_ERR(cred)) {
+ struct rpc_clnt *krb5i, *krb5;
+
+ /* Try krb5 */
+ krb5i = clp->cl_rpcclient;
+ krb5 = rpc_clone_client_set_auth(krb5i, RPC_AUTH_GSS_KRB5);
+ rpc_shutdown_client(krb5i);
+ /* Check that krb5 can be used */
+ cred = rpcauth_lookupcred(krb5->cl_auth, 0);
+ if (IS_ERR(cred)) {
+ rpc_shutdown_client(krb5);
+ clp->cl_rpcclient = ERR_PTR(-EINVAL);
+ return -EINVAL;
+ }
+ /* Use krb5 */
+ put_rpccred(cred);
+ clp->cl_rpcclient = krb5;
+ return 0;
+ }
+ /* Use krb5i */
+ put_rpccred(cred);
+ return 0;
+}
+
+/**
* nfs4_init_client - Initialise an NFS4 client record
*
* @clp: nfs_client to initialise
@@ -372,7 +413,8 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
__set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
__set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags);
- error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I);
+ /* Try RPC_AUTH_GSS_KRB51 then RPC_AUTH_GSS_KRB5 */
+ error = nfs_create_gss_rpc_client(clp, timeparms);
if (error == -EINVAL)
error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX);
if (error < 0)