home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume38 / shadow / part04 / lmain.c < prev    next >
C/C++ Source or Header  |  1993-08-14  |  19KB  |  911 lines

  1. /*
  2.  * Copyright 1989, 1990, 1991, 1992, 1993, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Permission is granted to copy and create derivative works for any
  6.  * non-commercial purpose, provided this copyright notice is preserved
  7.  * in all copies of source code, or included in human readable form
  8.  * and conspicuously displayed on all copies of object code or
  9.  * distribution media.
  10.  *
  11.  * This software is provided on an AS-IS basis and the author makes
  12.  * no warrantee of any kind.
  13.  */
  14.  
  15. #include "config.h"
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <stdio.h>
  19. #include "pwd.h"
  20. #ifdef SVR4
  21. #include <utmpx.h>
  22. #else
  23. #include <utmp.h>
  24. #endif
  25. #include <time.h>
  26. #include <signal.h>
  27. #ifndef    BSD
  28. #include <string.h>
  29. #include <memory.h>
  30. #else
  31. #include <strings.h>
  32. #define    strchr    index
  33. #define    strrchr    rindex
  34. #endif
  35. #ifndef    BSD
  36. #ifdef    SVR4
  37. #include <termios.h>
  38. #else    /* !SVR4 */
  39. #include <termio.h>
  40. #endif    /* SVR4 */
  41. #else
  42. #include <sgtty.h>
  43. #endif
  44. #ifdef    STDLIB_H
  45. #include <stdlib.h>
  46. #endif
  47. #ifdef    UNISTD_H
  48. #include <unistd.h>
  49. #endif
  50.  
  51. #include "lastlog.h"
  52. #include "faillog.h"
  53. #ifdef    SHADOWPWD
  54. #include "shadow.h"
  55. #endif
  56. #include "pwauth.h"
  57.  
  58. #ifdef SVR4_SI86_EUA
  59. #include <sys/proc.h>
  60. #include <sys/sysi86.h>
  61. #endif
  62.  
  63. #if !defined(BSD) && !defined(SUN)
  64. #define    bzero(a,n)    memset(a, 0, n);
  65. #endif
  66.  
  67. #ifdef    USE_SYSLOG
  68. #include <syslog.h>
  69.  
  70. #ifndef    LOG_WARN
  71. #define    LOG_WARN    LOG_WARNING
  72. #endif
  73. #endif
  74.  
  75. #ifndef    lint
  76. static    char    sccsid[] = "@(#)lmain.c    3.24    08:07:08    19 Jul 1993";
  77. #endif
  78.  
  79.                     /* danger - side effects */
  80. #define STRFCPY(A,B)    strncpy((A), (B), sizeof(A)), *((A)+sizeof(A)-1) = '\0'
  81.  
  82. #if defined(RLOGIN) || defined(UT_HOST) || defined(SVR4)
  83. char    host[BUFSIZ];
  84. char    term[128] = "TERM=";
  85. int    remote_speed = 9600;
  86. #endif
  87.  
  88. struct    passwd    pwent;
  89. #ifdef SVR4
  90. struct    utmpx    utxent, failent;
  91. struct    utmp    utent;
  92. #else    /*!SVR4 */
  93. struct    utmp    utent, failent;
  94. #endif    /* SVR4 */
  95. struct    lastlog    lastlog;
  96. int    pflg;
  97. int    rflg;
  98. int    fflg;
  99. #ifdef    RLOGIN
  100. int    hflg;
  101. #endif
  102. int    preauth_flag;
  103.  
  104. #if defined(SVR4) || defined(SUN4)
  105. #define    STTY(fd,termio) tcsetattr (fd, TCSANOW, termio)
  106. #define    GTTY(fd,termio) tcgetattr (fd, termio)
  107. #define    TERMIO    struct    termios
  108. #else
  109. #define    STTY(fd,termio) ioctl(fd, TCSETA, termio)
  110. #define    GTTY(fd,termio) ioctl(fd, TCGETA, termio)
  111. #define    TERMIO    struct    termio
  112. #endif    /* SVR4 || SUN4 */
  113. TERMIO    termio;
  114.  
  115. #ifndef    MAXENV
  116. #define    MAXENV    64
  117. #endif
  118.  
  119. /*
  120.  * Global variables.
  121.  */
  122.  
  123. char    *newenvp[MAXENV];
  124. char    *Prog;
  125. int    newenvc = 0;
  126. int    maxenv = MAXENV;
  127.  
  128. /*
  129.  * External identifiers.
  130.  */
  131.  
  132. extern    char    *getenv ();
  133. extern    char    *getpass ();
  134. extern    char    *tz ();
  135. extern    void    checkutmp ();
  136. extern    void    addenv ();
  137. extern    void    setenv ();
  138. extern    unsigned alarm ();
  139. extern    void    login ();
  140. extern    void    setutmp ();
  141. extern    void    subsystem ();
  142. extern    void    log ();
  143. extern    void    setup ();
  144. extern    int    expire ();
  145. extern    void    motd ();
  146. extern    void    mailcheck ();
  147. extern    void    shell ();
  148. extern    long    a64l ();
  149. extern    int    c64i ();
  150. extern    char    *getdef_str();
  151. extern    int    getdef_bool();
  152. extern    int    getdef_num();
  153. extern    long    getdef_long();
  154. extern    int    optind;
  155. extern    char    *optarg;
  156. extern    char    **environ;
  157. extern    int    pw_auth();
  158.  
  159. #ifdef HAVE_ULIMIT
  160. extern    long    ulimit();
  161. #endif
  162.  
  163. #ifndef    ALARM
  164. #define    ALARM    60
  165. #endif
  166.  
  167. #ifndef    RETRIES
  168. #define    RETRIES    3
  169. #endif
  170.  
  171. struct    faillog    faillog;
  172.  
  173. #define    NO_SHADOW    "no shadow password for `%s' on `%s'\n"
  174. #define    BAD_PASSWD_HOST    "invalid password for `%s' on `%s' from `%s'\n"
  175. #define    BAD_PASSWD    "invalid password for `%s' on `%s'\n"
  176. #define    BAD_DIALUP    "invalid dialup password for `%s' on `%s'\n"
  177. #define    BAD_TIME_HOST    "invalid login time for `%s' on `%s' from `%s'\n"
  178. #define    BAD_TIME    "invalid login time for `%s' on `%s'\n"
  179. #define    BAD_ROOT_LOGIN    "ILLEGAL ROOT LOGIN ON TTY `%s'\n"
  180. #define    ROOT_LOGIN    "ROOT LOGIN ON TTY `%s'\n"
  181. #define    FAILURE_CNT    "exceeded failure limit for `%s' on `%s'\n"
  182. #define    NOT_A_TTY    "not a tty\n"
  183. #define    NOT_ROOT    "-r or -f flag and not ROOT on `%s'\n"
  184. #define AUTHFAIL    "authentication failed for user `%s'\n"
  185.  
  186. /*
  187.  * usage - print login command usage and exit
  188.  *
  189.  * login [ name ]
  190.  * login -r hostname    (for rlogind)
  191.  * login -h hostname    (for telnetd, etc.)
  192.  * login -f name    (for pre-authenticated login: datakit, xterm, etc.)
  193.  */
  194.  
  195. void
  196. usage ()
  197. {
  198.     fprintf (stderr, "usage: login [ -p ] [ name ]\n");
  199. #ifdef    RLOGIN
  200.     fprintf (stderr, "       login [ -p ] -r name\n");
  201.     fprintf (stderr, "       login [ -p ] [ -f name ] -h host\n");
  202. #else
  203.     fprintf (stderr, "       login [ -p ] -f name\n");
  204. #endif    /* RLOGIN */
  205.     exit (1);
  206. }
  207.  
  208. #ifdef    RLOGIN
  209. struct    {
  210.     int    spd_name;
  211.     int    spd_baud;
  212. } speed_table [] = {
  213. #ifdef    B50
  214.     B50, 50,
  215. #endif
  216. #ifdef    B75
  217.     B75, 75,
  218. #endif
  219. #ifdef    B110
  220.     B110, 110,
  221. #endif
  222. #ifdef    B134
  223.     B134, 134,
  224. #endif
  225. #ifdef    B150
  226.     B150, 150,
  227. #endif
  228. #ifdef    B200
  229.     B200, 200,
  230. #endif
  231. #ifdef    B300
  232.     B300, 300,
  233. #endif
  234. #ifdef    B600
  235.     B600, 600,
  236. #endif
  237. #ifdef    B1200
  238.     B1200, 1200,
  239. #endif
  240. #ifdef    B1800
  241.     B1800, 1800,
  242. #endif
  243. #ifdef    B2400
  244.     B2400, 2400,
  245. #endif
  246. #ifdef    B4800
  247.     B4800, 4800,
  248. #endif
  249. #ifdef    B9600
  250.     B9600, 9600,
  251. #endif
  252. #ifdef    B19200
  253.     B19200, 19200,
  254. #endif
  255. #ifdef    B38400
  256.     B38400, 38400,
  257. #endif
  258.     -1,    -1
  259. };
  260.  
  261. rlogin (remote_host, name, namelen)
  262. char    *remote_host;
  263. char    *name;
  264. int    namelen;
  265. {
  266.     struct    passwd    *pwd;
  267.     char    remote_name[32];
  268.     char    *cp;
  269.     int    remote_speed = 9600;
  270.     int    speed_name = B9600;
  271.     int    i;
  272.  
  273.     get_remote_string (remote_name, sizeof remote_name);
  274.     get_remote_string (name, namelen);
  275.     get_remote_string (term + 5, sizeof term - 5);
  276.  
  277.     if (cp = strchr (term, '/')) {
  278.         *cp++ = '\0';
  279.  
  280.         if (! (remote_speed = atoi (cp)))
  281.             remote_speed = 9600;
  282.     }
  283.     for (i = 0;speed_table[i].spd_baud != remote_speed &&
  284.                 speed_table[i].spd_name != -1;i++)
  285.         ;
  286.  
  287.     if (speed_table[i].spd_name != -1)
  288.         speed_name = speed_table[i].spd_name;
  289.  
  290.     GTTY (0, &termio);
  291. #ifndef    BSD
  292.     termio.c_iflag |= ICRNL|IXON;
  293.     termio.c_oflag |= OPOST|ONLCR;
  294.     termio.c_lflag |= ICANON|ECHO|ECHOE;
  295.     termio.c_cflag = (termio.c_cflag & ~CBAUD) | speed_name;
  296. #endif
  297.     STTY (0, &termio);
  298.  
  299.     if (! (pwd = getpwnam (name)))
  300.         return 0;
  301.  
  302.     /*
  303.      * ruserok() returns 0 for success on modern systems, and 1 on
  304.      * older ones.  If you are having trouble with people logging
  305.      * in without giving a required password, THIS is the culprit -
  306.      * go fix the #define in config.h.
  307.      */
  308.  
  309. #ifndef    RUSEROK
  310.     return 0;
  311. #else
  312.     return ruserok (remote_host, pwd->pw_uid == 0,
  313.                 remote_name, name) == RUSEROK;
  314. #endif
  315. }
  316.  
  317. get_remote_string (buf, size)
  318. char    *buf;
  319. int    size;
  320. {
  321.     for (;;) {
  322.         if (read (0, buf, 1) != 1)
  323.               exit (1);
  324.         if (*buf == '\0')
  325.             return;
  326.         if (--size > 0)
  327.             ++buf;
  328.     }
  329.     /*NOTREACHED*/
  330. }
  331. #endif
  332.  
  333. /*
  334.  * login - create a new login session for a user
  335.  *
  336.  *    login is typically called by getty as the second step of a
  337.  *    new user session.  getty is responsible for setting the line
  338.  *    characteristics to a reasonable set of values and getting
  339.  *    the name of the user to be logged in.  login may also be
  340.  *    called to create a new user session on a pty for a variety
  341.  *    of reasons, such as X servers or network logins.
  342.  *
  343.  *    the flags which login supports are
  344.  *    
  345.  *    -p - preserve the environment
  346.  *    -r - perform autologin protocol for rlogin
  347.  *    -f - do not perform authentication, user is preauthenticated
  348.  *    -h - the name of the remote host
  349.  */
  350.  
  351. int
  352. main (argc, argv, envp)
  353. int    argc;
  354. char    **argv;
  355. char    **envp;
  356. {
  357.     char    name[32];
  358.     char    pass[32];
  359.     char    tty[BUFSIZ];
  360.     int    reason = PW_LOGIN;
  361.     int    retries;
  362.     int    failed;
  363.     int    flag;
  364.     int    subroot = 0;
  365.     char    *fname;
  366.     char    *cp;
  367.     char    *tmp;
  368.     char    buff[128];
  369.     struct    passwd    *pwd;
  370. #ifdef    SHADOWPWD
  371.     struct    spwd    *spwd;
  372.     struct    spwd    *getspnam();
  373. #endif
  374.  
  375.     /*
  376.      * Some quick initialization.
  377.      */
  378.  
  379.     name[0] = '\0';
  380.  
  381.     /*
  382.      * Get the utmp file entry and get the tty name from it.  The
  383.      * current process ID must match the process ID in the utmp
  384.      * file if there are no additional flags on the command line.
  385.      */
  386.  
  387.     checkutmp (argc == 1 || argv[1][0] != '-');
  388.     STRFCPY (tty, utent.ut_line);
  389.  
  390.     if (Prog = strrchr (argv[0], '/'))
  391.         Prog++;
  392.     else
  393.         Prog = argv[0];
  394.  
  395. #ifdef    RLOGIN
  396.     while ((flag = getopt (argc, argv, "pr:f:h:")) != EOF)
  397. #else
  398.     while ((flag = getopt (argc, argv, "pf:")) != EOF)
  399. #endif
  400.     {
  401.         switch (flag) {
  402.             case 'p': pflg++;
  403.                 break;
  404.             case 'f':
  405.                 fflg++;
  406.                 preauth_flag++;
  407.                 STRFCPY (name, optarg);
  408.                 break;
  409. #ifdef    RLOGIN
  410.             case 'r':
  411.                 rflg++;
  412.                 reason = PW_RLOGIN;
  413.                 STRFCPY (host, optarg);
  414. #ifdef    UT_HOST
  415.                 STRFCPY (utent.ut_host, optarg);
  416. #endif    /*UT_HOST*/
  417. #ifdef    SVR4
  418.                 STRFCPY (utxent.ut_host, optarg);
  419. #endif    /* SVR4 */
  420.                 if (rlogin (host, name, sizeof name))
  421.                     preauth_flag++;
  422.  
  423.                 break;
  424.             case 'h':
  425.                 hflg++;
  426.                 reason = PW_TELNET;
  427.                 STRFCPY (host, optarg);
  428. #ifdef    UT_HOST
  429.                 STRFCPY (utent.ut_host, optarg);
  430. #endif    /*UT_HOST*/
  431. #ifdef    SVR4
  432.                 STRFCPY (utxent.ut_host, optarg);
  433. #endif    /* SVR4 */
  434.                 break;
  435. #endif    /*RLOGIN*/
  436.             default:
  437.                 usage ();
  438.         }
  439.     }
  440.  
  441. #ifdef    RLOGIN
  442.     /*
  443.      * Neither -h nor -f should be combined with -r.
  444.      */
  445.  
  446.     if (rflg && (hflg || fflg))
  447.         usage ();
  448. #endif
  449.  
  450.     /*
  451.      * Allow authentication bypass only if real UID is zero.
  452.      */
  453.  
  454.     if ((rflg || fflg) && getuid () != 0) {
  455.         fprintf(stderr, "%s: permission denied\n", Prog);
  456.         exit (1);
  457.     }
  458.  
  459.     if (! isatty (0) || ! isatty (1) || ! isatty (2))
  460.         exit (1);        /* must be a terminal */
  461.  
  462. #ifdef    USE_SYSLOG
  463.     openlog (Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
  464. #endif
  465.  
  466. #ifndef    BSD
  467.     GTTY (0, &termio);        /* get terminal characteristics */
  468.  
  469.     /*
  470.      * Add your favorite terminal modes here ...
  471.      */
  472.  
  473.     termio.c_lflag |= ISIG;
  474.  
  475.     termio.c_cc[VERASE] = getdef_num("ERASECHAR", '\b');
  476.     termio.c_cc[VKILL] = getdef_num("KILLCHAR", '\025');
  477.  
  478.     /*
  479.      * ttymon invocation prefers this, but these settings won't come into
  480.      * effect after the first username login 
  481.      */
  482.  
  483.     STTY (0, &termio);
  484. #endif    /* !BSD */
  485.     umask (getdef_num("UMASK", 0));
  486. #ifdef HAVE_ULIMIT
  487.     {
  488.         /* 
  489.          * Use the ULIMIT in the login.defs file, and if
  490.          * there isn't one, use the default value.  The
  491.          * user may have one for themselves, but otherwise,
  492.          * just take what you get.
  493.          */
  494.  
  495.         long limit = getdef_long("ULIMIT", -1L);
  496.  
  497.         if (limit != -1)
  498.             ulimit (2, limit);
  499.     }
  500. #endif
  501.  
  502.     /*
  503.      * The entire environment will be preserved if the -p flag
  504.      * is used.
  505.      */
  506.  
  507.     if (pflg)
  508.         while (*envp)        /* add inherited environment, */
  509.             addenv (*envp++); /* some variables change later */
  510.  
  511. #ifdef    RLOGIN
  512.     if (term[5] != '\0')        /* see if anything after "TERM=" */
  513.         addenv (term);
  514. #endif
  515.     /*
  516.      * Add the timezone environmental variable so that time functions
  517.      * work correctly.
  518.      */
  519.  
  520.     if (tmp = getenv ("TZ")) {
  521.         strcat (strcpy (buff, "TZ="), tmp);
  522.         addenv (buff);
  523.     } else if (cp = getdef_str ("ENV_TZ"))
  524.         addenv (*cp == '/' ? tz (cp):cp);
  525.  
  526.     /* 
  527.      * Add the clock frequency so that profiling commands work
  528.      * correctly.
  529.      */
  530.  
  531.     if (tmp = getenv("HZ")) {
  532.         strcat (strcpy (buff, "HZ="), tmp);
  533.         addenv (buff);
  534.     } else if (cp = getdef_str("ENV_HZ"))
  535.         addenv (cp);
  536.  
  537.     if (optind < argc) {        /* get the user name */
  538.         if (rflg || fflg)
  539.             usage ();
  540.  
  541. #ifdef SVR4
  542.         /*
  543.          * The "-h" option can't be used with a command-line username,
  544.          * because telnetd invokes us as: login -h host TERM=...
  545.          */
  546.  
  547.         if (! hflg) {
  548.             STRFCPY (name, argv[optind]);
  549.             ++optind;
  550.         }
  551. #else
  552.         STRFCPY (name, argv[optind]);
  553.         ++optind;
  554. #endif
  555.     }
  556. #ifdef SVR4
  557.     /*
  558.      * check whether ttymon has done the prompt for us already
  559.      */
  560.  
  561.     {
  562.         char *ttymon_prompt;
  563.  
  564.         if ((ttymon_prompt = getenv("TTYPROMPT")) != NULL &&
  565.             (*ttymon_prompt != 0)) {
  566.         login(name, 0);    /* read name, without prompt */
  567.         }
  568.     }
  569. #endif /* SVR4 */
  570.     if (optind < argc)        /* now set command line variables */
  571.             setenv (argc - optind, &argv[optind]);
  572.  
  573. top:
  574.     (void) alarm (ALARM);        /* only allow ALARM sec. for login */
  575.  
  576.     environ = newenvp;        /* make new environment active */
  577.     retries = RETRIES;
  578.     while (1) {    /* repeatedly get login/password pairs */
  579.         failed = 0;        /* haven't failed authentication yet */
  580.         pass[0] = '\0';
  581.  
  582.         if (! name[0]) {    /* need to get a login id */
  583.             if (subroot) {
  584. #ifdef    USE_SYSLOG
  585.                 closelog ();
  586. #endif
  587.                 exit (1);
  588.             }
  589. #ifdef    RLOGIN
  590.             preauth_flag = 0;
  591. #endif
  592.             login (name, "login: ");
  593.             continue;
  594.         }
  595.         if (! (pwd = getpwnam (name))) {
  596.             pwent.pw_name = name;
  597.             pwent.pw_passwd = "!";
  598.             pwent.pw_shell = "/bin/sh";
  599.  
  600.             preauth_flag = 0;
  601.             failed = 1;
  602.         } else {
  603.             pwent = *pwd;
  604.         }
  605. #ifdef    SHADOWPWD
  606.         if (pwd) {
  607.             if (! (spwd = getspnam (name)))
  608. #ifdef    USE_SYSLOG
  609.                 syslog (LOG_WARN, NO_SHADOW, name, tty);
  610. #else
  611.                 ;
  612. #endif
  613.             else
  614.                 pwent.pw_passwd = spwd->sp_pwdp;
  615.         }
  616. #endif    /* SHADOWPWD */
  617. #ifdef    RLOGIN
  618.         /*
  619.          * If the encrypted password begins with a "!", the account
  620.          * is locked and the user cannot login, even if they have
  621.          * been "pre-authenticated."
  622.          */
  623.  
  624.         if (pwent.pw_passwd[0] == '!' || pwent.pw_passwd[0] == '*')
  625.             failed = 1;
  626.  
  627.         /*
  628.          * The -r and -f flags provide a name which has already
  629.          * been authenticated by some server.
  630.          */
  631.  
  632.         if (preauth_flag)
  633.             goto have_name;
  634. #endif    /*RLOGIN*/
  635.  
  636.         if (pw_auth (pwent.pw_passwd, name, reason, (char *) 0)) {
  637. #ifdef    USE_SYSLOG
  638. #ifdef UT_HOST
  639.             if (*(utent.ut_host))
  640.                 syslog (LOG_WARN, BAD_PASSWD_HOST,
  641.                     name, tty, utent.ut_host);
  642.             else
  643. #endif /* UT_HOST */
  644. #ifdef SVR4
  645.             if (*(utxent.ut_host))
  646.                 syslog (LOG_WARN, BAD_PASSWD_HOST,
  647.                     name, tty, utxent.ut_host);
  648.             else
  649. #endif /* SVR4 */
  650.                 syslog (LOG_WARN, BAD_PASSWD,
  651.                     name, tty);
  652. #endif /* USE_SYSLOG */
  653.             failed = 1;
  654.         }
  655.         goto auth_done;
  656.  
  657.         /*
  658.          * This is the point where all authenticated users
  659.          * wind up.  If you reach this far, your password has
  660.          * been authenticated and so on.
  661.          */
  662.  
  663. auth_done:
  664. #ifdef    RLOGIN
  665. have_name:
  666. #endif
  667.         if (getdef_bool("DIALUPS_CHECK_ENAB")) {
  668.             alarm (30);
  669.  
  670.             if (! dialcheck (tty, pwent.pw_shell[0] ?
  671.                     pwent.pw_shell:"/bin/sh")) {
  672. #ifdef    USE_SYSLOG
  673.                 syslog (LOG_WARN, BAD_DIALUP, name, tty);
  674. #endif
  675.                 failed = 1;
  676.             }
  677.         }
  678.         if (getdef_bool("PORTTIME_CHECKS_ENAB") &&
  679.             ! isttytime (pwent.pw_name, tty, time ((time_t *) 0))
  680.         ) {
  681. #ifdef    USE_SYSLOG
  682. #ifdef UT_HOST
  683.             if (*(utent.ut_host))
  684.                 syslog (LOG_WARN, BAD_TIME_HOST, name, tty,
  685.                     utent.ut_host);
  686.             else
  687. #endif    /* UT_HOST */
  688. #ifdef SVR4
  689.             if (*(utxent.ut_host))
  690.                 syslog (LOG_WARN, BAD_TIME_HOST, name, tty,
  691.                     utxent.ut_host);
  692.             else
  693. #endif    /* SVR4 */
  694.                 syslog (LOG_WARN, BAD_TIME, name, tty);
  695. #endif    /* USE_SYSLOG */
  696.                 failed = 1;
  697.         }
  698.         if (! failed && pwent.pw_name && pwent.pw_uid == 0 &&
  699.                 ! console (tty)) {
  700. #ifdef    USE_SYSLOG
  701.             syslog (LOG_CRIT, BAD_ROOT_LOGIN, tty);
  702. #endif
  703.             failed = 1;
  704.         }
  705.         if (pwd && getdef_bool("FAILLOG_ENAB") && 
  706.                 ! failcheck (pwent.pw_uid, &faillog, failed)) {
  707. #ifdef    USE_SYSLOG
  708.             syslog (LOG_CRIT, FAILURE_CNT, name, tty);
  709. #endif
  710.             failed = 1;
  711.         }
  712.         if (! failed)
  713.             break;
  714.  
  715.         puts ("Login incorrect");
  716. #ifdef    RLOGIN
  717.         if (rflg || fflg) {
  718. #ifdef    USE_SYSLOG
  719.             closelog ();
  720. #endif
  721.             exit (1);
  722.         }
  723. #endif    /*RLOGIN*/
  724.  
  725.         /* don't log non-existent users */
  726.         if (pwd && getdef_bool("FAILLOG_ENAB"))
  727.             failure (pwent.pw_uid, tty, &faillog);
  728.         if (getdef_str("FTMP_FILE") != NULL) {
  729. #ifdef    SVR4
  730.             failent = utxent;
  731. #else
  732.             failent = utent;
  733. #endif
  734.  
  735.             if (pwd)
  736.                 STRFCPY (failent.ut_name, pwent.pw_name);
  737.             else
  738.                 if (getdef_bool("LOG_UNKFAIL_ENAB"))
  739.                     STRFCPY (failent.ut_name, name);
  740.                 else
  741.                     STRFCPY (failent.ut_name, "UNKNOWN");
  742. #ifdef    SVR4
  743.             gettimeofday (&(failent.ut_tv));
  744. #else
  745.             time (&failent.ut_time);
  746. #endif
  747. #ifdef    USG_UTMP
  748.             failent.ut_type = USER_PROCESS;
  749. #endif
  750.             failtmp (&failent);
  751.         }
  752.  
  753.         if (--retries <= 0) {    /* only allow so many failures */
  754. #ifdef    USE_SYSLOG
  755.             closelog ();
  756. #endif
  757.             exit (1);
  758.         }
  759. again:
  760.         bzero (name, sizeof name);
  761.         bzero (pass, sizeof pass);
  762.  
  763.         /*
  764.          * Wait a while (a la SVR4 /usr/bin/login) before attempting
  765.          * to login the user again.  If the earlier alarm occurs
  766.          * before the sleep() below completes, login will exit.
  767.          */
  768.  
  769.         if (getdef_num ("FAIL_DELAY", 0))
  770.             sleep (getdef_num ("FAIL_DELAY", 0));
  771.     }
  772.     (void) alarm (0);        /* turn off alarm clock */
  773.  
  774.     /*
  775.      * Check to see if system is turned off for non-root users.
  776.      * This would be useful to prevent users from logging in
  777.      * during system maintenance.  We make sure the message comes
  778.      * out for root so she knows to remove the file if she's
  779.      * forgotten about it ...
  780.      */
  781.  
  782.     fname = getdef_str("NOLOGINS_FILE");
  783.     if (fname != NULL && access (fname, 0) == 0) {
  784.         FILE    *nlfp;
  785.         int    c;
  786.  
  787.         /*
  788.          * Cat the file if it can be opened, otherwise just
  789.          * print a default message
  790.          */
  791.  
  792.         if (nlfp = fopen (fname, "r")) {
  793.             while ((c = getc (nlfp)) != EOF) {
  794.                 if (c == '\n')
  795.                     putchar ('\r');
  796.  
  797.                 putchar (c);
  798.             }
  799.             fflush (stdout);
  800.             fclose (nlfp);
  801.         } else
  802.             printf ("\r\nSystem closed for routine maintenance\r\n");
  803.         /*
  804.          * Non-root users must exit.  Root gets the message, but
  805.          * gets to login.
  806.          */
  807.  
  808.         if (pwent.pw_uid != 0) {
  809.   
  810. #ifdef    USE_SYSLOG
  811.             closelog ();
  812. #endif
  813.             exit (0);
  814.         }
  815.         printf ("\r\n[Disconnect bypassed -- root login allowed.]\r\n");
  816.     }
  817.     if (getenv ("IFS"))        /* don't export user IFS ... */
  818.         addenv ("IFS= \t\n");    /* ... instead, set a safe IFS */
  819.  
  820.     setutmp (name, tty);        /* make entry in utmp & wtmp files */
  821.     if (pwent.pw_shell[0] == '*') {    /* subsystem root */
  822.         subsystem (&pwent);    /* figure out what to execute */
  823.         subroot++;        /* say i was here again */
  824.         endpwent ();        /* close all of the file which were */
  825.         endgrent ();        /* open in the original rooted file */
  826. #ifdef    SHADOWPWD
  827.         endspent ();        /* system.  they will be re-opened */
  828. #endif
  829. #ifdef    SHADOWGRP
  830.         endsgent ();        /* in the new rooted file system */
  831. #endif
  832.         goto top;        /* go do all this all over again */
  833.     }
  834.     if (getdef_bool("LASTLOG_ENAB"))
  835.         log ();            /* give last login and log this one */
  836.  
  837. #ifdef SVR4_SI86_EUA
  838.     sysi86(SI86LIMUSER, EUA_ADD_USER);    /* how do we test for fail? */
  839. #endif
  840.  
  841.     setup (&pwent);            /* set UID, GID, HOME, etc ... */
  842. #ifdef    AGING
  843. #ifdef    SHADOWPWD
  844.     if (spwd) {            /* check for age of password */
  845.         if (expire (&pwent, spwd)) {
  846.             spwd = getspnam (name);
  847.             pwd = getpwnam (name);
  848.             pwent = *pwd;
  849.         }
  850.     }
  851. #endif
  852. #ifdef    ATT_AGE
  853. #ifdef    SHADOWPWD
  854.     else
  855. #endif
  856.     if (pwent.pw_age && pwent.pw_age[0]) {
  857.         if (expire (&pwent, (void *) 0)) {
  858.             pwd = getpwnam (name);
  859.             pwent = *pwd;
  860.         }
  861.     }
  862. #endif    /* ATT_AGE */
  863. #endif    /* AGING */
  864.     if (! hushed (&pwent)) {
  865.         motd ();        /* print the message of the day */
  866.         if (getdef_bool ("FAILLOG_ENAB") && faillog.fail_cnt != 0)
  867.             failprint (&faillog);
  868.         if (getdef_bool ("LASTLOG_ENAB") && lastlog.ll_time != 0) {
  869.             printf ("Last login: %.19s on %s",
  870.                 ctime (&lastlog.ll_time), lastlog.ll_line);
  871. #ifdef    SVR4
  872.             if (lastlog.ll_host[0])
  873.                 printf(" from %.16s", lastlog.ll_host);
  874. #endif
  875.             printf("\n");
  876.         }
  877. #ifdef    AGING
  878. #ifdef    SHADOWPWD
  879.         agecheck (&pwent, spwd);
  880. #else
  881.         agecheck (&pwent, (void *) 0);
  882. #endif
  883. #endif    /* AGING */
  884.         mailcheck ();    /* report on the status of mail */
  885.     }
  886.     if (getdef_str("TTYTYPE_FILE") != NULL && getenv("TERM") == NULL)
  887.           ttytype (tty);
  888.  
  889.     signal (SIGINT, SIG_DFL);    /* default interrupt signal */
  890.     signal (SIGQUIT, SIG_DFL);    /* default quit signal */
  891.     signal (SIGTERM, SIG_DFL);    /* default terminate signal */
  892.     signal (SIGALRM, SIG_DFL);    /* default alarm signal */
  893.  
  894.     endpwent ();            /* stop access to password file */
  895.     endgrent ();            /* stop access to group file */
  896. #ifdef    SHADOWPWD
  897.     endspent ();            /* stop access to shadow passwd file */
  898. #endif
  899. #ifdef    SHADOWGRP
  900.     endsgent ();            /* stop access to shadow group file */
  901. #endif
  902. #ifdef    USE_SYSLOG
  903.     if (pwent.pw_uid == 0)
  904.         syslog (LOG_NOTICE, ROOT_LOGIN, tty);
  905.  
  906.     closelog ();
  907. #endif
  908.     shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
  909.     /*NOTREACHED*/
  910. }
  911.