commit-inetutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Inetutils branch, master, updated. inetutils-1_9_1-118-g164de


From: Mats Erik Andersson
Subject: [SCM] GNU Inetutils branch, master, updated. inetutils-1_9_1-118-g164de7c
Date: Thu, 21 Jun 2012 19:17:40 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Inetutils ".

The branch, master has been updated
       via  164de7caca05f8920e45c5a9b81e7a3069536b86 (commit)
       via  4049b81b064d58eef082eb8baae21271b9f55d85 (commit)
       via  6890a2236f3aabd2642c9e19a6ada4d187d788d1 (commit)
       via  e8385098de6d9cd3b34a560b34938f2167dd556d (commit)
       via  a4390104731d33a746dd0e4243e75daeddfde8f1 (commit)
      from  f0e555181d3f58c28c815ceee1c95df7178c9f67 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=164de7caca05f8920e45c5a9b81e7a3069536b86


commit 164de7caca05f8920e45c5a9b81e7a3069536b86
Author: Mats Erik Andersson <address@hidden>
Date:   Tue Jun 19 23:10:17 2012 +0200

    rshd: Add PAM session code.

diff --git a/ChangeLog b/ChangeLog
index 7a8a6ba..c395d5b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2012-06-19  Mats Erik Andersson  <address@hidden>
+
+       rshd: PAM session handling.
+
+       * src/rshd.c: Include <sys/wait.h>.
+       (doit) <port != 0 && parent> [WITH_PAM]: Call
+       pam_close_session(), pam_setcred(), and pam_end().
+       (doit) <without port> [WITH_PAM]: Call fork().  Parent
+       waits for child and properly closes PAM session.
+       (doit) <child> [WITH_PAM]: Call pam_open_session().
+
 2012-06-18  Mats Erik Andersson  <address@hidden>
 
        * configure.ac (WITH_ORCMD_AF, WITH_ORCMD, WITH_RCMD_AF)
diff --git a/src/rshd.c b/src/rshd.c
index 015bf8b..0979421 100644
--- a/src/rshd.c
+++ b/src/rshd.c
@@ -54,15 +54,35 @@
  *
  * Sample settings:
  *
- * auth      required    pam_rhosts.so
- * # auth      required    pam_rhosts_auth.so
- * auth      required    pam_nologin.so
- * # auth      required    pam_env.so
- * # auth      required    pam_group.so
+ *   GNU/Linux, et cetera:
  *
+ * auth      required    pam_nologin.so
+ * auth      required    pam_rhosts.so
+ * auth      required    pam_env.so
+ * auth      required    pam_group.so
+ * account   required    pam_nologin.so
  * account   required    pam_unix.so
- * # account   required    pam_unix_account.so
+ * session   required    pam_unix.so
+ * session   required    pam_lastlog.so silent
+ * password  required    pam_deny.so
+ *
+ *   OpenSolaris:
+ *
+ * auth      required    pam_rhosts_auth.so
+ * auth      required    pam_unix_cred.so
+ * account   required    pam_roles.so
+ * account   required    pam_unix_account.so
+ * session   required    pam_unix_session.so
+ * password  required    pam_deny.so
  *
+ *   BSD:
+ *
+ * auth      required    pam_nologin.so     # NetBSD
+ * auth      required    pam_rhosts.so
+ * account   required    pam_nologin.so     # FreeBSD
+ * account   required    pam_unix.so
+ * session   required    pam_lastlog.so
+ * password  required    pam_deny.so
  */
 
 /*
@@ -110,6 +130,7 @@
 #include <unistd.h>
 #include <grp.h>
 #include <sys/select.h>
+#include <sys/wait.h>
 #include <error.h>
 #include <progname.h>
 #include <argp.h>
@@ -1102,8 +1123,8 @@ doit (int sockfd, struct sockaddr_in *fromp, socklen_t 
fromlen)
 
   if (port)
     {
-      /* We nee a secondary channel,  Here's where we create
-       * the control process that'll handle this secondary
+      /* We need a secondary channel.  Here is where we create
+       * the control process that will handle this secondary
        * channel.
        * First create a pipe to use for communication between
        * the parent and child, then fork.
@@ -1314,6 +1335,20 @@ doit (int sockfd, struct sockaddr_in *fromp, socklen_t 
fromlen)
           * terminates.  The socket will terminate when the
           * client process terminates.
           */
+#ifdef WITH_PAM
+         /* The child opened the session; now it
+          * should be closed down properly.  */
+         pam_rc = pam_close_session (pam_handle, PAM_SILENT);
+         if (pam_rc != PAM_SUCCESS)
+           syslog (LOG_WARNING | LOG_AUTH, "pam_close_session: %s",
+                   pam_strerror (pam_handle, pam_rc));
+         pam_rc = pam_setcred (pam_handle, PAM_SILENT | PAM_DELETE_CRED);
+         if (pam_rc != PAM_SUCCESS)
+           syslog (LOG_WARNING | LOG_AUTH, "pam_setcred: %s",
+                   pam_strerror (pam_handle, pam_rc));
+         pam_end (pam_handle, pam_rc);
+#endif /* WITH_PAM */
+
          exit (EXIT_SUCCESS);
        }
 
@@ -1365,6 +1400,40 @@ doit (int sockfd, struct sockaddr_in *fromp, socklen_t 
fromlen)
                                           pipe to control process */
       close (pv[1]);
     }
+#ifdef WITH_PAM
+    /* Session handling must end also in this case.  */
+  else
+    {
+      pid = fork ();
+      if (pid < 0)
+       {
+         rshd_error ("Can't fork; try again.\n");
+         exit (EXIT_FAILURE);
+       }
+      if (pid)
+       {
+         /* Parent: Wait for child and tear down
+          * the PAM session.  */
+         int status;
+
+         while (wait (&status) < 0 && errno == EINTR)
+           ;
+
+         pam_rc = pam_close_session (pam_handle, PAM_SILENT);
+         if (pam_rc != PAM_SUCCESS)
+           syslog (LOG_WARNING | LOG_AUTH, "pam_close_session: %s",
+                   pam_strerror (pam_handle, pam_rc));
+         pam_rc = pam_setcred (pam_handle, PAM_SILENT | PAM_DELETE_CRED);
+         if (pam_rc != PAM_SUCCESS)
+           syslog (LOG_WARNING | LOG_AUTH, "pam_setcred: %s",
+                   pam_strerror (pam_handle, pam_rc));
+         pam_end (pam_handle, pam_rc);
+
+         exit (WIFEXITED (status) ? WEXITSTATUS (status) : EXIT_FAILURE);
+       }
+    }
+#endif /* WITH_PAM */
+
   if (*pwd->pw_shell == '\0')
     pwd->pw_shell = PATH_BSHELL;
 #if BSD > 43
@@ -1387,6 +1456,13 @@ doit (int sockfd, struct sockaddr_in *fromp, socklen_t 
fromlen)
              pam_strerror (pam_handle, pam_rc));
       pam_rc = PAM_SUCCESS;    /* Only report the above anomaly.  */
     }
+  pam_rc = pam_open_session (pam_handle, PAM_SILENT);
+  if (pam_rc != PAM_SUCCESS)
+    {
+      syslog (LOG_ERR | LOG_AUTH, "pam_open_session: %s",
+             pam_strerror (pam_handle, pam_rc));
+      pam_rc = PAM_SUCCESS;    /* Only report the above anomaly.  */
+    }
 #endif /* WITH_PAM */
 
   setuid ((uid_t) pwd->pw_uid);

http://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=4049b81b064d58eef082eb8baae21271b9f55d85


commit 4049b81b064d58eef082eb8baae21271b9f55d85
Author: Mats Erik Andersson <address@hidden>
Date:   Mon Jun 18 23:32:46 2012 +0200

    rcp, rsh, rshd: Alternate r-calls.
    
    Prefer address independent rcmd_af(), et cetera.

diff --git a/ChangeLog b/ChangeLog
index 182faf8..7a8a6ba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2012-06-18  Mats Erik Andersson  <address@hidden>
 
