diff --git a/libtirpc-0-2-2-rc1.patch b/libtirpc-0-2-2-rc1.patch new file mode 100644 index 0000000..a83d404 --- /dev/null +++ b/libtirpc-0-2-2-rc1.patch @@ -0,0 +1,314 @@ +commit 599511589ca7ddb3b2eac8d3aa5b0b38be7a7691 +Author: Jeff Layton +Date: Fri Mar 5 14:27:13 2010 -0500 + + libtirpc: allow larger ticket sizes with RPCSEC_GSS + + 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 + Signed-off-by: Jeff Layton + Signed-off-by: Steve Dickson + +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 + #include + ++/* 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); + } + +commit 89323aafc77e1a40800332fb135888782b1bfee6 +Author: Jeff Layton +Date: Fri Mar 5 12:55:31 2010 -0500 + + libtirpc: don't call abort() in the AUTH_UNIX creation codepaths + + When there are problems creating an AUTH_UNIX auth handle, libtirpc will + sometimes call abort(). It's bad for a library to do this since + decisions about how to handle errors are better left up to the + application and abort() generally causes the app to crash and dump core. + + Make it so that these functions return NULL instead in these situations. + authunix_create already returns NULL for other error conditions so it + seems like an appropriate way to handle errors in these codepaths. + + Have authunix_create and authunix_create_default set appropriate errors + in the rpc_createerr struct. It seems a little odd to do this since + rpc_createerr is supposed to report information about why CLIENT + creation failed, and the problem here is in creating an AUTH handle. + authgss_create does this already however, so there is some precedent. + + While we're at it, it's also bad for libraries to log to stderr. It's + possible that a daemon is calling here and it has closed stderr and is + resuing fd 2 for something else. Rip out the warnx calls from these two + functions to make sure that they don't cause problems. + + Signed-off-by: Jeff Layton + Signed-off-by: Steve Dickson + +diff --git a/src/auth_unix.c b/src/auth_unix.c +index 71ca15d..ddd89cc 100644 +--- a/src/auth_unix.c ++++ b/src/auth_unix.c +@@ -49,7 +49,9 @@ + #include + #include + #include ++#include + ++#include + #include + #include + #include +@@ -95,6 +97,8 @@ authunix_create(machname, uid, gid, len, aup_gids) + AUTH *auth; + struct audata *au; + ++ memset(&rpc_createerr, 0, sizeof(rpc_createerr)); ++ + /* + * Allocate and set up auth handle + */ +@@ -102,14 +106,16 @@ authunix_create(machname, uid, gid, len, aup_gids) + auth = mem_alloc(sizeof(*auth)); + #ifndef _KERNEL + if (auth == NULL) { +- warnx("authunix_create: out of memory"); ++ rpc_createerr.cf_stat = RPC_SYSTEMERROR; ++ rpc_createerr.cf_error.re_errno = ENOMEM; + goto cleanup_authunix_create; + } + #endif + au = mem_alloc(sizeof(*au)); + #ifndef _KERNEL + if (au == NULL) { +- warnx("authunix_create: out of memory"); ++ rpc_createerr.cf_stat = RPC_SYSTEMERROR; ++ rpc_createerr.cf_error.re_errno = ENOMEM; + goto cleanup_authunix_create; + } + #endif +@@ -134,15 +140,18 @@ authunix_create(machname, uid, gid, len, aup_gids) + * Serialize the parameters into origcred + */ + xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); +- if (! xdr_authunix_parms(&xdrs, &aup)) +- abort(); ++ if (!xdr_authunix_parms(&xdrs, &aup)) { ++ rpc_createerr.cf_stat = RPC_CANTENCODEARGS; ++ goto cleanup_authunix_create; ++ } + au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); + au->au_origcred.oa_flavor = AUTH_UNIX; + #ifdef _KERNEL + au->au_origcred.oa_base = mem_alloc((u_int) len); + #else + if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) { +- warnx("authunix_create: out of memory"); ++ rpc_createerr.cf_stat = RPC_SYSTEMERROR; ++ rpc_createerr.cf_error.re_errno = ENOMEM; + goto cleanup_authunix_create; + } + #endif +@@ -180,13 +189,22 @@ authunix_create_default() + gid_t gid; + gid_t gids[NGRPS]; + +- if (gethostname(machname, sizeof machname) == -1) +- abort(); ++ memset(&rpc_createerr, 0, sizeof(rpc_createerr)); ++ ++ if (gethostname(machname, sizeof machname) == -1) { ++ rpc_createerr.cf_stat = RPC_SYSTEMERROR; ++ rpc_createerr.cf_error.re_errno = errno; ++ return NULL; ++ } + machname[sizeof(machname) - 1] = 0; + uid = geteuid(); + gid = getegid(); +- if ((len = getgroups(NGRPS, gids)) < 0) +- abort(); ++ len = getgroups(NGRPS, gids); ++ if (len < 0) { ++ rpc_createerr.cf_stat = RPC_SYSTEMERROR; ++ rpc_createerr.cf_error.re_errno = errno; ++ return NULL; ++ } + /* XXX: interface problem; those should all have been unsigned */ + return (authunix_create(machname, uid, gid, len, gids)); + } diff --git a/libtirpc.spec b/libtirpc.spec index e0733de..86d87cb 100644 --- a/libtirpc.spec +++ b/libtirpc.spec @@ -1,11 +1,13 @@ Name: libtirpc Version: 0.2.1 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Transport Independent RPC Library Group: System Environment/Libraries License: SISSL and BSD URL: http://nfsv4.bullopensource.org/ +Patch001: libtirpc-0-2-2-rc1.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Source0: http://downloads.sourceforge.net/libtirpc/libtirpc-%{version}.tar.bz2 @@ -38,6 +40,8 @@ developing programs which use the tirpc library. %prep %setup -q +%patch001 -p1 + # Remove .orig files find . -name "*.orig" | xargs rm -f @@ -121,6 +125,9 @@ rm -rf %{buildroot} %{_mandir}/*/* %changelog +* Mon Mar 22 2010 Steve Dickson 0.2.1-2 +- Updated to latest RC release: libtirpc-0-2-2-rc1 + * Mon Nov 30 2009 Steve Dickson 0.2.1-1 - Updated to latest upstream version: 0.2.1