]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
nfs4: copy acceptor name from context to nfs_client
authorJeff Layton <jlayton@poochiereds.net>
Sun, 22 Jun 2014 00:52:17 +0000 (20:52 -0400)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Sat, 12 Jul 2014 22:41:25 +0000 (18:41 -0400)
The current CB_COMPOUND handling code tries to compare the principal
name of the request with the cl_hostname in the client. This is not
guaranteed to ever work, particularly if the client happened to mount
a CNAME of the server or a non-fqdn.

Fix this by instead comparing the cr_principal string with the acceptor
name that we get from gssd. In the event that gssd didn't send one
down (i.e. it was too old), then we fall back to trying to use the
cl_hostname as we do today.

Signed-off-by: Jeff Layton <jlayton@poochiereds.net>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/callback.c
fs/nfs/client.c
fs/nfs/nfs4proc.c
include/linux/nfs_fs_sb.h
include/linux/nfs_xdr.h

index 073b4cf67ed9d39690626add5517708debeab021..54de482143cc0708638e12bde9fbbfbd66d59224 100644 (file)
@@ -428,6 +428,18 @@ check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
        if (p == NULL)
                return 0;
 
+       /*
+        * Did we get the acceptor from userland during the SETCLIENID
+        * negotiation?
+        */
+       if (clp->cl_acceptor)
+               return !strcmp(p, clp->cl_acceptor);
+
+       /*
+        * Otherwise try to verify it using the cl_hostname. Note that this
+        * doesn't work if a non-canonical hostname was used in the devname.
+        */
+
        /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
 
        if (memcmp(p, "nfs@", 4) != 0)
index b213ee8fb01225e5adee9d447fed6aabe91d55a8..168aa0df2658039be23e71215e38f86223a38747 100644 (file)
@@ -252,6 +252,7 @@ void nfs_free_client(struct nfs_client *clp)
        put_net(clp->cl_net);
        put_nfs_version(clp->cl_nfs_mod);
        kfree(clp->cl_hostname);
+       kfree(clp->cl_acceptor);
        kfree(clp);
 
        dprintk("<-- nfs_free_client()\n");
index 0b8490eab486af8397f22bfd66609df9747772f1..b7babb3b8a4d537cb1abefe06eb2bda4272b37ae 100644 (file)
@@ -4936,6 +4936,18 @@ nfs4_init_callback_netid(const struct nfs_client *clp, char *buf, size_t len)
                return scnprintf(buf, len, "tcp");
 }
 
+static void nfs4_setclientid_done(struct rpc_task *task, void *calldata)
+{
+       struct nfs4_setclientid *sc = calldata;
+
+       if (task->tk_status == 0)
+               sc->sc_cred = get_rpccred(task->tk_rqstp->rq_cred);
+}
+
+static const struct rpc_call_ops nfs4_setclientid_ops = {
+       .rpc_call_done = nfs4_setclientid_done,
+};
+
 /**
  * nfs4_proc_setclientid - Negotiate client ID
  * @clp: state data structure
@@ -4962,6 +4974,14 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
                .rpc_resp = res,
                .rpc_cred = cred,
        };
+       struct rpc_task *task;
+       struct rpc_task_setup task_setup_data = {
+               .rpc_client = clp->cl_rpcclient,
+               .rpc_message = &msg,
+               .callback_ops = &nfs4_setclientid_ops,
+               .callback_data = &setclientid,
+               .flags = RPC_TASK_TIMEOUT,
+       };
        int status;
 
        /* nfs_client_id4 */
@@ -4988,7 +5008,18 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
        dprintk("NFS call  setclientid auth=%s, '%.*s'\n",
                clp->cl_rpcclient->cl_auth->au_ops->au_name,
                setclientid.sc_name_len, setclientid.sc_name);
-       status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
+       task = rpc_run_task(&task_setup_data);
+       if (IS_ERR(task)) {
+               status = PTR_ERR(task);
+               goto out;
+       }
+       status = task->tk_status;
+       if (setclientid.sc_cred) {
+               clp->cl_acceptor = rpcauth_stringify_acceptor(setclientid.sc_cred);
+               put_rpccred(setclientid.sc_cred);
+       }
+       rpc_put_task(task);
+out:
        trace_nfs4_setclientid(clp, status);
        dprintk("NFS reply setclientid: %d\n", status);
        return status;
index 1150ea41b626723b67720320a23f0810a2ec2be4..922be2e050f5c938b561daf4b5533d01f1d1d0bc 100644 (file)
@@ -45,6 +45,7 @@ struct nfs_client {
        struct sockaddr_storage cl_addr;        /* server identifier */
        size_t                  cl_addrlen;
        char *                  cl_hostname;    /* hostname of server */
+       char *                  cl_acceptor;    /* GSSAPI acceptor name */
        struct list_head        cl_share_link;  /* link in global client list */
        struct list_head        cl_superblocks; /* List of nfs_server structs */
 
index 81cbbf313272529b446fde3e5101689a4c571dd0..0040629894dfa42084161124edb2f494df5be4ea 100644 (file)
@@ -993,6 +993,7 @@ struct nfs4_setclientid {
        unsigned int                    sc_uaddr_len;
        char                            sc_uaddr[RPCBIND_MAXUADDRLEN + 1];
        u32                             sc_cb_ident;
+       struct rpc_cred                 *sc_cred;
 };
 
 struct nfs4_setclientid_res {