+       * configure.ac (WITH_ORCMD_AF, WITH_ORCMD, WITH_RCMD_AF)
+       (WITH_RRESVPORT_AF, WITH_IRUSEROK_AF, WITH_IRUSEROK_SA)
+       (WITH_RUSEROK_AF): New macros.
+       * src/rcp.c (toremote, tolocal, kerberos)
+       [WITH_ORCMD_AF || WITH_RCMD_AF || WITH_ORCMD]:
+       Replace rcmd() by orcmd_af(), rcmd_af(), or orcmd().
+       * src/rsh.c (main)
+       [WITH_ORCMD_AF || WITH_RCMD_AF || WITH_ORCMD]: Likewise.
+       * src/rshd.c (doit) [WITH_RRESVPORT_AF]: Use rresvport_af()
+       instead of rresvport().
+       [WITH_IRUSEROK_SA || WITH_IRUSEROK_AF]: Replace iruserok()
+       with iruserok_sa() or iruserok_af().
+       [WITH_RUSEROK_AF]: Use ruserok_af(), not ruserok().
+
+2012-06-18  Mats Erik Andersson  <address@hidden>
+
        * src/rshd.c (doit): New signature
        `(int, struct sockaddr_in *, socklen_t)'.
        (main): Pass FROMLEN to doit().
diff --git a/configure.ac b/configure.ac
index eaa68dd..376a063 100644
--- a/configure.ac
+++ b/configure.ac
@@ -232,17 +232,54 @@ else
   talk_BUILD=''
 fi
 
+# NetBSD offers orcmd() and orcmd_af() for getting
+# exactly the functionality that rcmd() and rcmd_af()
+# offer on all other targetted systems.
+AC_CHECK_FUNC(rcmd_af, , , [#include <netdb.h>])
+if test "$ac_cv_func_rcmd_af" = yes; then
+  AC_DEFINE([WITH_RCMD_AF], 1, [Define to one if you can use rcmd_af.])
+fi
+AC_CHECK_FUNC(orcmd, , , [#include <unistd.h>])
+if test "$ac_cv_func_orcmd" = yes; then
+  AC_DEFINE([WITH_ORCMD], 1, [Define to one if you can use orcmd.])
+fi
+AC_CHECK_FUNC(orcmd_af, , , [#include <unistd.h>])
+if test "$ac_cv_func_orcmd_af" = yes; then
+  AC_DEFINE([WITH_ORCMD_AF], 1, [Define to one if you can use orcmd_af.])
+fi
+AC_CHECK_FUNC(rresvport_af, , , [#include <netdb.h>])
+if test "$ac_cv_func_rresvport_af" = yes; then
+  AC_DEFINE([WITH_RRESVPORT_AF], 1,
+           [Define to one if you can use rresvport_af.])
+fi
+
 # FIXME: Presently rshd and rlogind prefer iruserok(3), which is not
 # universally available.  Replacement code?  A fallback is being built
-# from ruserok(3) and inet_ntoa(3).
+# from ruserok(3) and inet_ntoa(3).  Calls using iruserok/rusersok are
+# used for non-PAM configured executables rshd/rlogind.
 AC_CHECK_FUNC(iruserok, , , [#include <netdb.h>])
+AC_CHECK_FUNC(iruserok_af, , , [#include <netdb.h>])
+AC_CHECK_FUNC(iruserok_sa, , , [#include <netdb.h>])
 AC_CHECK_FUNC(ruserok, , , [#include <netdb.h>])
+AC_CHECK_FUNC(ruserok_af, , , [#include <netdb.h>])
 if test "$ac_cv_func_iruserok" = yes; then
   AC_DEFINE([WITH_IRUSEROK], 1, [Define to one if you can use iruserok.])
+  if test "$ac_cv_func_iruserok_af" = yes; then
+    AC_DEFINE([WITH_IRUSEROK_AF], 1,
+             [Define to one if you can use iruserok_af.])
+  fi
+  if test "$ac_cv_func_iruserok_sa" = yes; then
+    AC_DEFINE([WITH_IRUSEROK_SA], 1,
+             [Define to one if you can use iruserok_sa.])
+  fi
 else
   if test "$ac_cv_func_ruserok" = yes; then
     AC_DEFINE([WITH_RUSEROK], 1, [Define to one if you can use ruserok.])
     AC_MSG_WARN([iruserok is not available, falling back to ruserok.])
+    if test "$ac_cv_func_ruserok_af" = yes; then
+      AC_DEFINE([WITH_RUSEROK_AF], 1,
+               [Define to on if you can use ruserok_af.])
+    fi
   else
     AC_MSG_WARN([Disabling rlogind and rshd, since no iruserok and no 
ruserok.])
     enable_rlogind=no
diff --git a/src/rcp.c b/src/rcp.c
index 3907c53..0f8c114 100644
--- a/src/rcp.c
+++ b/src/rcp.c
@@ -429,8 +429,21 @@ toremote (char *targ, int argc, char *argv[])
                                tuser ? tuser : pwd->pw_name);
              else
 #endif
+#ifdef WITH_ORCMD_AF
+               rem = orcmd_af (&host, port, pwd->pw_name,
+                               tuser ? tuser : pwd->pw_name,
+                               bp, 0, AF_INET);
+#elif defined WITH_RCMD_AF
+               rem = rcmd_af (&host, port, pwd->pw_name,
+                              tuser ? tuser : pwd->pw_name,
+                              bp, 0, AF_INET);
+#elif defined WITH_ORCMD
+               rem = orcmd (&host, port, pwd->pw_name,
+                            tuser ? tuser : pwd->pw_name, bp, 0);
+#else /* !WITH_ORCMD_AF && !WITH_RCMD_AF && !WITH_ORCMD */
                rem = rcmd (&host, port, pwd->pw_name,
                            tuser ? tuser : pwd->pw_name, bp, 0);
+#endif
              if (rem < 0)
                exit (EXIT_FAILURE);
 #if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT
@@ -495,7 +508,15 @@ tolocal (int argc, char *argv[])
 #ifdef KERBEROS
        use_kerberos ? kerberos (&host, bp, pwd->pw_name, suser) :
 #endif
+#ifdef WITH_ORCMD_AF
+       orcmd_af (&host, port, pwd->pw_name, suser, bp, 0, AF_INET);
+#elif defined WITH_RCMD_AF
+       rcmd_af (&host, port, pwd->pw_name, suser, bp, 0, AF_INET);
+#elif defined WITH_ORCMD
+       orcmd (&host, port, pwd->pw_name, suser, bp, 0);
+#else /* !WITH_ORCMD_AF && !WITH_RCMD_AF && !WITH_ORCMD */
        rcmd (&host, port, pwd->pw_name, suser, bp, 0);
+#endif
       free (bp);
       if (rem < 0)
        {
@@ -1042,7 +1063,15 @@ again:
       if (doencrypt)
        error (EXIT_FAILURE, 0, "the -x option requires Kerberos 
authentication");
 # endif
+#ifdef WITH_ORCMD_AF
+      rem = orcmd_af (host, port, locuser, user, bp, 0, AF_INET);
+#elif defined WITH_RCMD_AF
+      rem = rcmd_af (host, port, locuser, user, bp, 0, AF_INET);
+#elif defined WITH_ORCMD
+      rem = orcmd (host, port, locuser, user, bp, 0);
+#else /* !WITH_ORCMD_AF && !WITH_RCMD_AF && !WITH_ORCMD */
       rem = rcmd (host, port, locuser, user, bp, 0);
+#endif
     }
   return rem;
 }
diff --git a/src/rsh.c b/src/rsh.c
index d7d164a..da3306f 100644
--- a/src/rsh.c
+++ b/src/rsh.c
@@ -445,13 +445,29 @@ try_connect:
        user = pw->pw_name;
       if (doencrypt)
        error (EXIT_FAILURE, 0, "the -x flag requires Kerberos authentication");
+# ifdef WITH_ORCMD_AF
+      rem = orcmd_af (&host, sp->s_port, pw->pw_name, user, args, &rfd2, 
AF_INET);
+# elif defined WITH_RCMD_AF
+      rem = rcmd_af (&host, sp->s_port, pw->pw_name, user, args, &rfd2, 
AF_INET);
+# elif defined WITH_ORCMD
+      rem = orcmd (&host, sp->s_port, pw->pw_name, user, args, &rfd2);
+# else /* !WITH_ORCMD_AF && !WITH_RCMD_AF && !WITH_ORCMD */
       rem = rcmd (&host, sp->s_port, pw->pw_name, user, args, &rfd2);
+# endif
     }
-#else
+#else /* !KERBEROS && !SHISHI */
   if (!user)
     user = pw->pw_name;
+# ifdef WITH_ORCMD_AF
+  rem = orcmd_af (&host, sp->s_port, pw->pw_name, user, args, &rfd2, AF_INET);
+# elif defined WITH_RCMD_AF
+  rem = rcmd_af (&host, sp->s_port, pw->pw_name, user, args, &rfd2, AF_INET);
+# elif defined WITH_ORCMD
+  rem = orcmd (&host, sp->s_port, pw->pw_name, user, args, &rfd2);
+# else /* !WITH_ORCMD_AF && !WITH_RCMD_AF && !WITH_ORCMD */
   rem = rcmd (&host, sp->s_port, pw->pw_name, user, args, &rfd2);
-#endif
+# endif
+#endif /* !KERBEROS && !SHISHI */
 
   if (rem < 0)
     exit (EXIT_FAILURE);
diff --git a/src/rshd.c b/src/rshd.c
index 131b3b2..015bf8b 100644
--- a/src/rshd.c
+++ b/src/rshd.c
@@ -553,7 +553,11 @@ doit (int sockfd, struct sockaddr_in *fromp, socklen_t 
fromlen)
        * to it, plus.
        */
       int lport = IPPORT_RESERVED - 1;
+#ifdef WITH_RRESVPORT_AF
+      s = rresvport_af (&lport, fromp->sin_family);
+#else
       s = rresvport (&lport);
+#endif
       if (s < 0)
        {
          syslog (LOG_ERR, "can't get stderr port: %m");
@@ -1021,17 +1025,29 @@ doit (int sockfd, struct sockaddr_in *fromp, socklen_t 
fromlen)
 #endif /* KERBEROS || SHISHI */
 
 #ifndef WITH_PAM
-# ifdef WITH_IRUSEROK
+# ifdef WITH_IRUSEROK_SA
+    if (errorstr || (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0'
+                     && (iruserok_sa ((void *) fromp, fromlen,
+                                     pwd->pw_uid == 0, remuser, locuser)) < 0))
+# elif defined WITH_IRUSEROK_AF
+    if (errorstr || (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0'
+                     && (iruserok_af (&fromp->sin_addr, pwd->pw_uid == 0,
+                                   remuser, locuser, fromp->sin_family)) < 0))
+# elif defined WITH_IRUSEROK
     if (errorstr || (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0'
                      && (iruserok (fromp->sin_addr.s_addr, pwd->pw_uid == 0,
                                    remuser, locuser)) < 0))
+# elif defined WITH_RUSEROK_AF
+    if (errorstr || (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0'
+                     && (ruserok_af (addrstr, pwd->pw_uid == 0,
+                                 remuser, locuser, fromp->sin_family)) < 0))
 # elif defined WITH_RUSEROK
     if (errorstr || (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0'
                      && (ruserok (addrstr, pwd->pw_uid == 0,
                                  remuser, locuser)) < 0))
-# else /* !WITH_IRUSEROK && !WITH_RUSEROK */
+# else /* !WITH_IRUSEROK* && !WITH_RUSEROK* */
 # error Unable to use mandatory iruserok/ruserok.  This should not happen.
-# endif /* !WITH_IRUSEROK && !WITH_RUSEROK */
+# endif /* !WITH_IRUSEROK* && !WITH_RUSEROK* */
 #else /* WITH_PAM */
     if (0)     /* Wrapper for `fail' jump label.  */
 #endif /* !WITH_PAM */

