diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-03-05 14:27:13 -0500 |
---|---|---|
committer | Steve Dickson <steved@redhat.com> | 2010-03-05 14:27:13 -0500 |
commit | 599511589ca7ddb3b2eac8d3aa5b0b38be7a7691 (patch) | |
tree | 5180447dfc96cda6bad58cb0814f2add66a3e9b4 | |
parent | 89323aafc77e1a40800332fb135888782b1bfee6 (diff) | |
download | ti-rpc-libtirpc-0-2-2-rc1.tar.gz |
libtirpc: allow larger ticket sizes with RPCSEC_GSSlibtirpc-0-2-2-rc1
libtirpc currently limits RPCSEC_GSS args to MAX_NETOBJ_SZ (1024) bytes.
This causes problems when you try to use large krb5 tickets, such as
those handed out by MS' Active Directory when the user has a large PAC.
This patch backports a set of changes from librpcsecgss which fixed this
problem there. It declares a new routine specifically for encoding
gss_buffer_t's and has the various auth_gss routines use that instead of
calling xdr_bytes directly.
An RPC_SLACK_SPACE constant is defined and added to the buffer length to
get a max buffer length to pass to xdr_rpc_gss_buf for the appropriate
callers.
This seems to fix the bug reported here:
https://bugzilla.redhat.com/show_bug.cgi?id=562807
Reported-by: Michael Young <m.a.young@durham.ac.uk>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
-rw-r--r-- | src/authgss_prot.c | 72 |
1 files changed, 51 insertions, 21 deletions
diff --git a/src/authgss_prot.c b/src/authgss_prot.c index ab72d91..9d7fa09 100644 --- a/src/authgss_prot.c +++ b/src/authgss_prot.c @@ -44,6 +44,34 @@ #include <rpc/rpc.h> #include <gssapi/gssapi.h> +/* additional space needed for encoding */ +#define RPC_SLACK_SPACE 1024 + +bool_t +xdr_rpc_gss_buf(XDR *xdrs, gss_buffer_t buf, u_int maxsize) +{ + bool_t xdr_stat; + u_int tmplen; + + if (xdrs->x_op != XDR_DECODE) { + if (buf->length > UINT_MAX) + return FALSE; + else + tmplen = buf->length; + } + xdr_stat = xdr_bytes(xdrs, (char **)&buf->value, &tmplen, maxsize); + + if (xdr_stat && xdrs->x_op == XDR_DECODE) + buf->length = tmplen; + + log_debug("xdr_rpc_gss_buf: %s %s (%p:%d)", + (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode", + (xdr_stat == TRUE) ? "success" : "failure", + buf->value, buf->length); + + return xdr_stat; +} + bool_t xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p) { @@ -53,8 +81,7 @@ xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p) xdr_enum(xdrs, (enum_t *)&p->gc_proc) && xdr_u_int(xdrs, &p->gc_seq) && xdr_enum(xdrs, (enum_t *)&p->gc_svc) && - xdr_bytes(xdrs, (char **)&p->gc_ctx.value, - (u_int *)&p->gc_ctx.length, MAX_AUTH_BYTES)); + xdr_rpc_gss_buf(xdrs, &p->gc_ctx, MAX_AUTH_BYTES)); log_debug("xdr_rpc_gss_cred: %s %s " "(v %d, proc %d, seq %d, svc %d, ctx %p:%d)", @@ -70,9 +97,9 @@ bool_t xdr_rpc_gss_init_args(XDR *xdrs, gss_buffer_desc *p) { bool_t xdr_stat; + u_int maxlen = (u_int)(p->length + RPC_SLACK_SPACE); - xdr_stat = xdr_bytes(xdrs, (char **)&p->value, - (u_int *)&p->length, MAX_NETOBJ_SZ); + xdr_stat = xdr_rpc_gss_buf(xdrs, p, maxlen); log_debug("xdr_rpc_gss_init_args: %s %s (token %p:%d)", (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode", @@ -87,13 +114,14 @@ xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p) { bool_t xdr_stat; - xdr_stat = (xdr_bytes(xdrs, (char **)&p->gr_ctx.value, - (u_int *)&p->gr_ctx.length, MAX_NETOBJ_SZ) && + u_int ctx_maxlen = (u_int)(p->gr_ctx.length + RPC_SLACK_SPACE); + u_int tok_maxlen = (u_int)(p->gr_token.length + RPC_SLACK_SPACE); + + xdr_stat = (xdr_rpc_gss_buf(xdrs, &p->gr_ctx, ctx_maxlen) && xdr_u_int(xdrs, &p->gr_major) && xdr_u_int(xdrs, &p->gr_minor) && xdr_u_int(xdrs, &p->gr_win) && - xdr_bytes(xdrs, (char **)&p->gr_token.value, - (u_int *)&p->gr_token.length, MAX_NETOBJ_SZ)); + xdr_rpc_gss_buf(xdrs, &p->gr_token, tok_maxlen)); log_debug("xdr_rpc_gss_init_res %s %s " "(ctx %p:%d, maj %d, min %d, win %d, token %p:%d)", @@ -115,28 +143,33 @@ xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, OM_uint32 maj_stat, min_stat; int start, end, conf_state; bool_t xdr_stat; + u_int databuflen, maxwrapsz; /* Skip databody length. */ start = XDR_GETPOS(xdrs); XDR_SETPOS(xdrs, start + 4); + memset(&databuf, 0, sizeof(databuf)); + memset(&wrapbuf, 0, sizeof(wrapbuf)); + /* Marshal rpc_gss_data_t (sequence number + arguments). */ if (!xdr_u_int(xdrs, &seq) || !(*xdr_func)(xdrs, xdr_ptr)) return (FALSE); end = XDR_GETPOS(xdrs); /* Set databuf to marshalled rpc_gss_data_t. */ - databuf.length = end - start - 4; + databuflen = end - start - 4; XDR_SETPOS(xdrs, start + 4); - databuf.value = XDR_INLINE(xdrs, databuf.length); + databuf.value = XDR_INLINE(xdrs, databuflen); xdr_stat = FALSE; if (svc == RPCSEC_GSS_SVC_INTEGRITY) { /* Marshal databody_integ length. */ XDR_SETPOS(xdrs, start); - if (!xdr_u_int(xdrs, (u_int *)&databuf.length)) + if (!xdr_u_int(xdrs, (u_int *)&databuflen)) return (FALSE); + databuf.length = databuflen; /* Checksum rpc_gss_data_t. */ maj_stat = gss_get_mic(&min_stat, ctx, qop, @@ -147,8 +180,8 @@ xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, } /* Marshal checksum. */ XDR_SETPOS(xdrs, end); - xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value, - (u_int *)&wrapbuf.length, MAX_NETOBJ_SZ); + maxwrapsz = (u_int)(wrapbuf.length + RPC_SLACK_SPACE); + xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, maxwrapsz); gss_release_buffer(&min_stat, &wrapbuf); } else if (svc == RPCSEC_GSS_SVC_PRIVACY) { @@ -161,8 +194,8 @@ xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, } /* Marshal databody_priv. */ XDR_SETPOS(xdrs, start); - xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value, - (u_int *)&wrapbuf.length, MAX_NETOBJ_SZ); + maxwrapsz = (u_int)(wrapbuf.length + RPC_SLACK_SPACE); + xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, maxwrapsz); gss_release_buffer(&min_stat, &wrapbuf); } return (xdr_stat); @@ -188,14 +221,12 @@ xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, if (svc == RPCSEC_GSS_SVC_INTEGRITY) { /* Decode databody_integ. */ - if (!xdr_bytes(xdrs, (char **)&databuf.value, (u_int *)&databuf.length, - MAX_NETOBJ_SZ)) { + if (!xdr_rpc_gss_buf(xdrs, &databuf, (u_int)-1)) { log_debug("xdr decode databody_integ failed"); return (FALSE); } /* Decode checksum. */ - if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, (u_int *)&wrapbuf.length, - MAX_NETOBJ_SZ)) { + if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (u_int)-1)) { gss_release_buffer(&min_stat, &databuf); log_debug("xdr decode checksum failed"); return (FALSE); @@ -213,8 +244,7 @@ xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, } else if (svc == RPCSEC_GSS_SVC_PRIVACY) { /* Decode databody_priv. */ - if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, (u_int *)&wrapbuf.length, - MAX_NETOBJ_SZ)) { + if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (u_int)-1)) { log_debug("xdr decode databody_priv failed"); return (FALSE); } |