home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / init_5 / login.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-03  |  10.7 KB  |  576 lines

  1. /*
  2.  * Login.c for MiNT version 0.6 (c) S.R.Usher 1991/92.
  3.  *
  4.  * Changelog
  5.  * ---------
  6.  *
  7.  * 25/9/91    S.R.Usher    0.2    Added encrypted passwords using
  8.  *                     Alec "Igor" Muffett's fcrypt()
  9.  *                     routine from his password cracker.
  10.  *                     (Thank's Alec!)
  11.  *
  12.  * 20/10/91    S.R.Usher    0.3    Added support for BSD style utmp/wtmp.
  13.  *
  14.  * 10/11/91    S.R.Usher    0.4    Added Dave Gymer's patches & started
  15.  *                    using my my_putenv() rather than
  16.  *                    Rob Newson's my_putenv().
  17.  *
  18.  * 18/1/92    S.R.Usher    0.5    Changed from using getenv("TTY") to
  19.  *                    using ttyname(0). Added seteuid() and
  20.  *                    setegid() so that this should work
  21.  *                    when used on filesystems with
  22.  *                    protection.
  23.  *
  24.  * 22/1/92    S.R.Usher    0.6    Moved the no home directory message
  25.  *                    before the motd etc, where it should
  26.  *                    have been in the first place!
  27.  *
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <signal.h>
  32. #include <stat.h>
  33. #include <pwd.h>
  34. #include <lastlog.h>
  35. #include <ttyent.h>
  36. #include <sys/ioctl.h>
  37. #include <sys/file.h>
  38. #include <sys/time.h>
  39.  
  40. /* default shell */
  41. #ifdef MINT
  42. # ifndef SHELL
  43. #  define SHELL "/bin/bash.ttp" 
  44. # endif
  45. #else
  46. #define SHELL "/bin/sh"
  47. #endif
  48.  
  49. struct passwd *pswdent, dummy;
  50. struct sgttyb orig, noecho;
  51.  
  52. void sighandler();
  53. char *fcrypt();
  54. void *malloc(), *realloc(), *strchr();
  55.  
  56. extern char **environ;
  57.  
  58. int env_index;
  59.  
  60. struct ttyent *ttyentry;
  61. char ourtty[32];
  62. int secure;
  63.  
  64. main(argc, argv)
  65. int argc;
  66. char *argv[];
  67. {
  68.     int i, nopasswd = 0, oktologin = 0, noentry = 0;
  69.     int preserve, name_in_argv;
  70.     char name[80], password[80];
  71.     char *ptr;
  72.  
  73.     signal(SIGALRM, sighandler);
  74.     sigblock(sigmask(SIGTTOU));
  75.     sigblock(sigmask(SIGTTIN));
  76.     sigblock(sigmask(SIGSTOP));
  77.  
  78. #ifndef MINT
  79. /* Oh dear.. mntlib16 doesn't have these! */
  80.     seteuid(0);
  81.     setegid(0);
  82. #else
  83.     setuid(0);
  84.     setgid(0);
  85. #endif
  86.  
  87.     check_nologin();
  88.  
  89.     strcpy(ourtty, (ptr = (char *) ttyname(0)));
  90.  
  91.     if ((ptr = (char *) strrchr(ptr, '/')) != NULL)
  92.         strcpy(ourtty, ++ptr);
  93.  
  94.     if ((ttyentry = getttynam(ourtty)) != NULL)
  95.     {
  96.         secure = (ttyentry->ty_status & TTY_SECURE);
  97.     }
  98.     else
  99.         fprintf(stderr, "getttynam() returned NULL for %s", ourtty);
  100.  
  101.     ioctl(fileno(stdin), TIOCGETP, &orig);
  102.     ioctl(fileno(stdin), TIOCGETP, &noecho);
  103.  
  104.     noecho.sg_flags &= ~ECHO;
  105.  
  106.     name_in_argv = parse_args(argc, argv, name, &preserve);
  107.  
  108.     for (i = 0; i < 4; i++)
  109.     {
  110.         if (name_in_argv == 0)
  111.         {
  112. again:
  113.             printf("login: ");
  114.             if (getstring(name) == EOF)
  115.                 exit(0);
  116.             if (strlen(name) == 0)
  117.                 goto again;
  118.         }
  119.         else
  120.         {
  121.             name_in_argv = 0;
  122.         }
  123.  
  124.         pswdent = getpwnam(name);
  125.  
  126.         if (pswdent == NULL)
  127.         {
  128.             pswdent = &dummy;
  129.             pswdent->pw_passwd = "\0";
  130.             oktologin = 0;
  131.             noentry = 1;
  132. #ifdef DEBUG
  133.             printf("Ooer! No entry!\n");
  134. #endif
  135.         }
  136.         else
  137.         {
  138.             if (strlen(pswdent->pw_passwd) == 0)
  139.             {
  140.                 nopasswd = 1;
  141.                 oktologin = 1;
  142. #ifdef DEBUG
  143.                 printf("Ooer! No password! (%s)\n", pswdent->pw_passwd);
  144. #endif
  145.             }
  146.             noentry = 0;
  147.         }
  148.  
  149.         
  150.         if (nopasswd == 0)
  151.         {
  152.             ioctl(fileno(stdin), TIOCSETP, &noecho);
  153.  
  154.             alarm(60);
  155.  
  156.             printf("Password:");
  157.             fflush(stdout);
  158.             gets(password);
  159.             printf("\n");
  160.  
  161.             alarm(0);
  162.  
  163.             ioctl(fileno(stdin), TIOCSETP, &orig);
  164.  
  165.             if ((check_passwd((char *)(fcrypt(password, "su") +2L), pswdent->pw_passwd) == 1) && (noentry == 0))
  166.                 oktologin = 1;
  167.         }
  168.  
  169.         if (!strcmp(pswdent->pw_name, "root") && !secure)
  170.             oktologin = 0;
  171.  
  172. #ifdef DEBUG
  173.         printf("oktologin = %s noentry = %s secure = %s\n", (oktologin == 1 ? "TRUE" : "FALSE"), (noentry == 1 ? "TRUE" : "FALSE"), (secure == 1 ? "TRUE" : "FALSE"));
  174. #endif
  175.         if ((oktologin == 1) && (noentry == 0))
  176.         {
  177.             execit(preserve);
  178.         }
  179.         else
  180.             printf("Login incorrect\n");
  181.     }
  182.     printf("Too many tries.\n");
  183. }
  184.  
  185. check_passwd(given_pw, encrypted_pw)
  186. char *given_pw;
  187. char *encrypted_pw;
  188. {
  189.     if ((strncmp(given_pw, encrypted_pw, strlen(given_pw)) == 0) && (strlen(given_pw) == strlen(encrypted_pw)))
  190.         return 1;
  191.     else
  192.         return 0;
  193. }
  194.  
  195. execit(preserve)
  196. int preserve;
  197. {
  198.     static char name[80];
  199.     static char argvzero[80];
  200.     char *pointer, tmpstring[80], *tmpptr, *tmpptr2;
  201.     static char *protoenv[100];
  202.     char *shellname = SHELL;
  203.  
  204.     if (pswdent->pw_shell != NULL && *pswdent->pw_shell != '\0')
  205.         shellname = pswdent->pw_shell;
  206.  
  207.     if ((pointer = (char *) strrchr(shellname, '/')) == NULL)
  208.         pointer = shellname;
  209.     else
  210.         pointer++;
  211.     strcpy(tmpstring, pointer);
  212.  
  213.     if ((pointer = (char *) strrchr(tmpstring, '.')) != NULL)
  214.         *pointer = '\0';
  215.  
  216.     sprintf(argvzero, "-%s", tmpstring);
  217.  
  218. #ifdef DEBUG
  219.     printf("argvzero = '%s'\n", argvzero);
  220. #endif
  221.  
  222.     if (preserve == 1)
  223.         env_index = copy_environment(protoenv);
  224.     else
  225.         env_index = 0;
  226.  
  227.     if (ourtty == NULL)
  228.     {
  229.         write_wtmp("console", pswdent->pw_name, "\0", time(0L));
  230.         write_utmp("console", pswdent->pw_name, "\0", time(0L));
  231.         my_putenv("TTY=console", protoenv);
  232.     }
  233.     else
  234.     {
  235.         sprintf(tmpstring, "TTY=%s", ourtty);
  236. #ifdef DEBUG
  237.         printf("%s\n", tmpstring);
  238. #endif
  239.         my_putenv(tmpstring, protoenv);
  240.         write_wtmp(ourtty, pswdent->pw_name, "\0", time(0L));
  241.         write_utmp(ourtty, pswdent->pw_name, "\0", time(0L));
  242.     }
  243.     
  244.     sprintf(tmpstring, "USER=%s", pswdent->pw_name);
  245. #ifdef DEBUG
  246.     printf("putenv(\"%s\") returned %d\n", tmpstring, 
  247. #endif
  248.     my_putenv(tmpstring, protoenv)
  249. #ifdef DEBUG
  250.     )
  251. #endif
  252.     ;
  253.  
  254.  
  255.     if (chdir(pswdent->pw_dir) != -1)
  256.     {
  257.         sprintf(tmpstring, "HOME=%s", pswdent->pw_dir);
  258.         my_putenv(tmpstring, protoenv);
  259.         chdir(pswdent->pw_dir);
  260.     }
  261.     else
  262.     {
  263.         sprintf(tmpstring, "HOME=/");
  264.         my_putenv(tmpstring, protoenv);
  265.         printf("\nNo home directory. home=/\n");
  266.         chdir("/");
  267.     }
  268.  
  269.     sprintf(tmpstring, "%s/.hushlogin", pswdent->pw_dir);
  270.  
  271.     if (access(tmpstring, F_OK) != 0)
  272.     {
  273.         last_time();
  274.         check_motd();
  275.         check_mail();
  276.     }
  277.  
  278.     setgid(pswdent->pw_gid);
  279.     setuid(pswdent->pw_uid);
  280.  
  281.     execle(shellname, argvzero, NULL, protoenv);
  282.  
  283.     printf("\nNo Shell\n");
  284.     exit();
  285. }
  286.  
  287. void sighandler()
  288. {
  289.     printf("\nTimed out after 60 seconds.\n");
  290.     ioctl(fileno(stdin), TIOCSETP, &orig);
  291.     exit();
  292. }
  293.  
  294. parse_args(argc, argv, name, preserve)
  295. int argc;
  296. char *argv[];
  297. char *name;
  298. int *preserve;
  299. {
  300.     register int i = 1, j;
  301.  
  302.     if (argc < 2)
  303.     {
  304.         *preserve = 0;
  305.         name[0] = '\0';
  306.         return 0;
  307.     }
  308.  
  309.     if (argc > 3)
  310.         usage(argv);
  311.  
  312.     if (argv[i][0] == '-')
  313.         if (argv[i++][1] == 'p')
  314.             *preserve = 1;
  315.         else
  316.             usage(argv);
  317.  
  318.     if (i < argc)
  319.     {
  320.         if ((j = strlen(argv[i])) > 8)
  321.             j = 8;
  322.         strncpy(name, argv[i], j);
  323.         name[8] = '\0';
  324.         return 1;
  325.     }
  326.     else
  327.     {
  328.         name[0] = '\0';
  329.         return 0;
  330.     }
  331. }
  332.  
  333. usage(argv)
  334. char *argv[];
  335. {
  336.     fprintf(stderr, "Usage: %s [-p] [name]\n", argv[0]);
  337.     exit(0);
  338. }
  339.  
  340. check_nologin()
  341. {
  342.     FILE *fp;
  343.     char string[1024];
  344.  
  345.     if ((fp = fopen("/etc/nologin", "r")) == NULL)
  346.     {
  347.         return;
  348.     }
  349.  
  350.     while(fgets(string, 1024, fp) != NULL)
  351.         printf("%s", string);
  352.  
  353.     exit(0);
  354. }
  355.  
  356. check_motd()
  357. {
  358.     FILE *fp;
  359.     char string[1024];
  360.  
  361.     if ((fp = fopen("/etc/motd", "r")) == NULL)
  362.     {
  363.         return;
  364.     }
  365.  
  366.     while(fgets(string, 1024, fp) != NULL)
  367.         printf("%s", string);
  368.  
  369.     fclose(fp);
  370.     
  371.     return;
  372. }
  373.  
  374. check_mail()
  375. {
  376.     char string[1024];
  377.     struct stat info;
  378.  
  379.     sprintf(string, "/usr/spool/mail/%s", pswdent->pw_name);
  380.  
  381.     if (!stat(string, &info) && info.st_size > 0)
  382.         printf("You have mail.\n");
  383. }
  384.  
  385. last_time()
  386. {
  387.     struct lastlog logent;
  388.     FILE *fp;
  389.     char *how, *my_line, output_string[80], *ptr;
  390.     struct tm *some_time;
  391.  
  392.     static char *dow[7] = {
  393.         "Sun",
  394.         "Mon",
  395.         "Tue",
  396.         "Wed",
  397.         "Thu",
  398.         "Fri",
  399.         "Sat"
  400.     };
  401.  
  402.     static char *moy[12] = {
  403.         "Jan",
  404.         "Feb",
  405.         "Mar",
  406.         "Apr",
  407.         "May",
  408.         "Jun",
  409.         "Jul",
  410.         "Aug",
  411.         "Sep",
  412.         "Oct",
  413.         "Nov",
  414.         "Dec"
  415.     };
  416.  
  417.     if (access("/var/adm/lastlog", F_OK) == 0)
  418.         how = "r+";
  419.     else
  420.         how = "w";
  421.  
  422.     if ((fp = fopen("/var/adm/lastlog", how)) == NULL)
  423.     {
  424.         perror("/var/adm/lastlog");
  425.         return;
  426.     }
  427.  
  428.     if (fseek(fp, (pswdent->pw_uid * sizeof(struct lastlog)), 0) != 0)
  429.     {
  430.         perror("/var/adm/lastlog");
  431.         fclose(fp);
  432.         return;
  433.     }
  434.  
  435.     if ((fread(&logent, sizeof(struct lastlog), 1, fp) != 1) || (logent.ll_time == 0))
  436.     {
  437.         sprintf(output_string, "Never logged in.\n");
  438.     }
  439.     else
  440.     {
  441.         some_time = localtime(&logent.ll_time);
  442.         sprintf(output_string,
  443.             "Last login: %s %s %02d %02d:%02d:%02d on %s\n",
  444.             dow[some_time->tm_wday],
  445.             moy[some_time->tm_mon],
  446.             some_time->tm_mday,
  447.             some_time->tm_hour,
  448.             some_time->tm_min,
  449.             some_time->tm_sec,
  450.             logent.ll_line);
  451.     }
  452.  
  453.     printf(output_string);
  454.  
  455.     logent.ll_time = time(0);
  456.     my_line = ourtty;
  457.     if (my_line == NULL)
  458.         my_line = "console";
  459.             
  460.     strcpy(logent.ll_line, my_line);
  461.     logent.ll_host[0] = '\0';
  462.  
  463.     if (fseek(fp, (pswdent->pw_uid * sizeof(struct lastlog)), 0) != 0)
  464.     {
  465.         perror("/var/adm/lastlog");
  466.         fflush(fp);
  467.         fclose(fp);
  468.         return;
  469.     }
  470.  
  471.     if (fwrite(&logent, sizeof(struct lastlog), 1, fp) != 1)
  472.         perror("Writing lastlog");
  473.  
  474.     fflush(fp);
  475.     fclose(fp);
  476. }
  477.  
  478. getstring(string)
  479. char *string;
  480. {
  481.     register int i, c;
  482.  
  483.     *string = '\0';
  484.  
  485.     for (i = 0; (c = fgetc(stdin)) != '\n'; i++)
  486.     {
  487.         if ((c == '\004') || (c == EOF))
  488.         {
  489.             printf("^D\n");
  490.             return EOF;
  491.         }
  492.  
  493.         if (c < 32)
  494.             printf("^%c", (c + 0x40));
  495.  
  496.         string[i] = c;
  497.     }
  498.  
  499.     string[i] = '\0';
  500.  
  501.     return 0;
  502. }
  503.  
  504. copy_environment(protoenv)
  505. char *protoenv[];
  506. {
  507.     register int i;
  508.     register char *ptr;
  509.  
  510.     for (i = 0; ((ptr = environ[i]) != NULL); i++)
  511.     {
  512.         if ((protoenv[i] = malloc(strlen(ptr) + 1)) == NULL)
  513.             exit(1);
  514.  
  515.         strcpy(protoenv[i], ptr);
  516.     }
  517.  
  518.     protoenv[i] = NULL;
  519.  
  520.     return i;
  521. }
  522.  
  523. /*
  524.  * This is my putenv routine, it first searches for an environment variable of
  525.  * the same name as the one to be added to the environment. If does find one,
  526.  * it attempts to reallocate the memory for the original string to hold the
  527.  * new one. If it doesn't find it then it malloc()s enough memory for the
  528.  * string and adds the pointer to the envronment pointer array.
  529.  *
  530.  * It was written so as to add entries to an environment list which may not
  531.  * be the standard one.
  532.  */
  533.  
  534. my_putenv(string, environment)
  535. char *string;
  536. char *environment[];
  537. {
  538.     register int i;
  539.     char match_string[80];
  540.     char *val_ptr, *env_ptr;
  541.     int string_len;
  542.  
  543.     if ((string_len = strlen(string)) == 0)
  544.         return -1;
  545.     
  546.     string_len++;
  547.  
  548.     if ((val_ptr = strchr(string, '=')) == NULL)
  549.         return -1;
  550.  
  551.     *val_ptr++ = '\0';
  552.  
  553.     strcpy(match_string, string);
  554.  
  555.     for (i = 0; ((env_ptr = environment[i]) != NULL); i++)
  556.     {
  557.         if (!strncmp(env_ptr, match_string, strlen(match_string)))
  558.         {
  559.             if ((env_ptr = realloc(env_ptr, string_len)) == NULL)
  560.                 return -1;
  561.             sprintf(env_ptr, "%s=%s", match_string, val_ptr);
  562.             environment[i] = env_ptr;
  563.             return 0;
  564.         }
  565.     }
  566.  
  567.     if ((env_ptr = malloc(string_len)) == NULL)
  568.         return -1;
  569.  
  570.     sprintf(env_ptr, "%s=%s", match_string, val_ptr);
  571.  
  572.     environment[i] = env_ptr;
  573.  
  574.     return 0;
  575. }
  576.