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

  1. /*
  2.  * Copyright 1989, 1990, 1991, 1992, 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. #ifdef SVR4
  16. #include <utmpx.h>
  17. #else
  18. #include <sys/types.h>
  19. #include <utmp.h>
  20. #endif
  21. #include <signal.h>
  22. #include <stdio.h>
  23. #include "pwd.h"
  24. #include <fcntl.h>
  25. #ifdef    BSD
  26. #include <strings.h>
  27. #define    strchr    index
  28. #define    strrchr    rindex
  29. #else
  30. #include <string.h>
  31. #include <memory.h>
  32. #endif
  33. #include "config.h"
  34. #include "pwauth.h"
  35.  
  36. #if defined(BSD) || defined(SUN)
  37. #include <sgtty.h>
  38. #define    USE_SGTTY    1
  39. #endif
  40. #if defined(USG) || defined(SUN4)
  41. #ifdef    _POSIX_SOURCE
  42. #include <termios.h>
  43. #define    USE_TERMIOS    1
  44. #else
  45. #include <termio.h>
  46. #define    USE_TERMIO    1
  47. #endif
  48. #endif
  49.  
  50. #ifdef    USE_SYSLOG
  51. #include <syslog.h>
  52.  
  53. #ifndef    LOG_WARN
  54. #define    LOG_WARN    LOG_WARNING
  55. #endif
  56. #endif
  57.  
  58. #ifndef    lint
  59. static    char    sccsid[] = "@(#)sulogin.c    3.12    13:04:09    27 Jul 1992";
  60. #endif
  61.  
  62. char    name[BUFSIZ];
  63. char    pass[BUFSIZ];
  64. char    home[BUFSIZ];
  65. char    prog[BUFSIZ];
  66. char    mail[BUFSIZ];
  67.  
  68. struct    passwd    pwent;
  69. #ifdef SVR4
  70. struct    utmpx    utent;
  71. #else
  72. struct    utmp    utent;
  73. #endif
  74.  
  75. #ifdef    USE_SGTTY
  76. struct    sgttyb    termio;
  77. #endif
  78. #ifdef    USE_TERMIO
  79. struct    termio    termio;
  80. #endif
  81. #ifdef    USE_TERMIOS
  82. struct    termios    termio;
  83. #endif
  84.  
  85. #ifndef    MAXENV
  86. #define    MAXENV    64
  87. #endif
  88.  
  89. char    *newenvp[MAXENV];
  90. int    newenvc = 0;
  91. int    maxenv = MAXENV;
  92. extern    char    **environ;
  93. extern    char    *getpass();
  94.  
  95. extern    char    *getdef_str();
  96.  
  97. #ifndef    ALARM
  98. #define    ALARM    60
  99. #endif
  100.  
  101. #ifndef    RETRIES
  102. #define    RETRIES    3
  103. #endif
  104.  
  105. catch (sig)
  106. int    sig;
  107. {
  108.     exit (1);
  109. }
  110.  
  111. /*ARGSUSED*/
  112. int
  113. main (argc, argv, envp)
  114. int    argc;
  115. char    **argv;
  116. char    **envp;
  117. {
  118.     char    *getenv ();
  119.     char    *ttyname ();
  120.     char    *getpass ();
  121.     char    *tz ();
  122.     char    *cp;
  123.  
  124. #ifdef    USE_SGTTY
  125.     ioctl (0, TIOCGETP, &termio);
  126.     termio.sg_flags |= (ECHO|CRMOD);
  127.     termio.sg_flags &= ~(RAW|CBREAK);
  128.     ioctl (0, TIOCSETN, &termio);
  129. #endif
  130. #ifdef    USE_TERMIO
  131.     ioctl (0, TCGETA, &termio);
  132.     termio.c_iflag |= (ICRNL|IXON);
  133.     termio.c_oflag |= (OPOST|ONLCR);
  134.     termio.c_cflag |= (CREAD);
  135.     termio.c_lflag |= (ISIG|ICANON|ECHO|ECHOE|ECHOK);
  136.     ioctl (0, TCSETAF, &termio);
  137. #endif
  138. #ifdef    USE_TERMIOS
  139.     tcgetattr (0, &termio);
  140.     termio.c_iflag |= (ICRNL|IXON);
  141.     termio.c_oflag |= (CREAD);
  142.     termio.c_lflag |= (ECHO|ECHOE|ECHOK|ICANON|ISIG);
  143.     tcsetattr (0, TCSANOW, &termio);
  144. #endif
  145. #ifdef    USE_SYSLOG
  146.     openlog ("sulogin", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
  147. #endif
  148.     if (argc > 1) {
  149.         close (0);
  150.         close (1);
  151.         close (2);
  152.  
  153.         if (open (argv[1], O_RDWR) >= 0) {
  154.             dup (0);
  155.             dup (0);
  156.         } else {
  157. #ifdef    USE_SYSLOG
  158.             syslog (LOG_WARN, "cannot open %s\n", argv[1]);
  159.             closelog ();
  160. #endif
  161.             exit (1);
  162.         }
  163.     }
  164.     if (access (PWDFILE, 0) == -1) { /* must be a password file! */
  165.         printf ("No password file\n");
  166. #ifdef    USE_SYSLOG
  167.         syslog (LOG_WARN, "No password file\n");
  168.         closelog ();
  169. #endif
  170.         exit (1);
  171.     }
  172. #ifndef    DEBUG
  173.     if (getppid () != 1) {        /* parent must be INIT */
  174. #ifdef    USE_SYSLOG
  175.         syslog (LOG_WARN, "Pid == %d, not 1\n", getppid ());
  176.         closelog ();
  177. #endif
  178.         exit (1);
  179.     }
  180. #endif
  181.     if (! isatty (0) || ! isatty (1) || ! isatty (2)) {
  182. #ifdef    USE_SYSLOG
  183.         closelog ();
  184. #endif
  185.         exit (1);        /* must be a terminal */
  186.     }
  187.     while (*envp)            /* add inherited environment, */
  188.         addenv (*envp++);    /* some variables change later */
  189.  
  190.     if (cp = getdef_str("ENV_TZ"))
  191.         addenv (*cp == '/' ? tz(cp) : cp);
  192.     if (cp = getdef_str("ENV_HZ"))
  193.         addenv (cp);        /* set the default $HZ, if one */
  194.     (void) strcpy (name, "root");    /* KLUDGE!!! */
  195.  
  196.     signal (SIGALRM, catch);    /* exit if the timer expires */
  197.     alarm (ALARM);            /* only wait so long ... */
  198.  
  199.     while (1) {        /* repeatedly get login/password pairs */
  200.         entry (name, &pwent);    /* get entry from password file */
  201.         if (pwent.pw_name == (char *) 0) {
  202.  
  203.             /*
  204.              * Fail secure
  205.              */
  206.  
  207.             printf ("No password entry for 'root'\n");
  208. #ifdef    USE_SYSLOG
  209.             syslog (LOG_WARN, "No password entry for 'root'\n");
  210.             closelog ();
  211. #endif
  212.             exit (1);
  213.         }
  214.  
  215.     /*
  216.      * Here we prompt for the root password, or if no password is
  217.      * given we just exit.
  218.      */
  219.  
  220.                     /* get a password for root */
  221.         if (! (cp = getpass ("Type control-d for normal startup,\n\
  222. (or give root password for system maintenance):"))) {
  223. #ifdef    USE_SYSLOG
  224.             syslog (LOG_INFO, "Normal startup\n");
  225.             closelog ();
  226. #endif
  227. #ifdef    TELINIT
  228.             execl ("/etc/telinit", "telinit", RUNLEVEL, (char *) 0);
  229. #endif
  230.             exit (0);
  231.         } else
  232.             strcpy (pass, cp);
  233.  
  234.         if (pwent.pw_name && pwent.pw_passwd[0] == '@') {
  235.             if (pw_auth (pwent.pw_passwd + 1, name, PW_LOGIN)) {
  236. #ifdef    USE_SYSLOG
  237.                 syslog (LOG_WARN,
  238.                     "Incorrect root authentication");
  239. #endif
  240.                 continue;
  241.             }
  242.             goto auth_done;
  243.         }
  244.         if (valid (pass, &pwent)) /* check encrypted passwords ... */
  245.             break;        /* ... encrypted passwords matched */
  246.  
  247.         puts ("Login incorrect");
  248. #ifdef    USE_SYSLOG
  249.         syslog (LOG_WARN, "Incorrect root password\n");
  250. #endif
  251.     }
  252. auth_done:
  253.     alarm (0);
  254.     signal (SIGALRM, SIG_DFL);
  255.     environ = newenvp;        /* make new environment active */
  256.  
  257.     puts ("Entering System Maintenance Mode");
  258. #ifdef    USE_SYSLOG
  259.     syslog (LOG_INFO, "System Maintenance Mode\n");
  260. #endif
  261.  
  262.     /*
  263.      * Normally there would be a utmp entry for login to mung on
  264.      * to get the tty name, date, etc. from.  We don't need all that
  265.      * stuff because we won't update the utmp or wtmp files.  BUT!,
  266.      * we do need the tty name so we can set the permissions and
  267.      * ownership.
  268.      */
  269.  
  270.     if (cp = ttyname (0)) {        /* found entry in /dev/ */
  271.         if (strrchr (cp, '/') != (char *) 0)
  272.             strcpy (utent.ut_line, strrchr (cp, '/') + 1);
  273.         else
  274.             strcpy (utent.ut_line, cp);
  275.     }
  276.     if (getenv ("IFS"))        /* don't export user IFS ... */
  277.         addenv ("IFS= \t\n");    /* ... instead, set a safe IFS */
  278.  
  279.     setup (&pwent);            /* set UID, GID, HOME, etc ... */
  280.  
  281. #ifdef    USE_SYSLOG
  282.     closelog ();
  283. #endif
  284.     shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
  285.     /*NOTREACHED*/
  286. }
  287.