Commit db1d6165 authored by Chuck Lever's avatar Chuck Lever

SUNRPC: Go back to using gsd->body_start

Now that svcauth_gss_prepare_to_wrap() no longer computes the
location of RPC header fields in the response buffer,
svcauth_gss_accept() can save the location of the databody
rather than the location of the verifier.
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 4bcf0343
...@@ -71,9 +71,7 @@ ...@@ -71,9 +71,7 @@
struct gss_svc_data { struct gss_svc_data {
/* decoded gss client cred: */ /* decoded gss client cred: */
struct rpc_gss_wire_cred clcred; struct rpc_gss_wire_cred clcred;
/* save a pointer to the beginning of the encoded verifier, u32 gsd_databody_offset;
* for use in encryption/checksumming in svcauth_gss_release: */
__be32 *verf_start;
struct rsc *rsci; struct rsc *rsci;
/* for temporary results */ /* for temporary results */
...@@ -1595,7 +1593,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp) ...@@ -1595,7 +1593,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
if (!svcdata) if (!svcdata)
goto auth_err; goto auth_err;
rqstp->rq_auth_data = svcdata; rqstp->rq_auth_data = svcdata;
svcdata->verf_start = NULL; svcdata->gsd_databody_offset = 0;
svcdata->rsci = NULL; svcdata->rsci = NULL;
gc = &svcdata->clcred; gc = &svcdata->clcred;
...@@ -1647,11 +1645,11 @@ svcauth_gss_accept(struct svc_rqst *rqstp) ...@@ -1647,11 +1645,11 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
goto complete; goto complete;
case RPC_GSS_PROC_DATA: case RPC_GSS_PROC_DATA:
rqstp->rq_auth_stat = rpcsec_gsserr_ctxproblem; rqstp->rq_auth_stat = rpcsec_gsserr_ctxproblem;
svcdata->verf_start = xdr_reserve_space(&rqstp->rq_res_stream, 0);
if (!svcauth_gss_encode_verf(rqstp, rsci->mechctx, gc->gc_seq)) if (!svcauth_gss_encode_verf(rqstp, rsci->mechctx, gc->gc_seq))
goto auth_err; goto auth_err;
if (!svcxdr_set_accept_stat(rqstp)) if (!svcxdr_set_accept_stat(rqstp))
goto auth_err; goto auth_err;
svcdata->gsd_databody_offset = xdr_stream_pos(&rqstp->rq_res_stream);
rqstp->rq_cred = rsci->cred; rqstp->rq_cred = rsci->cred;
get_group_info(rsci->cred.cr_group_info); get_group_info(rsci->cred.cr_group_info);
rqstp->rq_auth_stat = rpc_autherr_badcred; rqstp->rq_auth_stat = rpc_autherr_badcred;
...@@ -1705,30 +1703,24 @@ svcauth_gss_accept(struct svc_rqst *rqstp) ...@@ -1705,30 +1703,24 @@ svcauth_gss_accept(struct svc_rqst *rqstp)
return ret; return ret;
} }
static __be32 * static u32
svcauth_gss_prepare_to_wrap(struct svc_rqst *rqstp, struct gss_svc_data *gsd) svcauth_gss_prepare_to_wrap(struct svc_rqst *rqstp, struct gss_svc_data *gsd)
{ {
__be32 *p; u32 offset;
u32 verf_len;
p = gsd->verf_start; /* Release can be called twice, but we only wrap once. */
gsd->verf_start = NULL; offset = gsd->gsd_databody_offset;
gsd->gsd_databody_offset = 0;
/* AUTH_ERROR replies are not wrapped. */ /* AUTH_ERROR replies are not wrapped. */
if (rqstp->rq_auth_stat != rpc_auth_ok) if (rqstp->rq_auth_stat != rpc_auth_ok)
return NULL; return 0;
/* Skip the verifier: */
p += 1;
verf_len = ntohl(*p++);
p += XDR_QUADLEN(verf_len);
/* Also don't wrap if the accept_stat is nonzero: */ /* Also don't wrap if the accept_stat is nonzero: */
if (*rqstp->rq_accept_statp != rpc_success) if (*rqstp->rq_accept_statp != rpc_success)
return NULL; return 0;
p++; return offset;
return p;
} }
/* /*
...@@ -1756,21 +1748,21 @@ static int svcauth_gss_wrap_integ(struct svc_rqst *rqstp) ...@@ -1756,21 +1748,21 @@ static int svcauth_gss_wrap_integ(struct svc_rqst *rqstp)
struct xdr_buf *buf = xdr->buf; struct xdr_buf *buf = xdr->buf;
struct xdr_buf databody_integ; struct xdr_buf databody_integ;
struct xdr_netobj checksum; struct xdr_netobj checksum;
u32 offset, len, maj_stat; u32 offset, maj_stat;
__be32 *p;
p = svcauth_gss_prepare_to_wrap(rqstp, gsd); offset = svcauth_gss_prepare_to_wrap(rqstp, gsd);
if (p == NULL) if (!offset)
goto out; goto out;
offset = (u8 *)(p + 1) - (u8 *)buf->head[0].iov_base; if (xdr_buf_subsegment(buf, &databody_integ, offset + XDR_UNIT,
len = buf->len - offset; buf->len - offset - XDR_UNIT))
if (xdr_buf_subsegment(buf, &databody_integ, offset, len))
goto wrap_failed; goto wrap_failed;
/* Buffer space for these has already been reserved in /* Buffer space for these has already been reserved in
* svcauth_gss_accept(). */ * svcauth_gss_accept(). */
*p++ = cpu_to_be32(len); if (xdr_encode_word(buf, offset, databody_integ.len))
*p = cpu_to_be32(gc->gc_seq); goto wrap_failed;
if (xdr_encode_word(buf, offset + XDR_UNIT, gc->gc_seq))
goto wrap_failed;
checksum.data = gsd->gsd_scratch; checksum.data = gsd->gsd_scratch;
maj_stat = gss_get_mic(gsd->rsci->mechctx, &databody_integ, &checksum); maj_stat = gss_get_mic(gsd->rsci->mechctx, &databody_integ, &checksum);
...@@ -1817,17 +1809,19 @@ static int svcauth_gss_wrap_priv(struct svc_rqst *rqstp) ...@@ -1817,17 +1809,19 @@ static int svcauth_gss_wrap_priv(struct svc_rqst *rqstp)
struct kvec *head = buf->head; struct kvec *head = buf->head;
struct kvec *tail = buf->tail; struct kvec *tail = buf->tail;
u32 offset, pad, maj_stat; u32 offset, pad, maj_stat;
__be32 *p, *lenp; __be32 *p;
p = svcauth_gss_prepare_to_wrap(rqstp, gsd); offset = svcauth_gss_prepare_to_wrap(rqstp, gsd);
if (p == NULL) if (!offset)
return 0; return 0;
lenp = p++; /*
offset = (u8 *)p - (u8 *)head->iov_base; * Buffer space for this field has already been reserved
/* Buffer space for this field has already been reserved * in svcauth_gss_accept(). Note that the GSS sequence
* in svcauth_gss_accept(). */ * number is encrypted along with the RPC reply payload.
*p = cpu_to_be32(gc->gc_seq); */
if (xdr_encode_word(buf, offset + XDR_UNIT, gc->gc_seq))
goto wrap_failed;
/* /*
* If there is currently tail data, make sure there is * If there is currently tail data, make sure there is
...@@ -1863,12 +1857,15 @@ static int svcauth_gss_wrap_priv(struct svc_rqst *rqstp) ...@@ -1863,12 +1857,15 @@ static int svcauth_gss_wrap_priv(struct svc_rqst *rqstp)
tail->iov_len = 0; tail->iov_len = 0;
} }
maj_stat = gss_wrap(gsd->rsci->mechctx, offset, buf, buf->pages); maj_stat = gss_wrap(gsd->rsci->mechctx, offset + XDR_UNIT, buf,
buf->pages);
if (maj_stat != GSS_S_COMPLETE) if (maj_stat != GSS_S_COMPLETE)
goto bad_wrap; goto bad_wrap;
*lenp = cpu_to_be32(buf->len - offset); /* Wrapping can change the size of databody_priv. */
pad = xdr_pad_size(buf->len - offset); if (xdr_encode_word(buf, offset, buf->len - offset - XDR_UNIT))
goto wrap_failed;
pad = xdr_pad_size(buf->len - offset - XDR_UNIT);
p = (__be32 *)(tail->iov_base + tail->iov_len); p = (__be32 *)(tail->iov_base + tail->iov_len);
memset(p, 0, pad); memset(p, 0, pad);
tail->iov_len += pad; tail->iov_len += pad;
...@@ -1908,9 +1905,6 @@ svcauth_gss_release(struct svc_rqst *rqstp) ...@@ -1908,9 +1905,6 @@ svcauth_gss_release(struct svc_rqst *rqstp)
gc = &gsd->clcred; gc = &gsd->clcred;
if (gc->gc_proc != RPC_GSS_PROC_DATA) if (gc->gc_proc != RPC_GSS_PROC_DATA)
goto out; goto out;
/* Release can be called twice, but we only wrap once. */
if (gsd->verf_start == NULL)
goto out;
switch (gc->gc_svc) { switch (gc->gc_svc) {
case RPC_GSS_SVC_NONE: case RPC_GSS_SVC_NONE:
......
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