diff options
Diffstat (limited to 'fs')
| -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 | /* |