http://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=6890a2236f3aabd2642c9e19a6ada4d187d788d1


commit 6890a2236f3aabd2642c9e19a6ada4d187d788d1
Author: Mats Erik Andersson <address@hidden>
Date:   Mon Jun 18 23:29:21 2012 +0200

    rshd: Host resolver changes.
    
    Prefer resolver code based on getnameinfo()
    and getaddrinfo(), aiming at address indep.

diff --git a/ChangeLog b/ChangeLog
index 6d7b897..182faf8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2012-06-18  Mats Erik Andersson  <address@hidden>
+
+       * src/rshd.c (doit): New signature
+       `(int, struct sockaddr_in *, socklen_t)'.
+       (main): Pass FROMLEN to doit().
+       (doit): New variables INPORT, RC, PORTSTR, ADDRSTR.
+       (doit) [HAVE_DECL_GETNAMEINFO]: New variable ADDRNAME.
+       (doit): Put numeric info in ADDRSTR, INPORT, PORTSTR
+       early on, later replacing multiple inet_ntoa().  Do not
+       overwrite `fromp->sin_port', but use INPORT, PORTSTR.
+       Prefer using getnameinfo().
+       (doit) <address verification> [HAVE_DECL_GETNAMEINFO]:
+       New alternate code.
+
 2012-06-15  Mats Erik Andersson  <address@hidden>
 
        rshd: Duplicate static memory results.  Consistently
diff --git a/src/rshd.c b/src/rshd.c
index 35e4b37..131b3b2 100644
--- a/src/rshd.c
+++ b/src/rshd.c
@@ -142,7 +142,7 @@ int check_all;
 int log_success;               /* If TRUE, log all successful accesses */
 int sent_null;
 
-void doit (int, struct sockaddr_in *);
+void doit (int, struct sockaddr_in *, socklen_t);
 void rshd_error (const char *, ...);
 char *getstr (const char *);
 int local_domain (const char *);
@@ -333,7 +333,7 @@ main (int argc, char *argv[])
   if (setsockopt (sockfd, SOL_SOCKET, SO_LINGER, (char *) &linger,
                  sizeof linger) < 0)
     syslog (LOG_WARNING, "setsockopt (SO_LINGER): %m");
-  doit (sockfd, &from);
+  doit (sockfd, &from, fromlen);
   return 0;
 }
 
@@ -350,7 +350,7 @@ char *envinit[] = { homedir, shell, path, logname, 
username, rhost, NULL };
 extern char **environ;
 
 void
-doit (int sockfd, struct sockaddr_in *fromp)
+doit (int sockfd, struct sockaddr_in *fromp, socklen_t fromlen)
 {
 #ifdef HAVE___RCMD_ERRSTR
   extern char *__rcmd_errstr;  /* syslog hook from libc/net/rcmd.c. */
@@ -363,10 +363,14 @@ doit (int sockfd, struct sockaddr_in *fromp)
 #else /* !HAVE_GETPWNAM_R */
   struct passwd *pwd;
 #endif
-  unsigned short port;
+  unsigned short port, inport;
   fd_set ready, readfrom;
   int cc, nfd, pv[2], pid, s = sockfd;
-  int one = 1;
+  int rc, one = 1;
+  char portstr[8], addrstr[INET6_ADDRSTRLEN];
+#ifdef HAVE_DECL_GETNAMEINFO
+  char addrname[NI_MAXHOST];
+#endif
   const char *hostname, *errorstr, *errorhost = NULL;
   char *cp, sig, buf[BUFSIZ];
   char *cmdbuf, *locuser, *remuser;
@@ -376,7 +380,6 @@ doit (int sockfd, struct sockaddr_in *fromp)
   KTEXT ticket = (KTEXT) NULL;
   char instance[INST_SZ], version[VERSION_SIZE];
   struct sockaddr_in fromaddr;
-  int rc;
   long authopts;
   int pv1[2], pv2[2];
   fd_set wready, writeto;
@@ -412,6 +415,24 @@ doit (int sockfd, struct sockaddr_in *fromp)
       }
   }
 #endif
