Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 309805
b: refs/heads/master
c: fc2952a
h: refs/heads/master
i:
  309803: b7ec30d
v: v3
  • Loading branch information
Simo Sorce authored and J. Bruce Fields committed Apr 25, 2012
1 parent 08af93d commit ad247df
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 37 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f69adb2fe2553f0536ad3603828c835239d5ec3e
refs/heads/master: fc2952a2a9f724f7d200c69a2b059ec331a80363
100 changes: 64 additions & 36 deletions trunk/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 ad247df

Please sign in to comment.