diff options
Diffstat (limited to 'fs/nfs/nfs4namespace.c')
-rw-r--r-- | fs/nfs/nfs4namespace.c | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index a7f3dedc4ec..017b4b01a69 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
@@ -132,6 +132,35 @@ static size_t nfs_parse_server_name(char *string, size_t len, | |||
132 | return ret; | 132 | return ret; |
133 | } | 133 | } |
134 | 134 | ||
135 | rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors) | ||
136 | { | ||
137 | struct gss_api_mech *mech; | ||
138 | struct xdr_netobj oid; | ||
139 | int i; | ||
140 | rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX; | ||
141 | |||
142 | for (i = 0; i < flavors->num_flavors; i++) { | ||
143 | struct nfs4_secinfo_flavor *flavor; | ||
144 | flavor = &flavors->flavors[i]; | ||
145 | |||
146 | if (flavor->flavor == RPC_AUTH_NULL || flavor->flavor == RPC_AUTH_UNIX) { | ||
147 | pseudoflavor = flavor->flavor; | ||
148 | break; | ||
149 | } else if (flavor->flavor == RPC_AUTH_GSS) { | ||
150 | oid.len = flavor->gss.sec_oid4.len; | ||
151 | oid.data = flavor->gss.sec_oid4.data; | ||
152 | mech = gss_mech_get_by_OID(&oid); | ||
153 | if (!mech) | ||
154 | continue; | ||
155 | pseudoflavor = gss_svc_to_pseudoflavor(mech, flavor->gss.service); | ||
156 | gss_mech_put(mech); | ||
157 | break; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | return pseudoflavor; | ||
162 | } | ||
163 | |||
135 | static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr *name) | 164 | static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr *name) |
136 | { | 165 | { |
137 | struct page *page; | 166 | struct page *page; |
@@ -168,7 +197,7 @@ struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *clnt, struct inode *ino | |||
168 | rpc_authflavor_t flavor; | 197 | rpc_authflavor_t flavor; |
169 | 198 | ||
170 | flavor = nfs4_negotiate_security(inode, name); | 199 | flavor = nfs4_negotiate_security(inode, name); |
171 | if (flavor < 0) | 200 | if ((int)flavor < 0) |
172 | return ERR_PTR(flavor); | 201 | return ERR_PTR(flavor); |
173 | 202 | ||
174 | clone = rpc_clone_client(clnt); | 203 | clone = rpc_clone_client(clnt); |
@@ -300,7 +329,7 @@ out: | |||
300 | * @dentry - dentry of referral | 329 | * @dentry - dentry of referral |
301 | * | 330 | * |
302 | */ | 331 | */ |
303 | struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry) | 332 | static struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry) |
304 | { | 333 | { |
305 | struct vfsmount *mnt = ERR_PTR(-ENOMEM); | 334 | struct vfsmount *mnt = ERR_PTR(-ENOMEM); |
306 | struct dentry *parent; | 335 | struct dentry *parent; |
@@ -341,3 +370,25 @@ out: | |||
341 | dprintk("%s: done\n", __func__); | 370 | dprintk("%s: done\n", __func__); |
342 | return mnt; | 371 | return mnt; |
343 | } | 372 | } |
373 | |||
374 | struct vfsmount *nfs4_submount(struct nfs_server *server, struct dentry *dentry, | ||
375 | struct nfs_fh *fh, struct nfs_fattr *fattr) | ||
376 | { | ||
377 | struct dentry *parent = dget_parent(dentry); | ||
378 | struct rpc_clnt *client; | ||
379 | struct vfsmount *mnt; | ||
380 | |||
381 | /* Look it up again to get its attributes and sec flavor */ | ||
382 | client = nfs4_proc_lookup_mountpoint(parent->d_inode, &dentry->d_name, fh, fattr); | ||
383 | dput(parent); | ||
384 | if (IS_ERR(client)) | ||
385 | return ERR_CAST(client); | ||
386 | |||
387 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | ||
388 | mnt = nfs_do_refmount(client, dentry); | ||
389 | else | ||
390 | mnt = nfs_do_submount(dentry, fh, fattr, client->cl_auth->au_flavor); | ||
391 | |||
392 | rpc_shutdown_client(client); | ||
393 | return mnt; | ||
394 | } | ||