From 549aef483c9f1852e1fbefabc4ebbbe72e00c243 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Fri, 1 Apr 2016 15:28:09 +0200 Subject: Use TI-RPC functions if we compile and link against libtirpc. The old SunRPC functions don't work with IPv6. * configure.ac: Set and restore CPPFLAGS * modules/pam_unix/pam_unix_passwd.c: Replace getrpcport with rpcb_getaddr if available. --- modules/pam_unix/pam_unix_passwd.c | 73 +++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index e3d32096..fa293278 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -92,7 +92,7 @@ # include "yppasswd.h" -# if !HAVE_DECL_GETRPCPORT +# if !HAVE_DECL_GETRPCPORT &&!HAVE_RPCB_GETADDR extern int getrpcport(const char *host, unsigned long prognum, unsigned long versnum, unsigned int proto); # endif /* GNU libc 2.1 */ @@ -114,11 +114,48 @@ extern int getrpcport(const char *host, unsigned long prognum, #define MAX_PASSWD_TRIES 3 #ifdef HAVE_NIS +#ifdef HAVE_RPCB_GETADDR +static unsigned short +__taddr2port (const struct netconfig *nconf, const struct netbuf *nbuf) +{ + unsigned short port = 0; + struct __rpc_sockinfo si; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + if (!__rpc_nconf2sockinfo(nconf, &si)) + return 0; + + switch (si.si_af) + { + case AF_INET: + sin = nbuf->buf; + port = sin->sin_port; + break; + case AF_INET6: + sin6 = nbuf->buf; + port = sin6->sin6_port; + break; + default: + break; + } + + return htons (port); +} +#endif + static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl) { char *master; char *domainname; int port, err; +#if defined(HAVE_RPCB_GETADDR) + struct netconfig *nconf; + struct netbuf svcaddr; + char addrbuf[INET6_ADDRSTRLEN]; + void *handle; + int found; +#endif + #ifdef HAVE_YP_GET_DEFAULT_DOMAIN if ((err = yp_get_default_domain(&domainname)) != 0) { @@ -146,7 +183,41 @@ static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl) yperr_string(err)); return NULL; } +#ifdef HAVE_RPCB_GETADDR + svcaddr.len = 0; + svcaddr.maxlen = sizeof (addrbuf); + svcaddr.buf = addrbuf; + port = 0; + found = 0; + + handle = setnetconfig(); + while ((nconf = getnetconfig(handle)) != NULL) { + if (!strcmp(nconf->nc_proto, "udp")) { + if (rpcb_getaddr(YPPASSWDPROG, YPPASSWDPROC_UPDATE, + nconf, &svcaddr, master)) { + port = __taddr2port (nconf, &svcaddr); + endnetconfig (handle); + found=1; + break; + } + + if (rpc_createerr.cf_stat != RPC_UNKNOWNHOST) { + clnt_pcreateerror (master); + pam_syslog (pamh, LOG_ERR, + "rpcb_getaddr (%s) failed!", master); + return NULL; + } + } + } + + if (!found) { + pam_syslog (pamh, LOG_ERR, + "Cannot find suitable transport for protocol 'udp'"); + return NULL; + } +#else port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP); +#endif if (port == 0) { pam_syslog(pamh, LOG_WARNING, "yppasswdd not running on NIS master host"); -- cgit v1.2.3