From: nekral-guest Date: Tue, 1 Jan 2008 23:54:51 +0000 (+0000) Subject: Also split syslog_sg() out of main(). X-Git-Tag: 4.1.1~154 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=11864d22b442a1949909fa601e1c1bffb9219d77;p=shadow Also split syslog_sg() out of main(). --- diff --git a/ChangeLog b/ChangeLog index 8e4a3d89..4d03ccfe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,7 +5,7 @@ 2008-01-01 Nicolas François * src/newgrp.c: Avoid assignments in conditionals. - * src/newgrp.c: Split check_perms() out of main(). + * src/newgrp.c: Split check_perms(), syslog_sg() out of main(). 2008-01-01 Nicolas François diff --git a/src/newgrp.c b/src/newgrp.c index 8e3e926b..aefc9519 100644 --- a/src/newgrp.c +++ b/src/newgrp.c @@ -186,6 +186,104 @@ failure: exit (1); } +#ifdef USE_SYSLOG +/* + * syslog_sg - log the change of group to syslog + * + * The loggout will also be logged when the user will quit the + * sg/newgrp session. + */ +static void syslog_sg (gid_t gid, const char *name, const char *group) +{ + char *loginname = getlogin (); + char *tty = ttyname (0); + + if (loginname != NULL) + loginname = xstrdup (loginname); + if (tty != NULL) + tty = xstrdup (tty); + + if (loginname == NULL) + loginname = "???"; + if (tty == NULL) + tty = "???"; + else if (strncmp (tty, "/dev/", 5) == 0) + tty += 5; + SYSLOG ((LOG_INFO, + "user `%s' (login `%s' on %s) switched to group `%s'", + name, loginname, tty, group)); +#ifdef USE_PAM + /* + * We want to fork and exec the new shell in the child, leaving the + * parent waiting to log the session close. + * + * The parent must ignore signals generated from the console + * (SIGINT, SIGQUIT, SIGHUP) which might make the parent terminate + * before its child. When bash is exec'ed as the subshell, it + * generates a new process group id for itself, and consequently + * only SIGHUP, which is sent to all process groups in the session, + * can reach the parent. However, since arbitrary programs can be + * specified as login shells, there is no such guarantee in general. + * For the same reason, we must also ignore stop signals generated + * from the console (SIGTSTP, SIGTTIN, and SIGTTOU) in order to + * avoid any possibility of the parent being stopped when it + * receives SIGCHLD from the terminating subshell. -- JWP + */ + { + pid_t child, pid; + + signal (SIGINT, SIG_IGN); + signal (SIGQUIT, SIG_IGN); + signal (SIGHUP, SIG_IGN); + signal (SIGTSTP, SIG_IGN); + signal (SIGTTIN, SIG_IGN); + signal (SIGTTOU, SIG_IGN); + child = fork (); + if (child < 0) { + /* error in fork() */ + fprintf (stderr, _("%s: failure forking: %s"), + is_newgrp ? "newgrp" : "sg", strerror (errno)); +#ifdef WITH_AUDIT + audit_logger (AUDIT_USER_START, Prog, "changing", + NULL, getuid (), 0); +#endif + exit (1); + } else if (child) { + /* parent - wait for child to finish, then log session close */ + int cst = 0; + + do { + errno = 0; + pid = waitpid (child, &cst, WUNTRACED); + if (pid == child && WIFSTOPPED (cst)) { + /* stop when child stops */ + raise (SIGSTOP); + /* wake child when resumed */ + kill (child, SIGCONT); + } + } while ((pid == child && WIFSTOPPED (cst)) || + (pid != child && errno == EINTR)); + /* local, no need for xgetgrgid */ + SYSLOG ((LOG_INFO, + "user `%s' (login `%s' on %s) returned to group `%s'", + name, loginname, tty, + getgrgid (gid)->gr_name)); + closelog (); + exit (0); + } + + /* child - restore signals to their default state */ + signal (SIGINT, SIG_DFL); + signal (SIGQUIT, SIG_DFL); + signal (SIGHUP, SIG_DFL); + signal (SIGTSTP, SIG_DFL); + signal (SIGTTIN, SIG_DFL); + signal (SIGTTOU, SIG_DFL); + } +#endif /* USE_PAM */ +} +#endif /* USE_SYSLOG */ + /* * newgrp - change the invokers current real and effective group id */ @@ -448,92 +546,7 @@ int main (int argc, char **argv) */ #ifdef USE_SYSLOG if (getdef_bool ("SYSLOG_SG_ENAB")) { - char *loginname = getlogin (); - char *tty = ttyname (0); - - if (loginname != NULL) - loginname = xstrdup (loginname); - if (tty != NULL) - tty = xstrdup (tty); - - if (loginname == NULL) - loginname = "???"; - if (tty == NULL) - tty = "???"; - else if (strncmp (tty, "/dev/", 5) == 0) - tty += 5; - SYSLOG ((LOG_INFO, - "user `%s' (login `%s' on %s) switched to group `%s'", - name, loginname, tty, group)); -#ifdef USE_PAM - /* - * We want to fork and exec the new shell in the child, leaving the - * parent waiting to log the session close. - * - * The parent must ignore signals generated from the console - * (SIGINT, SIGQUIT, SIGHUP) which might make the parent terminate - * before its child. When bash is exec'ed as the subshell, it - * generates a new process group id for itself, and consequently - * only SIGHUP, which is sent to all process groups in the session, - * can reach the parent. However, since arbitrary programs can be - * specified as login shells, there is no such guarantee in general. - * For the same reason, we must also ignore stop signals generated - * from the console (SIGTSTP, SIGTTIN, and SIGTTOU) in order to - * avoid any possibility of the parent being stopped when it - * receives SIGCHLD from the terminating subshell. -- JWP - */ - { - pid_t child, pid; - - signal (SIGINT, SIG_IGN); - signal (SIGQUIT, SIG_IGN); - signal (SIGHUP, SIG_IGN); - signal (SIGTSTP, SIG_IGN); - signal (SIGTTIN, SIG_IGN); - signal (SIGTTOU, SIG_IGN); - child = fork (); - if (child < 0) { - /* error in fork() */ - fprintf (stderr, _("%s: failure forking: %s"), - is_newgrp ? "newgrp" : "sg", strerror (errno)); -#ifdef WITH_AUDIT - audit_logger (AUDIT_USER_START, Prog, "changing", - NULL, getuid (), 0); -#endif - exit (1); - } else if (child) { - /* parent - wait for child to finish, then log session close */ - int cst = 0; - - do { - errno = 0; - pid = waitpid (child, &cst, WUNTRACED); - if (pid == child && WIFSTOPPED (cst)) { - /* stop when child stops */ - raise (SIGSTOP); - /* wake child when resumed */ - kill (child, SIGCONT); - } - } while ((pid == child && WIFSTOPPED (cst)) || - (pid != child && errno == EINTR)); - /* local, no need for xgetgrgid */ - SYSLOG ((LOG_INFO, - "user `%s' (login `%s' on %s) returned to group `%s'", - name, loginname, tty, - getgrgid (gid)->gr_name)); - closelog (); - exit (0); - } - - /* child - restore signals to their default state */ - signal (SIGINT, SIG_DFL); - signal (SIGQUIT, SIG_DFL); - signal (SIGHUP, SIG_DFL); - signal (SIGTSTP, SIG_DFL); - signal (SIGTTIN, SIG_DFL); - signal (SIGTTOU, SIG_DFL); - } -#endif /* USE_PAM */ + syslog_sg (gid, name, group); } #endif /* USE_SYSLOG */