+
+#ifdef HAVE_DECL_GETNAMEINFO
+  rc = getnameinfo ((struct sockaddr *) fromp, fromlen,
+                   addrstr, sizeof (addrstr),
+                   portstr, sizeof (portstr),
+                   NI_NUMERICHOST | NI_NUMERICSERV);
+  if (rc != 0)
+    {
+      syslog (LOG_WARNING, "getnameinfo: %s", gai_strerror (rc));
+      exit (EXIT_FAILURE);
+    }
+  inport = atoi (portstr);
+#else /* !HAVE_DECL_GETNAMEINFO */
+  strncpy (addrstr, inet_ntoa (fromp->sin_addr), sizeof (addrstr));
+  inport = ntohs (fromp->sin_port);
+  snprintf (portstr, sizeof (portstr), "%u", inport);
+#endif
+
   /* Verify that the client's address is an Internet adress. */
   if (fromp->sin_family != AF_INET)
     {
@@ -451,7 +472,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
                 */
                syslog (LOG_NOTICE,
                        "Discarding connection from %s with set source routing",
-                       inet_ntoa (fromp->sin_addr));
+                       addrstr);
                exit (EXIT_FAILURE);
              }
            if (*cp == IPOPT_EOL)
@@ -472,7 +493,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
         * Make a report about them, erase them, and continue.  */
        syslog (LOG_NOTICE,
                "Connection received from %s using IP options (erased):%s",
-               inet_ntoa (fromp->sin_addr), lbuf);
+               addrstr, lbuf);
 
        /* Turn off the options.  If this doesn't work, we quit.  */
        if (setsockopt (sockfd, ipproto, IP_OPTIONS,
@@ -485,18 +506,15 @@ doit (int sockfd, struct sockaddr_in *fromp)
   }
 #endif
 
-  /* Need host byte ordered port# to compare */
-  fromp->sin_port = ntohs ((unsigned short) fromp->sin_port);
   /* Verify that the client's address was bound to a reserved port */
 #if defined KERBEROS || defined SHISHI
   if (!use_kerberos)
 #endif
-    if (fromp->sin_port >= IPPORT_RESERVED
-       || fromp->sin_port < IPPORT_RESERVED / 2)
+    if (inport >= IPPORT_RESERVED || inport < IPPORT_RESERVED / 2)
       {
        syslog (LOG_NOTICE | LOG_AUTH,
-               "Connection from %s on illegal port %u",
-               inet_ntoa (fromp->sin_addr), fromp->sin_port);
+               "Connection from %s on illegal port %s",
+               addrstr, portstr);
        exit (EXIT_FAILURE);
       }
 
@@ -555,7 +573,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
        * as secondary port by the client.
        */
       fromp->sin_port = htons (port);
-      if (connect (s, (struct sockaddr *) fromp, sizeof (*fromp)) < 0)
+      if (connect (s, (struct sockaddr *) fromp, fromlen) < 0)
        {
          syslog (LOG_INFO, "connect second port %d: %m", port);
          exit (EXIT_FAILURE);
@@ -582,6 +600,61 @@ doit (int sockfd, struct sockaddr_in *fromp)
    * used for the authentication below.
    */
   errorstr = NULL;
+#ifdef HAVE_DECL_GETNAMEINFO
+  rc = getnameinfo ((struct sockaddr *) fromp, fromlen,
+                   addrname, sizeof (addrname), NULL, 0, 0);
+  if (rc == 0)
+    {
+      hostname = addrname;
+# if defined KERBEROS || defined SHISHI
+      if (!use_kerberos)
+# endif
+       if (check_all || local_domain (addrname))
+         {
+           struct addrinfo hints, *ai, *res;
+
+           errorhost = addrname;
+           memset (&hints, 0, sizeof (hints));
+           hints.ai_family = fromp->sin_family;
+           hints.ai_socktype = SOCK_STREAM;
+
+           rc = getaddrinfo (hostname, NULL, &hints, &res);
+           if (rc != 0)
+             {
+               syslog (LOG_INFO, "Could not resolve address for %s",
+                       hostname);
+               errorstr = "Could not resolve address for your host (%s)\n";
+               hostname = addrstr;
+             }
+           else
+             {
+               for (ai = res; ai; ai = ai->ai_next)
+                 {
+                   char astr[INET6_ADDRSTRLEN] = "";
+
+                   if (getnameinfo (ai->ai_addr, ai->ai_addrlen,
+                                    astr, sizeof (astr),
+                                    NULL, 0, NI_NUMERICHOST))
+                     continue;
+                   if (!strcmp (addrstr, astr))
+                     {
+                       hostname = addrname;
+                       break;  /* equal, OK */
+                     }
+                 }
+               freeaddrinfo (res);
+               if (ai == NULL)
+                 {
+                   syslog (LOG_NOTICE,
+                           "Host addr %s not listed for host %s",
+                           addrstr, hostname);
+                   errorstr = "Host address mismatch for %s\n";
+                   hostname = addrstr;
+                 }
+             }
+         }
+    }
+#else /* !HAVE_DECL_GETNAMEINFO */
   hp = gethostbyaddr ((char *) &fromp->sin_addr, sizeof (struct in_addr),
                      fromp->sin_family);
   if (hp)
@@ -593,9 +666,9 @@ doit (int sockfd, struct sockaddr_in *fromp)
        * address corresponds to the name.
        */
       hostname = strdup (hp->h_name);
-#if defined KERBEROS || defined SHISHI
+# if defined KERBEROS || defined SHISHI
       if (!use_kerberos)
-#endif
+# endif
        if (check_all || local_domain (hp->h_name))
          {
            char *remotehost = alloca (strlen (hostname) + 1);
@@ -612,7 +685,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
                            "Couldn't look up address for %s", remotehost);
                    errorstr =
                      "Couldn't look up address for your host (%s)\n";
-                   hostname = strdup (inet_ntoa (fromp->sin_addr));
+                   hostname = addrstr;
                  }
                else
                  for (;; hp->h_addr_list++)
@@ -621,9 +694,9 @@ doit (int sockfd, struct sockaddr_in *fromp)
                        {
                          syslog (LOG_NOTICE,
                                  "Host addr %s not listed for host %s",
-                                 inet_ntoa (fromp->sin_addr), hp->h_name);
+                                 addrstr, hp->h_name);
                          errorstr = "Host address mismatch for %s\n";
-                         hostname = strdup (inet_ntoa (fromp->sin_addr));
+                         hostname = addrstr;
                          break;
                        }
                      if (!memcmp (hp->h_addr_list[0],
@@ -637,8 +710,9 @@ doit (int sockfd, struct sockaddr_in *fromp)
              }
          }
     }
+#endif /* !HAVE_DECL_GETNAMEINFO */
   else
-    errorhost = hostname = strdup (inet_ntoa (fromp->sin_addr));
+    errorhost = hostname = addrstr;
 
 #ifdef KERBEROS
   if (use_kerberos)
@@ -953,8 +1027,8 @@ doit (int sockfd, struct sockaddr_in *fromp)
                                    remuser, locuser)) < 0))
 # elif defined WITH_RUSEROK
     if (errorstr || (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0'
-                     && (ruserok (inet_ntoa (fromp->sin_addr),
-                                 pwd->pw_uid == 0, remuser, locuser)) < 0))
+                     && (ruserok (addrstr, pwd->pw_uid == 0,
+                                 remuser, locuser)) < 0))
 # else /* !WITH_IRUSEROK && !WITH_RUSEROK */
 # error Unable to use mandatory iruserok/ruserok.  This should not happen.
 # endif /* !WITH_IRUSEROK && !WITH_RUSEROK */

http://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=e8385098de6d9cd3b34a560b34938f2167dd556d


commit e8385098de6d9cd3b34a560b34938f2167dd556d
Author: Mats Erik Andersson <address@hidden>
Date:   Fri Jun 15 12:07:33 2012 +0200

    rshd: Support PAM.

diff --git a/ChangeLog b/ChangeLog
index fae35bf..6d7b897 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,39 @@
 2012-06-15  Mats Erik Andersson  <address@hidden>
 
