From 1340beed16de1b5f83c539aa49445ce48a60c6b9 Mon Sep 17 00:00:00 2001 From: nekral-guest Date: Mon, 13 Jun 2011 18:27:40 +0000 Subject: [PATCH] * src/su.c: Also drop the controlling terminal when PAM is not used. * src/su.c: Remove run_shell(). --- ChangeLog | 3 ++ src/su.c | 99 ++++++++++++++++++++++++++++++------------------------- 2 files changed, 58 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index fcb31271..5beed08e 100644 --- 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 diff --git a/src/su.c b/src/su.c index 869e0232..14483327 100644 --- a/src/su.c +++ b/src/su.c @@ -61,6 +61,13 @@ #include #include #include +#include +#ifndef USE_PAM +#include +#include +#include +#include +#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); }