diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ccca0ba --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/libtirpc-0.2.4.tar.bz2 diff --git a/.libtirpc.metadata b/.libtirpc.metadata new file mode 100644 index 0000000..1b58fe6 --- /dev/null +++ b/.libtirpc.metadata @@ -0,0 +1 @@ +1484e59eb9c0c6adf4b072f2b80ccb17465fd4a3 SOURCES/libtirpc-0.2.4.tar.bz2 diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/libtirpc-0.2.4-CVE-2017-8779.patch b/SOURCES/libtirpc-0.2.4-CVE-2017-8779.patch new file mode 100644 index 0000000..91b6157 --- /dev/null +++ b/SOURCES/libtirpc-0.2.4-CVE-2017-8779.patch @@ -0,0 +1,251 @@ +diff -up libtirpc-0.2.4/src/rpcb_prot.c.orig libtirpc-0.2.4/src/rpcb_prot.c +--- libtirpc-0.2.4/src/rpcb_prot.c.orig 2013-12-09 15:59:51.000000000 -0500 ++++ libtirpc-0.2.4/src/rpcb_prot.c 2017-05-17 13:05:47.562168877 -0400 +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include "rpc_com.h" + + bool_t + xdr_rpcb(xdrs, objp) +@@ -53,13 +54,13 @@ xdr_rpcb(xdrs, objp) + if (!xdr_u_int32_t(xdrs, &objp->r_vers)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_netid, RPC_MAXDATASIZE)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_addr, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_addr, RPC_MAXDATASIZE)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_owner, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_owner, RPC_MAXDATASIZE)) { + return (FALSE); + } + return (TRUE); +@@ -159,19 +160,19 @@ xdr_rpcb_entry(xdrs, objp) + XDR *xdrs; + rpcb_entry *objp; + { +- if (!xdr_string(xdrs, &objp->r_maddr, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_maddr, RPC_MAXDATASIZE)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_nc_netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_nc_netid, RPC_MAXDATASIZE)) { + return (FALSE); + } + if (!xdr_u_int32_t(xdrs, &objp->r_nc_semantics)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_nc_protofmly, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_nc_protofmly, RPC_MAXDATASIZE)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_nc_proto, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_nc_proto, RPC_MAXDATASIZE)) { + return (FALSE); + } + return (TRUE); +@@ -292,7 +293,7 @@ xdr_rpcb_rmtcallres(xdrs, p) + bool_t dummy; + struct r_rpcb_rmtcallres *objp = (struct r_rpcb_rmtcallres *)(void *)p; + +- if (!xdr_string(xdrs, &objp->addr, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->addr, RPC_MAXDATASIZE)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->results.results_len)) { +@@ -312,6 +313,11 @@ xdr_netbuf(xdrs, objp) + if (!xdr_u_int32_t(xdrs, (u_int32_t *) &objp->maxlen)) { + return (FALSE); + } ++ ++ if (objp->maxlen > RPC_MAXDATASIZE) { ++ return (FALSE); ++ } ++ + dummy = xdr_bytes(xdrs, (char **)&(objp->buf), + (u_int *)&(objp->len), objp->maxlen); + return (dummy); +diff -up libtirpc-0.2.4/src/rpcb_st_xdr.c.orig libtirpc-0.2.4/src/rpcb_st_xdr.c +--- libtirpc-0.2.4/src/rpcb_st_xdr.c.orig 2013-12-09 15:59:51.000000000 -0500 ++++ libtirpc-0.2.4/src/rpcb_st_xdr.c 2017-05-17 13:05:47.562168877 -0400 +@@ -38,6 +38,7 @@ + #include + + #include ++#include "rpc_com.h" + + /* Link list of all the stats about getport and getaddr */ + +@@ -59,7 +60,7 @@ xdr_rpcbs_addrlist(xdrs, objp) + if (!xdr_int(xdrs, &objp->failure)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->netid, RPC_MAXDATASIZE)) { + return (FALSE); + } + +@@ -110,7 +111,7 @@ xdr_rpcbs_rmtcalllist(xdrs, objp) + IXDR_PUT_INT32(buf, objp->failure); + IXDR_PUT_INT32(buf, objp->indirect); + } +- if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->netid, RPC_MAXDATASIZE)) { + return (FALSE); + } + if (!xdr_pointer(xdrs, (char **)&objp->next, +@@ -148,7 +149,7 @@ xdr_rpcbs_rmtcalllist(xdrs, objp) + objp->failure = (int)IXDR_GET_INT32(buf); + objp->indirect = (int)IXDR_GET_INT32(buf); + } +- if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->netid, RPC_MAXDATASIZE)) { + return (FALSE); + } + if (!xdr_pointer(xdrs, (char **)&objp->next, +@@ -176,7 +177,7 @@ xdr_rpcbs_rmtcalllist(xdrs, objp) + if (!xdr_int(xdrs, &objp->indirect)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->netid, RPC_MAXDATASIZE)) { + return (FALSE); + } + if (!xdr_pointer(xdrs, (char **)&objp->next, +diff -up libtirpc-0.2.4/src/rpc_generic.c.orig libtirpc-0.2.4/src/rpc_generic.c +--- libtirpc-0.2.4/src/rpc_generic.c.orig 2013-12-09 15:59:51.000000000 -0500 ++++ libtirpc-0.2.4/src/rpc_generic.c 2017-05-17 13:05:47.562168877 -0400 +@@ -615,6 +615,9 @@ __rpc_taddr2uaddr_af(int af, const struc + + switch (af) { + case AF_INET: ++ if (nbuf->len < sizeof(*sin)) { ++ return NULL; ++ } + sin = nbuf->buf; + if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf) + == NULL) +@@ -626,6 +629,9 @@ __rpc_taddr2uaddr_af(int af, const struc + break; + #ifdef INET6 + case AF_INET6: ++ if (nbuf->len < sizeof(*sin6)) { ++ return NULL; ++ } + sin6 = nbuf->buf; + if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) + == NULL) +@@ -668,6 +674,8 @@ __rpc_uaddr2taddr_af(int af, const char + + port = 0; + sin = NULL; ++ if (uaddr == NULL) ++ return NULL; + addrstr = strdup(uaddr); + if (addrstr == NULL) + return NULL; +diff -up libtirpc-0.2.4/src/xdr.c.orig libtirpc-0.2.4/src/xdr.c +--- libtirpc-0.2.4/src/xdr.c.orig 2013-12-09 15:59:51.000000000 -0500 ++++ libtirpc-0.2.4/src/xdr.c 2017-05-17 13:05:47.563168892 -0400 +@@ -43,8 +43,10 @@ + #include + #include + ++#include + #include + #include ++#include + + typedef quad_t longlong_t; /* ANSI long long type */ + typedef u_quad_t u_longlong_t; /* ANSI unsigned long long type */ +@@ -54,7 +56,6 @@ typedef u_quad_t u_longlong_t; + */ + #define XDR_FALSE ((long) 0) + #define XDR_TRUE ((long) 1) +-#define LASTUNSIGNED ((u_int) 0-1) + + /* + * for unit alignment +@@ -630,6 +631,7 @@ xdr_bytes(xdrs, cpp, sizep, maxsize) + { + char *sp = *cpp; /* sp is the actual string pointer */ + u_int nodesize; ++ bool_t ret, allocated = FALSE; + + /* + * first deal with the length since xdr bytes are counted +@@ -653,6 +655,7 @@ xdr_bytes(xdrs, cpp, sizep, maxsize) + } + if (sp == NULL) { + *cpp = sp = mem_alloc(nodesize); ++ allocated = TRUE; + } + if (sp == NULL) { + warnx("xdr_bytes: out of memory"); +@@ -661,7 +664,14 @@ xdr_bytes(xdrs, cpp, sizep, maxsize) + /* FALLTHROUGH */ + + case XDR_ENCODE: +- return (xdr_opaque(xdrs, sp, nodesize)); ++ ret = xdr_opaque(xdrs, sp, nodesize); ++ if ((xdrs->x_op == XDR_DECODE) && (ret == FALSE)) { ++ if (allocated == TRUE) { ++ free(sp); ++ *cpp = NULL; ++ } ++ } ++ return (ret); + + case XDR_FREE: + if (sp != NULL) { +@@ -755,6 +765,7 @@ xdr_string(xdrs, cpp, maxsize) + char *sp = *cpp; /* sp is the actual string pointer */ + u_int size; + u_int nodesize; ++ bool_t ret, allocated = FALSE; + + /* + * first deal with the length since xdr strings are counted-strings +@@ -794,8 +805,10 @@ xdr_string(xdrs, cpp, maxsize) + switch (xdrs->x_op) { + + case XDR_DECODE: +- if (sp == NULL) ++ if (sp == NULL) { + *cpp = sp = mem_alloc(nodesize); ++ allocated = TRUE; ++ } + if (sp == NULL) { + warnx("xdr_string: out of memory"); + return (FALSE); +@@ -804,7 +817,14 @@ xdr_string(xdrs, cpp, maxsize) + /* FALLTHROUGH */ + + case XDR_ENCODE: +- return (xdr_opaque(xdrs, sp, size)); ++ ret = xdr_opaque(xdrs, sp, size); ++ if ((xdrs->x_op == XDR_DECODE) && (ret == FALSE)) { ++ if (allocated == TRUE) { ++ free(sp); ++ *cpp = NULL; ++ } ++ } ++ return (ret); + + case XDR_FREE: + mem_free(sp, nodesize); +@@ -824,7 +844,7 @@ xdr_wrapstring(xdrs, cpp) + XDR *xdrs; + char **cpp; + { +- return xdr_string(xdrs, cpp, LASTUNSIGNED); ++ return xdr_string(xdrs, cpp, RPC_MAXDATASIZE); + } + + /* diff --git a/SOURCES/libtirpc-0.2.4-clnt-mthr-create.patch b/SOURCES/libtirpc-0.2.4-clnt-mthr-create.patch new file mode 100644 index 0000000..2152d9c --- /dev/null +++ b/SOURCES/libtirpc-0.2.4-clnt-mthr-create.patch @@ -0,0 +1,67 @@ +diff --git a/src/clnt_vc.c b/src/clnt_vc.c +index 61264d4..ebe28f8 100644 +--- a/src/clnt_vc.c ++++ b/src/clnt_vc.c +@@ -72,6 +72,8 @@ + #define CMGROUP_MAX 16 + #define SCM_CREDS 0x03 /* process creds (struct cmsgcred) */ + ++#undef rpc_createerr /* make it clear it is a thread safe variable */ ++ + /* + * Credentials structure, used to verify the identity of a peer + * process that has sent us a message. This is allocated by the +@@ -188,10 +190,11 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz) + cl = (CLIENT *)mem_alloc(sizeof (*cl)); + ct = (struct ct_data *)mem_alloc(sizeof (*ct)); + if ((cl == (CLIENT *)NULL) || (ct == (struct ct_data *)NULL)) { ++ struct rpc_createerr *ce = &get_rpc_createerr(); ++ ce->cf_stat = RPC_SYSTEMERROR; ++ ce->cf_error.re_errno = errno; + (void) syslog(LOG_ERR, clnt_vc_errstr, + clnt_vc_str, __no_mem_str); +- rpc_createerr.cf_stat = RPC_SYSTEMERROR; +- rpc_createerr.cf_error.re_errno = errno; + goto err; + } + ct->ct_addr.buf = NULL; +@@ -230,26 +233,29 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz) + assert(vc_cv != (cond_t *) NULL); + + /* +- * XXX - fvdl connecting while holding a mutex? ++ * Do not hold mutex during connect + */ ++ mutex_unlock(&clnt_fd_lock); ++ + slen = sizeof ss; + if (getpeername(fd, (struct sockaddr *)&ss, &slen) < 0) { + if (errno != ENOTCONN) { +- rpc_createerr.cf_stat = RPC_SYSTEMERROR; +- rpc_createerr.cf_error.re_errno = errno; +- mutex_unlock(&clnt_fd_lock); ++ struct rpc_createerr *ce = &get_rpc_createerr(); ++ ce->cf_stat = RPC_SYSTEMERROR; ++ ce->cf_error.re_errno = errno; + thr_sigsetmask(SIG_SETMASK, &(mask), NULL); + goto err; + } + if (connect(fd, (struct sockaddr *)raddr->buf, raddr->len) < 0){ +- rpc_createerr.cf_stat = RPC_SYSTEMERROR; +- rpc_createerr.cf_error.re_errno = errno; +- mutex_unlock(&clnt_fd_lock); +- thr_sigsetmask(SIG_SETMASK, &(mask), NULL); +- goto err; ++ if (errno != EISCONN) { ++ struct rpc_createerr *ce = &get_rpc_createerr(); ++ ce->cf_stat = RPC_SYSTEMERROR; ++ ce->cf_error.re_errno = errno; ++ thr_sigsetmask(SIG_SETMASK, &(mask), NULL); ++ goto err; ++ } + } + } +- mutex_unlock(&clnt_fd_lock); + if (!__rpc_fd2sockinfo(fd, &si)) + goto err; + thr_sigsetmask(SIG_SETMASK, &(mask), NULL); diff --git a/SOURCES/libtirpc-0.2.4-covscan.patch b/SOURCES/libtirpc-0.2.4-covscan.patch new file mode 100644 index 0000000..32adc91 --- /dev/null +++ b/SOURCES/libtirpc-0.2.4-covscan.patch @@ -0,0 +1,147 @@ +diff -up libtirpc-0.2.4/src/auth_gss.c.orig libtirpc-0.2.4/src/auth_gss.c +--- libtirpc-0.2.4/src/auth_gss.c.orig 2017-05-25 09:53:19.659862958 -0400 ++++ libtirpc-0.2.4/src/auth_gss.c 2018-09-11 13:16:34.644008111 -0400 +@@ -176,6 +176,7 @@ authgss_create(CLIENT *clnt, gss_name_t + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = ENOMEM; + free(auth); ++ free(gd); + return (NULL); + } + } +diff -up libtirpc-0.2.4/src/clnt_bcast.c.orig libtirpc-0.2.4/src/clnt_bcast.c +--- libtirpc-0.2.4/src/clnt_bcast.c.orig 2017-05-25 09:53:19.659862958 -0400 ++++ libtirpc-0.2.4/src/clnt_bcast.c 2018-09-11 13:16:34.644008111 -0400 +@@ -297,6 +297,7 @@ rpc_broadcast_exp(prog, vers, proc, xarg + if (nettype == NULL) + nettype = "datagram_n"; + if ((handle = __rpc_setconf(nettype)) == NULL) { ++ AUTH_DESTROY(sys_auth); + return (RPC_UNKNOWNPROTO); + } + while ((nconf = __rpc_getconf(handle)) != NULL) { +diff -up libtirpc-0.2.4/src/getnetconfig.c.orig libtirpc-0.2.4/src/getnetconfig.c +--- libtirpc-0.2.4/src/getnetconfig.c.orig 2013-12-09 15:59:51.000000000 -0500 ++++ libtirpc-0.2.4/src/getnetconfig.c 2018-09-11 13:16:34.644008111 -0400 +@@ -710,6 +710,8 @@ struct netconfig *ncp; + p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *)); + if (p->nc_lookups == NULL) { + free(p->nc_netid); ++ free(p); ++ free(tmp); + return(NULL); + } + for (i=0; i < p->nc_nlookups; i++) { +diff -up libtirpc-0.2.4/src/getnetpath.c.orig libtirpc-0.2.4/src/getnetpath.c +--- libtirpc-0.2.4/src/getnetpath.c.orig 2013-12-09 15:59:51.000000000 -0500 ++++ libtirpc-0.2.4/src/getnetpath.c 2018-09-11 13:16:34.645008107 -0400 +@@ -90,6 +90,7 @@ setnetpath() + } + if ((np_sessionp->nc_handlep = setnetconfig()) == NULL) { + syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); ++ free(np_sessionp); + return (NULL); + } + np_sessionp->valid = NP_VALID; +diff -up libtirpc-0.2.4/src/rpcb_clnt.c.orig libtirpc-0.2.4/src/rpcb_clnt.c +--- libtirpc-0.2.4/src/rpcb_clnt.c.orig 2017-05-25 09:53:19.660862942 -0400 ++++ libtirpc-0.2.4/src/rpcb_clnt.c 2018-09-11 13:16:34.645008107 -0400 +@@ -493,6 +493,7 @@ try_nconf: + if (tmpnconf == NULL) { + rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; + mutex_unlock(&loopnconf_lock); ++ endnetconfig(nc_handle); + return (NULL); + } + loopnconf = getnetconfigent(tmpnconf->nc_netid); +diff -up libtirpc-0.2.4/src/rpc_generic.c.orig libtirpc-0.2.4/src/rpc_generic.c +--- libtirpc-0.2.4/src/rpc_generic.c.orig 2017-05-25 09:53:19.669862794 -0400 ++++ libtirpc-0.2.4/src/rpc_generic.c 2018-09-11 13:16:34.645008107 -0400 +@@ -320,6 +320,7 @@ __rpc_setconf(nettype) + handle->nflag = FALSE; + break; + default: ++ free(handle); + return (NULL); + } + +diff -up libtirpc-0.2.4/src/rpc_soc.c.orig libtirpc-0.2.4/src/rpc_soc.c +--- libtirpc-0.2.4/src/rpc_soc.c.orig 2013-12-09 15:59:51.000000000 -0500 ++++ libtirpc-0.2.4/src/rpc_soc.c 2018-09-11 13:16:34.645008107 -0400 +@@ -627,15 +627,17 @@ svcunix_create(sock, sendsize, recvsize, + strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) + break; + } +- if (nconf == NULL) ++ if (nconf == NULL) { ++ endnetconfig(localhandle); + return(xprt); ++ } + + if ((sock = __rpc_nconf2fd(nconf)) < 0) + goto done; + + memset(&sun, 0, sizeof sun); + sun.sun_family = AF_LOCAL; +- strncpy(sun.sun_path, path, sizeof(sun.sun_path)); ++ strncpy(sun.sun_path, path, (sizeof(sun.sun_path)-1)); + addrlen = sizeof(struct sockaddr_un); + sa = (struct sockaddr *)&sun; + +@@ -656,6 +658,8 @@ svcunix_create(sock, sendsize, recvsize, + } + + xprt = (SVCXPRT *)svc_tli_create(sock, nconf, &taddr, sendsize, recvsize); ++ if (xprt == NULL) ++ close(sock); + + done: + endnetconfig(localhandle); +diff -up libtirpc-0.2.4/src/rtime.c.orig libtirpc-0.2.4/src/rtime.c +--- libtirpc-0.2.4/src/rtime.c.orig 2017-05-25 09:53:19.667862827 -0400 ++++ libtirpc-0.2.4/src/rtime.c 2018-09-11 13:16:34.645008107 -0400 +@@ -90,6 +90,7 @@ rtime(addrp, timep, timeout) + + /* TCP and UDP port are the same in this case */ + if ((serv = getservbyname("time", "tcp")) == NULL) { ++ do_close(s); + return(-1); + } + +diff -up libtirpc-0.2.4/src/svc_generic.c.orig libtirpc-0.2.4/src/svc_generic.c +--- libtirpc-0.2.4/src/svc_generic.c.orig 2017-05-25 09:53:19.657862991 -0400 ++++ libtirpc-0.2.4/src/svc_generic.c 2018-09-11 13:16:34.645008107 -0400 +@@ -112,6 +112,7 @@ svc_create(dispatch, prognum, versnum, n + if (l == NULL) { + warnx("svc_create: no memory"); + mutex_unlock(&xprtlist_lock); ++ __rpc_endconf(handle); + return (0); + } + l->xprt = xprt; +diff -up libtirpc-0.2.4/src/svc_simple.c.orig libtirpc-0.2.4/src/svc_simple.c +--- libtirpc-0.2.4/src/svc_simple.c.orig 2013-12-09 15:59:51.000000000 -0500 ++++ libtirpc-0.2.4/src/svc_simple.c 2018-09-11 13:16:34.646008103 -0400 +@@ -158,6 +158,7 @@ rpc_reg(prognum, versnum, procnum, progn + ((netid = strdup(nconf->nc_netid)) == NULL)) { + warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str); + SVC_DESTROY(svcxprt); ++ free(xdrbuf); + break; + } + madenow = TRUE; +diff -up libtirpc-0.2.4/src/xdr.c.orig libtirpc-0.2.4/src/xdr.c +--- libtirpc-0.2.4/src/xdr.c.orig 2017-05-25 09:53:19.669862794 -0400 ++++ libtirpc-0.2.4/src/xdr.c 2017-05-25 11:50:19.154648294 -0400 +@@ -636,9 +636,11 @@ xdr_bytes(xdrs, cpp, sizep, maxsize) + /* + * first deal with the length since xdr bytes are counted + */ ++ + if (! xdr_u_int(xdrs, sizep)) { + return (FALSE); + } ++ + nodesize = *sizep; + if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) { + return (FALSE); diff --git a/SOURCES/libtirpc-0.2.4-debug.patch b/SOURCES/libtirpc-0.2.4-debug.patch new file mode 100644 index 0000000..3afb48d --- /dev/null +++ b/SOURCES/libtirpc-0.2.4-debug.patch @@ -0,0 +1,1357 @@ +diff --git a/src/Makefile.am b/src/Makefile.am +index 3029b78..de57c8f 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -5,7 +5,7 @@ + ## program built. We also don't bother trying to assemble code, or + ## anything like that. + +-noinst_HEADERS = rpc_com.h ++noinst_HEADERS = rpc_com.h debug.h + + AM_CPPFLAGS = -I$(top_srcdir)/tirpc -DPORTMAP -DINET6 \ + -D_GNU_SOURCE -Wall -pipe +@@ -51,7 +51,7 @@ libtirpc_la_SOURCES = auth_none.c auth_unix.c authunix_prot.c bindresvport.c cln + rpc_callmsg.c rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c \ + rpcb_st_xdr.c svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_auth_none.c \ + svc_generic.c svc_raw.c svc_run.c svc_simple.c svc_vc.c getpeereid.c \ +- auth_time.c auth_des.c authdes_prot.c ++ auth_time.c auth_des.c authdes_prot.c debug.c + + ## XDR + libtirpc_la_SOURCES += xdr.c xdr_rec.c xdr_array.c xdr_float.c xdr_mem.c xdr_reference.c xdr_stdio.c +diff --git a/src/auth_des.c b/src/auth_des.c +index f0c8b8c..cff777c 100644 +--- a/src/auth_des.c ++++ b/src/auth_des.c +@@ -54,6 +54,8 @@ + #endif + #include + ++#include "debug.h" ++ + #define USEC_PER_SEC 1000000 + #define RTIME_TIMEOUT 5 /* seconds to wait for sync */ + +@@ -399,7 +401,7 @@ authdes_validate(AUTH *auth, struct opaque_auth *rverf) + */ + if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp, + sizeof(struct timeval)) != 0) { +- syslog(LOG_DEBUG, "authdes_validate: verifier mismatch"); ++ LIBTIRPC_DEBUG(1, ("authdes_validate: verifier mismatch")); + return (FALSE); + } + +@@ -433,16 +435,15 @@ authdes_refresh(AUTH *auth, void *dummy) + * Hope the clocks are synced! + */ + ad->ad_dosync = 0; +- syslog(LOG_DEBUG, +- "authdes_refresh: unable to synchronize clock"); ++ LIBTIRPC_DEBUG(1, ("authdes_refresh: unable to synchronize clock")); + } + } + ad->ad_xkey = auth->ah_key; + pkey.n_bytes = (char *)(ad->ad_pkey); + pkey.n_len = (u_int)strlen((char *)ad->ad_pkey) + 1; + if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) { +- syslog(LOG_INFO, +- "authdes_refresh: keyserv(1m) is unable to encrypt session key"); ++ LIBTIRPC_DEBUG(1, ++ ("authdes_refresh: keyserv(1m) is unable to encrypt session key")); + return (FALSE); + } + cred->adc_fullname.key = ad->ad_xkey; +diff --git a/src/auth_gss.c b/src/auth_gss.c +index 703bc3f..6db6a82 100644 +--- a/src/auth_gss.c ++++ b/src/auth_gss.c +@@ -49,14 +49,16 @@ + #include + #include + +-static void authgss_nextverf(); +-static bool_t authgss_marshal(); +-static bool_t authgss_refresh(); +-static bool_t authgss_validate(); +-static void authgss_destroy(); +-static void authgss_destroy_context(); +-static bool_t authgss_wrap(); +-static bool_t authgss_unwrap(); ++#include "debug.h" ++ ++static void authgss_nextverf(AUTH *); ++static bool_t authgss_marshal(AUTH *, XDR *); ++static bool_t authgss_refresh(AUTH *, void *); ++static bool_t authgss_validate(AUTH *, struct opaque_auth *); ++static void authgss_destroy(AUTH *); ++static void authgss_destroy_context(AUTH *); ++static bool_t authgss_wrap(AUTH *, XDR *, xdrproc_t, caddr_t); ++static bool_t authgss_unwrap(AUTH *, XDR *, xdrproc_t, caddr_t); + + + /* +@@ -78,7 +80,6 @@ static struct auth_ops authgss_ops = { + authgss_unwrap + }; + +-#ifdef DEBUG + + /* useful as i add more mechanisms */ + void +@@ -87,6 +88,9 @@ print_rpc_gss_sec(struct rpc_gss_sec *ptr) + int i; + char *p; + ++ if (libtirpc_debug_level < 4 || log_stderr == 0) ++ return; ++ + gss_log_debug("rpc_gss_sec:"); + if(ptr->mech == NULL) + gss_log_debug("NULL gss_OID mech"); +@@ -126,7 +130,6 @@ char *p; + fprintf(stderr, " service: %d\n", ptr->svc); + fprintf(stderr, " cred: %p\n", ptr->cred); + } +-#endif /*DEBUG*/ + + struct rpc_gss_data { + bool_t established; /* context established */ +@@ -166,9 +169,7 @@ authgss_create(CLIENT *clnt, gss_name_t name, struct rpc_gss_sec *sec) + free(auth); + return (NULL); + } +-#ifdef DEBUG +- fprintf(stderr, "authgss_create: name is %p\n", name); +-#endif ++ LIBTIRPC_DEBUG(3, ("authgss_create: name is %p", name)); + if (name != GSS_C_NO_NAME) { + if (gss_duplicate_name(&min_stat, name, &gd->name) + != GSS_S_COMPLETE) { +@@ -181,9 +182,7 @@ authgss_create(CLIENT *clnt, gss_name_t name, struct rpc_gss_sec *sec) + else + gd->name = name; + +-#ifdef DEBUG +- fprintf(stderr, "authgss_create: gd->name is %p\n", gd->name); +-#endif ++ LIBTIRPC_DEBUG(3, ("authgss_create: gd->name is %p", gd->name)); + gd->clnt = clnt; + gd->ctx = GSS_C_NO_CONTEXT; + gd->sec = *sec; +@@ -198,7 +197,7 @@ authgss_create(CLIENT *clnt, gss_name_t name, struct rpc_gss_sec *sec) + save_auth = clnt->cl_auth; + clnt->cl_auth = auth; + +- if (!authgss_refresh(auth)) ++ if (!authgss_refresh(auth, NULL)) + auth = NULL; + else + auth_get(auth); /* Reference for caller */ +@@ -227,7 +226,8 @@ authgss_create_default(CLIENT *clnt, char *service, struct rpc_gss_sec *sec) + &name); + + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_status("gss_import_name", maj_stat, min_stat); ++ gss_log_status("authgss_create_default: gss_import_name", ++ maj_stat, min_stat); + rpc_createerr.cf_stat = RPC_AUTHERROR; + return (NULL); + } +@@ -235,9 +235,7 @@ authgss_create_default(CLIENT *clnt, char *service, struct rpc_gss_sec *sec) + auth = authgss_create(clnt, name, sec); + + if (name != GSS_C_NO_NAME) { +-#ifdef DEBUG +- fprintf(stderr, "authgss_create_default: freeing name %p\n", name); +-#endif ++ LIBTIRPC_DEBUG(3, ("authgss_create_default: freeing name %p", name)); + gss_release_name(&min_stat, &name); + } + +@@ -346,7 +344,8 @@ authgss_marshal(AUTH *auth, XDR *xdrs) + &rpcbuf, &checksum); + + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_status("gss_get_mic", maj_stat, min_stat); ++ gss_log_status("authgss_marshal: gss_get_mic", ++ maj_stat, min_stat); + if (maj_stat == GSS_S_CONTEXT_EXPIRED) { + gd->established = FALSE; + authgss_destroy_context(auth); +@@ -406,8 +405,10 @@ authgss_validate(AUTH *auth, struct opaque_auth *verf) + + maj_stat = gss_verify_mic(&min_stat, gd->ctx, &signbuf, + &checksum, &qop_state); ++ + if (maj_stat != GSS_S_COMPLETE || qop_state != gd->sec.qop) { +- gss_log_status("gss_verify_mic", maj_stat, min_stat); ++ gss_log_status("authgss_validate: gss_verify_mic", ++ maj_stat, min_stat); + if (maj_stat == GSS_S_CONTEXT_EXPIRED) { + gd->established = FALSE; + authgss_destroy_context(auth); +@@ -418,7 +419,7 @@ authgss_validate(AUTH *auth, struct opaque_auth *verf) + } + + static bool_t +-authgss_refresh(AUTH *auth) ++authgss_refresh(AUTH *auth, void *dummy) + { + struct rpc_gss_data *gd; + struct rpc_gss_init_res gr; +@@ -436,19 +437,15 @@ authgss_refresh(AUTH *auth) + memset(&gr, 0, sizeof(gr)); + recv_tokenp = GSS_C_NO_BUFFER; + +-#ifdef DEBUG + print_rpc_gss_sec(&gd->sec); +-#endif /*DEBUG*/ + + for (;;) { +-#ifdef DEBUG + /* print the token we just received */ + if (recv_tokenp != GSS_C_NO_BUFFER) { + gss_log_debug("The token we just received (length %d):", + recv_tokenp->length); + gss_log_hexdump(recv_tokenp->value, recv_tokenp->length, 0); + } +-#endif + maj_stat = gss_init_sec_context(&min_stat, + gd->sec.cred, + &gd->ctx, +@@ -469,18 +466,17 @@ authgss_refresh(AUTH *auth) + } + if (maj_stat != GSS_S_COMPLETE && + maj_stat != GSS_S_CONTINUE_NEEDED) { +- gss_log_status("gss_init_sec_context", maj_stat, min_stat); ++ gss_log_status("authgss_refresh: gss_init_sec_context", ++ maj_stat, min_stat); + break; + } + if (send_token.length != 0) { + memset(&gr, 0, sizeof(gr)); + +-#ifdef DEBUG + /* print the token we are about to send */ + gss_log_debug("The token being sent (length %d):", + send_token.length); + gss_log_hexdump(send_token.value, send_token.length, 0); +-#endif + + call_stat = clnt_call(gd->clnt, NULLPROC, + (xdrproc_t)xdr_rpc_gss_init_args, +@@ -492,8 +488,17 @@ authgss_refresh(AUTH *auth) + + if (call_stat != RPC_SUCCESS || + (gr.gr_major != GSS_S_COMPLETE && +- gr.gr_major != GSS_S_CONTINUE_NEEDED)) ++ gr.gr_major != GSS_S_CONTINUE_NEEDED)) { ++ if (call_stat != RPC_SUCCESS) { ++ struct rpc_err err; ++ clnt_geterr(gd->clnt, &err); ++ LIBTIRPC_DEBUG(1, ("authgss_refresh: %s errno: %s", ++ clnt_sperrno(call_stat), strerror(err.re_errno))); ++ } else ++ gss_log_status("authgss_refresh:", ++ gr.gr_major, gr.gr_minor); + return FALSE; ++ } + + if (gr.gr_ctx.length != 0) { + if (gd->gc.gc_ctx.value) +@@ -528,7 +533,8 @@ authgss_refresh(AUTH *auth) + + if (maj_stat != GSS_S_COMPLETE + || qop_state != gd->sec.qop) { +- gss_log_status("gss_verify_mic", maj_stat, min_stat); ++ gss_log_status("authgss_refresh: gss_verify_mic", ++ maj_stat, min_stat); + if (maj_stat == GSS_S_CONTEXT_EXPIRED) { + gd->established = FALSE; + authgss_destroy_context(auth); +@@ -629,9 +635,7 @@ authgss_destroy(AUTH *auth) + + authgss_destroy_context(auth); + +-#ifdef DEBUG +- fprintf(stderr, "authgss_destroy: freeing name %p\n", gd->name); +-#endif ++ LIBTIRPC_DEBUG(3, ("authgss_destroy: freeing name %p", gd->name)); + if (gd->name != GSS_C_NO_NAME) + gss_release_name(&min_stat, &gd->name); + +@@ -639,7 +643,7 @@ authgss_destroy(AUTH *auth) + free(auth); + } + +-bool_t ++static bool_t + authgss_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) + { + struct rpc_gss_data *gd; +@@ -656,7 +660,7 @@ authgss_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) + gd->sec.svc, gd->gc.gc_seq)); + } + +-bool_t ++static bool_t + authgss_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) + { + struct rpc_gss_data *gd; +diff --git a/src/authgss_prot.c b/src/authgss_prot.c +index a3c93c9..669eab7 100644 +--- a/src/authgss_prot.c ++++ b/src/authgss_prot.c +@@ -42,8 +42,11 @@ + #include + #include + #include ++#include + #include + ++#include "debug.h" ++ + /* additional space needed for encoding */ + #define RPC_SLACK_SPACE 1024 + +@@ -175,7 +178,8 @@ xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, + maj_stat = gss_get_mic(&min_stat, ctx, qop, + &databuf, &wrapbuf); + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_debug("gss_get_mic failed"); ++ gss_log_status("xdr_rpc_gss_wrap_data: gss_get_mic", ++ maj_stat, min_stat); + return (FALSE); + } + /* Marshal checksum. */ +@@ -189,7 +193,8 @@ xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, + maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf, + &conf_state, &wrapbuf); + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_status("gss_wrap", maj_stat, min_stat); ++ gss_log_status("xdr_rpc_gss_wrap_data: gss_wrap", ++ maj_stat, min_stat); + return (FALSE); + } + /* Marshal databody_priv. */ +@@ -222,13 +227,13 @@ 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_rpc_gss_buf(xdrs, &databuf, (u_int)-1)) { +- gss_log_debug("xdr decode databody_integ failed"); ++ LIBTIRPC_DEBUG(1, ("xdr_rpc_gss_unwrap_data: decode databody_integ failed")); + return (FALSE); + } + /* Decode checksum. */ + if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (u_int)-1)) { + gss_release_buffer(&min_stat, &databuf); +- gss_log_debug("xdr decode checksum failed"); ++ LIBTIRPC_DEBUG(1, ("xdr_rpc_gss_unwrap_data: decode checksum failed")); + return (FALSE); + } + /* Verify checksum and QOP. */ +@@ -238,14 +243,15 @@ xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, + + if (maj_stat != GSS_S_COMPLETE || qop_state != qop) { + gss_release_buffer(&min_stat, &databuf); +- gss_log_status("gss_verify_mic", maj_stat, min_stat); ++ gss_log_status("xdr_rpc_gss_unwrap_data: gss_verify_mic", ++ maj_stat, min_stat); + return (FALSE); + } + } + else if (svc == RPCSEC_GSS_SVC_PRIVACY) { + /* Decode databody_priv. */ + if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (u_int)-1)) { +- gss_log_debug("xdr decode databody_priv failed"); ++ LIBTIRPC_DEBUG(1, ("xdr_rpc_gss_unwrap_data: decode databody_priv failed")); + return (FALSE); + } + /* Decrypt databody. */ +@@ -258,7 +264,8 @@ xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, + if (maj_stat != GSS_S_COMPLETE || qop_state != qop || + conf_state != TRUE) { + gss_release_buffer(&min_stat, &databuf); +- gss_log_status("gss_unwrap", maj_stat, min_stat); ++ gss_log_status("xdr_rpc_gss_unwrap_data: gss_unwrap", ++ maj_stat, min_stat); + return (FALSE); + } + } +@@ -271,7 +278,8 @@ xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, + + /* Verify sequence number. */ + if (xdr_stat == TRUE && seq_num != seq) { +- gss_log_debug("wrong sequence number in databody"); ++ LIBTIRPC_DEBUG(1, ++ ("xdr_rpc_gss_unwrap_data: wrong sequence number in databody")); + return (FALSE); + } + return (xdr_stat); +@@ -296,39 +304,32 @@ xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, + return (FALSE); + } + +-#ifdef DEBUG +-#include +- + void + gss_log_debug(const char *fmt, ...) + { + va_list ap; + + va_start(ap, fmt); +- fprintf(stderr, "rpcsec_gss: "); +- vfprintf(stderr, fmt, ap); +- fprintf(stderr, "\n"); ++ vlibtirpc_log_dbg(2, fmt, ap); + va_end(ap); + } + + void + gss_log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat) + { +- OM_uint32 min; +- gss_buffer_desc msg; +- int msg_ctx = 0; ++ OM_uint32 min, maj; ++ gss_buffer_desc maj_msg, min_msg; ++ u_int32_t msg_ctx = 0; + +- fprintf(stderr, "rpcsec_gss: %s: ", m); ++ gss_display_status(&maj, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID, ++ &msg_ctx, &maj_msg); ++ gss_display_status(&min, min_stat, GSS_C_MECH_CODE, GSS_C_NULL_OID, ++ &msg_ctx, &min_msg); + +- gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID, +- &msg_ctx, &msg); +- fprintf(stderr, "%s - ", (char *)msg.value); +- gss_release_buffer(&min, &msg); ++ LIBTIRPC_DEBUG(1, ("%s: %s - %s", m, (char *)maj_msg.value, (char *)min_msg.value)); + +- gss_display_status(&min, min_stat, GSS_C_MECH_CODE, GSS_C_NULL_OID, +- &msg_ctx, &msg); +- fprintf(stderr, "%s\n", (char *)msg.value); +- gss_release_buffer(&min, &msg); ++ gss_release_buffer(&maj, &maj_msg); ++ gss_release_buffer(&min, &min_msg); + } + + void +@@ -337,6 +338,9 @@ gss_log_hexdump(const u_char *buf, int len, int offset) + u_int i, j, jm; + int c; + ++ if (libtirpc_debug_level < 4 || log_stderr == 0) ++ return; ++ + fprintf(stderr, "\n"); + for (i = 0; i < len; i += 0x10) { + fprintf(stderr, " %04x: ", (u_int)(i + offset)); +@@ -364,23 +368,3 @@ gss_log_hexdump(const u_char *buf, int len, int offset) + } + } + +-#else +- +-void +-gss_log_debug(const char *fmt, ...) +-{ +-} +- +-void +-gss_log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat) +-{ +-} +- +-void +-gss_log_hexdump(const u_char *buf, int len, int offset) +-{ +-} +- +-#endif +- +- +diff --git a/src/clnt_bcast.c b/src/clnt_bcast.c +index 1055545..373d8a5 100644 +--- a/src/clnt_bcast.c ++++ b/src/clnt_bcast.c +@@ -55,9 +55,7 @@ + #endif /* PORTMAP */ + #include + #include +-#ifdef RPC_DEBUG + #include +-#endif + #include + #include + #include +@@ -66,6 +64,7 @@ + #include + + #include "rpc_com.h" ++#include "debug.h" + + #define MAXBCAST 20 /* Max no of broadcasting transports */ + #define INITTIME 4000 /* Time to wait initially */ +@@ -454,20 +453,15 @@ rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp, + outlen, 0, (struct sockaddr*)addr, + (size_t)fdlist[i].asize) != + outlen) { +-#ifdef RPC_DEBUG +- perror("sendto"); +-#endif +- warnx("clnt_bcast: cannot send" +- "broadcast packet"); ++ LIBTIRPC_DEBUG(1, ++ ("rpc_broadcast_exp: sendto failed: errno %d", errno)); ++ warnx("rpc_broadcast_exp: cannot send broadcast packet"); + stat = RPC_CANTSEND; + continue; + }; +-#ifdef RPC_DEBUG + if (!__rpc_lowvers) +- fprintf(stderr, "Broadcast packet sent " +- "for %s\n", +- fdlist[i].nconf->nc_netid); +-#endif ++ LIBTIRPC_DEBUG(3, ("rpc_broadcast_exp: Broadcast packet sent for %s\n", ++ fdlist[i].nconf->nc_netid)); + #ifdef PORTMAP + /* + * Send the version 2 packet also +@@ -485,11 +479,8 @@ rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp, + continue; + } + } +-#ifdef RPC_DEBUG +- fprintf(stderr, "PMAP Broadcast packet " +- "sent for %s\n", +- fdlist[i].nconf->nc_netid); +-#endif ++ LIBTIRPC_DEBUG(3, ("rpc_broadcast_exp: PMAP Broadcast packet sent for %s\n", ++ fdlist[i].nconf->nc_netid)); + #endif /* PORTMAP */ + } + /* End for sending all packets on this transport */ +@@ -532,10 +523,8 @@ rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp, + continue; + } else + fds_found++; +-#ifdef RPC_DEBUG +- fprintf(stderr, "response for %s\n", +- fdlist[i].nconf->nc_netid); +-#endif ++ LIBTIRPC_DEBUG(3, ("rpc_broadcast_exp: response for %s\n", ++ fdlist[i].nconf->nc_netid)); + try_again: + inlen = recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize, + 0, (struct sockaddr *)(void *)&fdlist[i].raddr, +@@ -596,10 +585,7 @@ rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp, + &taddr, fdlist[i].nconf); + } else { + #endif /* PORTMAP */ +-#ifdef RPC_DEBUG +- fprintf(stderr, "uaddr %s\n", +- uaddrp); +-#endif ++ LIBTIRPC_DEBUG(3, ("rpc_broadcast_exp: uaddr %s\n", uaddrp)); + np = uaddr2taddr( + fdlist[i].nconf, uaddrp); + done = (*eachresult)(resultsp, +diff --git a/src/debug.c b/src/debug.c +new file mode 100644 +index 0000000..b40ff37 +--- /dev/null ++++ b/src/debug.c +@@ -0,0 +1,65 @@ ++/* ++ * debug.c -- debugging routines for libtirpc ++ * ++ * Copyright (C) 2014 Red Hat, Steve Dickson ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, ++ * Boston, MA 02110-1301, USA. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "debug.h" ++ ++/* library global debug level */ ++int libtirpc_debug_level = 0; ++int log_stderr = 1; /* log to stderr instead of systlog */ ++ ++/* ++ * Set the debug level for the entire library. ++ * Different area will used the value to determin ++ * the verbosity of the debugging output. ++ */ ++void ++libtirpc_set_debug(char *name, int level, int use_stderr) ++{ ++ if (level < 0) ++ level = 0; ++ ++ log_stderr = use_stderr; ++ if (!use_stderr) ++ openlog(name, LOG_PID, LOG_DAEMON); ++ ++ libtirpc_debug_level = level; ++ LIBTIRPC_DEBUG(1, ("libtirpc: debug level %d", libtirpc_debug_level)); ++} ++ ++void ++libtirpc_log_dbg(char *fmt, ...) ++{ ++ va_list args; ++ ++ va_start(args, fmt); ++ if (log_stderr) { ++ vfprintf(stderr, fmt, args); ++ fprintf(stderr, "\n"); ++ } else ++ vsyslog(LOG_NOTICE, fmt, args); ++ va_end(args); ++} +diff --git a/src/debug.h b/src/debug.h +new file mode 100644 +index 0000000..c971ac3 +--- /dev/null ++++ b/src/debug.h +@@ -0,0 +1,51 @@ ++/* ++ * debug.h -- debugging routines for libtirpc ++ * ++ * Copyright (C) 2014 Red Hat, Steve Dickson ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, ++ * Boston, MA 02110-1301, USA. ++ */ ++ ++#ifndef _DEBUG_H ++#define _DEBUG_H ++ ++#include ++#include ++ ++extern int libtirpc_debug_level; ++extern int log_stderr; ++ ++void libtirpc_log_dbg(char *format, ...); ++void libtirpc_set_debug(char *name, int level, int use_stderr); ++ ++#define LIBTIRPC_DEBUG(level, msg) \ ++ do { \ ++ if (level <= libtirpc_debug_level) \ ++ libtirpc_log_dbg msg; \ ++ } while (0) ++ ++static inline void ++vlibtirpc_log_dbg(int level, const char *fmt, va_list args) ++{ ++ if (level <= libtirpc_debug_level) { ++ if (log_stderr) { ++ vfprintf(stderr, fmt, args); ++ fprintf(stderr, "\n"); ++ } else ++ vsyslog(LOG_NOTICE, fmt, args); ++ } ++} ++#endif /* _DEBUG_H */ +diff --git a/src/getpublickey.c b/src/getpublickey.c +index 332c725..85935d8 100644 +--- a/src/getpublickey.c ++++ b/src/getpublickey.c +@@ -46,6 +46,8 @@ + #include + #include + ++#include "debug.h" ++ + #define PKFILE "/etc/publickey" + + /* +@@ -120,9 +122,8 @@ getpublicandprivatekey(key, ret) + lookup = NULL; + err = yp_match(domain, PKMAP, key, strlen(key), &lookup, &len); + if (err) { +-#ifdef DEBUG +- fprintf(stderr, "match failed error %d\n", err); +-#endif ++ LIBTIRPC_DEBUG(1, ++ ("getpublicandprivatekey: match failed error %d\n", err)); + continue; + } + lookup[len] = 0; +@@ -131,10 +132,8 @@ getpublicandprivatekey(key, ret) + free(lookup); + return (2); + #else /* YP */ +-#ifdef DEBUG +- fprintf(stderr, +-"Bad record in %s '+' -- NIS not supported in this library copy\n", PKFILE); +-#endif /* DEBUG */ ++ LIBTIRPC_DEBUG(1, ++("Bad record in %s '+' -- NIS not supported in this library copy\n", PKFILE)); + continue; + #endif /* YP */ + } else { +diff --git a/src/key_call.c b/src/key_call.c +index 906b2f6..8b9f388 100644 +--- a/src/key_call.c ++++ b/src/key_call.c +@@ -59,16 +59,11 @@ + #include + #include + ++#include "dump.h" + + #define KEY_TIMEOUT 5 /* per-try timeout in seconds */ + #define KEY_NRETRY 12 /* number of retries */ + +-#ifdef DEBUG +-#define debug(msg) (void) fprintf(stderr, "%s\n", msg); +-#else +-#define debug(msg) +-#endif /* DEBUG */ +- + /* + * Hack to allow the keyserver to use AUTH_DES (for authenticated + * NIS+ calls, for example). The only functions that get called +@@ -96,7 +91,7 @@ key_setsecret(secretkey) + return (-1); + } + if (status != KEY_SUCCESS) { +- debug("set status is nonzero"); ++ LIBTIRPC_DEBUG(1, ("key_setsecret: set status is nonzero")); + return (-1); + } + return (0); +@@ -144,7 +139,7 @@ key_encryptsession_pk(remotename, remotekey, deskey) + return (-1); + } + if (res.status != KEY_SUCCESS) { +- debug("encrypt status is nonzero"); ++ LIBTIRPC_DEBUG(1, ("key_encryptsession_pk: encrypt status is nonzero")); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; +@@ -168,7 +163,7 @@ key_decryptsession_pk(remotename, remotekey, deskey) + return (-1); + } + if (res.status != KEY_SUCCESS) { +- debug("decrypt status is nonzero"); ++ LIBTIRPC_DEBUG(1, ("key_decryptsession_pk: decrypt status is nonzero")); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; +@@ -190,7 +185,7 @@ key_encryptsession(remotename, deskey) + return (-1); + } + if (res.status != KEY_SUCCESS) { +- debug("encrypt status is nonzero"); ++ LIBTIRPC_DEBUG(1, ("key_encryptsession: encrypt status is nonzero")); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; +@@ -212,7 +207,7 @@ key_decryptsession(remotename, deskey) + return (-1); + } + if (res.status != KEY_SUCCESS) { +- debug("decrypt status is nonzero"); ++ LIBTIRPC_DEBUG(1, ("key_decryptsession: decrypt status is nonzero")); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; +@@ -243,7 +238,7 @@ struct key_netstarg *arg; + } + + if (status != KEY_SUCCESS) { +- debug("key_setnet status is nonzero"); ++ LIBTIRPC_DEBUG(1, ("key_setnet: key_setnet status is nonzero")); + return (-1); + } + return (1); +@@ -262,7 +257,7 @@ key_get_conv(pkey, deskey) + return (-1); + } + if (res.status != KEY_SUCCESS) { +- debug("get_conv status is nonzero"); ++ LIBTIRPC_DEBUG(1, ("key_get_conv: get_conv status is nonzero")); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; +diff --git a/src/netnamer.c b/src/netnamer.c +index 9b3b7dc..53ba73b 100644 +--- a/src/netnamer.c ++++ b/src/netnamer.c +@@ -47,6 +47,8 @@ + #include + #include + ++#include "debug.h" ++ + static char *OPSYS = "unix"; + static char *NETID = "netid.byname"; + static char *NETIDFILE = "/etc/netid"; +@@ -159,10 +161,8 @@ _getgroups(uname, groups) + for (i = 0; grp->gr_mem[i]; i++) + if (!strcmp(grp->gr_mem[i], uname)) { + if (ngroups == NGROUPS) { +-#ifdef DEBUG +- fprintf(stderr, +- "initgroups: %s is in too many groups\n", uname); +-#endif ++ LIBTIRPC_DEBUG(1, ++ ("_getgroups: %s is in too many groups\n", uname)); + goto toomany; + } + /* filter out duplicate group entries */ +@@ -279,9 +279,7 @@ getnetid(key, ret) + err = yp_match(domain, NETID, key, + strlen(key), &lookup, &len); + if (err) { +-#ifdef DEBUG +- fprintf(stderr, "match failed error %d\n", err); +-#endif ++ LIBTIRPC_DEBUG(1, ("getnetid: match failed error %d", err)); + continue; + } + lookup[len] = 0; +@@ -291,11 +289,9 @@ getnetid(key, ret) + fclose(fd); + return (2); + #else /* YP */ +-#ifdef DEBUG +- fprintf(stderr, +-"Bad record in %s '+' -- NIS not supported in this library copy\n", +- NETIDFILE); +-#endif ++ LIBTIRPC_DEBUG(1, ++("Bad record in %s '+' -- NIS not supported in this library copy\n", ++ NETIDFILE)); + continue; + #endif /* YP */ + } else { +diff --git a/src/rpcb_clnt.c b/src/rpcb_clnt.c +index e9b7b5d..a796593 100644 +--- a/src/rpcb_clnt.c ++++ b/src/rpcb_clnt.c +@@ -54,6 +54,7 @@ + #include + + #include "rpc_com.h" ++#include "debug.h" + + static struct timeval tottimeout = { 60, 0 }; + static const struct timeval rmttimeout = { 3, 0 }; +@@ -152,10 +153,8 @@ check_cache(host, netid) + for (cptr = front; cptr != NULL; cptr = cptr->ac_next) { + if (!strcmp(cptr->ac_host, host) && + !strcmp(cptr->ac_netid, netid)) { +-#ifdef ND_DEBUG +- fprintf(stderr, "Found cache entry for %s: %s\n", +- host, netid); +-#endif ++ LIBTIRPC_DEBUG(3, ("check_cache: Found cache entry for %s: %s\n", ++ host, netid)); + return (cptr); + } + } +@@ -214,9 +213,7 @@ add_cache(host, netid, taddr, uaddr) + if (ad_cache->ac_taddr->buf == NULL) + goto out_free; + memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len); +-#ifdef ND_DEBUG +- fprintf(stderr, "Added to cache: %s : %s\n", host, netid); +-#endif ++ LIBTIRPC_DEBUG(3, ("add_cache: Added to cache: %s : %s\n", host, netid)); + + /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */ + +@@ -234,10 +231,8 @@ add_cache(host, netid, taddr, uaddr) + cptr = cptr->ac_next; + } + +-#ifdef ND_DEBUG +- fprintf(stderr, "Deleted from cache: %s : %s\n", +- cptr->ac_host, cptr->ac_netid); +-#endif ++ LIBTIRPC_DEBUG(3, ("add_cache: Deleted from cache: %s : %s\n", ++ cptr->ac_host, cptr->ac_netid)); + free(cptr->ac_host); + free(cptr->ac_netid); + free(cptr->ac_taddr->buf); +@@ -338,17 +333,14 @@ getclnthandle(host, nconf, targaddr) + hints.ai_socktype = si.si_socktype; + hints.ai_protocol = si.si_proto; + +-#ifdef CLNT_DEBUG +- printf("trying netid %s family %d proto %d socktype %d\n", +- nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype); +-#endif ++ LIBTIRPC_DEBUG(3, ("getclnthandle: trying netid %s family %d proto %d socktype %d\n", ++ nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype)); + + if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { + client = local_rpcb(); + if (! client) { +-#ifdef ND_DEBUG +- clnt_pcreateerror("rpcbind clnt interface"); +-#endif ++ LIBTIRPC_DEBUG(1, ("getclnthandle: %s", ++ clnt_spcreateerror("local_rpcb failed"))); + goto out_err; + } else { + struct sockaddr_un sun; +@@ -370,19 +362,13 @@ getclnthandle(host, nconf, targaddr) + taddr.buf = tres->ai_addr; + taddr.len = taddr.maxlen = tres->ai_addrlen; + +-#ifdef ND_DEBUG +- { ++ if (libtirpc_debug_level > 3 && log_stderr) { + char *ua; ++ int i; + + ua = taddr2uaddr(nconf, &taddr); +- fprintf(stderr, "Got it [%s]\n", ua); ++ fprintf(stderr, "Got it [%s]\n", ua); + free(ua); +- } +-#endif +- +-#ifdef ND_DEBUG +- { +- int i; + + fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n", + taddr.len, taddr.maxlen); +@@ -391,14 +377,13 @@ getclnthandle(host, nconf, targaddr) + fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]); + fprintf(stderr, "\n"); + } +-#endif ++ + client = clnt_tli_create(RPC_ANYFD, nconf, &taddr, + (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0); +-#ifdef ND_DEBUG + if (! client) { +- clnt_pcreateerror("rpcbind clnt interface"); ++ LIBTIRPC_DEBUG(1, ("getclnthandle: %s", ++ clnt_spcreateerror("clnt_tli_create failed"))); + } +-#endif + + if (client) { + tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL; +@@ -641,13 +626,8 @@ got_entry(relp, nconf) + (nconf->nc_semantics == rmap->r_nc_semantics) && + (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != 0)) { + na = uaddr2taddr(nconf, rmap->r_maddr); +-#ifdef ND_DEBUG +- fprintf(stderr, "\tRemote address is [%s].\n", +- rmap->r_maddr); +- if (!na) +- fprintf(stderr, +- "\tCouldn't resolve remote address!\n"); +-#endif ++ LIBTIRPC_DEBUG(3, ("got_entry: Remote address is [%s] %s", ++ rmap->r_maddr, (na ? "Resolvable" : "Not Resolvable"))); + break; + } + } +@@ -875,12 +855,9 @@ try_rpcbind: + goto error; + } + address = uaddr2taddr(nconf, ua); +-#ifdef ND_DEBUG +- fprintf(stderr, "\tRemote address is [%s]\n", ua); +- if (!address) +- fprintf(stderr, +- "\tCouldn't resolve remote address!\n"); +-#endif ++ LIBTIRPC_DEBUG(3, ("__rpcb_findaddr_timed: Remote address is [%s] %s", ++ ua, (address ? "Resolvable" : "Not Resolvable"))); ++ + xdr_free((xdrproc_t)xdr_wrapstring, + (char *)(void *)&ua); + +diff --git a/src/svc_auth_des.c b/src/svc_auth_des.c +index e0ff6cb..08e2bee 100644 +--- a/src/svc_auth_des.c ++++ b/src/svc_auth_des.c +@@ -64,9 +64,9 @@ + #include + #endif + +-extern int key_decryptsession_pk(const char *, netobj *, des_block *); ++#include "debug.h" + +-#define debug(msg) printf("svcauth_des: %s\n", msg) ++extern int key_decryptsession_pk(const char *, netobj *, des_block *); + + #define USEC_PER_SEC ((u_long) 1000000L) + #define BEFORE(t1, t2) timercmp(t1, t2, <) +@@ -178,20 +178,20 @@ _svcauth_des(rqst, msg) + + sessionkey = &cred->adc_fullname.key; + if (! getpublickey(cred->adc_fullname.name, pkey_data)) { +- debug("getpublickey"); ++ LIBTIRPC_DEBUG(1, ("_svcauth_des: getpublickey failed")); + return(AUTH_BADCRED); + } + pkey.n_bytes = pkey_data; + pkey.n_len = strlen(pkey_data) + 1; + if (key_decryptsession_pk(cred->adc_fullname.name, &pkey, + sessionkey) < 0) { +- debug("decryptsessionkey"); ++ LIBTIRPC_DEBUG(1, ("_svcauth_des: key_decryptsessionkey failed")); + return (AUTH_BADCRED); /* key not found */ + } + } else { /* ADN_NICKNAME */ + sid = (short)cred->adc_nickname; + if (sid < 0 || sid >= AUTHDES_CACHESZ) { +- debug("bad nickname"); ++ LIBTIRPC_DEBUG(1, ("_svcauth_des: bad nickname")); + return (AUTH_BADCRED); /* garbled credential */ + } + sessionkey = &authdes_cache[sid].key; +@@ -214,7 +214,7 @@ _svcauth_des(rqst, msg) + sizeof(des_block), DES_DECRYPT | DES_HW); + } + if (DES_FAILED(status)) { +- debug("decryption failure"); ++ LIBTIRPC_DEBUG(1, ("_svcauth_des: decryption failure")); + return (AUTH_FAILED); /* system error */ + } + +@@ -240,13 +240,13 @@ _svcauth_des(rqst, msg) + window = IXDR_GET_U_LONG(ixdr); + winverf = IXDR_GET_U_LONG(ixdr); + if (winverf != window - 1) { +- debug("window verifier mismatch"); ++ LIBTIRPC_DEBUG(1, ("_svcauth_des: window verifier mismatch")); + return (AUTH_BADCRED); /* garbled credential */ + } + sid = cache_spot(sessionkey, cred->adc_fullname.name, + ×tamp); + if (sid < 0) { +- debug("replayed credential"); ++ LIBTIRPC_DEBUG(1, ("_svcauth_des: replayed credential")); + return (AUTH_REJECTEDCRED); /* replay */ + } + nick = 0; +@@ -256,19 +256,19 @@ _svcauth_des(rqst, msg) + } + + if ((u_long)timestamp.tv_usec >= USEC_PER_SEC) { +- debug("invalid usecs"); ++ LIBTIRPC_DEBUG(1, ("_svcauth_des: invalid usecs")); + /* cached out (bad key), or garbled verifier */ + return (nick ? AUTH_REJECTEDVERF : AUTH_BADVERF); + } + if (nick && BEFORE(×tamp, + &authdes_cache[sid].laststamp)) { +- debug("timestamp before last seen"); ++ LIBTIRPC_DEBUG(1, ("_svcauth_des: timestamp before last seen")); + return (AUTH_REJECTEDVERF); /* replay */ + } + (void) gettimeofday(¤t, (struct timezone *)NULL); + current.tv_sec -= window; /* allow for expiration */ + if (!BEFORE(¤t, ×tamp)) { +- debug("timestamp expired"); ++ LIBTIRPC_DEBUG(1, ("_svcauth_des: timestamp expired")); + /* replay, or garbled credential */ + return (nick ? AUTH_REJECTEDVERF : AUTH_BADCRED); + } +@@ -292,7 +292,7 @@ _svcauth_des(rqst, msg) + status = ecb_crypt((char *)sessionkey, (char *)cryptbuf, + sizeof(des_block), DES_ENCRYPT | DES_HW); + if (DES_FAILED(status)) { +- debug("encryption failure"); ++ LIBTIRPC_DEBUG(1, ("_svcauth_des: encryption failure")); + return (AUTH_FAILED); /* system error */ + } + verf.adv_xtimestamp = cryptbuf[0]; +@@ -328,7 +328,7 @@ _svcauth_des(rqst, msg) + if (entry->rname != NULL) { + (void) strcpy(entry->rname, cred->adc_fullname.name); + } else { +- debug("out of memory"); ++ LIBTIRPC_DEBUG(1, ("_svcauth_des: out of memory")); + } + entry->key = *sessionkey; + entry->window = window; +@@ -472,7 +472,7 @@ authdes_getucred(adc, uid, gid, grouplen, groups) + + sid = adc->adc_nickname; + if (sid >= AUTHDES_CACHESZ) { +- debug("invalid nickname"); ++ LIBTIRPC_DEBUG(1, ("authdes_getucred: invalid nickname")); + return (0); + } + cred = (struct bsdcred *)authdes_cache[sid].localcred; +@@ -488,11 +488,11 @@ authdes_getucred(adc, uid, gid, grouplen, groups) + if (!netname2user(adc->adc_fullname.name, &i_uid, &i_gid, + &i_grouplen, groups)) + { +- debug("unknown netname"); ++ LIBTIRPC_DEBUG(1, ("authdes_getucred: unknown netname")); + cred->grouplen = UNKNOWN; /* mark as lookup up, but not found */ + return (0); + } +- debug("missed ucred cache"); ++ LIBTIRPC_DEBUG(1, ("authdes_getucred: missed ucred cache")); + *uid = cred->uid = i_uid; + *gid = cred->gid = i_gid; + *grouplen = cred->grouplen = i_grouplen; +diff --git a/src/svc_auth_gss.c b/src/svc_auth_gss.c +index 0aa712a..3a3c980 100644 +--- a/src/svc_auth_gss.c ++++ b/src/svc_auth_gss.c +@@ -93,7 +93,8 @@ svcauth_gss_set_svc_name(gss_name_t name) + maj_stat = gss_release_name(&min_stat, &_svcauth_gss_name); + + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_status("gss_release_name", maj_stat, min_stat); ++ gss_log_status("svcauth_gss_set_svc_name: gss_release_name", ++ maj_stat, min_stat); + return (FALSE); + } + _svcauth_gss_name = NULL; +@@ -101,7 +102,8 @@ svcauth_gss_set_svc_name(gss_name_t name) + maj_stat = gss_duplicate_name(&min_stat, name, &_svcauth_gss_name); + + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_status("gss_duplicate_name", maj_stat, min_stat); ++ gss_log_status("svcauth_gss_set_svc_name: gss_duplicate_name", ++ maj_stat, min_stat); + return (FALSE); + } + +@@ -124,7 +126,8 @@ svcauth_gss_import_name(char *service) + (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &name); + + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_status("gss_import_name", maj_stat, min_stat); ++ gss_log_status("svcauth_gss_import_name: gss_import_name", ++ maj_stat, min_stat); + return (FALSE); + } + if (svcauth_gss_set_svc_name(name) != TRUE) { +@@ -146,7 +149,8 @@ svcauth_gss_acquire_cred(void) + &_svcauth_gss_creds, NULL, NULL); + + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_status("gss_acquire_cred", maj_stat, min_stat); ++ gss_log_status("svcauth_gss_acquire_cred: gss_acquire_cred", ++ maj_stat, min_stat); + return (FALSE); + } + return (TRUE); +@@ -162,7 +166,8 @@ svcauth_gss_release_cred(void) + maj_stat = gss_release_cred(&min_stat, &_svcauth_gss_creds); + + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_status("gss_release_cred", maj_stat, min_stat); ++ gss_log_status("svcauth_gss_release_cred: gss_release_cred", ++ maj_stat, min_stat); + return (FALSE); + } + +@@ -208,7 +213,8 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, + + if (gr->gr_major != GSS_S_COMPLETE && + gr->gr_major != GSS_S_CONTINUE_NEEDED) { +- gss_log_status("accept_sec_context", gr->gr_major, gr->gr_minor); ++ gss_log_status("svcauth_gss_accept_sec_context: accept_sec_context", ++ gr->gr_major, gr->gr_minor); + gd->ctx = GSS_C_NO_CONTEXT; + gss_release_buffer(&min_stat, &gr->gr_token); + return (FALSE); +@@ -238,10 +244,10 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, + maj_stat = gss_display_name(&min_stat, gd->client_name, + &gd->cname, &gd->sec.mech); + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_status("display_name", maj_stat, min_stat); ++ gss_log_status("svcauth_gss_accept_sec_context: display_name", ++ maj_stat, min_stat); + return (FALSE); + } +-#ifdef DEBUG + #ifdef HAVE_KRB5 + { + gss_buffer_desc mechname; +@@ -262,7 +268,6 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, + gd->cname.length, (char *)gd->cname.value, + gd->sec.qop, gd->sec.svc); + #endif +-#endif /* DEBUG */ + seq = htonl(gr->gr_win); + seqbuf.value = &seq; + seqbuf.length = sizeof(seq); +@@ -326,7 +331,8 @@ svcauth_gss_validate(struct svc_rpc_gss_data *gd, struct rpc_msg *msg) + free(rpchdr); + + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_status("gss_verify_mic", maj_stat, min_stat); ++ gss_log_status("svcauth_gss_validate: gss_verify_mic", ++ maj_stat, min_stat); + return (FALSE); + } + return (TRUE); +@@ -353,7 +359,8 @@ svcauth_gss_nextverf(struct svc_req *rqst, u_int num) + &signbuf, &checksum); + + if (maj_stat != GSS_S_COMPLETE) { +- gss_log_status("gss_get_mic", maj_stat, min_stat); ++ gss_log_status("svcauth_gss_nextverf: gss_get_mic", ++ maj_stat, min_stat); + return (FALSE); + } + rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; +diff --git a/src/svc_dg.c b/src/svc_dg.c +index 6e00191..f8255cc 100644 +--- a/src/svc_dg.c ++++ b/src/svc_dg.c +@@ -49,13 +49,11 @@ + #include + #include + #include +-#ifdef RPC_CACHE_DEBUG + #include +-#include +-#endif + #include + + #include "rpc_com.h" ++#include "debug.h" + + #define su_data(xprt) ((struct svc_dg_data *)(xprt->xp_p2)) + #define rpc_buffer(xprt) ((xprt)->xp_p1) +@@ -506,10 +504,8 @@ cache_set(xprt, replylen) + struct cl_cache *uc = (struct cl_cache *) su->su_cache; + u_int loc; + char *newbuf; +-#ifdef RPC_CACHE_DEBUG + struct netconfig *nconf; + char *uaddr; +-#endif + + mutex_lock(&dupreq_lock); + /* +@@ -549,17 +545,17 @@ cache_set(xprt, replylen) + /* + * Store it away + */ +-#ifdef RPC_CACHE_DEBUG +- if (nconf = getnetconfigent(xprt->xp_netid)) { +- uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr); +- freenetconfigent(nconf); +- printf( +- "cache set for xid= %x prog=%d vers=%d proc=%d for rmtaddr=%s\n", +- su->su_xid, uc->uc_prog, uc->uc_vers, +- uc->uc_proc, uaddr); +- free(uaddr); ++ if (libtirpc_debug_level > 3) { ++ if ((nconf = getnetconfigent(xprt->xp_netid))) { ++ uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr); ++ freenetconfigent(nconf); ++ LIBTIRPC_DEBUG(4, ++ ("cache set for xid= %x prog=%d vers=%d proc=%d for rmtaddr=%s\n", ++ su->su_xid, uc->uc_prog, uc->uc_vers, ++ uc->uc_proc, uaddr)); ++ free(uaddr); ++ } + } +-#endif + victim->cache_replylen = replylen; + victim->cache_reply = rpc_buffer(xprt); + rpc_buffer(xprt) = newbuf; +@@ -596,10 +592,8 @@ cache_get(xprt, msg, replyp, replylenp) + cache_ptr ent; + struct svc_dg_data *su = su_data(xprt); + struct cl_cache *uc = (struct cl_cache *) su->su_cache; +-#ifdef RPC_CACHE_DEBUG + struct netconfig *nconf; + char *uaddr; +-#endif + + mutex_lock(&dupreq_lock); + loc = CACHE_LOC(xprt, su->su_xid); +@@ -611,18 +605,19 @@ cache_get(xprt, msg, replyp, replylenp) + ent->cache_addr.len == xprt->xp_rtaddr.len && + (memcmp(ent->cache_addr.buf, xprt->xp_rtaddr.buf, + xprt->xp_rtaddr.len) == 0)) { +-#ifdef RPC_CACHE_DEBUG +- if (nconf = getnetconfigent(xprt->xp_netid)) { +- uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr); +- freenetconfigent(nconf); +- printf( +- "cache entry found for xid=%x prog=%d vers=%d proc=%d for rmtaddr=%s\n", +- su->su_xid, msg->rm_call.cb_prog, +- msg->rm_call.cb_vers, +- msg->rm_call.cb_proc, uaddr); +- free(uaddr); ++ if (libtirpc_debug_level > 3) { ++ if ((nconf = getnetconfigent(xprt->xp_netid))) { ++ uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr); ++ freenetconfigent(nconf); ++ LIBTIRPC_DEBUG(4, ++ ("cache entry found for xid=%x prog=%d" ++ "vers=%d proc=%d for rmtaddr=%s\n", ++ su->su_xid, msg->rm_call.cb_prog, ++ msg->rm_call.cb_vers, ++ msg->rm_call.cb_proc, uaddr)); ++ free(uaddr); ++ } + } +-#endif + *replyp = ent->cache_reply; + *replylenp = ent->cache_replylen; + mutex_unlock(&dupreq_lock); +diff --git a/src/svc_vc.c b/src/svc_vc.c +index 14bc2af..884294e 100644 +--- a/src/svc_vc.c ++++ b/src/svc_vc.c +@@ -275,7 +275,7 @@ makefd_xprt(fd, sendsize, recvsize) + memset(xprt, 0, sizeof *xprt); + cd = mem_alloc(sizeof(struct cf_conn)); + if (cd == NULL) { +- warnx("svc_tcp: makefd_xprt: out of memory"); ++ warnx("svc_vc: makefd_xprt: out of memory"); + mem_free(xprt, sizeof(SVCXPRT)); + xprt = NULL; + goto done; diff --git a/SOURCES/libtirpc-0.2.4-makefd_xprt-fd.patch b/SOURCES/libtirpc-0.2.4-makefd_xprt-fd.patch new file mode 100644 index 0000000..4913bea --- /dev/null +++ b/SOURCES/libtirpc-0.2.4-makefd_xprt-fd.patch @@ -0,0 +1,93 @@ +diff -up libtirpc-0.2.4/src/rtime.c.orig libtirpc-0.2.4/src/rtime.c +--- libtirpc-0.2.4/src/rtime.c.orig 2013-12-09 15:59:51.000000000 -0500 ++++ libtirpc-0.2.4/src/rtime.c 2017-02-25 12:29:25.227847702 -0500 +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -67,7 +68,8 @@ rtime(addrp, timep, timeout) + struct timeval *timeout; + { + int s; +- fd_set readfds; ++ struct pollfd fd; ++ int milliseconds; + int res; + unsigned long thetime; + struct sockaddr_in from; +@@ -94,31 +96,32 @@ rtime(addrp, timep, timeout) + addrp->sin_port = serv->s_port; + + if (type == SOCK_DGRAM) { +- res = sendto(s, (char *)&thetime, sizeof(thetime), 0, ++ res = sendto(s, (char *)&thetime, sizeof(thetime), 0, + (struct sockaddr *)addrp, sizeof(*addrp)); + if (res < 0) { + do_close(s); +- return(-1); ++ return(-1); + } +- do { +- FD_ZERO(&readfds); +- FD_SET(s, &readfds); +- res = select(_rpc_dtablesize(), &readfds, +- (fd_set *)NULL, (fd_set *)NULL, timeout); +- } while (res < 0 && errno == EINTR); ++ ++ milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); ++ fd.fd = s; ++ fd.events = POLLIN; ++ do ++ res = poll (&fd, 1, milliseconds); ++ while (res < 0 && errno == EINTR); + if (res <= 0) { + if (res == 0) { + errno = ETIMEDOUT; + } + do_close(s); +- return(-1); ++ return(-1); + } + fromlen = sizeof(from); +- res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0, ++ res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0, + (struct sockaddr *)&from, &fromlen); + do_close(s); + if (res < 0) { +- return(-1); ++ return(-1); + } + } else { + if (connect(s, (struct sockaddr *)addrp, sizeof(*addrp)) < 0) { +diff -up libtirpc-0.2.4/src/svc_vc.c.orig libtirpc-0.2.4/src/svc_vc.c +--- libtirpc-0.2.4/src/svc_vc.c.orig 2017-02-25 12:26:55.430978326 -0500 ++++ libtirpc-0.2.4/src/svc_vc.c 2017-02-25 12:29:25.227847702 -0500 +@@ -260,14 +260,8 @@ makefd_xprt(fd, sendsize, recvsize) + struct cf_conn *cd; + const char *netid; + struct __rpc_sockinfo si; +- +- assert(fd != -1); + +- if (fd >= FD_SETSIZE) { +- warnx("svc_vc: makefd_xprt: fd too high\n"); +- xprt = NULL; +- goto done; +- } ++ assert(fd != -1); + + xprt = mem_alloc(sizeof(SVCXPRT)); + if (xprt == NULL) { +@@ -340,6 +334,8 @@ again: + */ + + newxprt = makefd_xprt(sock, r->sendsize, r->recvsize); ++ if (!newxprt) ++ return (FALSE); + + if (!__rpc_set_netbuf(&newxprt->xp_rtaddr, &addr, len)) + return (FALSE); diff --git a/SOURCES/libtirpc-0.2.4-mem-leak.patch b/SOURCES/libtirpc-0.2.4-mem-leak.patch new file mode 100644 index 0000000..a0b9079 --- /dev/null +++ b/SOURCES/libtirpc-0.2.4-mem-leak.patch @@ -0,0 +1,37 @@ +diff -up libtirpc-0.2.4/src/svc_generic.c.orig libtirpc-0.2.4/src/svc_generic.c +--- libtirpc-0.2.4/src/svc_generic.c.orig 2013-12-09 15:59:51.000000000 -0500 ++++ libtirpc-0.2.4/src/svc_generic.c 2015-06-29 10:20:27.239019533 -0400 +@@ -283,6 +283,8 @@ svc_tli_create(fd, nconf, bindaddr, send + xprt->xp_type = __rpc_socktype2seman(si.si_socktype); + + if (nconf) { ++ if (xprt->xp_netid != NULL) ++ free(xprt->xp_netid); + xprt->xp_netid = strdup(nconf->nc_netid); + xprt->xp_tp = strdup(nconf->nc_device); + } +diff -up libtirpc-0.2.4/src/svc_vc.c.orig libtirpc-0.2.4/src/svc_vc.c +--- libtirpc-0.2.4/src/svc_vc.c.orig 2015-06-29 10:19:21.205835483 -0400 ++++ libtirpc-0.2.4/src/svc_vc.c 2015-06-29 10:20:34.616151809 -0400 +@@ -393,6 +393,12 @@ svc_vc_destroy(xprt) + __svc_vc_dodestroy(xprt); + } + ++static bool_t ++__svc_rendezvous_socket(xprt) ++ SVCXPRT *xprt; ++{ ++ return (xprt->xp_ops->xp_recv == rendezvous_request); ++} + static void + __svc_vc_dodestroy(xprt) + SVCXPRT *xprt; +@@ -404,7 +410,7 @@ __svc_vc_dodestroy(xprt) + + if (xprt->xp_fd != RPC_ANYFD) + (void)close(xprt->xp_fd); +- if (xprt->xp_port != 0) { ++ if (__svc_rendezvous_socket(xprt)) { + /* a rendezvouser socket */ + r = (struct cf_rendezvous *)xprt->xp_p1; + mem_free(r, sizeof (struct cf_rendezvous)); diff --git a/SOURCES/libtirpc-0.2.4-nonblocking-mode.patch b/SOURCES/libtirpc-0.2.4-nonblocking-mode.patch new file mode 100644 index 0000000..3748e07 --- /dev/null +++ b/SOURCES/libtirpc-0.2.4-nonblocking-mode.patch @@ -0,0 +1,57 @@ +commit a4fa582908b9c63957240cb0cb68b59d56244ef5 +Author: Bodo Stroesser +Date: Thu Nov 6 13:26:00 2014 -0500 + + write_vc: fix write retry loop for nonblocking mode + + This is a simple fix for the write retry loop that is used on + non-blocking connections if write() failed with -EAGAIN. + + Additionally it removes a redundant if () {} + + Erroneously at each cycle of the loop the length of the data + to send is incremented and the buffer pointer is decremented. + Thus, it might happen that: + * the application crashes + * data from the memory before the buffer is sent + + Signed-off-by: Bodo Stroesser + Signed-off-by: Steve Dickson + +diff --git a/src/svc_vc.c b/src/svc_vc.c +index 4c70de8..4d3ea51 100644 +--- a/src/svc_vc.c ++++ b/src/svc_vc.c +@@ -559,20 +559,19 @@ write_vc(xprtp, buf, len) + cd->strm_stat = XPRT_DIED; + return (-1); + } +- if (cd->nonblock && i != cnt) { +- /* +- * For non-blocking connections, do not +- * take more than 2 seconds writing the +- * data out. +- * +- * XXX 2 is an arbitrary amount. +- */ +- gettimeofday(&tv1, NULL); +- if (tv1.tv_sec - tv0.tv_sec >= 2) { +- cd->strm_stat = XPRT_DIED; +- return (-1); +- } ++ /* ++ * For non-blocking connections, do not ++ * take more than 2 seconds writing the ++ * data out. ++ * ++ * XXX 2 is an arbitrary amount. ++ */ ++ gettimeofday(&tv1, NULL); ++ if (tv1.tv_sec - tv0.tv_sec >= 2) { ++ cd->strm_stat = XPRT_DIED; ++ return (-1); + } ++ i = 0; /* Don't change buf and cnt */ + } + } + diff --git a/SOURCES/libtirpc-0.2.4-svc-buffer-overflow.patch b/SOURCES/libtirpc-0.2.4-svc-buffer-overflow.patch new file mode 100644 index 0000000..6432788 --- /dev/null +++ b/SOURCES/libtirpc-0.2.4-svc-buffer-overflow.patch @@ -0,0 +1,49 @@ +commit cf2e0082ce88fc2c75479c26a4b9f69f1b028c80 +Author: Steve Dickson +Date: Thu May 29 09:40:59 2014 -0400 + + Avoid buffer overruns by allocating buffer in svcauth_gss_validate() + + Reviewed-by: Chuck Lever + Signed-off-by: Steve Dickson + +diff --git a/src/svc_auth_gss.c b/src/svc_auth_gss.c +index 601a691..26c1065 100644 +--- a/src/svc_auth_gss.c ++++ b/src/svc_auth_gss.c +@@ -286,21 +286,19 @@ svcauth_gss_validate(struct svc_rpc_gss_data *gd, struct rpc_msg *msg) + struct opaque_auth *oa; + gss_buffer_desc rpcbuf, checksum; + OM_uint32 maj_stat, min_stat, qop_state; +- u_char rpchdr[128]; ++ u_char *rpchdr; + int32_t *buf; + + gss_log_debug("in svcauth_gss_validate()"); + +- memset(rpchdr, 0, sizeof(rpchdr)); +- + /* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */ + oa = &msg->rm_call.cb_cred; + if (oa->oa_length > MAX_AUTH_BYTES) + return (FALSE); +- +- /* 8 XDR units from the IXDR macro calls. */ +- if (sizeof(rpchdr) < (8 * BYTES_PER_XDR_UNIT + +- RNDUP(oa->oa_length))) ++ ++ rpchdr = (u_char *)calloc(((8 * BYTES_PER_XDR_UNIT) + ++ RNDUP(oa->oa_length)), 1); ++ if (rpchdr == NULL) + return (FALSE); + + buf = (int32_t *)rpchdr; +@@ -325,6 +323,8 @@ svcauth_gss_validate(struct svc_rpc_gss_data *gd, struct rpc_msg *msg) + maj_stat = gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum, + &qop_state); + ++ free(rpchdr); ++ + if (maj_stat != GSS_S_COMPLETE) { + gss_log_status("gss_verify_mic", maj_stat, min_stat); + return (FALSE); diff --git a/SOURCES/libtirpc-0.2.4-svc-gss-memleaks.patch b/SOURCES/libtirpc-0.2.4-svc-gss-memleaks.patch new file mode 100644 index 0000000..c9ef2ff --- /dev/null +++ b/SOURCES/libtirpc-0.2.4-svc-gss-memleaks.patch @@ -0,0 +1,364 @@ +diff --git a/src/svc.c b/src/svc.c +index 08cd6c9..8afd15d 100644 +--- a/src/svc.c ++++ b/src/svc.c +@@ -649,6 +649,7 @@ svc_getreq_common (fd) + { + if (SVC_RECV (xprt, &msg)) + { ++ bool_t no_dispatch; + + /* now find the exported program and call it */ + struct svc_callout *s; +@@ -660,11 +661,14 @@ svc_getreq_common (fd) + r.rq_proc = msg.rm_call.cb_proc; + r.rq_cred = msg.rm_call.cb_cred; + /* first authenticate the message */ +- if ((why = _authenticate (&r, &msg)) != AUTH_OK) ++ why = _gss_authenticate(&r, &msg, &no_dispatch); ++ if (why != AUTH_OK) + { + svcerr_auth (xprt, why); + goto call_done; + } ++ if (no_dispatch) ++ goto call_done; + /* now match message with a registered service */ + prog_found = FALSE; + low_vers = (rpcvers_t) - 1L; +diff --git a/src/svc_auth.c b/src/svc_auth.c +index e80d5f9..31241c9 100644 +--- a/src/svc_auth.c ++++ b/src/svc_auth.c +@@ -82,9 +82,10 @@ static struct authsvc *Auths = NULL; + * invalid. + */ + enum auth_stat +-_authenticate(rqst, msg) ++_gss_authenticate(rqst, msg, no_dispatch) + struct svc_req *rqst; + struct rpc_msg *msg; ++ bool_t *no_dispatch; + { + int cred_flavor; + struct authsvc *asp; +@@ -97,6 +98,7 @@ _authenticate(rqst, msg) + rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; + rqst->rq_xprt->xp_verf.oa_length = 0; + cred_flavor = rqst->rq_cred.oa_flavor; ++ *no_dispatch = FALSE; + switch (cred_flavor) { + case AUTH_NONE: + dummy = _svcauth_none(rqst, msg); +@@ -112,6 +114,11 @@ _authenticate(rqst, msg) + dummy = _svcauth_des(rqst, msg); + return (dummy); + #endif ++#ifdef HAVE_RPCSEC_GSS ++ case RPCSEC_GSS: ++ dummy = _svcauth_gss(rqst, msg, no_dispatch); ++ return (dummy); ++#endif + default: + break; + } +@@ -132,6 +139,13 @@ _authenticate(rqst, msg) + return (AUTH_REJECTEDCRED); + } + ++enum auth_stat ++_authenticate(struct svc_req *rqst, struct rpc_msg *msg) ++{ ++ bool_t no_dispatch; ++ return _gss_authenticate(rqst, msg, &no_dispatch); ++} ++ + /* + * Allow the rpc service to register new authentication types that it is + * prepared to handle. When an authentication flavor is registered, +@@ -161,6 +175,9 @@ svc_auth_reg(cred_flavor, handler) + #ifdef DES_BUILTIN + case AUTH_DES: + #endif ++#ifdef HAVE_RPCSEC_GSS ++ case RPCSEC_GSS: ++#endif + /* already registered */ + return (1); + +diff --git a/src/svc_auth_gss.c b/src/svc_auth_gss.c +index 3a3c980..7376107 100644 +--- a/src/svc_auth_gss.c ++++ b/src/svc_auth_gss.c +@@ -116,6 +116,7 @@ svcauth_gss_import_name(char *service) + gss_name_t name; + gss_buffer_desc namebuf; + OM_uint32 maj_stat, min_stat; ++ bool_t result; + + gss_log_debug("in svcauth_gss_import_name()"); + +@@ -130,11 +131,9 @@ svcauth_gss_import_name(char *service) + maj_stat, min_stat); + return (FALSE); + } +- if (svcauth_gss_set_svc_name(name) != TRUE) { +- gss_release_name(&min_stat, &name); +- return (FALSE); +- } +- return (TRUE); ++ result = svcauth_gss_set_svc_name(name); ++ gss_release_name(&min_stat, &name); ++ return result; + } + + static bool_t +@@ -211,6 +210,8 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, + NULL, + NULL); + ++ xdr_free((xdrproc_t)xdr_rpc_gss_init_args, (caddr_t)&recv_tok); ++ + if (gr->gr_major != GSS_S_COMPLETE && + gr->gr_major != GSS_S_CONTINUE_NEEDED) { + gss_log_status("svcauth_gss_accept_sec_context: accept_sec_context", +@@ -279,8 +280,11 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst, + return (FALSE); + + rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; +- rqst->rq_xprt->xp_verf.oa_base = checksum.value; ++ memcpy(rqst->rq_xprt->xp_verf.oa_base, checksum.value, ++ checksum.length); + rqst->rq_xprt->xp_verf.oa_length = checksum.length; ++ ++ gss_release_buffer(&min_stat, &checksum); + } + return (TRUE); + } +@@ -363,10 +367,13 @@ svcauth_gss_nextverf(struct svc_req *rqst, u_int num) + maj_stat, min_stat); + return (FALSE); + } ++ + rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; +- rqst->rq_xprt->xp_verf.oa_base = (caddr_t)checksum.value; ++ memcpy(rqst->rq_xprt->xp_verf.oa_base, checksum.value, checksum.length); + rqst->rq_xprt->xp_verf.oa_length = (u_int)checksum.length; + ++ gss_release_buffer(&min_stat, &checksum); ++ + return (TRUE); + } + +@@ -379,8 +386,10 @@ _svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) + struct rpc_gss_cred *gc; + struct rpc_gss_init_res gr; + int call_stat, offset; ++ enum auth_stat result = AUTH_OK; ++ OM_uint32 min_stat; + +- gss_log_debug("in svcauth_gss()"); ++ gss_log_debug("in _svcauth_gss()"); + + /* Initialize reply. */ + rqst->rq_xprt->xp_verf = _null_auth; +@@ -419,19 +428,25 @@ _svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) + XDR_DESTROY(&xdrs); + + /* Check version. */ +- if (gc->gc_v != RPCSEC_GSS_VERSION) +- return (AUTH_BADCRED); ++ if (gc->gc_v != RPCSEC_GSS_VERSION) { ++ result = AUTH_BADCRED; ++ goto out; ++ } + + /* Check RPCSEC_GSS service. */ + if (gc->gc_svc != RPCSEC_GSS_SVC_NONE && + gc->gc_svc != RPCSEC_GSS_SVC_INTEGRITY && +- gc->gc_svc != RPCSEC_GSS_SVC_PRIVACY) +- return (AUTH_BADCRED); ++ gc->gc_svc != RPCSEC_GSS_SVC_PRIVACY) { ++ result = AUTH_BADCRED; ++ goto out; ++ } + + /* Check sequence number. */ + if (gd->established) { +- if (gc->gc_seq > MAXSEQ) +- return (RPCSEC_GSS_CTXPROBLEM); ++ if (gc->gc_seq > MAXSEQ) { ++ result = RPCSEC_GSS_CTXPROBLEM; ++ goto out; ++ } + + if ((offset = gd->seqlast - gc->gc_seq) < 0) { + gd->seqlast = gc->gc_seq; +@@ -441,7 +456,8 @@ _svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) + } + else if (offset >= gd->win || (gd->seqmask & (1 << offset))) { + *no_dispatch = 1; +- return (RPCSEC_GSS_CTXPROBLEM); ++ result = RPCSEC_GSS_CTXPROBLEM; ++ goto out; + } + gd->seq = gc->gc_seq; + gd->seqmask |= (1 << offset); +@@ -452,35 +468,52 @@ _svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) + rqst->rq_svcname = (char *)gd->ctx; + } + ++ rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base; ++ + /* Handle RPCSEC_GSS control procedure. */ + switch (gc->gc_proc) { + + case RPCSEC_GSS_INIT: + case RPCSEC_GSS_CONTINUE_INIT: +- if (rqst->rq_proc != NULLPROC) +- return (AUTH_FAILED); /* XXX ? */ ++ if (rqst->rq_proc != NULLPROC) { ++ result = AUTH_FAILED; ++ break; ++ } + + if (_svcauth_gss_name == NULL) { +- if (!svcauth_gss_import_name("nfs")) +- return (AUTH_FAILED); ++ if (!svcauth_gss_import_name("nfs")) { ++ result = AUTH_FAILED; ++ break; ++ } + } + +- if (!svcauth_gss_acquire_cred()) +- return (AUTH_FAILED); ++ if (!svcauth_gss_acquire_cred()) { ++ result = AUTH_FAILED; ++ break; ++ } + +- if (!svcauth_gss_accept_sec_context(rqst, &gr)) +- return (AUTH_REJECTEDCRED); ++ if (!svcauth_gss_accept_sec_context(rqst, &gr)) { ++ result = AUTH_REJECTEDCRED; ++ break; ++ } + +- if (!svcauth_gss_nextverf(rqst, htonl(gr.gr_win))) +- return (AUTH_FAILED); ++ if (!svcauth_gss_nextverf(rqst, htonl(gr.gr_win))) { ++ result = AUTH_FAILED; ++ break; ++ } + + *no_dispatch = TRUE; + + call_stat = svc_sendreply(rqst->rq_xprt, + (xdrproc_t)xdr_rpc_gss_init_res, (caddr_t)&gr); + +- if (!call_stat) +- return (AUTH_FAILED); ++ gss_release_buffer(&min_stat, &gr.gr_token); ++ free(gr.gr_ctx.value); ++ ++ if (!call_stat) { ++ result = AUTH_FAILED; ++ break; ++ } + + if (gr.gr_major == GSS_S_COMPLETE) + gd->established = TRUE; +@@ -488,25 +521,36 @@ _svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) + break; + + case RPCSEC_GSS_DATA: +- if (!svcauth_gss_validate(gd, msg)) +- return (RPCSEC_GSS_CREDPROBLEM); ++ if (!svcauth_gss_validate(gd, msg)) { ++ result = RPCSEC_GSS_CREDPROBLEM; ++ break; ++ } + +- if (!svcauth_gss_nextverf(rqst, htonl(gc->gc_seq))) +- return (AUTH_FAILED); ++ if (!svcauth_gss_nextverf(rqst, htonl(gc->gc_seq))) { ++ result = AUTH_FAILED; ++ break; ++ } + break; + + case RPCSEC_GSS_DESTROY: +- if (rqst->rq_proc != NULLPROC) +- return (AUTH_FAILED); /* XXX ? */ +- +- if (!svcauth_gss_validate(gd, msg)) +- return (RPCSEC_GSS_CREDPROBLEM); ++ if (rqst->rq_proc != NULLPROC) { ++ result = AUTH_FAILED; /* XXX ? */ ++ break; ++ } ++ if (!svcauth_gss_validate(gd, msg)) { ++ result = RPCSEC_GSS_CREDPROBLEM; ++ break; ++ } + +- if (!svcauth_gss_nextverf(rqst, htonl(gc->gc_seq))) +- return (AUTH_FAILED); ++ if (!svcauth_gss_nextverf(rqst, htonl(gc->gc_seq))) { ++ result = AUTH_FAILED; ++ break; ++ } + +- if (!svcauth_gss_release_cred()) +- return (AUTH_FAILED); ++ if (!svcauth_gss_release_cred()) { ++ result = AUTH_FAILED; ++ break; ++ } + + SVCAUTH_DESTROY(rqst->rq_xprt->xp_auth); + rqst->rq_xprt->xp_auth = &svc_auth_none; +@@ -514,10 +558,15 @@ _svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) + break; + + default: +- return (AUTH_REJECTEDCRED); ++ result = AUTH_REJECTEDCRED; + break; + } +- return (AUTH_OK); ++out: ++ xdr_free((xdrproc_t)xdr_rpc_gss_cred, (caddr_t)gc); ++ if (result != AUTH_OK) ++ gss_log_debug("_svcauth_gss() failed: %d", result); ++ ++ return result; + } + + bool_t +diff --git a/tirpc/rpc/auth.h b/tirpc/rpc/auth.h +index 4ce11f0..7c8f813 100644 +--- a/tirpc/rpc/auth.h ++++ b/tirpc/rpc/auth.h +@@ -399,6 +399,7 @@ struct rpc_msg; + enum auth_stat _svcauth_none (struct svc_req *, struct rpc_msg *); + enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *); + enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *); ++enum auth_stat _svcauth_gss (struct svc_req *, struct rpc_msg *, bool_t *); + __END_DECLS + + #define AUTH_NONE 0 /* no authentication */ +diff --git a/tirpc/rpc/svc_auth.h b/tirpc/rpc/svc_auth.h +index 14269d1..723c989 100644 +--- a/tirpc/rpc/svc_auth.h ++++ b/tirpc/rpc/svc_auth.h +@@ -66,6 +66,8 @@ typedef struct SVCAUTH { + * Server side authenticator + */ + __BEGIN_DECLS ++extern enum auth_stat _gss_authenticate(struct svc_req *, struct rpc_msg *, ++ bool_t *); + extern enum auth_stat _authenticate(struct svc_req *, struct rpc_msg *); + extern int svc_auth_reg(int, enum auth_stat (*)(struct svc_req *, + struct rpc_msg *)); diff --git a/SOURCES/libtirpc-0.2.4-svc_vc_create-memleak.patch b/SOURCES/libtirpc-0.2.4-svc_vc_create-memleak.patch new file mode 100644 index 0000000..3ec299b --- /dev/null +++ b/SOURCES/libtirpc-0.2.4-svc_vc_create-memleak.patch @@ -0,0 +1,16 @@ +diff -up libtirpc-0.2.4/src/svc_vc.c.orig libtirpc-0.2.4/src/svc_vc.c +--- libtirpc-0.2.4/src/svc_vc.c.orig 2016-04-08 10:52:23.254767196 -0400 ++++ libtirpc-0.2.4/src/svc_vc.c 2016-04-08 10:57:44.461237876 -0400 +@@ -158,8 +158,10 @@ svc_vc_create(fd, sendsize, recvsize) + warnx("svc_vc_create: out of memory"); + goto cleanup_svc_vc_create; + } +- if (!__rpc_fd2sockinfo(fd, &si)) +- return NULL; ++ if (!__rpc_fd2sockinfo(fd, &si)) { ++ warnx("svc_vc_create: __rpc_fd2sockinfo failed"); ++ goto cleanup_svc_vc_create; ++ } + r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); + r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); + r->maxrec = __svc_maxrec; diff --git a/SOURCES/libtirpc-0.2.4-xdrstdio.patch b/SOURCES/libtirpc-0.2.4-xdrstdio.patch new file mode 100644 index 0000000..0b701c0 --- /dev/null +++ b/SOURCES/libtirpc-0.2.4-xdrstdio.patch @@ -0,0 +1,42 @@ +diff -up libtirpc-0.2.4/src/xdr_stdio.c.orig libtirpc-0.2.4/src/xdr_stdio.c +--- libtirpc-0.2.4/src/xdr_stdio.c.orig 2013-12-09 15:59:51.000000000 -0500 ++++ libtirpc-0.2.4/src/xdr_stdio.c 2018-07-20 12:19:18.682840483 -0400 +@@ -39,6 +39,7 @@ + */ + + #include ++#include + + #include + #include +@@ -104,10 +105,12 @@ xdrstdio_getlong(xdrs, lp) + XDR *xdrs; + long *lp; + { ++ int32_t mycopy; + +- if (fread(lp, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1) ++ if (fread(&mycopy, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1) + return (FALSE); +- *lp = (long)ntohl((u_int32_t)*lp); ++ ++ *lp = (long)ntohl(mycopy); + return (TRUE); + } + +@@ -116,8 +119,14 @@ xdrstdio_putlong(xdrs, lp) + XDR *xdrs; + const long *lp; + { +- long mycopy = (long)htonl((u_int32_t)*lp); ++ int32_t mycopy; ++ ++#if defined(_LP64) ++ if ((*lp > UINT32_MAX) || (*lp < INT32_MIN)) ++ return (FALSE); ++#endif + ++ mycopy = (int32_t)htonl((int32_t)*lp); + if (fwrite(&mycopy, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1) + return (FALSE); + return (TRUE); diff --git a/SPECS/libtirpc.spec b/SPECS/libtirpc.spec new file mode 100644 index 0000000..d0c060a --- /dev/null +++ b/SPECS/libtirpc.spec @@ -0,0 +1,446 @@ +%define _root_libdir /%{_lib} + +Name: libtirpc +Version: 0.2.4 +Release: 0.15%{?dist} +Summary: Transport Independent RPC Library +Group: System Environment/Libraries +License: SISSL and BSD +URL: http://git.linux-nfs.org/?p=steved/libtirpc.git;a=summary + +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +Source0: http://downloads.sourceforge.net/libtirpc/libtirpc-%{version}.tar.bz2 + +BuildRequires: automake, autoconf, libtool, pkgconfig +BuildRequires: krb5-devel + +# +# RHEL7.1 +# +Patch001: libtirpc-0.2.4-svc-buffer-overflow.patch +Patch002: libtirpc-0.2.4-nonblocking-mode.patch + +# +# RHEL7.2 +# +Patch003: libtirpc-0.2.4-mem-leak.patch + +# +# RHEL7.3 +# +Patch004: libtirpc-0.2.4-debug.patch +Patch005: libtirpc-0.2.4-svc_vc_create-memleak.patch +Patch006: libtirpc-0.2.4-svc-gss-memleaks.patch +Patch007: libtirpc-0.2.4-clnt-mthr-create.patch + +# +# RHEL7.4 +# +Patch008: libtirpc-0.2.4-makefd_xprt-fd.patch +Patch009: libtirpc-0.2.4-CVE-2017-8779.patch + +# +# RHEL7.6 +Patch010: libtirpc-0.2.4-xdrstdio.patch +Patch011: libtirpc-0.2.4-covscan.patch + +%description +This package contains SunLib's implementation of transport-independent +RPC (TI-RPC) documentation. This library forms a piece of the base of +Open Network Computing (ONC), and is derived directly from the +Solaris 2.3 source. + +TI-RPC is an enhanced version of TS-RPC that requires the UNIX System V +Transport Layer Interface (TLI) or an equivalent X/Open Transport Interface +(XTI). TI-RPC is on-the-wire compatible with the TS-RPC, which is supported +by almost 70 vendors on all major operating systems. TS-RPC source code +(RPCSRC 4.0) remains available from several internet sites. + +%package devel +Summary: Development files for the libtirpc library +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +Requires: pkgconfig man-db + +%description devel +This package includes header files and libraries necessary for +developing programs which use the tirpc library. + + +%prep +%setup -q +# 1102765 - rpcbind segfaults in svc_vc_recv +%patch001 -p1 +# 1162714 - Non blocking mode for writes is broken +%patch002 -p1 +# 1236187 - Memory Leak in libtirpc +%patch003 -p1 +# 1273159 - Backport libtirpc's new debugging interface from upstream +%patch004 -p1 +# 1276685 - memory leak in svc_vc_create +%patch005 -p1 +# 1282488 - Address memory leaks in server-side GSS authenticator +%patch006 -p1 +# 1342545 - Threads specifically interacting with libtirpc library... +%patch007 -p1 +# 1410617 - makefd_xprt: remove obsolete check for fd number +%patch008 -p1 +# CVE-2017-8779 libtirpc: libtirpc, libntirpc: Memory leak.... +%patch009 -p1 +# 1261738 - xdrstdio_create buffers do not output encoded values on ppc +%patch010 -p1 +# 1627856 - Backport important issues found by covscan in... +%patch011 -p1 + +# Remove .orig files +find . -name "*.orig" | xargs rm -f + +%build +sh autogen.sh +autoreconf -fisv +%configure +make all + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}/etc +mkdir -p %{buildroot}%{_root_libdir} +mkdir -p %{buildroot}%{_libdir}/pkgconfig +make install DESTDIR=%{buildroot} \ + libdir=%{_root_libdir} pkgconfigdir=%{_libdir}/pkgconfig +# Don't package .a or .la files +rm -f %{buildroot}%{_root_libdir}/*.{a,la} + +# Creat the man diretory +mv %{buildroot}%{_mandir}/man3 %{buildroot}%{_mandir}/man3t + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%post devel +# Register the new man section +#if [ "$1" -eq 1 ]; then +# makewhatis -s 3t +#fi + +%postun devel +# Remove the existance of the man section +#makewhatis -s 3t + + +%clean +rm -rf %{buildroot} + +%files +%defattr(-,root,root) +%doc AUTHORS ChangeLog NEWS README +%{_root_libdir}/libtirpc.so.* +%config(noreplace)%{_sysconfdir}/netconfig + +%files devel +%defattr(0644,root,root,755) +%dir %{_includedir}/tirpc +%dir %{_includedir}/tirpc/rpc +%dir %{_includedir}/tirpc/rpcsvc +%{_root_libdir}/libtirpc.so +%{_libdir}/pkgconfig/libtirpc.pc +%{_includedir}/tirpc/netconfig.h +%{_includedir}/tirpc/rpc/auth.h +%{_includedir}/tirpc/rpc/auth_des.h +%{_includedir}/tirpc/rpc/auth_gss.h +%{_includedir}/tirpc/rpc/auth_kerb.h +%{_includedir}/tirpc/rpc/auth_unix.h +%{_includedir}/tirpc/rpc/clnt.h +%{_includedir}/tirpc/rpc/clnt_soc.h +%{_includedir}/tirpc/rpc/clnt_stat.h +%{_includedir}/tirpc/rpc/des.h +%{_includedir}/tirpc/rpc/des_crypt.h +%{_includedir}/tirpc/rpc/nettype.h +%{_includedir}/tirpc/rpc/pmap_clnt.h +%{_includedir}/tirpc/rpc/pmap_prot.h +%{_includedir}/tirpc/rpc/pmap_rmt.h +%{_includedir}/tirpc/rpc/raw.h +%{_includedir}/tirpc/rpc/rpc.h +%{_includedir}/tirpc/rpc/rpc_com.h +%{_includedir}/tirpc/rpc/rpc_msg.h +%{_includedir}/tirpc/rpc/rpcb_clnt.h +%{_includedir}/tirpc/rpc/rpcb_prot.h +%{_includedir}/tirpc/rpc/rpcb_prot.x +%{_includedir}/tirpc/rpc/rpcent.h +%{_includedir}/tirpc/rpc/svc.h +%{_includedir}/tirpc/rpc/svc_auth.h +%{_includedir}/tirpc/rpc/svc_dg.h +%{_includedir}/tirpc/rpc/svc_soc.h +%{_includedir}/tirpc/rpc/types.h +%{_includedir}/tirpc/rpc/xdr.h +%{_includedir}/tirpc/rpcsvc/crypt.h +%{_includedir}/tirpc/rpcsvc/crypt.x +%{_mandir}/*/* + +%changelog +* Wed Sep 19 2018 Steve Dickson 0.2.4-0.15 +- Fixed typo in spec file (bz 1627856) + +* Fri Sep 14 2018 Steve Dickson 0.2.4-0.14 +- Removed a false positive from the covscan (bz 1627856) + +* Tue Sep 11 2018 Steve Dickson 0.2.4-0.13 +- Fix issues found from covscan (bz 1627856) + +* Fri Jul 20 2018 Steve Dickson 0.2.4-0.12 +- xdrstdio_create buffers do not output encoded values on ppc (bz 1261738) + +* Tue Jul 10 2018 Steve Dickson 0.2.4-0.11 +- Updated the URL (bz 1583922) + +* Wed May 17 2017 Steve Dickson 0.2.4-0.10 +- Fix for CVE-2017-8779 (bz 1449463) + +* Sat Feb 25 2017 Steve Dickson 0.2.4-0.9 +- makefd_xprt: remove obsolete check for fd number (bz 1410617) + +* Mon Jun 6 2016 Steve Dickson 0.2.4-0.8 +- handle concurrent connect calls in clnt_vc_create() (bz 1342545) + +* Fri Apr 8 2016 Steve Dickson 0.2.4-0.7 +- Backported upstream debugging (bz 1273159) +- Fixed memory leak in svc_vc_create (bz 1276685) +- Fixed memory leaks in server-side GSS authenticator (bz 1282488) + +* Mon Jun 29 2015 Steve Dickson 0.2.4-0.6 +- Fixed a couple memory leaks (bz 1236187) + +* Sat Nov 15 2014 Steve Dickson 0.2.4-0.5 +- Fixed the non-blocking mode (bz 1162714) + +* Wed Sep 17 2014 Steve Dickson 0.2.4-0.4 +- Avoid buffer overruns svcauth_gss_validate() (bz 1102765) + +* Fri Jan 24 2014 Daniel Mach - 0.2.4-0.3 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 0.2.4-0.2 +- Mass rebuild 2013-12-27 + +* Fri Dec 13 2013 Steve Dickson 0.2.4-0.1 +- Update to latest upstream release: 0.2.4 (bz 1040593) + +* Wed Dec 11 2013 Steve Dickson 0.2.4-0 +- Update to latest upstream release: 0.2.4 (bz 1038736) + +* Tue Nov 26 2013 Steve Dickson 0.2.3-4 +- Update to latest RC release: libtirpc-0-2-4-rc3 (bz 1034434) + +* Tue Jul 2 2013 Steve Dickson 0.2.3-3 +- Update to latest RC release: libtirpc-0-2-4-rc2 (bz 959469) + +* Mon Apr 22 2013 Steve Dickson 0.2.3-2 +- Update to latest RC release: libtirpc-0-2-4-rc1 (bz 948378) + +* Thu Apr 11 2013 Guenther Deschner 0.2.3-1 +- Removed libgssglue dependency (patch from master) + +* Wed Feb 13 2013 Steve Dickson 0.2.3-0 +- Updated to latest upstream release: 0.2.3 + +* Tue Nov 13 2012 Steve Dickson 0.2.1-43 +- Updated to latest upstream RC release: 0.2.3-rc4 + +* Thu Jul 19 2012 Fedora Release Engineering - 0.2.2-42 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Thu Apr 26 2012 Steve Dickson 0.2.1-4.1 +- Updated to latest upstream RC release: libtirpc-0.2.3-rc3 + +* Mon Mar 19 2012 Steve Dickson 0.2.1-3.1 +- Fixed the install path in doc/Makefile.am + +* Fri Jan 13 2012 Fedora Release Engineering - 0.2.2-2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Jul 20 2011 Steve Dickson 0.2.1-1.1 +- Fixed segfault in SVCAUTH_WRAP call (bz 722594) + +* Tue Jun 21 2011 Steve Dickson 0.2.1-1 +- Updated to latest upstream version: 0.2.3-rc1 + +* Mon May 2 2011 Steve Dickson 0.2.1-0 +- Updated to latest upstream version: 0.2.2 + +* Tue Apr 12 2011 Karsten Hopp 0.2.1-7.1 +- replace Requires(devel) with a simple Requires as the new rpm + aborts otherwise with "Bad Requireflags: qualifiers: Requires(devel)" + +* Tue Feb 08 2011 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Thu Dec 2 2010 Steve Dickson 0.2.1-6 +- Moved the libraries from /usr/lib to /lib + +* Mon Aug 30 2010 Steve Dickson 0.2.1-5 +- Relicense these SISSL files to 3 clause BSD +- Fixed last remaining BSD license issues + +* Fri Jul 16 2010 Steve Dickson 0.2.1-4 +- Add back SISSL license attribution + +* Fri Jul 09 2010 Mike McGrath 0.2.1-3.1 +- Rebuild to fix broken man dep s/man/man-db/ + +* Tue May 18 2010 Steve Dickson 0.2.1-3 +- Updated to latest RC release: libtirpc-0-2-2-rc2 [bz 519430] + +* 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 + +* Sat Jul 25 2009 Fedora Release Engineering - 0.2.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Thu Jul 9 2009 Steve Dickson 0.2.0-3 +- Updated to latest upstream tag: 0-2-1-rc3 + Fixed the --disable-gss options + Fixed a number of warnings + Change how architectures are define in xdr_float.c + +* Mon Jun 29 2009 Steve Dickson 0.2.0-2 +- Updated to latest upstream tag: 0-2-1-rc2 + rpcb_clnt: RPC_PROGNOTREGISTERED is a permanent error + clnt_dg: Fix infinite loop when datagram call times ou + Updated .gitignore file + Replace the hard coded path name with the top_srcdir macrc + Added 'doc' to the SUBDIRS list so make install work correctly. + +* Fri May 29 2009 Steve Dickson 0.2.0-1 +- Updated to latest upstream version: 0.2.0 + +* Tue May 19 2009 Tom "spot" Callaway 0.1.11-3 +- Replace the Sun RPC license with the BSD license, with the explicit permission of Sun Microsystems + +* Mon Apr 20 2009 Steve Dickson 0.1.11-2 +- Updated to libtirpc-0.1.12-rc1 + +* Mon Apr 20 2009 Steve Dickson 0.1.11-1 +- Updated to the latest release: 0.1.11 + +* Fri Mar 13 2009 Steve Dickson 0.1.10-6 +- libtirpc: set r_netid and r_owner in __rpcb_findaddr_timed +- libtirpc: be sure to free cl_netid and cl_tp +- libtirpc: must free saved wire verifier when destroying context + +* Wed Feb 25 2009 Fedora Release Engineering - 0.1.10-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Wed Jan 28 2009 Steve Dickson 0.1.10-4 +- Converted all uids and uids to type uid_t and gid_t (sf 2446314) + +* Wed Jan 28 2009 Steve Dickson 0.1.10-3 +- backwards compatibility: fix order of fields in TI-RPC's + svc_req (bz 481388) +- Removed a number warnings. + +* Thu Jan 22 2009 Steve Dickson 0.1.10-2 +- Header file fixes for C++ + +* Thu Nov 20 2008 Steve Dickson 0.1.10-1 +- Updated to latest upstream version: 0.1.10 + +* Tue Oct 28 2008 Steve Dickson 0.1.9-7 +- Fixed some incorrect function declarations (bz468815) + +* Mon Oct 27 2008 Steve Dickson 0.1.9-6 +- Fix bad assumption taddr2uaddr processing that + caused a segfault (bz468014) + +* Tue Sep 16 2008 Steve Dickson 0.1.9-5 +- Fix for taddr2addr conversion bug of local addresses +- Fixed some of warnings in: src/auth_time.c, src/clnt_dg.c and + src/clnt_raw.c +- Added some #ifdef NOTUSED around some code in src/rpbc_clnt.c + that was not being used... + +* Thu Sep 4 2008 Steve Dickson 0.1.9-4 +- Always make IPv6 sockets V6ONLY +- Fix incorrect sizeof() in __rpc_getbroadifs + +* Thu Aug 7 2008 Tom "spot" Callaway 0.1.9-3 +- fix license tag + +* Tue Jul 8 2008 Steve Dickson 0.1.9-1 +- Update to latest upstream version 0.1.9 + +* Fri Jun 27 2008 Steve Dickson 0.1.8-2 +- Added super-H(sh3,4) architecture support (bz 446559) + +* Tue Jun 10 2008 Steve Dickson 0.1.8-1 +- Update to latest upstream version 0.1.8 + +* Wed Mar 12 2008 Steve Dickson 0.1.7-18 +- Install man pages in the 3t section + +* Tue Feb 19 2008 Fedora Release Engineering - 0.1.7-17 +- Autorebuild for GCC 4.3 + +* Mon Feb 18 2008 Steve Dickson 0.1.7-16 +- Added patch that creates a libtirpc.pc used by the + pkg-config command. + +* Thu Jan 24 2008 Steve Dickson 0.1.7-15 +- Protect from buffer overflow in the GSS code. (bz 362121) + +* Mon Dec 17 2007 Steve Dickson 0.1.7-14 +- Fixed typo in /etc/netconfig file (bz 414471) + +* Thu Oct 25 2007 Steve Dickson 0.1.7-13 +- Added a check for the ARM arch (bz 351071) + +* Wed Oct 17 2007 Steve Dickson 0.1.7-12 +- Switch the libgssapi dependency to libgssglue + +* Mon Oct 15 2007 Steve Dickson 0.1.7-11 +- Made tcp6/udp6 network ids no longer visible in the netconfig + file since the ipv6 code is not fully baked yet in rpcbind. (bz 249121) + +* Wed Aug 29 2007 Fedora Release Engineering - 0.1.7-10 +- Rebuild for selinux ppc32 issue. + +* Mon Jul 30 2007 0.1.7-9 +- Fixed mutex lock problem in clnt_raw_create() +- Ignore the return value of snprintf() and use strlen() instead + to bump the pointer in clnt_sperror() +- A couple ntohs() were needed in bindresvport_sa() +- Added IP_RECVERR processing with to clnt_dg_call() so + application will see errors instead of timing out +- Make sure remote address (xp_rtaddr) is populated + with the correct type of address. +- Change the order of network ids in /etc/netconfg + putting ipv4 ids before ipv6. +- Bumped up Release from 8 to 9. + +* Mon Jul 9 2007 0.1.7-7 +- Fixed infinite loop in svc_run() (bz 246677) + +* Thu Apr 26 2007 0.1.7-6 +- Fixed potential buffer overflow in xdr_strings +- Added a optimization to bindresvport that allows more + ports to be tried. + +* Mon Mar 26 2007 Steve Dickson 0.1.7-5 +- Fixed Unowned Directory RPM problem (bz 233873) + +* Mon Aug 28 2006 Steve Dickson 0.1.7-4 +- Fixed undefined symbol (bz 204296) + +* Mon Aug 14 2006 Steve Dickson 0.1.7-3 +- Added in svc_auth_none needed by the GSSAPI code. +- Added compile define for ppc64 archs + +* Fri Aug 11 2006 Steve Dickson 0.1.7-2 +- Uncommented tcp6 and udp6 in the default /etc/netconfig file. +- Added hooks to used the libgssapi library. + +* Fri Aug 4 2006 Steve Dickson 0.1.7-1 +- Initial commit