+       rshd: Duplicate static memory results.  Consistently
+       needed on systems running DragonFlyBSD.
+
+       * src/rshd.c (doit): When assigning HOSTNAME, apply
+       strdup() to results of inet_ntoa() and `hp->h_name'
+       in order to avoid loss of its contents later on.
+
+       rshd: Implement PAM support.
+
+       * src/Makefile.am (rshd_LDADD): Add also $(LIBPAM).
+       * src/rshd.c [HAVE_SECURITY_PAM_APPL_H]: Include
+       <security/pam_appl.h>.
+       (pam_rc, pam_handle, pam_conv) [WITH_PAM]: New variables.
+       (rsh_conv) [WITH_PAM]: New function.
+       (iruserok) [!WITH_PAM && __GLIBC__ && WITH_IRUSEROK]:
+       Set prototype only in absence of WITH_PAM.
+       (doc) [WITH_PAM]: Expand string content.
+       (username, logname, homedir, shell, path): Increase lengths,
+       including a preamble like `SHELL='.
+       (rhost): New variable used for environment variable RHOST.
+       (envinit) [!WITH_PAM]: Use only in absence of PAM support.
+       (doit) [WITH_PAM]: New code.
+       [!WITH_PAM && WITH_IRUSEROK]: Call iruserok() only in
+       absence of PAM.
+       [!WITH_PAM && !WITH_IRUSEROK && WITH_RUSEROK]: Likewise
+       for ruserok().
+       (doit) <fail label> [WITH_PAM]: Report errors via syslog.
+       (doit): Replace numerical offset by key string size when
+       setting `homedir', `path', `shell', and `username'.
+       Really assign a value to `logname', for portability.
+       (doit) <failed execl>: Report to syslog.
+
+2012-06-15  Mats Erik Andersson  <address@hidden>
+
        * src/rshd.c (doit) [HAVE_GETPWNAM_R]: New variables
        PWBUF, PWBUFLEN, PWSTOR, and RET.  Call getpwnam_r(),
        checking both `ret' and `pwd == NULL' for failure.
diff --git a/src/Makefile.am b/src/Makefile.am
index 75d5e6c..c108668 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -84,7 +84,7 @@ EXTRA_PROGRAMS += rlogind
 
 inetdaemon_PROGRAMS += $(rshd_BUILD)
 rshd_SOURCES = rshd.c
-rshd_LDADD = $(LDADD) $(LIBAUTH)
+rshd_LDADD = $(LDADD) $(LIBAUTH) $(LIBPAM)
 EXTRA_PROGRAMS += rshd
 
 inetdaemon_PROGRAMS += $(syslogd_BUILD)
diff --git a/src/rshd.c b/src/rshd.c
index a65c812..35e4b37 100644
--- a/src/rshd.c
+++ b/src/rshd.c
@@ -48,6 +48,24 @@
  */
 
 /*
+ * PAM implementation by Mats Erik Andersson.
+ *
+ * TODO: Check cooperation between PAM and Shishi/Kerberos.
+ *
+ * Sample settings:
+ *
+ * auth      required    pam_rhosts.so
+ * # auth      required    pam_rhosts_auth.so
+ * auth      required    pam_nologin.so
+ * # auth      required    pam_env.so
+ * # auth      required    pam_group.so
+ *
+ * account   required    pam_unix.so
+ * # account   required    pam_unix_account.so
+ *
+ */
+
+/*
  * remote shell server exchange protocol:
  *     [port]\0
  *     remuser\0
@@ -98,6 +116,9 @@
 #include <libinetutils.h>
 #include "xalloc.h"
 
+#ifdef HAVE_SECURITY_PAM_APPL_H
+# include <security/pam_appl.h>
+#endif
 #ifdef KERBEROS
 # ifdef HAVE_KERBEROSIV_DES_H
 #  include <kerberosIV/des.h>
@@ -127,6 +148,15 @@ char *getstr (const char *);
 int local_domain (const char *);
 const char *topdomain (const char *);
 
+#ifdef WITH_PAM
+static int pam_rc = PAM_AUTH_ERR;
+
+static pam_handle_t *pam_handle = NULL;
+static int rsh_conv (int, const struct pam_message **,
+                    struct pam_response **, void *);
+static struct pam_conv pam_conv = { rsh_conv, NULL };
+#endif /* WITH_PAM */
+
 #if defined KERBEROS || defined SHISHI
 # ifdef KERBEROS
 Key_schedule schedule;
@@ -172,10 +202,12 @@ static struct argp_option options[] = {
 extern int __check_rhosts_file;        /* hook in rcmd(3) */
 #endif
 
-#if defined __GLIBC__ && defined WITH_IRUSEROK
+#ifndef WITH_PAM
+# if defined __GLIBC__ && defined WITH_IRUSEROK
 extern int iruserok (uint32_t raddr, int superuser,
                      const char *ruser, const char *luser);
-#endif
+# endif
+#endif /* WITH_PAM */
 
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
@@ -224,7 +256,12 @@ parse_opt (int key, char *arg, struct argp_state *state)
 }
 
 
-const char doc[] = "Remote shell server";
+const char doc[] =
+#ifdef WITH_PAM
+                  "Remote shell server, using PAM service 'rsh'.";
+#else /* !WITH_PAM */
+                  "Remote shell server.";
+#endif
 static struct argp argp = { options, parse_opt, NULL, doc};
 
 
@@ -300,12 +337,16 @@ main (int argc, char *argv[])
   return 0;
 }
 
-char username[20] = "USER=";
-char logname[23] = "LOGNAME=";
-char homedir[64] = "HOME=";
-char shell[64] = "SHELL=";
-char path[100] = "PATH=";
-char *envinit[] = { homedir, shell, path, logname, username, 0 };
+char username[32 + sizeof ("USER=")] = "USER=";
+char logname[32 + sizeof ("LOGNAME=")] = "LOGNAME=";
+char homedir[256 + sizeof ("HOME=")] = "HOME=";
+char shell[64 + sizeof ("SHELL=")] = "SHELL=";
+char path[sizeof (PATH_DEFPATH) + sizeof ("PATH=")] = "PATH=";
+char rhost[128 + sizeof ("RHOST=")] = "RHOST=";
+
+#ifndef WITH_PAM
+char *envinit[] = { homedir, shell, path, logname, username, rhost, NULL };
+#endif
 extern char **environ;
 
 void
@@ -374,7 +415,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
   /* Verify that the client's address is an Internet adress. */
   if (fromp->sin_family != AF_INET)
     {
-      syslog (LOG_ERR, "malformed \"from\" address (af %d)\n",
+      syslog (LOG_ERR, "malformed originating address (af %d)\n",
              fromp->sin_family);
       exit (EXIT_FAILURE);
     }
@@ -571,7 +612,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
                            "Couldn't look up address for %s", remotehost);
                    errorstr =
                      "Couldn't look up address for your host (%s)\n";
-                   hostname = inet_ntoa (fromp->sin_addr);
+                   hostname = strdup (inet_ntoa (fromp->sin_addr));
                  }
                else
                  for (;; hp->h_addr_list++)
@@ -582,14 +623,14 @@ doit (int sockfd, struct sockaddr_in *fromp)
                                  "Host addr %s not listed for host %s",
                                  inet_ntoa (fromp->sin_addr), hp->h_name);
                          errorstr = "Host address mismatch for %s\n";
-                         hostname = inet_ntoa (fromp->sin_addr);
+                         hostname = strdup (inet_ntoa (fromp->sin_addr));
                          break;
                        }
                      if (!memcmp (hp->h_addr_list[0],
                                   (caddr_t) & fromp->sin_addr,
                                   sizeof fromp->sin_addr))
                        {
-                         hostname = hp->h_name;
+                         hostname = strdup (hp->h_name);
                          break;        /* equal, OK */
                        }
                    }
@@ -597,7 +638,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
          }
     }
   else
-    errorhost = hostname = inet_ntoa (fromp->sin_addr);
+    errorhost = hostname = strdup (inet_ntoa (fromp->sin_addr));
 
 #ifdef KERBEROS
   if (use_kerberos)
@@ -798,6 +839,81 @@ doit (int sockfd, struct sockaddr_in *fromp)
       goto fail;
     }
 
