]> granicus.if.org Git - linux-pam/commitdiff
Use TI-RPC functions if we compile and link against libtirpc.
authorThorsten Kukuk <kukuk@thkukuk.de>
Fri, 1 Apr 2016 13:28:09 +0000 (15:28 +0200)
committerThorsten Kukuk <kukuk@thkukuk.de>
Fri, 1 Apr 2016 13:28:09 +0000 (15:28 +0200)
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.

configure.ac
modules/pam_unix/pam_unix_passwd.c

index 534194d4d8116691a2235ca4d755c0d1cd5eb612..20f6ba355e22ed0de8b29ec644cea693d0de9d0a 100644 (file)
@@ -451,18 +451,21 @@ AC_ARG_ENABLE([nis],
 
 AS_IF([test "x$enable_nis" != "xno"], [
   old_CFLAGS=$CFLAGS
+  old_CPPFLAGS=$CPPFLAGS
   old_LIBS=$LIBS
 
   dnl if there's libtirpc available, prefer that over the system
   dnl implementation.
   PKG_CHECK_MODULES([TIRPC], [libtirpc], [
     CFLAGS="$CFLAGS $TIRPC_CFLAGS"
+    CPPFLAGS="$CPPFLAGS $TIRPC_CFLAGS"
     LIBS="$LIBS $TIRPC_LIBS"
   ], [:;])
 
   PKG_CHECK_MODULES([NSL], [libnsl], [],
     [AC_CHECK_LIB([nsl],[yp_match],[NSL_LIBS="-lnsl"],[NSL_LIBS=""])])
   CFLAGS="$CFLAGS $NSL_CFLAGS"
+  CPPFLAGS="$CPPFLAGS $NSL_CFLAGS"
   LIBS="$LIBS $NSL_LIBS"
 
   AC_CHECK_FUNCS([yp_get_default_domain yperr_string yp_master yp_bind yp_match yp_unbind])
@@ -475,6 +478,7 @@ AS_IF([test "x$enable_nis" != "xno"], [
   ])
 
   CFLAGS="$old_CFLAGS"
+  CPPFLAGS="$old_CPPFLAGS"
   LIBS="$old_LIBS"
 ])
 
index e3d320969c97a4675f2d6c81a5d52ef6926b4af3..fa2932780c4570ef390432fb597bd71374f8d557 100644 (file)
@@ -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");