home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1989, 1990, John F. Haugh II
- * All rights reserved.
- *
- * Use, duplication, and disclosure prohibited without
- * the express written permission of the author.
- */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdio.h>
- #include <pwd.h>
- #include <utmp.h>
- #include <time.h>
- #include <signal.h>
- #ifndef BSD
- #include <string.h>
- #include <memory.h>
- #else
- #include <strings.h>
- #define strchr index
- #define strrchr rindex
- #endif
- #ifndef BSD
- #include <termio.h>
- #else
- #include <sgtty.h>
- #endif
- #include "config.h"
- #include "lastlog.h"
- #include "faillog.h"
- #ifdef SHADOWPWD
- #include "shadow.h"
- #endif
-
- #ifndef lint
- static char _sccsid[] = "@(#)lmain.c 2.7 10:20:08 11/9/90";
- #endif
-
- #ifndef ERASECHAR
- #define ERASECHAR '\b' /* backspace */
- #endif
-
- #ifndef KILLCHAR
- #define KILLCHAR '\025' /* control U */
- #endif
-
- char name[BUFSIZ];
- char pass[BUFSIZ];
- char home[BUFSIZ];
- char prog[BUFSIZ];
- char mail[BUFSIZ];
- #ifdef HUSHLOGIN
- char hush[BUFSIZ];
- int hushed;
- #endif
-
- struct passwd pwent;
- struct utmp utent;
- struct lastlog lastlog;
- #ifndef BSD
- struct termio termio;
- #endif
-
- #ifndef MAXENV
- #define MAXENV 64
- #endif
-
- char *newenvp[MAXENV];
- int newenvc = 0;
- int maxenv = MAXENV;
- extern char **environ;
-
- char *getenv ();
- void checkutmp ();
- void addenv ();
- void setenv ();
- unsigned alarm ();
- void login ();
- void entry ();
- void setutmp ();
- void subsystem ();
- void log ();
- void setup ();
- void expire ();
- void motd ();
- void mailcheck ();
- void shell ();
- long a64l ();
- int c64i ();
-
- #ifdef TZ
- FILE *tzfile;
- char tzbuf[32] = TZ;
- #endif
-
- #ifndef ALARM
- #define ALARM 60
- #endif
-
- #ifndef RETRIES
- #define RETRIES 3
- #endif
-
- #ifdef FAILLOG
- struct faillog faillog;
- #endif
- #ifdef FTMP
- struct utmp failent;
- #endif
- #ifndef WARNAGE
- #define WARNAGE 0
- #endif
-
- int main (argc, argv, envp)
- int argc;
- char **argv;
- char **envp;
- {
- int retries = RETRIES;
- int failed;
- #ifdef CONSOLE
- int conflag;
- char console[BUFSIZ];
- FILE *fp;
- struct stat statbuf;
- #endif
- #ifdef SHADOWPWD
- struct spwd *spwd;
- struct spwd *getspnam();
- #endif
-
- checkutmp (); /* must be lowest level shell */
-
- if (! isatty (0)) /* must be a terminal */
- exit (1);
-
- #ifndef BSD
- (void) ioctl (0, TCGETA, &termio); /* get terminal characteristics */
-
- /*
- * Add your favorite terminal modes here ...
- */
-
- termio.c_lflag |= ISIG;
-
- termio.c_cc[VERASE] = ERASECHAR;
- termio.c_cc[VKILL] = KILLCHAR;
- (void) ioctl (0, TCSETAF, &termio); /* set erase and kill characters */
- #endif
- #ifdef UMASK
- umask (UMASK); /* override the default umask */
- #endif
- #ifdef ULIMIT
- ulimit (2, (long) ULIMIT); /* override the default ulimit */
- #endif
- while (*envp) /* add inherited environment, */
- addenv (*envp++); /* some variables change later */
-
- #ifdef TZ
- if (tzbuf[0] == '/') {
- if ((tzfile = fopen (tzbuf, "r")) != (FILE *) 0) {
- if (fgets (tzbuf, sizeof tzbuf, tzfile)) {
- tzbuf[strlen (tzbuf) - 1] = '\0';
- addenv (tzbuf);
- }
- fclose (tzfile);
- }
- } else {
- addenv (tzbuf);
- }
- #endif
- #ifdef HZ
- addenv (HZ); /* set the default $HZ, if one */
- #endif
- if (argc >= 2) { /* now set command line variables */
- setenv (argc - 2, &argv[2]);
- (void) strncpy (name, argv[1], sizeof name);
- }
- (void) alarm (ALARM); /* only allow ALARM sec. for login */
-
- while (1) { /* repeatedly get login/password pairs */
- if (! name[0]) { /* need to get a login id */
- login (name);
- continue;
- }
- entry (name, &pwent); /* get entry from password file */
- failed = 0; /* hasn't failed validation yet */
-
- /*
- * Here we have a sticky situation. Some accounts may have no
- * password entry in the password file. So, we don't ask for a
- * password. Others, have a blank password entered - you be the
- * judge. The conditional compilation NOBLANK requires even
- * blank passwords to be prompted for. This may well break
- * quite a few systems. Use with discretion.
- */
-
- #ifdef NOBLANK
- /* get a password from user */
- if (! password ("Password:", pass))
- continue;
- #else
- if ((! pwent.pw_name ||
- (pwent.pw_passwd && strlen (pwent.pw_passwd) > 0))
- && ! password ("Password:", pass))
- continue;
- #endif
- if (! valid (pass, &pwent)) /* check encrypted passwords ... */
- failed = 1;
-
- #ifdef DIALUP
- alarm (30);
- if (! dialcheck (utent.ut_line,
- pwent.pw_shell ? pwent.pw_shell:"/bin/sh"))
- failed = 1;
- #endif
- #ifdef PORTTIME
- if (pwent.pw_name &&
- ! isttytime (utent.ut_line, pwent.pw_name,
- time ((long *) 0)))
- failed = 1;
- #endif
- #ifdef CONSOLE
- if (pwent.pw_uid == 0 && stat (CONSOLE, &statbuf) == 0) {
- if ((statbuf.st_mode & S_IFMT) == S_IFREG) {
- fp = fopen (CONSOLE, "r");
- while (fp && fgets (console, BUFSIZ, fp)
- == console) {
- console[strlen (console) - 1] = '\0';
- if (! strcmp (console, utent.ut_line))
- break;
- }
- if (! fp || feof (fp))
- failed = 1;
-
- fclose (fp);
- } else {
- if (strcmp (CONSOLE, utent.ut_line))
- failed = 1;
- }
- }
- #endif
- #ifdef FAILLOG
- if (! failcheck (pwent.pw_uid, &faillog, failed))
- failed = 1;
- #endif
- if (! failed)
- break;
-
- puts ("Login incorrect");
- #ifdef FAILLOG
- if (pwent.pw_name) /* don't log non-existent users */
- failure (pwent.pw_uid, utent.ut_line, &faillog);
- #endif
- #ifdef FTMP
- failent = utent;
-
- if (pwent.pw_name)
- strncpy (failent.ut_name,
- pwent.pw_name, sizeof failent.ut_name);
- else
- #ifdef UNKNOWNS
- strcpy (failent.ut_name, name);
- #else
- strcpy (failent.ut_name, "UNKNOWN");
- #endif
- failent.ut_time = time ((time_t *) 0);
- failent.ut_type = USER_PROCESS;
-
- failtmp (&failent);
- #endif /* FTMP */
- if (--retries <= 0) /* only allow so many failures */
- exit (1);
-
- #ifndef BSD
- (void) memset (name, '\0', sizeof name);
- (void) memset (pass, '\0', sizeof pass);
- #else
- bzero (name, sizeof name);
- bzero (pass, sizeof pass);
- #endif
- }
- (void) alarm (0); /* turn off alarm clock */
- #ifdef NOLOGINS
- /*
- * Check to see if system is turned off for non-root users.
- * This would be useful to prevent users from logging in
- * during system maintenance.
- */
-
- if (pwent.pw_uid != 0 && access (NOLOGINS, 0) == 0) {
- printf ("\r\nSystem closed for routine maintenance\n");
- exit (0);
- }
- #endif
- environ = newenvp; /* make new environment active */
-
- if (getenv ("IFS")) /* don't export user IFS ... */
- addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
-
- setutmp (); /* make entry in utmp & wtmp files */
- if (pwent.pw_shell && pwent.pw_shell[0] == '*') /* subsystem root */
- subsystem (); /* figure out what to execute */
-
- #ifdef LASTLOG
- log (); /* give last login and log this one */
- #endif
- #ifdef SHADOWPWD
- /*
- * Need to get expiration information before changing UID
- */
-
- spwd = getspnam (pwent.pw_name);
- #endif
- setup (&pwent); /* set UID, GID, HOME, etc ... */
- #ifdef AGING
- #ifdef SHADOWPWD
- if (spwd)
- expire (spwd->sp_namp, spwd->sp_lstchg,
- spwd->sp_min, spwd->sp_max);
- else
- #endif
- if (pwent.pw_age && pwent.pw_age[0]) { /* check for age of password */
- expire (pwent.pw_name, (strlen (pwent.pw_age) == 4 ?
- a64l (pwent.pw_age + 2):0L) * 7,
- c64i (pwent.pw_age[1]) * 7,
- c64i (pwent.pw_age[0]) * 7);
- }
- #endif
- #ifdef HUSHLOGIN
- sprintf (hush, "%s/.hushlogin", strchr (home, '=') + 1);
- hushed = access (hush, 0) != -1;
- #endif
- #ifdef MOTD
- motd (); /* print the message of the day */
- #endif
- #ifdef FAILLOG
- if (faillog.fail_cnt != 0)
- failprint (pwent.pw_uid, &faillog);
- #endif
- #ifdef LASTLOG
- if (lastlog.ll_time != 0 && ! hushed)
- printf ("Last login: %.19s on %s\n",
- ctime (&lastlog.ll_time), lastlog.ll_line);
- #endif
- #ifdef AGING
- #ifdef SHADOWPWD
- if (spwd)
- agecheck (spwd->sp_lstchg,
- spwd->sp_min, spwd->sp_max, 1);
- else
- #endif
- agecheck (strlen (pwent.pw_age) == 4 ?
- a64l (pwent.pw_age + 2):0L,
- c64i (pwent.pw_age[1]), c64i (pwent.pw_age[0]), 7);
- #endif
- #ifdef MAILCHECK
- mailcheck (); /* report on the status of mail */
- #endif
- #ifdef TTYTYPE
- ttytype (utent.ut_line);
- #endif
- signal (SIGINT, SIG_DFL); /* default interrupt signal */
- signal (SIGQUIT, SIG_DFL); /* default quit signal */
- signal (SIGTERM, SIG_DFL); /* default terminate signal */
- signal (SIGALRM, SIG_DFL); /* default alarm signal */
-
- shell (pwent.pw_shell); /* exec the shell finally. */
- /*NOTREACHED*/
- }
-