+#ifdef WITH_PAM
+  pam_rc = pam_start ("rsh", locuser, &pam_conv, &pam_handle);
+  if (pam_rc == PAM_SUCCESS)
+    pam_rc = pam_set_item (pam_handle, PAM_RHOST, hostname);
+  if (pam_rc == PAM_SUCCESS)
+    pam_rc = pam_set_item (pam_handle, PAM_RUSER, remuser);
+  if (pam_rc == PAM_SUCCESS)
+    pam_rc = pam_set_item (pam_handle, PAM_TTY, "rsh");
+  if (pam_rc != PAM_SUCCESS)
+    {
+      errorstr = "Try again.\n";
+      goto fail;
+    }
+
+  pam_rc = pam_authenticate (pam_handle, PAM_SILENT);
+  if (pam_rc != PAM_SUCCESS)
+    {
+      switch (pam_rc)
+       {
+       case PAM_ABORT:
+         pam_end (pam_handle, pam_rc);
+         exit (EXIT_FAILURE);
+       default:
+         errorstr = "Password incorrect.\n";
+         goto fail;
+       }
+    }
+
+  pam_rc = pam_acct_mgmt (pam_handle, PAM_SILENT);
+  if (pam_rc != PAM_SUCCESS)
+    {
+      switch (pam_rc)
+       {
+       case PAM_NEW_AUTHTOK_REQD:
+       case PAM_AUTH_ERR:
+         errorstr = "Password incorrect.\n";
+         goto fail;
+         break;
+       case PAM_ACCT_EXPIRED:
+       case PAM_PERM_DENIED:
+       case PAM_USER_UNKNOWN:
+       default:
+         errorstr = "Permission denied.";
+         goto fail;
+         break;
+       }
+    }
+
+  /* Renew client information, since the PAM stack may have
+   * mapped the request onto another identity.
+   */
+  free (locuser);
+  locuser = NULL;
+  pam_rc = pam_get_item (pam_handle, PAM_USER, (const void **) &locuser);
+  if (pam_rc != PAM_SUCCESS)
+    {
+      syslog (LOG_NOTICE | LOG_AUTH, "pam_get_item(PAM_USER): %s",
+             pam_strerror (pam_handle, pam_rc));
+      /* Intentionally let `locuser' be ill defined.  */
+    }
+# ifdef HAVE_GETPWNAM_R
+  ret = getpwnam_r (locuser, &pwstor, pwbuf, pwbuflen, &pwd);
+  if (ret || pwd == NULL)
+# else /* !HAVE_GETPWNAM_R */
+  pwd = getpwnam (locuser);
+  if (pwd == NULL)
+# endif /* HAVE_GETPWNAM_R */
+    {
+      syslog (LOG_INFO | LOG_AUTH, "address@hidden as %s: unknown login. 
cmd='%.80s'",
+             remuser, hostname, locuser, cmdbuf);
+      errorstr = "Login incorrect.\n";
+      goto fail;
+    }
+#endif /* WITH_PAM */
+
 #ifdef KERBEROS
   if (use_kerberos)
     {
@@ -829,17 +945,22 @@ doit (int sockfd, struct sockaddr_in *fromp)
     }
   else
 #endif /* KERBEROS || SHISHI */
-#ifdef WITH_IRUSEROK
+
+#ifndef WITH_PAM
+# ifdef WITH_IRUSEROK
     if (errorstr || (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0'
                      && (iruserok (fromp->sin_addr.s_addr, pwd->pw_uid == 0,
                                    remuser, locuser)) < 0))
-#elif defined WITH_RUSEROK
+# elif defined WITH_RUSEROK
     if (errorstr || (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0'
                      && (ruserok (inet_ntoa (fromp->sin_addr),
                                  pwd->pw_uid == 0, remuser, locuser)) < 0))
-#else /* !WITH_IRUSEROK && !WITH_RUSEROK */
-#error Unable to use mandatory iruserok/ruserok.  This should not happen.
-#endif /* !WITH_IRUSEROK && !WITH_RUSEROK */
+# else /* !WITH_IRUSEROK && !WITH_RUSEROK */
+# error Unable to use mandatory iruserok/ruserok.  This should not happen.
+# endif /* !WITH_IRUSEROK && !WITH_RUSEROK */
+#else /* WITH_PAM */
+    if (0)     /* Wrapper for `fail' jump label.  */
+#endif /* !WITH_PAM */
     {
 #ifdef HAVE___RCMD_ERRSTR
       if (__rcmd_errstr)
@@ -852,6 +973,16 @@ doit (int sockfd, struct sockaddr_in *fromp)
                "address@hidden as %s: permission denied. cmd='%.80s'",
                remuser, hostname, locuser, cmdbuf);
     fail:
+#ifdef WITH_PAM
+      if (pam_handle)
+       {
+         if (pam_rc != PAM_SUCCESS)
+           syslog (LOG_NOTICE | LOG_AUTH, "address@hidden as %s, PAM: %s",
+                   remuser, hostname, locuser,
+                   pam_strerror (pam_handle, pam_rc));
+         pam_end (pam_handle, pam_rc);
+       }
+#endif /* WITH_PAM */
       if (errorstr == NULL)
        errorstr = "Permission denied.\n";
       rshd_error (errorstr, errorhost);
@@ -1151,13 +1282,23 @@ doit (int sockfd, struct sockaddr_in *fromp)
     syslog (LOG_ERR, "setlogin() failed: %m");
 #endif
 
-  /* Set the fid, then uid to become the user specified by "locuser" */
+  /* Set the gid, then uid to become the user specified by "locuser" */
   setegid ((gid_t) pwd->pw_gid);
   setgid ((gid_t) pwd->pw_gid);
 #ifdef HAVE_INITGROUPS
   initgroups (pwd->pw_name, pwd->pw_gid);      /* BSD groups */
 #endif
 
+#ifdef WITH_PAM
+  pam_rc = pam_setcred (pam_handle, PAM_SILENT | PAM_ESTABLISH_CRED);
+  if (pam_rc != PAM_SUCCESS)
+    {
+      syslog (LOG_ERR | LOG_AUTH, "pam_setcred: %s",
+             pam_strerror (pam_handle, pam_rc));
+      pam_rc = PAM_SUCCESS;    /* Only report the above anomaly.  */
+    }
+#endif /* WITH_PAM */
+
   setuid ((uid_t) pwd->pw_uid);
 
   /* We'll execute the client's command in the home directory
@@ -1175,14 +1316,35 @@ doit (int sockfd, struct sockaddr_in *fromp)
     }
 
   /* Set up an initial environment for the shell that we exec() */
+  strncat (homedir, pwd->pw_dir, sizeof (homedir) - sizeof ("HOME=") - 1);
+  strncat (path, PATH_DEFPATH, sizeof (path) - sizeof ("PATH=") - 1);
+  strncat (shell, pwd->pw_shell, sizeof (shell) - sizeof ("SHELL=") - 1);
+  strncat (username, pwd->pw_name, sizeof (username) - sizeof ("USER=") - 1);
+  strncat (logname, pwd->pw_name, sizeof (logname) - sizeof ("LOGNAME=") - 1);
+  strncat (rhost, hostname, sizeof (rhost) - sizeof ("RHOST=") - 1);
+
+#ifdef WITH_PAM
+  if (pam_getenv (pam_handle, "PATH") == NULL)
+    (void) pam_putenv (pam_handle, path);
+  if (pam_getenv (pam_handle, "HOME") == NULL)
+    (void) pam_putenv (pam_handle, homedir);
+  if (pam_getenv (pam_handle, "SHELL") == NULL)
+    (void) pam_putenv (pam_handle, shell);
+  if (pam_getenv (pam_handle, "USER") == NULL)
+    (void) pam_putenv (pam_handle, username);
+  if (pam_getenv (pam_handle, "LOGNAME") == NULL)
+    (void) pam_putenv (pam_handle, logname);
+  if (pam_getenv (pam_handle, "RHOST") == NULL)
+    (void) pam_putenv (pam_handle, rhost);
+
+  environ = pam_getenvlist (pam_handle);
+#else /* !WITH_PAM */
   environ = envinit;
