diff options
Diffstat (limited to 'src/su.c')
-rw-r--r-- | src/su.c | 102 |
1 files changed, 47 insertions, 55 deletions
@@ -1,33 +1,10 @@ /* - * Copyright (c) 1989 - 1994, Julianne Frances Haugh - * Copyright (c) 1996 - 2000, Marek Michałkiewicz - * Copyright (c) 2000 - 2006, Tomasz Kłoczko - * Copyright (c) 2007 - 2013, Nicolas François - * All rights reserved. + * SPDX-FileCopyrightText: 1989 - 1994, Julianne Frances Haugh + * SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz + * SPDX-FileCopyrightText: 2000 - 2006, Tomasz Kłoczko + * SPDX-FileCopyrightText: 2007 - 2013, Nicolas François * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the copyright holders or contributors may not be used to - * endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ /* Some parts substantially derived from an ancestor of: @@ -77,12 +54,12 @@ #endif /* USE_PAM */ /*@-exitarg@*/ #include "exitcodes.h" +#include "shadowlog.h" /* * Global variables */ const char *Prog; -FILE *shadow_logfd = NULL; static /*@observer@*/const char *caller_tty = NULL; /* Name of tty SU is run from */ static bool caller_is_root = false; static uid_t caller_uid; @@ -295,6 +272,21 @@ static void prepare_pam_close_session (void) sigset_t ourset; int status; int ret; + struct sigaction action; + + /* reset SIGCHLD handling to default */ + action.sa_handler = SIG_DFL; + sigemptyset (&action.sa_mask); + action.sa_flags = 0; + if (0 == caught && sigaction (SIGCHLD, &action, NULL) != 0) { + fprintf (stderr, + _("%s: signal masking malfunction\n"), + Prog); + SYSLOG ((LOG_WARN, "Will not execute %s", shellstr)); + closelog (); + exit (1); + /* Only the child returns. See above. */ + } pid_child = fork (); if (pid_child == 0) { /* child shell */ @@ -318,11 +310,7 @@ static void prepare_pam_close_session (void) caught = SIGTERM; } if (0 == caught) { - struct sigaction action; - action.sa_handler = catch_signals; - sigemptyset (&action.sa_mask); - action.sa_flags = 0; sigemptyset (&ourset); if ( (sigaddset (&ourset, SIGTERM) != 0) @@ -397,22 +385,28 @@ static void prepare_pam_close_session (void) snprintf (kill_msg, sizeof kill_msg, _(" ...killed.\n")); snprintf (wait_msg, sizeof wait_msg, _(" ...waiting for child to terminate.\n")); + /* Any signals other than SIGCHLD and SIGALRM will no longer have any effect, + * so it's time to block all of them. */ + sigfillset (&ourset); + if (sigprocmask (SIG_BLOCK, &ourset, NULL) != 0) { + fprintf (stderr, _("%s: signal masking malfunction\n"), Prog); + kill_child (0); + /* Never reach (_exit called). */ + } + + /* Send SIGKILL to the child if it doesn't + * exit within 2 seconds (after SIGTERM) */ (void) signal (SIGALRM, kill_child); (void) signal (SIGCHLD, catch_signals); (void) alarm (2); - sigemptyset (&ourset); - if ((sigaddset (&ourset, SIGALRM) != 0) - || (sigprocmask (SIG_BLOCK, &ourset, NULL) != 0)) { - fprintf (stderr, _("%s: signal masking malfunction\n"), Prog); - kill_child (0); - } else { - while (0 == waitpid (pid_child, &status, WNOHANG)) { - sigsuspend (&ourset); - } - pid_child = 0; - (void) sigprocmask (SIG_UNBLOCK, &ourset, NULL); + (void) sigdelset (&ourset, SIGALRM); + (void) sigdelset (&ourset, SIGCHLD); + + while (0 == waitpid (pid_child, &status, WNOHANG)) { + sigsuspend (&ourset); } + pid_child = 0; (void) fputs (_(" ...terminated.\n"), stderr); } @@ -508,13 +502,13 @@ static void check_perms_nopam (const struct passwd *pw) if (strcmp (pw->pw_passwd, "") == 0) { char *prevent_no_auth = getdef_str("PREVENT_NO_AUTH"); - if(prevent_no_auth == NULL) { + if (prevent_no_auth == NULL) { prevent_no_auth = "superuser"; } - if(strcmp(prevent_no_auth, "yes") == 0) { + if (strcmp(prevent_no_auth, "yes") == 0) { fprintf(stderr, _("Password field is empty, this is forbidden for all accounts.\n")); exit(1); - } else if( (pw->pw_uid == 0) + } else if ((pw->pw_uid == 0) && (strcmp(prevent_no_auth, "superuser") == 0)) { fprintf(stderr, _("Password field is empty, this is forbidden for super-user.\n")); exit(1); @@ -579,7 +573,7 @@ static void check_perms_nopam (const struct passwd *pw) oldsig = signal (SIGQUIT, die); /* - * See if the system defined authentication method is being used. + * See if the system defined authentication method is being used. * The first character of an administrator defined method is an '@' * character. */ @@ -717,7 +711,8 @@ static void save_caller_context (char **argv) * most error messages. */ Prog = Basename (argv[0]); - shadow_logfd = stderr; + log_set_progname(Prog); + log_set_logfd(stderr); caller_uid = getuid (); caller_is_root = (caller_uid == 0); @@ -1156,12 +1151,9 @@ int main (int argc, char **argv) } } - /* - * 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); - */ +#ifdef USE_PAM + (void) pam_end (pamh, PAM_SUCCESS | PAM_DATA_SILENT); +#endif endpwent (); endspent (); |