home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / UUCPbb_2_1_src.lzh / UUCPBB21 / login.c < prev    next >
C/C++ Source or Header  |  1994-09-25  |  21KB  |  681 lines

  1. /*  L o g i n . C
  2.     -- a level independent login program for OS-9
  3.  
  4.     AUTHOR
  5.       Peter Durham
  6.       The Wentworth Timesharing System
  7.       summer: 6 Twin Brook Circle        school: Quincy House D-24
  8.               Andover, MA 01810                  58 Plympton St.
  9.               (617) 475-4243                     Cambridge, MA 02138
  10.                                                  (617) 498-3209
  11.       cis:    73177,1215                 delphi: PEDXING
  12.       unix:   harvard!husc4!durham_2     intnet: durham_2@husc4.harvard.edu 
  13.  
  14.     Hacked upon by Mark Griffith [MDG], CIS 76070,41
  15.     Hacked upon by Bob Billson (REB) <uunet!kc2wz!bob> for the OS-9 UUCP
  16.         package, UUCPbb.
  17.  
  18.     VERSION
  19.       02.00.00   86/06/25   Changes for CoCo OS-9 02.00.00:
  20.                             * Added CR since echo off doesn't echo CR
  21.                             * If directory isn't found, remains in current
  22.                             * Checks for mail in "mailbox" file in login dir
  23.       02.00.01   87/06/05   Changes for CoCo OS-9 Level II 02.00.01:
  24.                             * ifdef added for Level II set user
  25.       02.01.00   87/06/14   Changes to help clean up
  26.                             * strings put all in one place
  27.                             * detects level
  28.       02.02.00   88/10/12   Heavily modified to support user logging
  29.                             * changes in mail check routines,
  30.                             * and other trivial things [MDG]
  31.                             * This version requires the Kreider "C" library
  32.       02.02.01   90/01/13   Modified to check login times for lockout periods
  33.                             [Added - MDG]
  34.       02.02.02   90/05/14   Hacks by E Gresick [EG]
  35.                             * Added 'alias' file to get
  36.                             * alias site and remote names.
  37.                             * Added 'login.errors' file to store incorrect
  38.                             * login entries.
  39.       02.02.03   90/06/03   * Added tty locking code for UUCP
  40.                             * Removed listing of MOTD also for UUCP
  41.                             * (put 'list motd' in users ulogin file)
  42.                             * Removed checking for mail
  43.                             * (put 'lmail -c' in ulogin file) [MDG]
  44.       02.02.04   90/07/17   * Added input timeouts for logging in to
  45.                             * prevent stuck login processes [MDG]
  46.       02.02.05   90/07/27   * added Ed Gresick's logerr() function
  47.       02.30      ????????   * Released as version 2.3
  48.  
  49.       02.31      91/07/17   Minor updates done by Bob Billson (REB)
  50.                             <...!uunet!kc2wz!bob>
  51.                             * Fixed minor bug which caused input timeout to
  52.                             * to work only if no characters were received.
  53.                             * Any input would cause login to wait for the CR
  54.                             * Changed some #define macros into functions.
  55.       02.32      94/03/20   Updates by Bob Billson
  56.                             * Changed to use password functions from Kreider
  57.                             * clib.l.
  58.                             * Only prompt for password if one is required.
  59. */
  60.  
  61. #define MAIN                /* Added -- REB */
  62.  
  63. #include "uucp.h"           /* several variables defined here - REQUIRED */
  64. #include <os9.h>
  65. #include <time.h>
  66. #include <utime.h>
  67. #include <sgstat.h>
  68. #include <password.h>       /* From Carl Kreider's CLIB -- REB */
  69.  
  70.  
  71. #define   LEVEL2   TRUE     /* make this FALSE (0) if compiling for Level 1 */
  72. #define   TIMEOUT   10      /* seconds before response timeout */
  73. #define   ON         1
  74. #define   OFF        0
  75. #define   NODATA    -1
  76.  
  77. /* Changed these strings into functions.  Makes the resulting code just a tad
  78.    smaller. --REB
  79. #define   _fix(x)   while (*_f++ != '\n'); *--_f = '\0'
  80. #define   getstr(x) {char *_f = x; readln(0, x, sizeof(x)); _fix(x);}
  81. */
  82.  
  83. QQ PWENT *pwentry;
  84. QQ FILE *fp, *fdA;
  85. QQ char *login_name;                    /* name User logins in as */
  86. char tempstr[256],
  87.      devname[9],                        /* Buffer for device name */
  88.      oldlogname[PWNSIZ+1],
  89.      inname[PWNSIZ+1],                  /* User name input */
  90.      inpass[PWPSIZ+1];                  /* User password input */
  91.  
  92. long curr_time;                         /* holds login time [MDG] */
  93. struct sgtbuf os9_time;
  94. char *chk_alias();
  95.  
  96. /*  S t r i n g s */
  97.  
  98. QQ char NewLine = '\n',
  99.         *Sorry = " Can't open password file\n",
  100.         *Syntax = " Syntax error in password file!\n",
  101.         *lfile_err = " Can't open logins file\n",
  102.         *ufile_err = " Can't open user.login file\n",
  103.         *log_err = " Can't change log directory",
  104.         *timeout = " Timeout period exceeded\n<click>\n",
  105.         *badtime = " Login out of allowed time period\n";
  106.  
  107. /* Change these strings as needed for your system (adds flexibility [MDG])
  108.    logdir, DEFWORKDIR and DEFEXECDIR are defined in uucp.h. --REB */
  109.  
  110. QQ char *defw = DEFWORKDIR,             /* default data and execution */
  111.         *defx = DEFEXECDIR;             /* directories in case of error */
  112.  
  113. /*  F u n c t i o n s */
  114.  
  115. /*  FUNCTION    main()
  116.     PURPOSE     main loop  */
  117.  
  118. main()
  119. {
  120.      int i;
  121.  
  122.      setbuf (stdout, NULL);
  123.      setbuf (stdin, NULL);
  124.  
  125.      if ((logdir = getenv ("LOGDIR")) != NULL)
  126.           logdir = strdup (logdir);
  127.      else 
  128.           logdir = LOGDIR;
  129.  
  130.      _gs_devn (2, tempstr);                     /* get dev from stderr */
  131.      strhcpy (devname, tempstr);                /* copy changing high bit */
  132.      asetuid (0);               /* must be superuser to read/write password */
  133.      puts ("\nWelcome to the OS-9 Level Two Timesharing System");
  134.  
  135.      /* Try to login; if it returns here attempt failed */
  136.      for (i = 0; i < 3; ++i)
  137.        {
  138.           putchar (NewLine);
  139.           trylogin();
  140.           puts ("Bad login.  Try again.");
  141.        }
  142.  
  143.      /* If user doesn't make it in 3 tries, say bye */
  144.      puts ("\nIncorrect login, 3 tries and you're out!\n<click>");
  145.      myexit (0);
  146. }
  147.  
  148.  
  149.  
  150. /*  FUNCTION    trylogin()
  151.     PURPOSE     Function where all the work is done.  We prompt for
  152.                 username and password here, and check them. */
  153.  
  154. int trylogin()
  155. {
  156.      union {long l; char c[4];} crcpass;     /* Crc of password */
  157.      int path,                               /* Password path number */
  158.          procid;                             /* This process' ID number */
  159.      long  htol();                           /* Declare long function */
  160.      char tmptime[26];                       /* temporary time holder [REB] */
  161.  
  162.      /* Get the user name and the password */
  163.  
  164.      fputs ("login: ", stdout);
  165.  
  166.      /* Get login name and password. The timeout period is #defined in
  167.         TIMEOUT.  Returns TRUE if the user timed out.  FALSE is returned and
  168.         response is returned in 'inname' or 'inpass', otherwise.  The third
  169.         parameter is a flag telling if everything type should be echoed to the
  170.         standard output or not. --REB */
  171.  
  172.      if (get_response (inname, ON))
  173.        {
  174.           fputs (timeout, stdout);
  175.           logerr (2);
  176.           myexit (0);
  177.        }
  178.      putchar (NewLine);
  179.  
  180.      /* See if there is an entry for this name in the password file */
  181.      pwentry = getpwnam (inname);
  182.      endpwent();
  183.  
  184.      if (pwentry == (PWENT *) ERROR)
  185.        {
  186.           fputs (Sorry, stdout);
  187.           logerr (3);
  188.           myexit (1);
  189.        }
  190.  
  191.      if (pwentry == NULL)
  192.        {
  193.           /*  Add invalid entry in error log  [EG] */
  194.           logerr (1);
  195.           return;
  196.        }
  197.  
  198.      /* Do we need to get a password? */
  199.      if (0L != htol (pwentry->upw))
  200.        {
  201.         fputs ("Password: ", stdout);
  202.  
  203.           if (get_response (inpass, OFF))
  204.             {
  205.                fputs (timeout, stdout);
  206.                logerr (2);
  207.                myexit (0);
  208.             }
  209.           putchar (NewLine);
  210.  
  211.           /* Get the CRC of the password */
  212.           crcpass.l = 0xffffffL;
  213.           crc (inpass, strlen (inpass), &crcpass.c[1]);
  214.  
  215.           if (crcpass.l != htol (pwentry->upw))
  216.             {
  217.                logerr (1);
  218.                return;
  219.             }
  220.        }
  221.  
  222.      /* Check to see if this login is an alias and/or if they are allowed
  223.         to log in at this time.  Changed --REB */
  224.  
  225.      login_name = chk_alias (pwentry->unam);
  226.      chk_time (login_name);
  227.  
  228.      /* get our process ID */
  229.      procid = getpid();
  230.  
  231.      /* Get the login time and update the log file - added [MDG] */
  232.      curr_time = time ((long *)0);
  233.  
  234.      if (chdir (logdir) == -1)
  235.        {
  236.           fputs (log_err, stdout);
  237.           logerr (4);
  238.           myexit (0);
  239.        }
  240.  
  241.      sprintf (tempstr, "%s.login", login_name);
  242.      if ((fp = fopen (tempstr, "r+")) == 0)
  243.        {
  244.           fputs (ufile_err, stdout);
  245.           logerr (4);
  246.           myexit (0);
  247.        }
  248.  
  249.      strcpy (tmptime, ctime (&curr_time));
  250.      tmptime[3] = tmptime[10] = tmptime[19] = tmptime[24] = '\0';
  251.  
  252.      /* Print login messages */
  253.      fputs ("\nUser ", stdout);
  254.      putd (1, atoi (pwentry->uid));
  255.      printf (" logged in on %s, %s %s at %s as process ",
  256.              &tmptime[0], &tmptime[20], &tmptime[4], &tmptime[11]);
  257.      putd (1, procid);
  258.      printf (" on /%s\nLast login: ", devname);
  259.  
  260.      /* Read, print, and then update user login file.  Changed --REB */
  261.      mfgets (tempstr, sizeof (tempstr), fp);
  262.      puts (tempstr);
  263.      rewind (fp);
  264.      fprintf (fp, "%s, %s %s at %s\n%s",
  265.                   &tmptime[0], &tmptime[20], &tmptime[4], &tmptime[11],
  266.                   tempstr);
  267.  
  268.      fclose (fp);
  269.      putchar (NewLine);
  270.  
  271.      /* Update user login file */
  272.      strcpy (tempstr, "logins");
  273.  
  274.      if ((fp = fopen (tempstr, "a+")) == 0)
  275.        {
  276.           fixperms (fp);
  277.           fputs (lfile_err, stdout);
  278.           logerr (5);
  279.           myexit (0);
  280.        }
  281.  
  282.      sprintf (tempstr,"%s,%s,",login_name, devname);       /* added --REB */
  283.      fwrite (tempstr, strlen (tempstr), sizeof(char), fp);
  284.      fwrite (ctime (&curr_time), strlen (ctime (&curr_time)), sizeof(char), fp);
  285.      fclose (fp);
  286.  
  287.      /* Change directories */
  288.      if ((chxdir (pwentry->ucmd) == -1) || (chdir (pwentry->udat) == -1))
  289.        {
  290.           puts (" Can't find your login directory... will use default");
  291.           chdir (defw);
  292.           chxdir (defx);
  293.        }
  294.  
  295.      /* Set up the user's id and priority */
  296.      asetuid ((unsigned) atoi (pwentry->uid));
  297.      setpr (procid, atoi (pwentry->upri));
  298.  
  299.      /* Chain to the user's command - changed [MDG] */
  300.      sprintf (tempstr, "%s\n", pwentry->ujob);
  301.      chain ("shell", strlen (tempstr), tempstr, 1, 1, 0);
  302. }
  303.  
  304.  
  305.  
  306. /*  FUNCTION    putd()
  307.     PURPOSE     Writes a decimal number to a path
  308.     TAKES       int p, the path to write to
  309.                 int x, the number to write  */
  310.  
  311. int putd (p, x)
  312. int p, x;
  313. {
  314.      if (x > 99)
  315.           putch (p, x/100 + '0');
  316.  
  317.      if (x > 9)
  318.           putch (p, x%100/10 + '0');
  319.  
  320.      putch (p, x%10 + '0');
  321. }
  322.  
  323.  
  324.  
  325. /*  Added [EG]
  326.     mfgets  (modified fgets)
  327.     Same as fgets() only this version deletes '\n'
  328.     From Mark Griffiths UUCP.c program  */
  329.  
  330. char *mfgets (s, n, iop)
  331. register char   *s;
  332. register int     n;
  333. register FILE   *iop;
  334. {
  335.      register int    c;
  336.      register char   *cs;
  337.  
  338.      cs = s;
  339.      while (--n > 0 && (c = getc (iop)) != EOF)
  340.           if (c == 0x0D)
  341.             {
  342.                *cs = '\0';
  343.                break;
  344.             }
  345.           else
  346.                *cs++ = c;
  347.  
  348.      return ((c == EOF  && cs == s) ? (char *)NULL : s);
  349. }
  350.  
  351.  
  352.  
  353. /*  Checks alias file for any alias of the login name.
  354.     Returns a pointer to login name use.  This will be changed if an alias
  355.     was found.
  356.  
  357.     Note - 'oldlogname' (which must be a global variable)
  358.            holds original login name.
  359.  
  360.     declare oldlogname as 'char oldlogname[PWNSIZ+1]'  */
  361.  
  362. char *chk_alias (name)
  363. char *name;
  364. {
  365.      static char newlogname[PWNSIZ+1];
  366.      char logname[PWNSIZ+1], *words[2];
  367.      register char *p;
  368.      int i;
  369.  
  370.      p = tempstr;
  371.  
  372.      /* Save the original name "just in case" */
  373.      strcpy (newlogname, name);
  374.      strcpy (oldlogname, name);
  375.      sprintf (p, "%s/login.alias", logdir);
  376.  
  377.      /* Expected line format is:
  378.  
  379.            alias username
  380.  
  381.         Any lines starting with '#', <space>, <tab> or <cr> are comment lines
  382.         and are ignored.  Changed --REB */
  383.  
  384.      if ((fdA = fopen (p, "r" )) != NULL)
  385.        {
  386.           fixperms (fdA);
  387.           while (mfgets (p, sizeof (tempstr), fdA) != NULL)
  388.                if ( ISCOMMENT (*p) == FALSE)
  389.                     if ((i = getargs (words, tempstr, 2)) == 2)
  390.                          if (strnucmp (name, *words, strlen (name)) == 0)
  391.                            {
  392.                               strcpy (newlogname, words[1]);
  393.                               break;
  394.                            }
  395.           fclose(fdA);
  396.        }
  397.      return (newlogname);
  398. }
  399.  
  400.  
  401.  
  402. /*  Checks the login time for individual users and either allows login
  403.     to continue or exits with an error message [MDG]
  404.  
  405.     Allows unlimited logins to any user who does not have an entry in the
  406.     login.times file.
  407.  
  408.     This function applies either of 3 rules to determine whether 
  409.     the caller is calling at an allowed time.
  410.  
  411.     Rule 1: If 'endtime' is less than 'starttime' AND 
  412.             'curtime' is less than 'endtime' then add
  413.             2400 to 'curtime' and 'endtime'.
  414.                       - or -
  415.     Rule 2: If 'endtime' is less than 'starttime' then add
  416.             2400 to 'endtime'.
  417.  
  418.     Rule 3: If the second field of the entry is the word 'never', the user's
  419.             login attempt is always rejected.  --Added REB */
  420.  
  421. int chk_time (name)
  422. char *name;
  423. {
  424.      register char *p1;
  425.      char *curtime[20],
  426.           *p = &os9_time,
  427.           *words[3],
  428.           *nologin = "\n\nSORRY - You cannot login at this time! <click!>";
  429.      flag found_it = FALSE;
  430.      int curtm, starttime, endtime, i;
  431.  
  432.      getime (p);
  433.      sprintf (curtime, "%02d%02d", p->t_hour, p->t_minute);
  434.      sprintf (tempstr, "%s/login.times", logdir);
  435.      p1 = tempstr;
  436.  
  437.      /* Expected line format is:
  438.  
  439.            username  start_time end_time
  440.  
  441.         The second and third field is in 24-hour time format, i.e. 0930
  442.         is 9:30 am, 2145 is 9:45 pm.  Any lines starting with '#', <space>,
  443.         <tab> or <cr> are comment lines and are ignored.  Below, words[0]
  444.         is field 1, words[1] is field 2 and words[2] is field 3.
  445.         Changed --REB */
  446.  
  447.      if ((fdA = fopen (p1, "r" )) != NULL)
  448.        {
  449.           fixperms (fdA);
  450.           while (mfgets (p1, sizeof (tempstr), fdA) != NULL)
  451.                if ( ISCOMMENT (*p1) == FALSE)
  452.                     if ((i = getargs (words, tempstr, 3)) >= 2)
  453.                          if (strnucmp (name, *words, strlen (name)) == 0)
  454.                            {
  455.                               found_it = TRUE;
  456.                               break;
  457.                            }
  458.           fclose (fdA);
  459.        }
  460.  
  461.     /* if an entry was found, check the times */
  462.     if (found_it)
  463.       {
  464.           if (i == 2)
  465.                if (strucmp (words[1], "NEVER") == 0)
  466.                  {
  467.                     puts (nologin);
  468.                     logerr (7);
  469.                     myexit (0);
  470.                  }
  471.                else
  472.                  {
  473.                     logerr (9);
  474.                     myexit (0);
  475.                  }
  476.  
  477.           curtm = atoi (curtime);
  478.           starttime = atoi (words[1]);
  479.           endtime = atoi (words[2]);
  480.  
  481.           if ((endtime < starttime) && (curtm < endtime))
  482.             {
  483.                curtm += 2400;
  484.                endtime += 2400;
  485.             }
  486.           else if (endtime < starttime)
  487.                endtime += 2400;
  488.  
  489.           if ((curtm < starttime) || (curtm > endtime))
  490.             {
  491.                puts (nologin);
  492.                logerr (7);
  493.                myexit (0);
  494.             }
  495.        }
  496. }
  497.  
  498.  
  499.  
  500. /*  Writes log-in error information to /dd/LOG/login.errors.
  501.     due to:
  502.  
  503.     1  incorrect login name or password
  504.     2  timeout while waiting for a user response
  505.     3  can't open the password file
  506.     4  can't open the user.login file
  507.     5  can't open the logins file
  508.     6  syntax error in the password file
  509.     7  login during lockout period
  510.     8  can't change to LOG directory
  511.     9  syntax error in login.times file  */
  512.  
  513. int logerr (err)
  514. int err;
  515. {
  516.      char err_log[100];
  517.  
  518.      sprintf (err_log, "%s/login.errors", logdir);
  519.      curr_time = time ((long *)0);
  520.  
  521.      if ((fdA = fopen (err_log, "a+" )) != 0)
  522.        {
  523.           fixperms (fdA);
  524.           sprintf (tempstr,"%s, %s, ",inname,inpass);
  525.           fwrite (tempstr, strlen (tempstr), sizeof (char), fdA);
  526.           fwrite (ctime (&curr_time), (strlen (ctime (&curr_time)) - 1),
  527.                     sizeof (char), fdA);
  528.  
  529.           switch (err)
  530.             { 
  531.                case 1:
  532.                     strcpy (tempstr, " Invalid user/password\n");
  533.                     break;
  534.  
  535.                case 2:
  536.                     strcpy (tempstr, timeout);
  537.                     break;
  538.  
  539.                case 3:
  540.                     strcpy (tempstr, Sorry);
  541.                     break;
  542.  
  543.                case 4:
  544.                     strcpy (tempstr, ufile_err);
  545.                     break;
  546.  
  547.                case 5:
  548.                     strcpy (tempstr, lfile_err);
  549.                     break;
  550.  
  551.                case 6:
  552.                     strcpy (tempstr, Syntax);
  553.                     break;
  554.  
  555.                case 7:
  556.                     strcpy (tempstr, badtime);
  557.                     break;
  558.  
  559.                case 8:
  560.                     strcpy (tempstr, log_err);
  561.                     break;
  562.  
  563.                case 9:
  564.                     strcpy (tempstr, "syntax error in login.times");
  565.                     break;
  566.  
  567.                default:
  568.                     strcpy (tempstr, "\n");
  569.                     break;
  570.             }
  571.           fwrite (tempstr, strlen (tempstr), sizeof (char), fdA);
  572.           fclose (fdA);
  573.        }
  574. }
  575.  
  576.  
  577.  
  578. /*  Exit with status 'n' after unlocking the port */
  579.  
  580. int myexit (n)
  581. int n;
  582. {
  583.      free (logdir);
  584.      exit (n);
  585. }
  586.  
  587.  
  588.  
  589. /* If a character is not received within TIMEOUT seconds, TRUE is returned.
  590.    This fixes a previous bug which cause LOGIN to time out only if nothing was
  591.    ever typed.  Noise or someone calling, typing a character or two with no
  592.    CR, then hanging up would make LOGIN wait forever...not nice. :-)
  593.    If the CR is received within the timeout window, FALSE is returned and then
  594.    received characters are put in BUFFER.
  595.  
  596.    ECHOFLAG determines whether or not characters are echoed to the standard
  597.    output, which should be the port the is coming in on. --REB  */
  598.  
  599. int get_response (buffer, echoflag)
  600. int echoflag;
  601. char *buffer;
  602. {
  603.      int tdone, done;
  604.      struct sgtbuf t;
  605.      register char *p;
  606.      char *start;                    /* used so we don't backspace too far */
  607.  
  608.      p = start = buffer;
  609.      echo (OFF);                        /* turn off echoing to standard out */
  610.      for (;;)
  611.        {
  612.           getime (&t);                              /* start/reset timer */
  613.  
  614.           if ((tdone = t.t_second + TIMEOUT) > 59)
  615.                tdone -= 60;
  616.  
  617.           done = FALSE;
  618.           while (!done)
  619.                if (_gs_rdy (STDIN) == NODATA)               /* any key hit? */
  620.                  {
  621.                     getime(&t);
  622.  
  623.                     if (tdone == t.t_second)                /* timed out?   */
  624.                       {
  625.                          echo (ON);                         /* ...yup */
  626.                          return (TRUE);
  627.                       }
  628.                  }
  629.                else
  630.                  {
  631.                     read (STDIN, p, 1);                    /* got something */
  632.                     switch (*p)
  633.                       {
  634.                          case '\n':                        /* CR ends input */
  635.                               *p = '\0'; 
  636.                               echo (ON);
  637.                               write (STDOUT, "\n", 1);
  638.                               return (FALSE);
  639.  
  640.                          case '\b':       /* backspace, don't go past start */
  641.                               --p;
  642.  
  643.                               if (p < start)
  644.                                    p = start;
  645.                               else if (echoflag == ON)
  646.                                    write (STDOUT, "\b \b",3);
  647.                               break;
  648.  
  649.                          default:          /* echo character if flag is set */
  650.                               if (echoflag == ON)
  651.                                    write (STDOUT, p, 1);
  652.  
  653.                               ++p;
  654.                               done = TRUE;                  /* reset timer */
  655.                               break;
  656.                       }
  657.                  }
  658.        }
  659. }
  660.  
  661.  
  662.  
  663. int putch (path, x)
  664. int path;
  665. char x; 
  666. {
  667.      writeln (path, &x, 1);
  668. }
  669.  
  670.  
  671.  
  672. int echo (onoroff)
  673. int onoroff;
  674. {
  675.      struct sgbuf s;
  676.  
  677.      _gs_opt (1, &s);
  678.      s.sg_echo = onoroff;
  679.      _ss_opt (1, &s);
  680. }
  681.