]> granicus.if.org Git - linux-pam/blobdiff - modules/pam_unix/pam_unix_passwd.c
Use TI-RPC functions if we compile and link against libtirpc.
[linux-pam] / modules / pam_unix / pam_unix_passwd.c
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");