From b39f54a4c27dac57064ba3b0d0ed10ef4523ea6f Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 03 2016 05:43:08 +0000 Subject: import libtirpc-0.2.4-0.8.el7 --- 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-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-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/SPECS/libtirpc.spec b/SPECS/libtirpc.spec index cdb7f85..19e47a9 100644 --- a/SPECS/libtirpc.spec +++ b/SPECS/libtirpc.spec @@ -2,7 +2,7 @@ Name: libtirpc Version: 0.2.4 -Release: 0.6%{?dist} +Release: 0.8%{?dist} Summary: Transport Independent RPC Library Group: System Environment/Libraries License: SISSL and BSD @@ -25,6 +25,14 @@ Patch002: libtirpc-0.2.4-nonblocking-mode.patch # 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 + %description This package contains SunLib's implementation of transport-independent RPC (TI-RPC) documentation. This library forms a piece of the base of @@ -56,6 +64,14 @@ developing programs which use the tirpc library. %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 # Remove .orig files find . -name "*.orig" | xargs rm -f @@ -144,6 +160,14 @@ rm -rf %{buildroot} %{_mandir}/*/* %changelog +* 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) @@ -305,7 +329,7 @@ rm -rf %{buildroot} * Thu Aug 7 2008 Tom "spot" Callaway 0.1.9-3 - fix license tag -* Tue Jul 9 2008 Steve Dickson 0.1.9-1 +* 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