diff options
Diffstat (limited to 'fs/nfs/callback.c')
-rw-r--r-- | fs/nfs/callback.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index c2e9cfd9e5a4..3e634f2a1083 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
17 | #include <linux/freezer.h> | 17 | #include <linux/freezer.h> |
18 | #include <linux/kthread.h> | 18 | #include <linux/kthread.h> |
19 | #include <linux/sunrpc/svcauth_gss.h> | ||
19 | 20 | ||
20 | #include <net/inet_sock.h> | 21 | #include <net/inet_sock.h> |
21 | 22 | ||
@@ -182,10 +183,34 @@ void nfs_callback_down(void) | |||
182 | mutex_unlock(&nfs_callback_mutex); | 183 | mutex_unlock(&nfs_callback_mutex); |
183 | } | 184 | } |
184 | 185 | ||
186 | static int check_gss_callback_principal(struct nfs_client *clp, | ||
187 | struct svc_rqst *rqstp) | ||
188 | { | ||
189 | struct rpc_clnt *r = clp->cl_rpcclient; | ||
190 | char *p = svc_gss_principal(rqstp); | ||
191 | |||
192 | /* | ||
193 | * It might just be a normal user principal, in which case | ||
194 | * userspace won't bother to tell us the name at all. | ||
195 | */ | ||
196 | if (p == NULL) | ||
197 | return SVC_DENIED; | ||
198 | |||
199 | /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */ | ||
200 | |||
201 | if (memcmp(p, "nfs@", 4) != 0) | ||
202 | return SVC_DENIED; | ||
203 | p += 4; | ||
204 | if (strcmp(p, r->cl_server) != 0) | ||
205 | return SVC_DENIED; | ||
206 | return SVC_OK; | ||
207 | } | ||
208 | |||
185 | static int nfs_callback_authenticate(struct svc_rqst *rqstp) | 209 | static int nfs_callback_authenticate(struct svc_rqst *rqstp) |
186 | { | 210 | { |
187 | struct nfs_client *clp; | 211 | struct nfs_client *clp; |
188 | RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); | 212 | RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); |
213 | int ret = SVC_OK; | ||
189 | 214 | ||
190 | /* Don't talk to strangers */ | 215 | /* Don't talk to strangers */ |
191 | clp = nfs_find_client(svc_addr(rqstp), 4); | 216 | clp = nfs_find_client(svc_addr(rqstp), 4); |
@@ -194,21 +219,22 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp) | |||
194 | 219 | ||
195 | dprintk("%s: %s NFSv4 callback!\n", __func__, | 220 | dprintk("%s: %s NFSv4 callback!\n", __func__, |
196 | svc_print_addr(rqstp, buf, sizeof(buf))); | 221 | svc_print_addr(rqstp, buf, sizeof(buf))); |
197 | nfs_put_client(clp); | ||
198 | 222 | ||
199 | switch (rqstp->rq_authop->flavour) { | 223 | switch (rqstp->rq_authop->flavour) { |
200 | case RPC_AUTH_NULL: | 224 | case RPC_AUTH_NULL: |
201 | if (rqstp->rq_proc != CB_NULL) | 225 | if (rqstp->rq_proc != CB_NULL) |
202 | return SVC_DENIED; | 226 | ret = SVC_DENIED; |
203 | break; | 227 | break; |
204 | case RPC_AUTH_UNIX: | 228 | case RPC_AUTH_UNIX: |
205 | break; | 229 | break; |
206 | case RPC_AUTH_GSS: | 230 | case RPC_AUTH_GSS: |
207 | /* FIXME: RPCSEC_GSS handling? */ | 231 | ret = check_gss_callback_principal(clp, rqstp); |
232 | break; | ||
208 | default: | 233 | default: |
209 | return SVC_DENIED; | 234 | ret = SVC_DENIED; |
210 | } | 235 | } |
211 | return SVC_OK; | 236 | nfs_put_client(clp); |
237 | return ret; | ||
212 | } | 238 | } |
213 | 239 | ||
214 | /* | 240 | /* |