-  strncat (homedir, pwd->pw_dir, sizeof (homedir) - 6);
-  strcat (path, PATH_DEFPATH);
-  strncat (shell, pwd->pw_shell, sizeof (shell) - 7);
-  strncat (username, pwd->pw_name, sizeof (username) - 6);
+#endif /* WITH_PAM */
+
   cp = strrchr (pwd->pw_shell, '/');
   if (cp)
-    cp++;                      /* step past first slash */
+    cp++;                      /* step past last slash */
   else
     cp = pwd->pw_shell;                /* no slash in shell string */
   endpwent ();
@@ -1205,6 +1367,11 @@ doit (int sockfd, struct sockaddr_in *fromp)
   else
 #endif /* SHISHI */
     execl (pwd->pw_shell, cp, "-c", cmdbuf, NULL);
+
+#ifdef WITH_PAM
+  pam_end (pam_handle, PAM_SUCCESS);
+#endif
+  syslog (LOG_ERR, "execl failed for \"%s\": %m", pwd->pw_name);
   error (EXIT_FAILURE, errno, "cannot execute %s", pwd->pw_shell);
 }
 
@@ -1327,3 +1494,34 @@ topdomain (const char *h)
     }
   return maybe;
 }
+
+#ifdef WITH_PAM
+/* Call back function for passing user's information
+ * to any PAM module requesting this information.
+ */
+static int
+rsh_conv (int num, const struct pam_message **pam_msg,
+           struct pam_response **pam_resp, void *data)
+{
+  struct pam_response *resp;
+
+  /* Reject composite calls at the time being.  */
+  if (num <= 0 || num > 1)
+    return PAM_CONV_ERR;
+
+  /* Ensure an empty response.  */
+  *pam_resp = NULL;
+
+  switch ((*pam_msg)->msg_style)
+    {
+    case PAM_PROMPT_ECHO_OFF:  /* Return an empty password.  */
+      return PAM_SUCCESS;
+    case PAM_TEXT_INFO:                /* Not yet supported.  */
+    case PAM_ERROR_MSG:                /* Likewise.  */
+    case PAM_PROMPT_ECHO_ON:   /* Interactivity is not supported.  */
+    default:
+      return PAM_CONV_ERR;
+    }
+  return PAM_CONV_ERR; /* Never reached.  */
+}
+#endif /* WITH_PAM */

http://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=a4390104731d33a746dd0e4243e75daeddfde8f1


commit a4390104731d33a746dd0e4243e75daeddfde8f1
Author: Mats Erik Andersson <address@hidden>
Date:   Fri Jun 15 11:45:49 2012 +0200

    rshd: Prefer use of getpwnam_r.

diff --git a/ChangeLog b/ChangeLog
index 4910d84..fae35bf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2012-06-15  Mats Erik Andersson  <address@hidden>
+
+       * src/rshd.c (doit) [HAVE_GETPWNAM_R]: New variables
+       PWBUF, PWBUFLEN, PWSTOR, and RET.  Call getpwnam_r(),
+       checking both `ret' and `pwd == NULL' for failure.
+
 2012-06-15  Simon Josefsson  <address@hidden>
 
        * bootstrap: Updated from gnulib.
diff --git a/src/rshd.c b/src/rshd.c
index c0cd7db..a65c812 100644
--- a/src/rshd.c
+++ b/src/rshd.c
@@ -139,12 +139,12 @@ Shishi_key *enckey;
 shishi_ivector iv1, iv2, iv3, iv4;
 shishi_ivector *ivtab[4];
 int protocol;
-# endif
+# endif /* SHISHI */
 # define VERSION_SIZE  9
 # define SECURE_MESSAGE  "This rsh session is using DES encryption for all 
transmissions.\r\n"
 int doencrypt, use_kerberos, vacuous;
 #else
-#endif
+#endif /* KERBEROS || SHISHI */
 
 static struct argp_option options[] = {
   { "verify-hostname", 'a', NULL, 0,
@@ -164,7 +164,7 @@ static struct argp_option options[] = {
   /* FIXME: Option name is misleading */
   { "vacuous", 'v', NULL, 0,
     "require Kerberos authentication" },
-#endif
+#endif /* KERBEROS */
   { NULL }
 };
 
@@ -210,7 +210,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       doencrypt = 1;
       break;
 # endif
-#endif
+#endif /* KERBEROS || SHISHI */
 
     case 'L':
       log_success = 1;
@@ -264,8 +264,8 @@ main (int argc, char *argv[])
       syslog (LOG_ERR, "-k is required for -x");
       exit (EXIT_FAILURE);
     }
-# endif
-#endif
+# endif /* ENCRYPTION */
+#endif /* KERBEROS || SHISHI */
 
   /*
    * We assume we're invoked by inetd, so the socket that the
@@ -315,7 +315,13 @@ doit (int sockfd, struct sockaddr_in *fromp)
   extern char *__rcmd_errstr;  /* syslog hook from libc/net/rcmd.c. */
 #endif
   struct hostent *hp;
+#ifdef HAVE_GETPWNAM_R
+  char *pwbuf;
+  int ret, pwbuflen;
+  struct passwd *pwd, pwstor;
+#else /* !HAVE_GETPWNAM_R */
   struct passwd *pwd;
+#endif
   unsigned short port;
   fd_set ready, readfrom;
   int cc, nfd, pv[2], pid, s = sockfd;
@@ -335,14 +341,22 @@ doit (int sockfd, struct sockaddr_in *fromp)
   fd_set wready, writeto;
 
   fromaddr = *fromp;
-#elif defined SHISHI
+#elif defined SHISHI /* !KERBEROS */
   int n;
   int pv1[2], pv2[2];
   fd_set wready, writeto;
   int keytype, keylen;
   int cksumtype, cksumlen;
   char *cksum = NULL;
-#endif
+#endif /* KERBEROS || SHISHI */
+
+#ifdef HAVE_GETPWNAM_R
+  pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
+  if (pwbuflen <= 0)
+    pwbuflen = 1024;   /* Guessing only.  */
+
+  pwbuf = xmalloc (pwbuflen);
+#endif /* HAVE_GETPWNAM_R */
 
   signal (SIGINT, SIG_DFL);
   signal (SIGQUIT, SIG_DFL);
@@ -513,7 +527,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
       rshd_error ("rshd: remote host requires Kerberos authentication\n");
       exit (EXIT_FAILURE);
     }
-#endif
+#endif /* KERBEROS || SHISHI */
 
   /* from inetd, socket is already on 0, 1, 2 */
   if (sockfd != STDIN_FILENO)
@@ -612,7 +626,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
          des_set_key (kdata->session, schedule);
        }
       else
-# endif
+# endif /* ENCRYPTION */
        rc = krb_recvauth (authopts, 0, ticket, "rcmd",
                           instance, &fromaddr,
                           (struct sockaddr_in *) 0,
@@ -625,7 +639,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
        }
     }
   else
-#elif defined (SHISHI)
+#elif defined (SHISHI) /* !KERBEROS */
   if (use_kerberos)
     {
       int rc;
@@ -641,7 +655,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
        }
     }
   else
-#endif
+#endif /* KERBEROS || SHISHI */
     remuser = getstr ("remuser");
 
   /* Read three strings from the client. */
@@ -717,7 +731,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
            }
 
        }
-# endif
+# endif /* ENCRYPTION */
 
     remuser = getstr ("remuser");
     rc = read (STDIN_FILENO, &error, sizeof (int));
@@ -763,14 +777,19 @@ doit (int sockfd, struct sockaddr_in *fromp)
     shishi_ap_done (ap);
 
   }
-#endif
+#endif /* SHISHI */
 
-  /* Look up locuser in the passerd file.  The locuser has\* to be a
+  /* Look up locuser in the passwd file.  The locuser has to be a
    * valid account on this system.
    */
   setpwent ();
+#ifdef HAVE_GETPWNAM_R
+  ret = getpwnam_r (locuser, &pwstor, pwbuf, pwbuflen, &pwd);
+  if (ret || pwd == NULL)
+#else /* !HAVE_GETPWNAM_R */
   pwd = getpwnam (locuser);
   if (pwd == NULL)
