diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 18 | ||||
-rw-r--r-- | src/chpasswd.c | 2 | ||||
-rw-r--r-- | src/newusers.c | 8 | ||||
-rw-r--r-- | src/passwd.c | 2 | ||||
-rw-r--r-- | src/su.c | 54 | ||||
-rw-r--r-- | src/useradd.c | 76 | ||||
-rw-r--r-- | src/usermod.c | 23 |
7 files changed, 155 insertions, 28 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index dc520b5d..12ef6308 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,9 +7,10 @@ usbindir = ${prefix}/sbin suidperms = 4755 sgidperms = 2755 -INCLUDES = \ +AM_CPPFLAGS = \ -I${top_srcdir}/lib \ - -I$(top_srcdir)/libmisc + -I$(top_srcdir)/libmisc \ + -DLOCALEDIR=\"$(datadir)/locale\" # XXX why are login and su in /bin anyway (other than for # historical reasons)? @@ -54,10 +55,10 @@ noinst_PROGRAMS = id sulogin suidbins = su suidubins = chage chfn chsh expiry gpasswd newgrp passwd if ACCT_TOOLS_SETUID - suidubins += chage chgpasswd chpasswd groupadd groupdel groupmod newusers useradd userdel usermod +suidubins += chage chgpasswd chpasswd groupadd groupdel groupmod newusers useradd userdel usermod endif if ENABLE_SUBIDS - suidubins += newgidmap newuidmap +suidubins += newgidmap newuidmap endif if WITH_TCB @@ -69,7 +70,6 @@ LDADD = $(INTLLIBS) \ $(LIBTCB) \ $(top_builddir)/libmisc/libmisc.a \ $(top_builddir)/lib/libshadow.la -AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" if ACCT_TOOLS_SETUID LIBPAM_SUID = $(LIBPAM) @@ -113,7 +113,7 @@ pwunconv_LDADD = $(LDADD) $(LIBSELINUX) su_SOURCES = \ su.c \ suauth.c -su_LDADD = $(LDADD) $(LIBPAM) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) +su_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) sulogin_LDADD = $(LDADD) $(LIBCRYPT) useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) @@ -125,14 +125,14 @@ install-am: all-am ln -sf newgrp $(DESTDIR)$(ubindir)/sg ln -sf vipw $(DESTDIR)$(usbindir)/vigr for i in $(suidbins); do \ - chmod -f $(suidperms) $(DESTDIR)$(bindir)/$$i; \ + chmod $(suidperms) $(DESTDIR)$(bindir)/$$i; \ done for i in $(suidubins); do \ - chmod -f $(suidperms) $(DESTDIR)$(ubindir)/$$i; \ + chmod $(suidperms) $(DESTDIR)$(ubindir)/$$i; \ done if WITH_TCB for i in $(shadowsgidubins); do \ chown root:shadow $(DESTDIR)$(ubindir)/$$i; \ - chmod -f $(sgidperms) $(DESTDIR)$(ubindir)/$$i; \ + chmod $(sgidperms) $(DESTDIR)$(ubindir)/$$i; \ done endif diff --git a/src/chpasswd.c b/src/chpasswd.c index 21008f58..f9856726 100644 --- a/src/chpasswd.c +++ b/src/chpasswd.c @@ -552,7 +552,7 @@ int main (int argc, char **argv) if (NULL != sp) { newsp = *sp; newsp.sp_pwdp = cp; - newsp.sp_lstchg = (long) time ((time_t *)NULL) / SCALE; + newsp.sp_lstchg = (long) gettime () / SCALE; if (0 == newsp.sp_lstchg) { /* Better disable aging than requiring a * password change */ diff --git a/src/newusers.c b/src/newusers.c index 724cbb40..c38aec4b 100644 --- a/src/newusers.c +++ b/src/newusers.c @@ -496,7 +496,7 @@ static int add_passwd (struct passwd *pwd, const char *password) } spent.sp_pwdp = cp; } - spent.sp_lstchg = (long) time ((time_t *) 0) / SCALE; + spent.sp_lstchg = (long) gettime () / SCALE; if (0 == spent.sp_lstchg) { /* Better disable aging than requiring a password * change */ @@ -553,7 +553,7 @@ static int add_passwd (struct passwd *pwd, const char *password) */ spent.sp_pwdp = "!"; #endif - spent.sp_lstchg = (long) time ((time_t *) 0) / SCALE; + spent.sp_lstchg = (long) gettime () / SCALE; if (0 == spent.sp_lstchg) { /* Better disable aging than requiring a password change */ spent.sp_lstchg = -1; @@ -988,8 +988,8 @@ int main (int argc, char **argv) is_shadow_grp = sgr_file_present (); #endif #ifdef ENABLE_SUBIDS - is_sub_uid = sub_uid_file_present (); - is_sub_gid = sub_gid_file_present (); + is_sub_uid = sub_uid_file_present () && !rflg; + is_sub_gid = sub_gid_file_present () && !rflg; #endif /* ENABLE_SUBIDS */ open_files (); diff --git a/src/passwd.c b/src/passwd.c index 1191111d..3af3e651 100644 --- a/src/passwd.c +++ b/src/passwd.c @@ -668,7 +668,7 @@ static void update_shadow (void) } #ifndef USE_PAM if (do_update_age) { - nsp->sp_lstchg = (long) time ((time_t *) 0) / SCALE; + nsp->sp_lstchg = (long) gettime () / SCALE; if (0 == nsp->sp_lstchg) { /* Better disable aging than requiring a password * change */ @@ -219,6 +219,22 @@ static /*@noreturn@*/void su_failure (const char *tty, bool su_to_root) } closelog (); #endif + +#ifdef WITH_AUDIT + audit_fd = audit_open (); + audit_log_acct_message (audit_fd, + AUDIT_USER_ROLE_CHANGE, + NULL, /* Prog. name */ + "su", + ('\0' != caller_name[0]) ? caller_name : "???", + AUDIT_NO_ID, + "localhost", + NULL, /* addr */ + tty, + 0); /* result */ + close (audit_fd); +#endif /* WITH_AUDIT */ + exit (1); } @@ -363,23 +379,38 @@ static void prepare_pam_close_session (void) /* wake child when resumed */ kill (pid, SIGCONT); stop = false; + } else if ( (pid_t)-1 != pid) { + pid_child = 0; } } while (!stop); } - if (0 != caught) { + if (0 != caught && 0 != pid_child) { (void) fputs ("\n", stderr); (void) fputs (_("Session terminated, terminating shell..."), stderr); (void) kill (-pid_child, caught); - snprintf (kill_msg, 256, _(" ...killed.\n")); - snprintf (wait_msg, 256, _(" ...waiting for child to terminate.\n")); + snprintf (kill_msg, sizeof kill_msg, _(" ...killed.\n")); + snprintf (wait_msg, sizeof wait_msg, _(" ...waiting for child to terminate.\n")); (void) signal (SIGALRM, kill_child); + (void) signal (SIGCHLD, catch_signals); (void) alarm (2); - (void) wait (&status); + 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) fputs (_(" ...terminated.\n"), stderr); } @@ -1076,6 +1107,21 @@ int main (int argc, char **argv) } #endif /* !USE_PAM */ +#ifdef WITH_AUDIT + audit_fd = audit_open (); + audit_log_acct_message (audit_fd, + AUDIT_USER_ROLE_CHANGE, + NULL, /* Prog. name */ + "su", + ('\0' != caller_name[0]) ? caller_name : "???", + AUDIT_NO_ID, + "localhost", + NULL, /* addr */ + caller_tty, + 1); /* result */ + close (audit_fd); +#endif /* WITH_AUDIT */ + set_environment (pw); if (!doshell) { diff --git a/src/useradd.c b/src/useradd.c index fefa234c..0e0fa1f8 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -51,7 +51,9 @@ #include <string.h> #include <sys/stat.h> #include <sys/types.h> +#include <sys/wait.h> #include <time.h> +#include <unistd.h> #include "chkname.h" #include "defines.h" #include "faillog.h" @@ -213,6 +215,7 @@ static void open_files (void); static void open_shadow (void); static void faillog_reset (uid_t); static void lastlog_reset (uid_t); +static void tallylog_reset (char *); static void usr_update (void); static void create_home (void); static void create_mail (void); @@ -825,7 +828,7 @@ static void new_spent (struct spwd *spent) memzero (spent, sizeof *spent); spent->sp_namp = (char *) user_name; spent->sp_pwdp = (char *) user_pass; - spent->sp_lstchg = (long) time ((time_t *) 0) / SCALE; + spent->sp_lstchg = (long) gettime () / SCALE; if (0 == spent->sp_lstchg) { /* Better disable aging than requiring a password change */ spent->sp_lstchg = -1; @@ -1789,6 +1792,52 @@ static void lastlog_reset (uid_t uid) } } +static void tallylog_reset (char *user_name) +{ + const char pam_tally2[] = "/sbin/pam_tally2"; + const char *pname; + pid_t childpid; + int failed; + int status; + + if (access(pam_tally2, X_OK) == -1) + return; + + failed = 0; + switch (childpid = fork()) + { + case -1: /* error */ + failed = 1; + break; + case 0: /* child */ + pname = strrchr(pam_tally2, '/'); + if (pname == NULL) + pname = pam_tally2; + else + pname++; /* Skip the '/' */ + execl(pam_tally2, pname, "--user", user_name, "--reset", "--quiet", NULL); + /* If we come here, something has gone terribly wrong */ + perror(pam_tally2); + exit(42); /* don't continue, we now have 2 processes running! */ + /* NOTREACHED */ + break; + default: /* parent */ + if (waitpid(childpid, &status, 0) == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) + failed = 1; + break; + } + + if (failed) + { + fprintf (stderr, + _("%s: failed to reset the tallylog entry of user \"%s\"\n"), + Prog, user_name); + SYSLOG ((LOG_WARN, "failed to reset the tallylog entry of user \"%s\"", user_name)); + } + + return; +} + /* * usr_update - create the user entries * @@ -1896,6 +1945,9 @@ static void create_home (void) if (access (user_home, F_OK) != 0) { #ifdef WITH_SELINUX if (set_selinux_file_context (user_home) != 0) { + fprintf (stderr, + _("%s: cannot set SELinux context for home directory %s\n"), + Prog, user_home); fail_exit (E_HOMEDIR); } #endif @@ -1925,6 +1977,9 @@ static void create_home (void) #ifdef WITH_SELINUX /* Reset SELinux to create files with default contexts */ if (reset_selinux_file_context () != 0) { + fprintf (stderr, + _("%s: cannot reset SELinux file creation context\n"), + Prog); fail_exit (E_HOMEDIR); } #endif @@ -1994,8 +2049,8 @@ int main (int argc, char **argv) #endif /* ACCT_TOOLS_SETUID */ #ifdef ENABLE_SUBIDS - uid_t uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL); - uid_t uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL); + uid_t uid_min; + uid_t uid_max; #endif /* @@ -2027,17 +2082,19 @@ int main (int argc, char **argv) is_shadow_grp = sgr_file_present (); #endif + get_defaults (); + process_flags (argc, argv); #ifdef ENABLE_SUBIDS + uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL); + uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL); is_sub_uid = sub_uid_file_present () && !rflg && (!user_id || (user_id <= uid_max && user_id >= uid_min)); is_sub_gid = sub_gid_file_present () && !rflg && (!user_id || (user_id <= uid_max && user_id >= uid_min)); #endif /* ENABLE_SUBIDS */ - get_defaults (); - #ifdef ACCT_TOOLS_SETUID #ifdef USE_PAM { @@ -2225,6 +2282,15 @@ int main (int argc, char **argv) close_files (); + /* + * tallylog_reset needs to be able to lookup + * a valid existing user name, + * so we canot call it before close_files() + */ + if (!lflg && getpwuid (user_id) != NULL) { + tallylog_reset (user_name); + } + #ifdef WITH_SELINUX if (Zflg) { if (set_seuser (user_name, user_selinux) != 0) { diff --git a/src/usermod.c b/src/usermod.c index 687487d9..9c5e479f 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -641,7 +641,7 @@ static void new_spent (struct spwd *spent) spent->sp_pwdp = new_pw_passwd (spent->sp_pwdp); if (pflg) { - spent->sp_lstchg = (long) time ((time_t *) 0) / SCALE; + spent->sp_lstchg = (long) gettime () / SCALE; if (0 == spent->sp_lstchg) { /* Better disable aging than requiring a password * change. */ @@ -1673,7 +1673,7 @@ static void usr_update (void) spent.sp_pwdp = xstrdup (pwent.pw_passwd); pwent.pw_passwd = xstrdup (SHADOW_PASSWD_STRING); - spent.sp_lstchg = (long) time ((time_t *) 0) / SCALE; + spent.sp_lstchg = (long) gettime () / SCALE; if (0 == spent.sp_lstchg) { /* Better disable aging than * requiring a password change */ @@ -1756,6 +1756,14 @@ static void move_home (void) fail_exit (E_HOMEDIR); } +#ifdef WITH_AUDIT + if (uflg || gflg) { + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, + "changing home directory owner", + user_newname, (unsigned int) user_newid, 1); + } +#endif + if (rename (user_home, user_newhome) == 0) { /* FIXME: rename above may have broken symlinks * pointing to the user's home directory @@ -2148,7 +2156,7 @@ int main (int argc, char **argv) unsigned long count = ptr->range.last - ptr->range.first + 1; if (sub_uid_add(user_name, ptr->range.first, count) == 0) { fprintf (stderr, - _("%s: failed to add uid range %lu-%lu from '%s'\n"), + _("%s: failed to add uid range %lu-%lu to '%s'\n"), Prog, ptr->range.first, ptr->range.last, sub_uid_dbname ()); fail_exit (E_SUB_UID_UPDATE); @@ -2174,7 +2182,7 @@ int main (int argc, char **argv) unsigned long count = ptr->range.last - ptr->range.first + 1; if (sub_gid_add(user_name, ptr->range.first, count) == 0) { fprintf (stderr, - _("%s: failed to add gid range %lu-%lu from '%s'\n"), + _("%s: failed to add gid range %lu-%lu to '%s'\n"), Prog, ptr->range.first, ptr->range.last, sub_gid_dbname ()); fail_exit (E_SUB_GID_UPDATE); @@ -2252,6 +2260,13 @@ int main (int argc, char **argv) * ownership. * */ +#ifdef WITH_AUDIT + if (uflg || gflg) { + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, + "changing home directory owner", + user_newname, (unsigned int) user_newid, 1); + } +#endif if (chown_tree (dflg ? user_newhome : user_home, user_id, uflg ? user_newid : (uid_t)-1, |