]> granicus.if.org Git - shadow/commitdiff
* src/su.c: Also drop the controlling terminal when PAM is not
authornekral-guest <nekral-guest@5a98b0ae-9ef6-0310-add3-de5d479b70d7>
Mon, 13 Jun 2011 18:27:40 +0000 (18:27 +0000)
committernekral-guest <nekral-guest@5a98b0ae-9ef6-0310-add3-de5d479b70d7>
Mon, 13 Jun 2011 18:27:40 +0000 (18:27 +0000)
used.
* src/su.c: Remove run_shell().

ChangeLog
src/su.c

index fcb31271237e7e22237a941ca35fd99edb569e79..5beed08e38d30931d58e5204d7380b073ce697b5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,9 @@
        prepare_pam_close_session() is now executed before the creation of
        the pam session and before the UID is changed. This allows to
        close the session as root.
+       * src/su.c: Also drop the controlling terminal when PAM is not
+       used.
+       * src/su.c: Remove run_shell().
 
 2011-06-12  Nicolas François  <nicolas.francois@centraliens.net>
 
index 869e0232bb6e9ee853c76a582ebb6138152075e4..14483327afd2460a5b256396701dcb5de0d8e72e 100644 (file)
--- a/src/su.c
+++ b/src/su.c
 #include <signal.h>
 #include <stdio.h>
 #include <sys/types.h>
+#include <unistd.h>
+#ifndef USE_PAM
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif                         /* !USE_PAM */
 #include "prototypes.h"
 #include "defines.h"
 #include "pwauth.h"
@@ -119,6 +126,7 @@ static void execve_shell (const char *shellstr,
                           char *const envp[]);
 #ifdef USE_PAM
 static RETSIGTYPE kill_child (int unused(s));
+static void prepare_pam_close_session (void);
 #else                          /* !USE_PAM */
 static RETSIGTYPE die (int);
 static bool iswheel (const char *);
@@ -258,9 +266,10 @@ static void catch_signals (int sig)
 }
 
 /*
- * Create a session and fork.
- * Only the child returns. The parent will wait for the child to terminate
- * and exit.
+ * prepare_pam_close_session - Fork and wait for the child to close the session
+ *
+ *     Only the child returns. The parent will wait for the child to
+ *     terminate and exit.
  */
 static void prepare_pam_close_session (void)
 {
@@ -385,35 +394,11 @@ static void prepare_pam_close_session (void)
                                        : WTERMSIG (status) + 128);
        /* Only the child returns. See above. */
 }
-
-static void run_shell (const char *shellstr, char *args[], bool doshell,
-                       char *const envp[])
-{
-               /*
-                * PAM_DATA_SILENT is not supported by some modules, and
-                * there is no strong need to clean up the process space's
-                * memory since we will either call exec or exit.
-               pam_end (pamh, PAM_SUCCESS | PAM_DATA_SILENT);
-                */
-
-               if (doshell) {
-                       (void) shell (shellstr, (char *) args[0], envp);
-               } else {
-                       /* There is no need for a controlling terminal.
-                        * This avoids the callee to inject commands on
-                        * the caller's tty. */
-                       (void) setsid ();
-
-                       execve_shell (shellstr, (char **) args, envp);
-               }
-
-               exit (errno == ENOENT ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
-}
 #endif                         /* USE_PAM */
 
 /*
  * usage - print command line syntax and exit
 */
+ */
 static void usage (int status)
 {
        fputs (_("Usage: su [options] [LOGIN]\n"
@@ -1049,6 +1034,40 @@ int main (int argc, char **argv)
 
        set_environment (pw);
 
+       if (!doshell) {
+               /* There is no need for a controlling terminal.
+                * This avoids the callee to inject commands on
+                * the caller's tty. */
+               int err = -1;
+
+#ifdef USE_PAM
+               /* When PAM is used, we are on the child */
+               err = setsid ();
+#else
+               /* Otherwise, we cannot use setsid */
+               int fd = open ("/dev/tty", O_RDWR);
+
+               if (fd >= 0) {
+                       err = ioctl (fd, TIOCNOTTY, (char *) 0);
+                       (void) close (fd);
+               }
+#endif                         /* USE_PAM */
+
+               if (-1 == err) {
+                       (void) fprintf (stderr,
+                                       _("%s: Cannot drop the controlling terminal\n"),
+                                       Prog);
+                       exit (1);
+               }
+       }
+
+       /*
+        * PAM_DATA_SILENT is not supported by some modules, and
+        * there is no strong need to clean up the process space's
+        * memory since we will either call exec or exit.
+       pam_end (pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+        */
+
        endpwent ();
        endspent ();
        /*
@@ -1081,6 +1100,7 @@ int main (int argc, char **argv)
        }
 
        if (!doshell) {
+               int err;
                /* Position argv to the remaining arguments */
                argv += optind;
                if (NULL != command) {
@@ -1093,24 +1113,15 @@ int main (int argc, char **argv)
                 * with the rest of the command line included.
                 */
                argv[-1] = cp;
-#ifndef USE_PAM
                execve_shell (shellstr, &argv[-1], environ);
                err = errno;
-               (void) fputs (_("No shell\n"), stderr);
-               SYSLOG ((LOG_WARN, "Cannot execute %s", shellstr));
-               closelog ();
-               exit ((ENOENT == err) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
-#else
-               run_shell (shellstr, &argv[-1], false, environ); /* no return */
-#endif
+               (void) fprintf (stderr,
+                               _("Cannot execute %s\n"), shellstr);
+               errno = err;
+       } else {
+               (void) shell (shellstr, cp, environ);
        }
-#ifndef USE_PAM
-       err = shell (shellstr, cp, environ);
-       exit ((ENOENT == err) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
-#else
-       run_shell (shellstr, &cp, true, environ);
-#endif
-       /* NOT REACHED */
-       exit (1);
+
+       return (errno == ENOENT ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
 }