diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 53 |
1 files changed, 47 insertions, 6 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 09c7e3b87c46..85b190643e30 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -435,6 +435,20 @@ wait_on_recovery: | |||
435 | return ret; | 435 | return ret; |
436 | } | 436 | } |
437 | 437 | ||
438 | /* | ||
439 | * Return 'true' if 'clp' is using an rpc_client that is integrity protected | ||
440 | * or 'false' otherwise. | ||
441 | */ | ||
442 | static bool _nfs4_is_integrity_protected(struct nfs_client *clp) | ||
443 | { | ||
444 | rpc_authflavor_t flavor = clp->cl_rpcclient->cl_auth->au_flavor; | ||
445 | |||
446 | if (flavor == RPC_AUTH_GSS_KRB5I || | ||
447 | flavor == RPC_AUTH_GSS_KRB5P) | ||
448 | return true; | ||
449 | |||
450 | return false; | ||
451 | } | ||
438 | 452 | ||
439 | static void do_renew_lease(struct nfs_client *clp, unsigned long timestamp) | 453 | static void do_renew_lease(struct nfs_client *clp, unsigned long timestamp) |
440 | { | 454 | { |
@@ -5842,10 +5856,13 @@ int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, | |||
5842 | } | 5856 | } |
5843 | 5857 | ||
5844 | /** | 5858 | /** |
5845 | * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if | 5859 | * If 'use_integrity' is true and the state managment nfs_client |
5846 | * possible) as per RFC3530bis and RFC5661 Security Considerations sections | 5860 | * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient |
5861 | * and the machine credential as per RFC3530bis and RFC5661 Security | ||
5862 | * Considerations sections. Otherwise, just use the user cred with the | ||
5863 | * filesystem's rpc_client. | ||
5847 | */ | 5864 | */ |
5848 | static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) | 5865 | static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors, bool use_integrity) |
5849 | { | 5866 | { |
5850 | int status; | 5867 | int status; |
5851 | struct nfs4_secinfo_arg args = { | 5868 | struct nfs4_secinfo_arg args = { |
@@ -5860,11 +5877,21 @@ static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct | |||
5860 | .rpc_argp = &args, | 5877 | .rpc_argp = &args, |
5861 | .rpc_resp = &res, | 5878 | .rpc_resp = &res, |
5862 | }; | 5879 | }; |
5863 | struct rpc_clnt *clnt = NFS_SERVER(dir)->nfs_client->cl_rpcclient; | 5880 | struct rpc_clnt *clnt = NFS_SERVER(dir)->client; |
5881 | |||
5882 | if (use_integrity) { | ||
5883 | clnt = NFS_SERVER(dir)->nfs_client->cl_rpcclient; | ||
5884 | msg.rpc_cred = nfs4_get_clid_cred(NFS_SERVER(dir)->nfs_client); | ||
5885 | } | ||
5864 | 5886 | ||
5865 | dprintk("NFS call secinfo %s\n", name->name); | 5887 | dprintk("NFS call secinfo %s\n", name->name); |
5866 | status = nfs4_call_sync(clnt, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); | 5888 | status = nfs4_call_sync(clnt, NFS_SERVER(dir), &msg, &args.seq_args, |
5889 | &res.seq_res, 0); | ||
5867 | dprintk("NFS reply secinfo: %d\n", status); | 5890 | dprintk("NFS reply secinfo: %d\n", status); |
5891 | |||
5892 | if (msg.rpc_cred) | ||
5893 | put_rpccred(msg.rpc_cred); | ||
5894 | |||
5868 | return status; | 5895 | return status; |
5869 | } | 5896 | } |
5870 | 5897 | ||
@@ -5874,7 +5901,21 @@ int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, | |||
5874 | struct nfs4_exception exception = { }; | 5901 | struct nfs4_exception exception = { }; |
5875 | int err; | 5902 | int err; |
5876 | do { | 5903 | do { |
5877 | err = _nfs4_proc_secinfo(dir, name, flavors); | 5904 | err = -NFS4ERR_WRONGSEC; |
5905 | |||
5906 | /* try to use integrity protection with machine cred */ | ||
5907 | if (_nfs4_is_integrity_protected(NFS_SERVER(dir)->nfs_client)) | ||
5908 | err = _nfs4_proc_secinfo(dir, name, flavors, true); | ||
5909 | |||
5910 | /* | ||
5911 | * if unable to use integrity protection, or SECINFO with | ||
5912 | * integrity protection returns NFS4ERR_WRONGSEC (which is | ||
5913 | * disallowed by spec, but exists in deployed servers) use | ||
5914 | * the current filesystem's rpc_client and the user cred. | ||
5915 | */ | ||
5916 | if (err == -NFS4ERR_WRONGSEC) | ||
5917 | err = _nfs4_proc_secinfo(dir, name, flavors, false); | ||
5918 | |||
5878 | trace_nfs4_secinfo(dir, name, err); | 5919 | trace_nfs4_secinfo(dir, name, err); |
5879 | err = nfs4_handle_exception(NFS_SERVER(dir), err, | 5920 | err = nfs4_handle_exception(NFS_SERVER(dir), err, |
5880 | &exception); | 5921 | &exception); |