+#endif /* HAVE_GETPWNAM_R */
     {
       syslog (LOG_INFO | LOG_AUTH, "address@hidden as %s: unknown login. 
cmd='%.80s'",
              remuser, hostname, locuser, cmdbuf);
@@ -794,7 +813,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
        }
     }
   else
-#elif defined(SHISHI)
+#elif defined(SHISHI) /* !KERBEROS */
   if (use_kerberos)
     {                          /*
                                   if (pwd->pw_passwd != 0 && *pwd->pw_passwd 
!= '\0')
@@ -809,7 +828,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
                                   } */
     }
   else
-#endif
+#endif /* KERBEROS || SHISHI */
 #ifdef WITH_IRUSEROK
     if (errorstr || (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0'
                      && (iruserok (fromp->sin_addr.s_addr, pwd->pw_uid == 0,
@@ -828,7 +847,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
                "address@hidden as %s: permission denied (%s). cmd='%.80s'",
                remuser, hostname, locuser, __rcmd_errstr, cmdbuf);
       else
-#endif
+#endif /* HAVE___RCMD_ERRSTR */
        syslog (LOG_INFO | LOG_AUTH,
                "address@hidden as %s: permission denied. cmd='%.80s'",
                remuser, hostname, locuser, cmdbuf);
@@ -888,8 +907,8 @@ doit (int sockfd, struct sockaddr_in *fromp)
              exit (EXIT_FAILURE);
            }
        }
-# endif
-#endif
+# endif /* KERBEROS || SHISHI */
+#endif /* ENCRYPTION */
       pid = fork ();
       if (pid == -1)
        {
@@ -913,15 +932,15 @@ doit (int sockfd, struct sockaddr_in *fromp)
              des_write (s, msg, sizeof (msg) - 1);
            }
          else
-# elif defined(SHISHI)
+# elif defined(SHISHI) /* !KERBEROS */
          if (doencrypt)
            {
              close (pv1[1]);
              close (pv2[1]);
            }
          else
-# endif
-#endif
+# endif /* KERBEROS || SHISHI */
+#endif /* ENCRYPTION */
            {
              /* child handles the original socket */
              close (STDIN_FILENO);
@@ -951,8 +970,8 @@ doit (int sockfd, struct sockaddr_in *fromp)
              nfd = MAX (nfd, pv1[0]);
            }
          else
-# endif
-#endif
+# endif /* KERBEROS || SHISHI */
+#endif /* ENCRYPTION */
            ioctl (pv[0], FIONBIO, (char *) &one);
          /* should set s nbio! */
          nfd++;
@@ -965,7 +984,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
                {
 #  ifdef SHISHI
                  wready = readfrom;
-#  else
+#  else /* KERBEROS && !SHISHI */
                  wready = writeto;
 #  endif
                  if (select (nfd, &ready, &wready, (fd_set *) 0,
@@ -973,11 +992,11 @@ doit (int sockfd, struct sockaddr_in *fromp)
                    break;
                }
              else
-# endif
-#endif
+# endif /* KERBEROS || SHISHI */
+#endif /* ENCRYPTION */
              if (select (nfd, &ready, (fd_set *) 0,
                            (fd_set *) 0, (struct timeval *) 0) < 0)
-               /* wait until something to read */
+               /* wait until there is something to read */
                break;
              if (FD_ISSET (s, &ready))
                {
@@ -987,12 +1006,12 @@ doit (int sockfd, struct sockaddr_in *fromp)
                  if (doencrypt)
                    ret = des_read (s, &sig, 1);
                  else
-# elif defined(SHISHI)
+# elif defined(SHISHI) /* !KERBEROS */
                  if (doencrypt)
                    readenc (h, s, &sig, &ret, &iv2, enckey, protocol);
                  else
-# endif
-#endif
+# endif /* KERBEROS || SHISHI */
+#endif /* ENCRYPTION */
                    ret = read (s, &sig, 1);
                  if (ret <= 0)
                    FD_CLR (s, &readfrom);
@@ -1015,12 +1034,12 @@ doit (int sockfd, struct sockaddr_in *fromp)
                      if (doencrypt)
                        des_write (s, buf, cc);
                      else
-# elif defined(SHISHI)
+# elif defined(SHISHI) /* !KERBEROS */
                      if (doencrypt)
                        writeenc (h, s, buf, cc, &n, &iv4, enckey, protocol);
                      else
-# endif
-#endif
+# endif /* KERBEROS || SHISHI */
+#endif /* ENCRYPTION */
                        write (s, buf, cc);
                    }
                }
@@ -1039,7 +1058,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
 #  ifdef SHISHI
                    writeenc (h, STDOUT_FILENO, buf, cc, &n, &iv3, enckey,
                              protocol);
-#  else
+#  else /* KERBEROS */
                    des_write (STDOUT_FILENO, buf, cc);
 #  endif
                }
@@ -1049,7 +1068,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
                  errno = 0;
 #  ifdef SHISHI
                  readenc (h, STDIN_FILENO, buf, &cc, &iv1, enckey, protocol);
-#  else
+#  else /* KERBEROS */
                  cc = des_read (STDIN_FILENO, buf, sizeof buf);
 #  endif
                  if (cc <= 0)
@@ -1060,18 +1079,18 @@ doit (int sockfd, struct sockaddr_in *fromp)
                  else
                    write (pv2[0], buf, cc);
                }
-# endif
-#endif
+# endif /* KERBEROS || SHISHI */
+#endif /* ENCRYPTION */
            }
          while (FD_ISSET (s, &readfrom) ||
 #ifdef ENCRYPTION
 # if defined KERBEROS || defined SHISHI
                 (doencrypt && FD_ISSET (pv1[0], &readfrom)) ||
 # endif
-#endif
+#endif /* ENCRYPTION */
                 FD_ISSET (pv[0], &readfrom));
-         /* The pipe will generat an EOR whe the shell
-          * terminates.  The socket will terninate whe the
+         /* The pipe will generate an EOF when the shell
+          * terminates.  The socket will terminate when the
           * client process terminates.
           */
          exit (EXIT_SUCCESS);
@@ -1097,8 +1116,8 @@ doit (int sockfd, struct sockaddr_in *fromp)
          close (pv1[1]);
          close (pv2[1]);
        }
-# endif
-#endif
+# endif /* KERBEROS || SHISHI */
+#endif /* ENCRYPTION */
 
 #if defined SHISHI
       if (use_kerberos)
@@ -1116,10 +1135,10 @@ doit (int sockfd, struct sockaddr_in *fromp)
                  free (ivtab[i]->iv);
                }
            }
-# endif
+# endif /* ENCRYPTION */
        }
 
-#endif
+#endif /* SHISHI */
 
       dup2 (pv[1], STDERR_FILENO);     /* stderr of shell has to go
                                           pipe to control process */
@@ -1176,7 +1195,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
                kdata->pname, kdata->pinst, kdata->prealm,
                hostname, locuser, cmdbuf);
       else
-#endif
+#endif /* KERBEROS */
        syslog (LOG_INFO | LOG_AUTH, "address@hidden as %s: cmd='%.80s'",
                remuser, hostname, locuser, cmdbuf);
     }
@@ -1184,7 +1203,7 @@ doit (int sockfd, struct sockaddr_in *fromp)
   if (doencrypt)
     execl (pwd->pw_shell, cp, "-c", cmdbuf + 3, NULL);
   else
-#endif
+#endif /* SHISHI */
     execl (pwd->pw_shell, cp, "-c", cmdbuf, NULL);
   error (EXIT_FAILURE, errno, "cannot execute %s", pwd->pw_shell);
 }

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog       |   81 ++++++++
 configure.ac    |   39 ++++-
 src/Makefile.am |    2 +-
 src/rcp.c       |   29 +++
 src/rsh.c       |   20 ++-
 src/rshd.c      |  573 ++++++++++++++++++++++++++++++++++++++++++++++---------
 6 files changed, 645 insertions(+), 99 deletions(-)


hooks/post-receive
-- 
GNU Inetutils 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]