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) \
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(grace_period, unsigned long, simple_strtoul,
nlm_grace_period_min, nlm_grace_period_max)
......@@ -483,4 +497,5 @@ static struct svc_program nlmsvc_program = {
.pg_name = "lockd", /* service name */
.pg_class = "nfsd", /* share authentication with nfsd */
.pg_stats = &nlmsvc_stats, /* stats table */
.pg_authenticate = &lockd_authenticate /* export authentication */
};
......@@ -378,4 +378,6 @@ struct svc_program nfsd_program = {
.pg_name = "nfsd", /* program name */
.pg_class = "nfsd", /* authentication class */
.pg_stats = &nfsd_svcstats, /* version table */
.pg_authenticate = &svc_set_client, /* export authentication */
};
......@@ -253,6 +253,7 @@ struct svc_program {
struct svc_stat * pg_stats; /* rpc statistics */
/* Override authentication. NULL means use default */
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)
svc_putu32(resv, rpc_success);
goto complete;
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;
if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
goto auth_err;
......@@ -924,8 +919,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
if (unwrap_integ_data(&rqstp->rq_arg,
gc->gc_seq, rsci->mechctx))
goto auth_err;
svcdata->rsci = rsci;
cache_get(&rsci->h);
/* placeholders for length and seq. number: */
svcdata->body_start = resv->iov_base + resv->iov_len;
svc_putu32(resv, 0);
......@@ -936,6 +929,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
default:
goto auth_err;
}
svcdata->rsci = rsci;
cache_get(&rsci->h);
ret = SVC_OK;
goto out;
}
......
......@@ -264,6 +264,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
u32 dir, prog, vers, proc,
auth_stat, rpc_stat;
int auth_res;
u32 *accept_statp;
rpc_stat = rpc_success;
......@@ -299,6 +300,9 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
if (vers != 2) /* RPC version number */
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 */
rqstp->rq_prog = prog = ntohl(svc_getu32(argv)); /* program number */
......@@ -315,6 +319,11 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
auth_res = progp->pg_authenticate_obsolete(rqstp, &auth_stat);
else
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) {
case SVC_OK:
break;
......@@ -437,7 +446,8 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
err_bad_auth:
dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat));
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); /* AUTH_ERROR */
svc_putu32(resv, auth_stat); /* status */
......
......@@ -368,7 +368,6 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
struct kvec *argv = &rqstp->rq_arg.head[0];
struct kvec *resv = &rqstp->rq_res.head[0];
struct svc_cred *cred = &rqstp->rq_cred;
int rv=0;
cred->cr_group_info = NULL;
rqstp->rq_client = NULL;
......@@ -394,19 +393,11 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
if (cred->cr_group_info == NULL)
return SVC_DROP; /* kmalloc failure - client must retry */
rv = svcauth_unix_set_client(rqstp);
if (rv == SVC_DENIED)
goto badcred;
/* Put NULL verifier */
svc_putu32(resv, RPC_AUTH_NULL);
svc_putu32(resv, 0);
return rv;
badcred:
*authp = rpc_autherr_badcred;
return SVC_DENIED;
return SVC_OK;
}
static int
......@@ -441,7 +432,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
struct svc_cred *cred = &rqstp->rq_cred;
u32 slen, i;
int len = argv->iov_len;
int rv=0;
cred->cr_group_info = NULL;
rqstp->rq_client = NULL;
......@@ -473,15 +463,11 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
return SVC_DENIED;
}
rv = svcauth_unix_set_client(rqstp);
if (rv == SVC_DENIED)
goto badcred;
/* Put NULL verifier */
svc_putu32(resv, RPC_AUTH_NULL);
svc_putu32(resv, 0);
return rv;
return SVC_OK;
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