Skip to content

Commit

Permalink
SUNRPC: split upcall function to extract reusable parts
Browse files Browse the repository at this point in the history
This is needed to share code between the current server upcall mechanism
and the new gssproxy upcall mechanism introduced in a following patch.

Signed-off-by: Simo Sorce <[email protected]>
Signed-off-by: J. Bruce Fields <[email protected]>
  • Loading branch information
simo5 authored and J. Bruce Fields committed Apr 25, 2012
1 parent f69adb2 commit fc2952a
Showing 1 changed file with 64 additions and 36 deletions.
100 changes: 64 additions & 36 deletions net/sunrpc/auth_gss/svcauth_gss.c
Original file line number Diff line number Diff line change
Expand Up @@ -964,39 +964,31 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
}

static inline int
gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi *rsip)
gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
struct xdr_netobj *out_handle, int *major_status)
{
struct rsc *rsci;
int rc;

if (rsip->major_status != GSS_S_COMPLETE)
if (*major_status != GSS_S_COMPLETE)
return gss_write_null_verf(rqstp);
rsci = gss_svc_searchbyctx(cd, &rsip->out_handle);
rsci = gss_svc_searchbyctx(cd, out_handle);
if (rsci == NULL) {
rsip->major_status = GSS_S_NO_CONTEXT;
*major_status = GSS_S_NO_CONTEXT;
return gss_write_null_verf(rqstp);
}
rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
cache_put(&rsci->h, cd);
return rc;
}

/*
* Having read the cred already and found we're in the context
* initiation case, read the verifier and initiate (or check the results
* of) upcalls to userspace for help with context initiation. If
* the upcall results are available, write the verifier and result.
* Otherwise, drop the request pending an answer to the upcall.
*/
static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
struct rpc_gss_wire_cred *gc, __be32 *authp)
static inline int
gss_read_verf(struct rpc_gss_wire_cred *gc,
struct kvec *argv, __be32 *authp,
struct xdr_netobj *in_handle,
struct xdr_netobj *in_token)
{
struct kvec *argv = &rqstp->rq_arg.head[0];
struct kvec *resv = &rqstp->rq_res.head[0];
struct xdr_netobj tmpobj;
struct rsi *rsip, rsikey;
int ret;
struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);

/* Read the verifier; should be NULL: */
*authp = rpc_autherr_badverf;
Expand All @@ -1006,24 +998,67 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
return SVC_DENIED;
if (svc_getnl(argv) != 0)
return SVC_DENIED;

/* Martial context handle and token for upcall: */
*authp = rpc_autherr_badcred;
if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0)
return SVC_DENIED;
memset(&rsikey, 0, sizeof(rsikey));
if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx))
if (dup_netobj(in_handle, &gc->gc_ctx))
return SVC_CLOSE;
*authp = rpc_autherr_badverf;
if (svc_safe_getnetobj(argv, &tmpobj)) {
kfree(rsikey.in_handle.data);
kfree(in_handle->data);
return SVC_DENIED;
}
if (dup_netobj(&rsikey.in_token, &tmpobj)) {
kfree(rsikey.in_handle.data);
if (dup_netobj(in_token, &tmpobj)) {
kfree(in_handle->data);
return SVC_CLOSE;
}

return 0;
}

static inline int
gss_write_resv(struct kvec *resv, size_t size_limit,
struct xdr_netobj *out_handle, struct xdr_netobj *out_token,
int major_status, int minor_status)
{
if (resv->iov_len + 4 > size_limit)
return -1;
svc_putnl(resv, RPC_SUCCESS);
if (svc_safe_putnetobj(resv, out_handle))
return -1;
if (resv->iov_len + 3 * 4 > size_limit)
return -1;
svc_putnl(resv, major_status);
svc_putnl(resv, minor_status);
svc_putnl(resv, GSS_SEQ_WIN);
if (svc_safe_putnetobj(resv, out_token))
return -1;
return 0;
}

/*
* Having read the cred already and found we're in the context
* initiation case, read the verifier and initiate (or check the results
* of) upcalls to userspace for help with context initiation. If
* the upcall results are available, write the verifier and result.
* Otherwise, drop the request pending an answer to the upcall.
*/
static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
struct rpc_gss_wire_cred *gc, __be32 *authp)
{
struct kvec *argv = &rqstp->rq_arg.head[0];
struct kvec *resv = &rqstp->rq_res.head[0];
struct rsi *rsip, rsikey;
int ret;
struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);

memset(&rsikey, 0, sizeof(rsikey));
ret = gss_read_verf(gc, argv, authp,
&rsikey.in_handle, &rsikey.in_token);
if (ret)
return ret;

/* Perform upcall, or find upcall result: */
rsip = rsi_lookup(sn->rsi_cache, &rsikey);
rsi_free(&rsikey);
Expand All @@ -1035,19 +1070,12 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,

ret = SVC_CLOSE;
/* Got an answer to the upcall; use it: */
if (gss_write_init_verf(sn->rsc_cache, rqstp, rsip))
if (gss_write_init_verf(sn->rsc_cache, rqstp,
&rsip->out_handle, &rsip->major_status))
goto out;
if (resv->iov_len + 4 > PAGE_SIZE)
goto out;
svc_putnl(resv, RPC_SUCCESS);
if (svc_safe_putnetobj(resv, &rsip->out_handle))
goto out;
if (resv->iov_len + 3 * 4 > PAGE_SIZE)
goto out;
svc_putnl(resv, rsip->major_status);
svc_putnl(resv, rsip->minor_status);
svc_putnl(resv, GSS_SEQ_WIN);
if (svc_safe_putnetobj(resv, &rsip->out_token))
if (gss_write_resv(resv, PAGE_SIZE,
&rsip->out_handle, &rsip->out_token,
rsip->major_status, rsip->minor_status))
goto out;

ret = SVC_COMPLETE;
Expand Down

0 comments on commit fc2952a

Please sign in to comment.