Commit 556d600c authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] nfsd: svcrpc: move export table checks to a per-program pg_add_client method

svcauth_null_accept() and svcauth_unix_accept() are currently hard-wired to
check the source ip address on an incoming request against the export table,
which make sense for nfsd but not necessarily for other rpc-based services.

So instead we have the accept() method call a program-specific
pg_authenticate() method.  We also move the call to this method into
svc_process instead of calling it from the flavor-specific accept() routines.
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6147285b
...@@ -403,6 +403,20 @@ static int param_set_##name(const char *val, struct kernel_param *kp) \ ...@@ -403,6 +403,20 @@ static int param_set_##name(const char *val, struct kernel_param *kp) \
return 0; \ return 0; \
} }
static int lockd_authenticate(struct svc_rqst *rqstp)
{
rqstp->rq_client = NULL;
switch (rqstp->rq_authop->flavour) {
case RPC_AUTH_NULL:
case RPC_AUTH_UNIX:
if (rqstp->rq_proc == 0)
return SVC_OK;
return svc_set_client(rqstp);
}
return SVC_DENIED;
}
param_set_min_max(port, int, simple_strtol, 0, 65535) param_set_min_max(port, int, simple_strtol, 0, 65535)
param_set_min_max(grace_period, unsigned long, simple_strtoul, param_set_min_max(grace_period, unsigned long, simple_strtoul,
nlm_grace_period_min, nlm_grace_period_max) nlm_grace_period_min, nlm_grace_period_max)
...@@ -483,4 +497,5 @@ static struct svc_program nlmsvc_program = { ...@@ -483,4 +497,5 @@ static struct svc_program nlmsvc_program = {
.pg_name = "lockd", /* service name */ .pg_name = "lockd", /* service name */
.pg_class = "nfsd", /* share authentication with nfsd */ .pg_class = "nfsd", /* share authentication with nfsd */
.pg_stats = &nlmsvc_stats, /* stats table */ .pg_stats = &nlmsvc_stats, /* stats table */
.pg_authenticate = &lockd_authenticate /* export authentication */
}; };
...@@ -378,4 +378,6 @@ struct svc_program nfsd_program = { ...@@ -378,4 +378,6 @@ struct svc_program nfsd_program = {
.pg_name = "nfsd", /* program name */ .pg_name = "nfsd", /* program name */
.pg_class = "nfsd", /* authentication class */ .pg_class = "nfsd", /* authentication class */
.pg_stats = &nfsd_svcstats, /* version table */ .pg_stats = &nfsd_svcstats, /* version table */
.pg_authenticate = &svc_set_client, /* export authentication */
}; };
...@@ -253,6 +253,7 @@ struct svc_program { ...@@ -253,6 +253,7 @@ struct svc_program {
struct svc_stat * pg_stats; /* rpc statistics */ struct svc_stat * pg_stats; /* rpc statistics */
/* Override authentication. NULL means use default */ /* Override authentication. NULL means use default */
int (*pg_authenticate_obsolete)(struct svc_rqst *, u32 *); int (*pg_authenticate_obsolete)(struct svc_rqst *, u32 *);
int (*pg_authenticate)(struct svc_rqst *);
}; };
/* /*
......
...@@ -906,11 +906,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp) ...@@ -906,11 +906,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
svc_putu32(resv, rpc_success); svc_putu32(resv, rpc_success);
goto complete; goto complete;
case RPC_GSS_PROC_DATA: case RPC_GSS_PROC_DATA:
*authp = rpc_autherr_badcred;
rqstp->rq_client =
find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
if (rqstp->rq_client == NULL)
goto auth_err;
*authp = rpcsec_gsserr_ctxproblem; *authp = rpcsec_gsserr_ctxproblem;
if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
goto auth_err; goto auth_err;
...@@ -924,8 +919,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp) ...@@ -924,8 +919,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
if (unwrap_integ_data(&rqstp->rq_arg, if (unwrap_integ_data(&rqstp->rq_arg,
gc->gc_seq, rsci->mechctx)) gc->gc_seq, rsci->mechctx))
goto auth_err; goto auth_err;
svcdata->rsci = rsci;
cache_get(&rsci->h);
/* placeholders for length and seq. number: */ /* placeholders for length and seq. number: */
svcdata->body_start = resv->iov_base + resv->iov_len; svcdata->body_start = resv->iov_base + resv->iov_len;
svc_putu32(resv, 0); svc_putu32(resv, 0);
...@@ -936,6 +929,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp) ...@@ -936,6 +929,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
default: default:
goto auth_err; goto auth_err;
} }
svcdata->rsci = rsci;
cache_get(&rsci->h);
ret = SVC_OK; ret = SVC_OK;
goto out; goto out;
} }
......
...@@ -264,6 +264,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) ...@@ -264,6 +264,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
u32 dir, prog, vers, proc, u32 dir, prog, vers, proc,
auth_stat, rpc_stat; auth_stat, rpc_stat;
int auth_res; int auth_res;
u32 *accept_statp;
rpc_stat = rpc_success; rpc_stat = rpc_success;
...@@ -299,6 +300,9 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) ...@@ -299,6 +300,9 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
if (vers != 2) /* RPC version number */ if (vers != 2) /* RPC version number */
goto err_bad_rpc; goto err_bad_rpc;
/* Save position in case we later decide to reject: */
accept_statp = resv->iov_base + resv->iov_len;
svc_putu32(resv, xdr_zero); /* ACCEPT */ svc_putu32(resv, xdr_zero); /* ACCEPT */
rqstp->rq_prog = prog = ntohl(svc_getu32(argv)); /* program number */ rqstp->rq_prog = prog = ntohl(svc_getu32(argv)); /* program number */
...@@ -315,6 +319,11 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) ...@@ -315,6 +319,11 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
auth_res = progp->pg_authenticate_obsolete(rqstp, &auth_stat); auth_res = progp->pg_authenticate_obsolete(rqstp, &auth_stat);
else else
auth_res = svc_authenticate(rqstp, &auth_stat); auth_res = svc_authenticate(rqstp, &auth_stat);
/* Also give the program a chance to reject this call: */
if (auth_res == SVC_OK) {
auth_stat = rpc_autherr_badcred;
auth_res = progp->pg_authenticate(rqstp);
}
switch (auth_res) { switch (auth_res) {
case SVC_OK: case SVC_OK:
break; break;
...@@ -437,7 +446,8 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) ...@@ -437,7 +446,8 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
err_bad_auth: err_bad_auth:
dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat)); dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat));
serv->sv_stats->rpcbadauth++; serv->sv_stats->rpcbadauth++;
resv->iov_len -= 4; /* Restore write pointer to location of accept status: */
xdr_ressize_check(rqstp, accept_statp);
svc_putu32(resv, xdr_one); /* REJECT */ svc_putu32(resv, xdr_one); /* REJECT */
svc_putu32(resv, xdr_one); /* AUTH_ERROR */ svc_putu32(resv, xdr_one); /* AUTH_ERROR */
svc_putu32(resv, auth_stat); /* status */ svc_putu32(resv, auth_stat); /* status */
......
...@@ -368,7 +368,6 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp) ...@@ -368,7 +368,6 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
struct kvec *argv = &rqstp->rq_arg.head[0]; struct kvec *argv = &rqstp->rq_arg.head[0];
struct kvec *resv = &rqstp->rq_res.head[0]; struct kvec *resv = &rqstp->rq_res.head[0];
struct svc_cred *cred = &rqstp->rq_cred; struct svc_cred *cred = &rqstp->rq_cred;
int rv=0;
cred->cr_group_info = NULL; cred->cr_group_info = NULL;
rqstp->rq_client = NULL; rqstp->rq_client = NULL;
...@@ -394,19 +393,11 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp) ...@@ -394,19 +393,11 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
if (cred->cr_group_info == NULL) if (cred->cr_group_info == NULL)
return SVC_DROP; /* kmalloc failure - client must retry */ return SVC_DROP; /* kmalloc failure - client must retry */
rv = svcauth_unix_set_client(rqstp);
if (rv == SVC_DENIED)
goto badcred;
/* Put NULL verifier */ /* Put NULL verifier */
svc_putu32(resv, RPC_AUTH_NULL); svc_putu32(resv, RPC_AUTH_NULL);
svc_putu32(resv, 0); svc_putu32(resv, 0);
return rv; return SVC_OK;
badcred:
*authp = rpc_autherr_badcred;
return SVC_DENIED;
} }
static int static int
...@@ -441,7 +432,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp) ...@@ -441,7 +432,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
struct svc_cred *cred = &rqstp->rq_cred; struct svc_cred *cred = &rqstp->rq_cred;
u32 slen, i; u32 slen, i;
int len = argv->iov_len; int len = argv->iov_len;
int rv=0;
cred->cr_group_info = NULL; cred->cr_group_info = NULL;
rqstp->rq_client = NULL; rqstp->rq_client = NULL;
...@@ -473,15 +463,11 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp) ...@@ -473,15 +463,11 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
return SVC_DENIED; return SVC_DENIED;
} }
rv = svcauth_unix_set_client(rqstp);
if (rv == SVC_DENIED)
goto badcred;
/* Put NULL verifier */ /* Put NULL verifier */
svc_putu32(resv, RPC_AUTH_NULL); svc_putu32(resv, RPC_AUTH_NULL);
svc_putu32(resv, 0); svc_putu32(resv, 0);
return rv; return SVC_OK;
badcred: badcred:
*authp = rpc_autherr_badcred; *authp = rpc_autherr_badcred;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment