2 * Copyright (c) 1989 - 1994, Julianne Frances Haugh
3 * Copyright (c) 1996 - 2001, Marek Michałkiewicz
4 * Copyright (c) 2001 - 2006, Tomasz Kłoczko
5 * Copyright (c) 2007 - 2009, Nicolas François
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the copyright holders or contributors may not be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 #include <sys/ioctl.h>
52 #include "prototypes.h"
54 #include "exitcodes.h"
58 static pam_handle_t *pamh = NULL;
60 #define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \
61 fprintf(stderr,"\n%s\n",pam_strerror(pamh, retcode)); \
62 SYSLOG((LOG_ERR,"%s",pam_strerror(pamh, retcode))); \
63 (void) pam_end(pamh, retcode); \
66 #define PAM_END { retcode = pam_close_session(pamh,0); \
67 (void) pam_end(pamh,retcode); }
73 * Needed for MkLinux DR1/2/2.1 - J.
76 #define LASTLOG_FILE "/var/log/lastlog"
85 static const char *hostname = "";
86 static /*@null@*/ /*@only@*/char *username = NULL;
87 static int reason = PW_LOGIN;
90 static struct lastlog ll;
92 static bool pflg = false;
93 static bool fflg = false;
96 static bool rflg = false;
100 static bool hflg = false;
101 static bool preauth_flag = false;
104 static unsigned int timeout;
107 * External identifiers.
110 extern char **newenvp;
111 extern size_t newenvc;
112 extern char **environ;
122 /* local function prototypes */
123 static void usage (void);
124 static void setup_tty (void);
125 static void process_flags (int argc, char *const *argv);
126 static /*@observer@*/const char *get_failent_user (/*@returned@*/const char *user);
127 static void update_utmp (const char *user,
130 /*@null@*/const struct utmp *utent);
133 static struct faillog faillog;
135 static void bad_time_notify (void);
136 static void check_nologin (bool login_to_root);
138 static void get_pam_user (char **ptr_pam_user);
141 static void init_env (void);
142 static RETSIGTYPE alarm_handler (int);
145 * usage - print login command usage and exit
148 * login -r hostname (for rlogind)
149 * login -h hostname (for telnetd, etc.)
150 * login -f name (for pre-authenticated login: datakit, xterm, etc.)
152 static void usage (void)
154 fprintf (stderr, _("Usage: %s [-p] [name]\n"), Prog);
158 fprintf (stderr, _(" %s [-p] [-h host] [-f name]\n"), Prog);
160 fprintf (stderr, _(" %s [-p] -r host\n"), Prog);
165 static void setup_tty (void)
171 if (GTTY (0, &termio) == 0) { /* get terminal characteristics */
174 * Add your favorite terminal modes here ...
176 termio.c_lflag |= ISIG | ICANON | ECHO | ECHOE;
177 termio.c_iflag |= ICRNL;
179 #if defined(ECHOKE) && defined(ECHOCTL)
180 termio.c_lflag |= ECHOKE | ECHOCTL;
182 #if defined(ECHOPRT) && defined(NOFLSH) && defined(TOSTOP)
183 termio.c_lflag &= ~(ECHOPRT | NOFLSH | TOSTOP);
186 termio.c_oflag |= ONLCR;
189 /* leave these values unchanged if not specified in login.defs */
190 erasechar = getdef_num ("ERASECHAR", (int) termio.c_cc[VERASE]);
191 killchar = getdef_num ("KILLCHAR", (int) termio.c_cc[VKILL]);
192 termio.c_cc[VERASE] = (cc_t) erasechar;
193 termio.c_cc[VKILL] = (cc_t) killchar;
194 /* Make sure the values were valid.
195 * getdef_num cannot validate this.
197 if (erasechar != (int) termio.c_cc[VERASE]) {
199 _("configuration error - cannot parse %s value: '%d'"),
200 "ERASECHAR", erasechar);
203 if (killchar != (int) termio.c_cc[VKILL]) {
205 _("configuration error - cannot parse %s value: '%d'"),
206 "KILLCHAR", killchar);
211 * ttymon invocation prefers this, but these settings
212 * won't come into effect after the first username login
214 (void) STTY (0, &termio);
221 * Tell the user that this is not the right time to login at this tty
223 static void bad_time_notify (void)
225 (void) puts (_("Invalid login time"));
226 (void) fflush (stdout);
229 static void check_nologin (bool login_to_root)
234 * Check to see if system is turned off for non-root users.
235 * This would be useful to prevent users from logging in
236 * during system maintenance. We make sure the message comes
237 * out for root so she knows to remove the file if she's
238 * forgotten about it ...
240 fname = getdef_str ("NOLOGINS_FILE");
241 if ((NULL != fname) && (access (fname, F_OK) == 0)) {
246 * Cat the file if it can be opened, otherwise just
247 * print a default message
249 nlfp = fopen (fname, "r");
251 while ((c = getc (nlfp)) != EOF) {
253 (void) putchar ('\r');
258 (void) fflush (stdout);
259 (void) fclose (nlfp);
261 (void) puts (_("\nSystem closed for routine maintenance"));
264 * Non-root users must exit. Root gets the message, but
268 if (!login_to_root) {
272 (void) puts (_("\n[Disconnect bypassed -- root login allowed.]"));
275 #endif /* !USE_PAM */
277 static void process_flags (int argc, char *const *argv)
283 * Check the flags for proper form. Every argument starting with
284 * "-" must be exactly two characters long. This closes all the
285 * clever rlogin, telnet, and getty holes.
287 for (arg = 1; arg < argc; arg++) {
288 if (argv[arg][0] == '-' && strlen (argv[arg]) > 2) {
291 if (strcmp(argv[arg], "--") == 0) {
292 break; /* stop checking on a "--" */
299 while ((flag = getopt (argc, argv, "d:fh:pr:")) != EOF) {
302 /* "-d device" ignored for compatibility */
329 * Neither -h nor -f should be combined with -r.
332 if (rflg && (hflg || fflg)) {
338 * Allow authentication bypass only if real UID is zero.
341 if ((rflg || fflg || hflg) && !amroot) {
342 fprintf (stderr, _("%s: Permission denied.\n"), Prog);
350 assert (NULL == username);
351 username = xstrdup (argv[optind]);
352 strzero (argv[optind]);
357 if (rflg && (NULL != username)) {
361 if (fflg && (NULL == username)) {
368 static void init_env (void)
375 tmp = getenv ("LANG");
377 addenv ("LANG", tmp);
381 * Add the timezone environmental variable so that time functions
390 cp = getdef_str ("ENV_TZ");
392 addenv (('/' == *cp) ? tz (cp) : cp, NULL);
395 #endif /* !USE_PAM */
397 * Add the clock frequency so that profiling commands work
406 cp = getdef_str ("ENV_HZ");
411 #endif /* !USE_PAM */
415 static RETSIGTYPE alarm_handler (unused int sig)
417 fprintf (stderr, _("\nLogin timed out after %u seconds.\n"), timeout);
423 * get_pam_user - Get the username according to PAM
425 * ptr_pam_user shall point to a malloc'ed string (or NULL).
427 static void get_pam_user (char **ptr_pam_user)
432 assert (NULL != ptr_pam_user);
434 retcode = pam_get_item (pamh, PAM_USER, (const void **)&ptr_user);
437 if (NULL != *ptr_pam_user) {
438 free (*ptr_pam_user);
440 if (NULL != ptr_user) {
441 *ptr_pam_user = xstrdup ((const char *)ptr_user);
443 *ptr_pam_user = NULL;
449 * get_failent_user - Return a string that can be used to log failure
452 * This will be either the user argument, or "UNKNOWN".
454 * It is quite common to mistyped the password for username, and passwords
455 * should not be logged.
457 static /*@observer@*/const char *get_failent_user (/*@returned@*/const char *user)
459 const char *failent_user = "UNKNOWN";
460 bool log_unkfail_enab = getdef_bool("LOG_UNKFAIL_ENAB");
462 if ((NULL != user) && ('\0' != user[0])) {
463 if ( log_unkfail_enab
464 || (getpwnam (user) != NULL)) {
473 * update_utmp - Update or create an utmp entry in utmp, wtmp, utmpw, and
476 * utent should be the utmp entry returned by get_current_utmp (or
479 static void update_utmp (const char *user,
482 /*@null@*/const struct utmp *utent)
484 struct utmp *ut = prepare_utmp (user, tty, host, utent);
486 struct utmpx *utx = prepare_utmpx (user, tty, host, utent);
487 #endif /* USE_UTMPX */
489 (void) setutmp (ut); /* make entry in the utmp & wtmp files */
493 (void) setutmpx (utx); /* make entry in the utmpx & wtmpx files */
495 #endif /* USE_UTMPX */
499 * login - create a new login session for a user
501 * login is typically called by getty as the second step of a
502 * new user session. getty is responsible for setting the line
503 * characteristics to a reasonable set of values and getting
504 * the name of the user to be logged in. login may also be
505 * called to create a new user session on a pty for a variety
506 * of reasons, such as X servers or network logins.
508 * the flags which login supports are
510 * -p - preserve the environment
511 * -r - perform autologin protocol for rlogin
512 * -f - do not perform authentication, user is preauthenticated
513 * -h - the name of the remote host
515 int main (int argc, char **argv)
523 #if defined(HAVE_STRFTIME) && !defined(USE_PAM)
527 unsigned int retries;
529 bool subroot = false;
537 struct passwd *pwd = NULL;
538 char **envp = environ;
539 const char *failent_user;
540 /*@null@*/struct utmp *utent;
545 char *pam_user = NULL;
547 struct spwd *spwd = NULL;
550 * Some quick initialization.
555 (void) setlocale (LC_ALL, "");
556 (void) bindtextdomain (PACKAGE, LOCALEDIR);
557 (void) textdomain (PACKAGE);
561 amroot = (getuid () == 0);
562 Prog = Basename (argv[0]);
564 if (geteuid() != 0) {
565 fprintf (stderr, _("%s: Cannot possibly work without effective root\n"), Prog);
569 process_flags (argc, argv);
571 if ((isatty (0) == 0) || (isatty (1) == 0) || (isatty (2) == 0)) {
572 exit (1); /* must be a terminal */
575 utent = get_current_utmp ();
577 * Be picky if run by normal users (possible if installed setuid
578 * root), but not if run by root. This way it still allows logins
579 * even if your getty is broken, or if something corrupts utmp,
580 * but users must "exec login" which will use the existing utmp
581 * entry (will not overwrite remote hostname). --marekm
583 if (!amroot && (NULL == utent)) {
584 (void) puts (_("No utmp entry. You must exec \"login\" from the lowest level \"sh\""));
587 /* NOTE: utent might be NULL afterwards */
589 tmptty = ttyname (0);
590 if (NULL == tmptty) {
593 STRFCPY (tty, tmptty);
596 is_console = console (tty);
601 * Add remote hostname to the environment. I think
602 * (not sure) I saw it once on Irix. --marekm
604 addenv ("REMOTEHOST", hostname);
614 assert (NULL == username);
615 username = xmalloc (USER_NAME_MAX_LENGTH + 1);
616 username[USER_NAME_MAX_LENGTH] = '\0';
617 if (do_rlogin (hostname, username, USER_NAME_MAX_LENGTH, term, sizeof term)) {
631 (void) umask (getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));
635 * Use the ULIMIT in the login.defs file, and if
636 * there isn't one, use the default value. The
637 * user may have one for themselves, but otherwise,
638 * just take what you get.
640 long limit = getdef_long ("ULIMIT", -1L);
643 set_filesize_limit (limit);
649 * The entire environment will be preserved if the -p flag
653 while (NULL != *envp) { /* add inherited environment, */
654 addenv (*envp, NULL); /* some variables change later */
660 if (term[0] != '\0') {
661 addenv ("TERM", term);
665 /* preserve TERM from getty */
667 tmp = getenv ("TERM");
669 addenv ("TERM", tmp);
676 if (optind < argc) { /* now set command line variables */
677 set_env (argc - optind, &argv[optind]);
682 #ifdef HAVE_STRUCT_UTMP_UT_HOST
683 } else if ((NULL != utent) && ('\0' != utent->ut_host[0])) {
685 #endif /* HAVE_STRUCT_UTMP_UT_HOST */
691 snprintf (fromhost, sizeof fromhost,
692 " on '%.100s' from '%.200s'", tty, cp);
694 snprintf (fromhost, sizeof fromhost,
695 " on '%.100s'", tty);
699 /* only allow ALARM sec. for login */
700 (void) signal (SIGALRM, alarm_handler);
701 timeout = getdef_unum ("LOGIN_TIMEOUT", ALARM);
703 (void) alarm (timeout);
706 environ = newenvp; /* make new environment active */
707 delay = getdef_unum ("FAIL_DELAY", 1);
708 retries = getdef_unum ("LOGIN_RETRIES", RETRIES);
711 retcode = pam_start ("login", username, &conv, &pamh);
712 if (retcode != PAM_SUCCESS) {
714 _("login: PAM Failure, aborting: %s\n"),
715 pam_strerror (pamh, retcode));
716 SYSLOG ((LOG_ERR, "Couldn't initialize PAM: %s",
717 pam_strerror (pamh, retcode)));
722 * hostname & tty are either set to NULL or their correct values,
723 * depending on how much we know. We also set PAM's fail delay to
726 * PAM_RHOST and PAM_TTY are used for authentication, only use
727 * information coming from login or from the caller (e.g. no utmp)
729 retcode = pam_set_item (pamh, PAM_RHOST, hostname);
731 retcode = pam_set_item (pamh, PAM_TTY, tty);
733 #ifdef HAS_PAM_FAIL_DELAY
734 retcode = pam_fail_delay (pamh, 1000000 * delay);
737 /* if fflg, then the user has already been authenticated */
741 char loginprompt[256]; /* That's one hell of a prompt :) */
743 /* Make the login prompt look like we want it */
744 if (gethostname (hostn, sizeof (hostn)) == 0) {
745 snprintf (loginprompt,
746 sizeof (loginprompt),
747 _("%s login: "), hostn);
749 snprintf (loginprompt,
750 sizeof (loginprompt), _("login: "));
753 retcode = pam_set_item (pamh, PAM_USER_PROMPT, loginprompt);
756 /* if we didn't get a user on the command line,
758 get_pam_user (&pam_user);
759 if ((NULL != pam_user) && ('\0' == pam_user[0])) {
760 retcode = pam_set_item (pamh, PAM_USER, NULL);
765 * There may be better ways to deal with some of
766 * these conditions, but at least this way I don't
767 * think we'll be giving away information. Perhaps
768 * someday we can trust that all PAM modules will
769 * pay attention to failure count and get rid of
777 #ifdef HAS_PAM_FAIL_DELAY
779 retcode = pam_fail_delay(pamh, 1000000*delay);
784 retcode = pam_authenticate (pamh, 0);
786 get_pam_user (&pam_user);
787 failent_user = get_failent_user (pam_user);
789 if (retcode == PAM_MAXTRIES) {
791 "TOO MANY LOGIN TRIES (%d)%s FOR '%s'",
792 failcount, fromhost, failent_user));
794 _("Maximum number of tries exceeded (%d)\n"),
798 } else if (retcode == PAM_ABORT) {
799 /* Serious problems, quit now */
800 (void) fputs (_("login: abort requested by PAM\n"), stderr);
801 SYSLOG ((LOG_ERR,"PAM_ABORT returned from pam_authenticate()"));
804 } else if (retcode != PAM_SUCCESS) {
805 SYSLOG ((LOG_NOTICE,"FAILED LOGIN (%d)%s FOR '%s', %s",
806 failcount, fromhost, failent_user,
807 pam_strerror (pamh, retcode)));
816 audit_fd = audit_open ();
817 audit_log_acct_message (audit_fd,
819 NULL, /* Prog. name */
828 #endif /* WITH_AUDIT */
831 (void) puts (_("Login incorrect"));
833 if (failcount >= retries) {
835 "TOO MANY LOGIN TRIES (%d)%s FOR '%s'",
836 failcount, fromhost, failent_user));
838 _("Maximum number of tries exceeded (%d)\n"),
845 * Let's give it another go around.
846 * Even if a username was given on the command
847 * line, prompt again for the username.
849 retcode = pam_set_item (pamh, PAM_USER, NULL);
853 /* We don't get here unless they were authenticated above */
857 /* Check the account validity */
858 retcode = pam_acct_mgmt (pamh, 0);
859 if (retcode == PAM_NEW_AUTHTOK_REQD) {
860 retcode = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
864 /* Open the PAM session */
865 get_pam_user (&pam_user);
866 retcode = pam_open_session (pamh, hushed (pam_user) ? PAM_SILENT : 0);
869 /* Grab the user information out of the password file for future usage
870 * First get the username that we are actually using, though.
872 * From now on, we will discard changes of the user (PAM_USER) by
875 get_pam_user (&pam_user);
876 if (NULL != username) {
880 failent_user = get_failent_user (username);
882 pwd = xgetpwnam (username);
884 SYSLOG ((LOG_ERR, "cannot find user %s", failent_user));
888 /* This set up the process credential (group) and initialize the
889 * supplementary group access list.
890 * This has to be done before pam_setcred
892 if (setup_groups (pwd) != 0) {
896 retcode = pam_setcred (pamh, PAM_ESTABLISH_CRED);
898 /* NOTE: If pam_setcred changes PAM_USER, this will not be taken
902 #else /* ! USE_PAM */
903 while (true) { /* repeatedly get login/password pairs */
904 /* user_passwd is always a pointer to this constant string
905 * or a passwd or shadow password that will be memzero by
906 * pw_free / spw_free.
907 * Do not free() user_passwd. */
908 const char *user_passwd = "!";
910 /* Do some cleanup to avoid keeping entries we do not need
920 failed = false; /* haven't failed authentication yet */
921 if (NULL == username) { /* need to get a login id */
926 preauth_flag = false;
927 username = xmalloc (USER_NAME_MAX_LENGTH + 1);
928 username[USER_NAME_MAX_LENGTH] = '\0';
929 login_prompt (_("\n%s login: "), username, USER_NAME_MAX_LENGTH);
931 if ('\0' == username[0]) {
932 /* Prompt for a new login */
938 /* Get the username to be used to log failures */
939 failent_user = get_failent_user (username);
941 pwd = xgetpwnam (username);
943 preauth_flag = false;
946 user_passwd = pwd->pw_passwd;
948 * If the encrypted password begins with a "!",
949 * the account is locked and the user cannot
950 * login, even if they have been
951 * "pre-authenticated."
953 if ( ('!' == user_passwd[0])
954 || ('*' == user_passwd[0])) {
959 if (strcmp (user_passwd, SHADOW_PASSWD_STRING) == 0) {
960 spwd = xgetspnam (username);
962 user_passwd = spwd->sp_pwdp;
964 /* The user exists in passwd, but not in
965 * shadow. SHADOW_PASSWD_STRING indicates
966 * that the password shall be in shadow.
969 "no shadow password for '%s'%s",
970 username, fromhost));
975 * The -r and -f flags provide a name which has already
976 * been authenticated by some server.
982 if (pw_auth (user_passwd, username, reason, (char *) 0) == 0) {
986 SYSLOG ((LOG_WARN, "invalid password for '%s' %s",
987 failent_user, fromhost));
992 * This is the point where all authenticated users wind up.
993 * If you reach this far, your password has been
994 * authenticated and so on.
998 && (0 == pwd->pw_uid)
1000 SYSLOG ((LOG_CRIT, "ILLEGAL ROOT LOGIN %s", fromhost));
1004 && !login_access (username, ('\0' != *hostname) ? hostname : tty)) {
1005 SYSLOG ((LOG_WARN, "LOGIN '%s' REFUSED %s",
1006 username, fromhost));
1010 && getdef_bool ("FAILLOG_ENAB")
1011 && !failcheck (pwd->pw_uid, &faillog, failed)) {
1013 "exceeded failure limit for '%s' %s",
1014 username, fromhost));
1021 /* don't log non-existent users */
1022 if ((NULL != pwd) && getdef_bool ("FAILLOG_ENAB")) {
1023 failure (pwd->pw_uid, tty, &faillog);
1025 if (getdef_str ("FTMP_FILE") != NULL) {
1027 struct utmpx *failent =
1028 prepare_utmpx (failent_user,
1030 /* FIXME: or fromhost? */hostname,
1032 #else /* !USE_UTMPX */
1033 struct utmp *failent =
1034 prepare_utmp (failent_user,
1038 #endif /* !USE_UTMPX */
1039 failtmp (failent_user, failent);
1045 SYSLOG ((LOG_CRIT, "REPEATED login failures%s",
1050 * If this was a passwordless account and we get here, login
1051 * was denied (securetty, faillog, etc.). There was no
1052 * password prompt, so do it now (will always fail - the bad
1053 * guys won't see that the passwordless account exists at
1056 if (user_passwd[0] == '\0') {
1057 pw_auth ("!", username, reason, (char *) 0);
1061 * Authentication of this user failed.
1062 * The username must be confirmed in the next try.
1068 * Wait a while (a la SVR4 /usr/bin/login) before attempting
1069 * to login the user again. If the earlier alarm occurs
1070 * before the sleep() below completes, login will exit.
1073 (void) sleep (delay);
1076 (void) puts (_("Login incorrect"));
1078 /* allow only one attempt with -r or -f */
1079 if (rflg || fflg || (retries <= 0)) {
1083 } /* while (true) */
1084 #endif /* ! USE_PAM */
1085 assert (NULL != username);
1086 assert (NULL != pwd);
1088 (void) alarm (0); /* turn off alarm clock */
1090 #ifndef USE_PAM /* PAM does this */
1092 * porttime checks moved here, after the user has been
1093 * authenticated. now prints a message, as suggested
1094 * by Ivan Nejgebauer <ian@unsux.ns.ac.yu>. --marekm
1096 if ( getdef_bool ("PORTTIME_CHECKS_ENAB")
1097 && !isttytime (username, tty, time ((time_t *) 0))) {
1098 SYSLOG ((LOG_WARN, "invalid login time for '%s'%s",
1099 username, fromhost));
1105 check_nologin (pwd->pw_uid == 0);
1108 if (getenv ("IFS")) { /* don't export user IFS ... */
1109 addenv ("IFS= \t\n", NULL); /* ... instead, set a safe IFS */
1112 update_utmp (username, tty, hostname, utent);
1114 if (pwd->pw_shell[0] == '*') { /* subsystem root */
1115 pwd->pw_shell++; /* skip the '*' */
1116 subsystem (pwd); /* figure out what to execute */
1117 subroot = true; /* say I was here again */
1118 endpwent (); /* close all of the file which were */
1119 endgrent (); /* open in the original rooted file */
1120 endspent (); /* system. they will be re-opened */
1122 endsgent (); /* in the new rooted file system */
1124 goto top; /* go do all this all over again */
1128 audit_fd = audit_open ();
1129 audit_log_acct_message (audit_fd,
1131 NULL, /* Prog. name */
1140 #endif /* WITH_AUDIT */
1142 #ifndef USE_PAM /* pam_lastlog handles this */
1143 if (getdef_bool ("LASTLOG_ENAB")) { /* give last login and log this one */
1144 dolastlog (&ll, pwd, tty, hostname);
1148 #ifndef USE_PAM /* PAM handles this as well */
1150 * Have to do this while we still have root privileges, otherwise we
1151 * don't have access to /etc/shadow.
1153 if (NULL != spwd) { /* check for age of password */
1154 if (expire (pwd, spwd)) {
1155 /* The user updated her password, get the new
1157 * Use the x variants because we need to keep the
1158 * entry for a long time, and there might be other
1159 * getxxyy in between.
1162 pwd = xgetpwnam (username);
1165 "cannot find user %s after update of expired password",
1170 spwd = xgetspnam (username);
1173 setup_limits (pwd); /* nice, ulimit etc. */
1174 #endif /* ! USE_PAM */
1179 * We must fork before setuid() because we need to call
1180 * pam_close_session() as root.
1182 (void) signal (SIGINT, SIG_IGN);
1185 /* error in fork() */
1186 fprintf (stderr, _("%s: failure forking: %s"),
1187 Prog, strerror (errno));
1190 } else if (child != 0) {
1192 * parent - wait for child to finish, then cleanup
1201 /* If we were init, we need to start a new session */
1202 if (getppid() == 1) {
1204 if (ioctl(0, TIOCSCTTY, 1) != 0) {
1205 fprintf (stderr, _("TIOCSCTTY failed on %s"), tty);
1210 /* The pwd and spwd entries for the user have been copied.
1212 * Close all the files so that unauthorized access won't occur.
1214 endpwent (); /* stop access to password file */
1215 endgrent (); /* stop access to group file */
1216 endspent (); /* stop access to shadow passwd file */
1218 endsgent (); /* stop access to shadow group file */
1221 /* Drop root privileges */
1223 if (setup_uid_gid (pwd, is_console))
1225 /* The group privileges were already dropped.
1226 * See setup_groups() above.
1228 if (change_uid (pwd))
1234 setup_env (pwd); /* set env vars, cd to the home dir */
1238 const char *const *env;
1240 env = (const char *const *) pam_getenvlist (pamh);
1241 while ((NULL != env) && (NULL != *env)) {
1242 addenv (*env, NULL);
1248 (void) setlocale (LC_ALL, "");
1249 (void) bindtextdomain (PACKAGE, LOCALEDIR);
1250 (void) textdomain (PACKAGE);
1252 if (!hushed (username)) {
1253 addenv ("HUSHLOGIN=FALSE", NULL);
1255 * pam_unix, pam_mail and pam_lastlog should take care of
1259 motd (); /* print the message of the day */
1260 if ( getdef_bool ("FAILLOG_ENAB")
1261 && (0 != faillog.fail_cnt)) {
1262 failprint (&faillog);
1263 /* Reset the lockout times if logged in */
1264 if ( (0 != faillog.fail_max)
1265 && (faillog.fail_cnt >= faillog.fail_max)) {
1266 (void) puts (_("Warning: login re-enabled after temporary lockout."));
1268 "login '%s' re-enabled after temporary lockout (%d failures)",
1269 username, (int) faillog.fail_cnt));
1272 if ( getdef_bool ("LASTLOG_ENAB")
1273 && (ll.ll_time != 0)) {
1274 time_t ll_time = ll.ll_time;
1276 #ifdef HAVE_STRFTIME
1277 (void) strftime (ptime, sizeof (ptime),
1278 "%a %b %e %H:%M:%S %z %Y",
1279 localtime (&ll_time));
1280 printf (_("Last login: %s on %s"),
1283 printf (_("Last login: %.19s on %s"),
1284 ctime (&ll_time), ll.ll_line);
1286 #ifdef HAVE_LL_HOST /* __linux__ || SUN4 */
1287 if ('\0' != ll.ll_host[0]) {
1288 printf (_(" from %.*s"),
1289 (int) sizeof ll.ll_host, ll.ll_host);
1296 mailcheck (); /* report on the status of mail */
1297 #endif /* !USE_PAM */
1299 addenv ("HUSHLOGIN=TRUE", NULL);
1304 (void) signal (SIGQUIT, SIG_DFL); /* default quit signal */
1305 (void) signal (SIGTERM, SIG_DFL); /* default terminate signal */
1306 (void) signal (SIGALRM, SIG_DFL); /* default alarm signal */
1307 (void) signal (SIGHUP, SIG_DFL); /* added this. --marekm */
1308 (void) signal (SIGINT, SIG_DFL); /* default interrupt signal */
1310 if (0 == pwd->pw_uid) {
1311 SYSLOG ((LOG_NOTICE, "ROOT LOGIN %s", fromhost));
1312 } else if (getdef_bool ("LOG_OK_LOGINS")) {
1313 SYSLOG ((LOG_INFO, "'%s' logged in %s", username, fromhost));
1316 tmp = getdef_str ("FAKE_SHELL");
1318 err = shell (tmp, pwd->pw_shell, newenvp); /* fake shell */
1320 /* exec the shell finally */
1321 err = shell (pwd->pw_shell, (char *) 0, newenvp);
1323 exit (err == ENOENT ? E_CMD_NOTFOUND : E_CMD_NOEXEC);