home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1512 / gpmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  7.1 KB  |  360 lines

  1. /*
  2.  * Copyright 1990, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Non-commercial distribution permitted.  You must provide this source
  6.  * code in any distribution.  This notice must remain intact.
  7.  */
  8.  
  9. #include <sys/types.h>
  10. #include <stdio.h>
  11. #include <pwd.h>
  12. #include <grp.h>
  13. #include <fcntl.h>
  14. #include <signal.h>
  15. #include <errno.h>
  16. #ifndef    BSD
  17. #include <termio.h>
  18. #ifdef SYS3
  19. #include <sys/ioctl.h>
  20. #endif
  21. #include <string.h>
  22. #ifndef    SYS3
  23. #include <memory.h>
  24. #endif
  25. #else
  26. #include <sgtty.h>
  27. #include <strings.h>
  28. #define    strchr    index
  29. #define    strrchr    rindex
  30. #endif
  31. #include "config.h"
  32.  
  33. #ifndef    PASSLENGTH
  34. #define    PASSLENGTH    5
  35. #endif
  36.  
  37. #ifndef    lint
  38. static    char    _sccsid[] = "@(#)gpmain.c    1.3    09:19:10    6/26/90";
  39. #endif
  40.  
  41. char    name[BUFSIZ];
  42. char    pass[BUFSIZ];
  43. char    pass2[BUFSIZ];
  44.  
  45. struct    group    grent;
  46.  
  47. char    *myname;
  48.  
  49. #ifndef    RETRIES
  50. #define    RETRIES    3
  51. #endif
  52.  
  53. char    *l64a ();
  54. char    *crypt ();
  55. extern    int    errno;
  56. long    a64l ();
  57. void    entry ();
  58. time_t    time ();
  59.  
  60. /*
  61.  * usage - display usage message
  62.  */
  63.  
  64. void
  65. usage ()
  66. {
  67.     fprintf (stderr, "usage: %s [ -r ] group\n", myname);
  68.     exit (1);
  69. }
  70.  
  71. int
  72. main (argc, argv)
  73. int    argc;
  74. char    **argv;
  75. {
  76.     extern    int    optind;
  77.     extern    char    *optarg;
  78.     char    *group;
  79.     int    flag;
  80.     int    i;
  81.     void    die ();
  82.     char    *cp;
  83.     char    *getlogin ();
  84.     int    amroot;
  85.     int    lockfd = -1;
  86.     int    remove = 0;
  87.     int    retries;
  88.     int    ruid = getuid();
  89.     int    suid = geteuid();
  90.     long    salttime;
  91.     struct    group    *gr;
  92.     struct    group    *getgrnam ();
  93.     struct    group    *sgetgrent ();
  94.     struct    passwd    *pw;
  95.     struct    passwd    *getpwuid ();
  96.     struct    passwd    *getpwnam ();
  97.     FILE    *ngrp;
  98.     FILE    *ogrp;
  99.     char    buf[BUFSIZ];
  100.     char    tmp[BUFSIZ];
  101.  
  102.     amroot = getuid () == 0;
  103.     setuid (geteuid ());
  104.     myname = argv[0];
  105.  
  106.     if (! isatty (0) || ! isatty (1))
  107.         exit (1);
  108.  
  109.     die (0);            /* save tty modes */
  110.  
  111.     signal (SIGHUP, die);
  112.     signal (SIGINT, die);
  113.     signal (SIGQUIT, die);
  114.     signal (SIGTERM, die);
  115.  
  116.     while ((flag = getopt (argc, argv, "gr")) != EOF) {
  117.         switch (flag) {
  118.             case 'g':    /* no-op from normal password */
  119.                 break;
  120.             case 'r':    /* remove group password */
  121.                 remove = 1;
  122.                 break;
  123.             default:
  124.                 usage ();
  125.         }
  126.     }
  127.     if (cp = getlogin ())        /* need user name */
  128.         (void) strcpy (name, cp);
  129.     else if (pw = getpwuid (ruid)) /* get it from password file */
  130.         strcpy (name, pw->pw_name);
  131.     else {                /* can't find user name! */
  132.         fprintf (stderr, "Who are you?\n");
  133.         exit (1);
  134.     }
  135.     if (! (pw = getpwnam (name)))
  136.         goto failure;        /* can't get my name ... */
  137.         
  138.     if (! (group = argv[optind]))
  139.         usage ();
  140.  
  141.     if (! (gr = getgrnam (group))) {
  142.         fprintf (stderr, "unknown group: %s\n", group);
  143.         exit (1);
  144.     }
  145.     if (! amroot) {
  146.         if (gr->gr_mem[0] == (char *) 0)
  147.             goto failure;
  148.  
  149.         if (strcmp (gr->gr_mem[0], name) != 0)
  150.             goto failure;
  151.     }
  152.     if (remove) {
  153.         if (! amroot && (gr->gr_mem[0] &&
  154.                 strcmp (name, gr->gr_mem[0]) != 0))
  155.             goto failure;
  156.  
  157.         gr->gr_passwd = "";
  158.         goto output;
  159.     }
  160.     printf ("Changing password for group %s\n", group);
  161.  
  162.     printf ("Enter new password (minimum of %d characters)\n", PASSLENGTH);
  163.     retries = RETRIES;
  164. retry:
  165.     if (! password ("New Password:", pass))
  166.         exit (1);
  167.  
  168.     if (! password ("Re-enter new password:", pass2))
  169.         exit (1);
  170.  
  171.     if (strcmp (pass, pass2) != 0) {
  172.         puts ("They don't match; try again");
  173.  
  174.         if (retries-- > 0)
  175.             goto retry;
  176.         else
  177.             goto toomany;
  178.     }
  179.     (void) time (&salttime);
  180.     salttime = ((salttime & 07777) ^ ((salttime >> 12) & 07777)) & 07777;
  181.     grent.gr_passwd = tmp;
  182.     strcpy (grent.gr_passwd, crypt (pass, l64a (salttime)));
  183. #ifdef    DOUBLESIZE
  184.     if (strlen (pass) > 8) {
  185.         strcpy (grent.gr_passwd + 13,
  186.             crypt (pass + 8, l64a (salttime)) + 2);
  187.     }
  188. #endif
  189. output:
  190.  
  191.     /*
  192.      * Now we get to race the bad guy.  I don't think he can get us.
  193.      *
  194.      * Ignore most reasonable signals.
  195.      *    Maybe we should ignore more?  He can't hurt us until the end.
  196.      *
  197.      * Get a lock file.
  198.      *
  199.      * Copy first part of password file to new file.
  200.      *    Illegal lines are copied verbatim.
  201.      *    File permissions are r--r--r--, owner root, group root.
  202.      *
  203.      * Output the new entry.
  204.      *    Only fields in struct passwd are output.
  205.      *
  206.      * Copy the rest of the file verbatim.
  207.      *
  208.      * Rename (link, unlink) password file to backup.
  209.      *    Kill me now and nothing changes or no one gets in.
  210.      *
  211.      * Rename (link, unlink) temporary file to password file.
  212.      *    Kill me now and no one gets in or lock is left.
  213.      *
  214.      * Remove locking file.
  215.      *
  216.      * That's all folks ...
  217.      */
  218.  
  219.     signal (SIGHUP, SIG_IGN);
  220.     signal (SIGINT, SIG_IGN);
  221.     signal (SIGQUIT, SIG_IGN);
  222.     signal (SIGTERM, SIG_IGN);
  223.  
  224.     ulimit (30000);            /* prevent any funny business */
  225.     umask (0);            /* get new files modes correct */
  226. #ifndef    NDEBUG
  227.     if ((lockfd = open (".grplock", O_RDONLY|O_CREAT|O_EXCL), 0444) == -1)
  228. #else
  229.     if ((lockfd = open (GRPLOCK, O_RDONLY|O_CREAT|O_EXCL), 0444) == -1)
  230. #endif    /* NDEBUG */
  231.     {
  232.         puts ("Can't get lock");
  233.         exit (1);
  234.     }
  235.     umask (077);            /* close security holes to come ... */
  236.     if (access (NGRPFILE, 0) == 0 && unlink (NGRPFILE) == -1)
  237.         goto failure;
  238.  
  239. #ifndef    NDEBUG
  240.     if ((ngrp = fopen ("ngroup", "w")) == (FILE *) 0)
  241. #else
  242.     umask (077);        /* no permissions for non-roots */
  243.  
  244.     if ((ngrp = fopen (NGRPFILE, "w")) == (FILE *) 0)
  245. #endif    /* NDEBUG */
  246.         goto failure;
  247.  
  248. #ifndef    NDEBUG
  249.     chmod (NGRPFILE, 0444);        /* lets have some security here ... */
  250.     chown (NGRPFILE, 0, 0);        /* ... and keep the bad guy away */
  251. #endif    /* NDEBUG */
  252.     if ((ogrp = fopen (GRPFILE, "r")) == (FILE *) 0)
  253.         goto failure;
  254.  
  255.     while (fgets (buf, sizeof buf, ogrp) != (char *) 0) {
  256.         if (buf[0] == '#' || ! (gr = sgetgrent (buf))) {
  257.             fputs (buf, ngrp);
  258.         } else if (strcmp (gr->gr_name, group) != 0)
  259.             fputs (buf, ngrp);
  260.         else
  261.             break;
  262.     }
  263.     if (gr) {
  264.         (void) fprintf (ngrp, "%s:%s:%d%s",
  265.             gr->gr_name,
  266.                 grent.gr_passwd ? grent.gr_passwd:"x",
  267.                 gr->gr_gid, strrchr (buf, ':'));
  268.  
  269.         while (fgets (buf, BUFSIZ, ogrp) != (char *) 0)
  270.             fputs (buf, ngrp);
  271.     }
  272.     if (ferror (ngrp)) {
  273.         perror (NGRPFILE);
  274.         if (unlink (NGRPFILE) || unlink (GRPLOCK))
  275.             fputs ("Help!\n", stderr);
  276.  
  277.         exit (1);
  278.     }
  279.     fflush (ngrp);
  280.     fclose (ngrp);
  281. #ifdef    NDEBUG
  282.     chmod (NGRPFILE, 0644);
  283.     if (unlink (OGRPFILE) == -1) {
  284.         if (errno != ENOENT) {
  285.             puts ("Can't unlink backup file");
  286.             goto unlock;
  287.         }
  288.     }
  289.     if (link (GRPFILE, OGRPFILE) || unlink (GRPFILE)) {
  290.         puts ("Can't save backup file");
  291.         goto unlock;
  292.     }
  293. #ifndef    BSD
  294.     if (link (NGRPFILE, GRPFILE) || unlink (NGRPFILE))
  295. #else
  296.     if (rename (NGRPFILE, GRPFILE))
  297. #endif
  298.     {
  299.         puts ("Can't rename new file");
  300.         goto unlock;
  301.     }
  302. #endif    /* NDEBUG */
  303. #ifndef    NDEBUG
  304.     (void) unlink (".grplock");
  305. #else
  306.     (void) unlink (GRPLOCK);
  307. #endif
  308.     exit (0);
  309.     /*NOTREACHED*/
  310.  
  311. failure:
  312.     puts ("Permission denied.");
  313. unlock:
  314.     if (lockfd >= 0)
  315.         (void) unlink (GRPLOCK);
  316.  
  317.     (void) unlink (NGRPFILE);
  318.     exit (1);
  319.     /*NOTREACHED*/
  320.  
  321. toomany:
  322.     puts ("Too many tries; try again later.");
  323.     exit (1);
  324.     /*NOTREACHED*/
  325. }
  326.  
  327. /*
  328.  * die - set or reset termio modes.
  329.  *
  330.  *    die() is called before processing begins.  signal() is then
  331.  *    called with die() as the signal handler.  If signal later
  332.  *    calls die() with a signal number, the terminal modes are
  333.  *    then reset.
  334.  */
  335.  
  336. void    die (killed)
  337. int    killed;
  338. {
  339. #ifdef    BSD
  340.     static    struct    sgtty    sgtty;
  341.  
  342.     if (killed)
  343.         stty (0, &sgtty);
  344.     else
  345.         gtty (0, &sgtty);
  346. #else
  347.     static    struct    termio    sgtty;
  348.  
  349.     if (killed)
  350.         ioctl (0, TCSETA, &sgtty);
  351.     else
  352.         ioctl (0, TCGETA, &sgtty);
  353. #endif
  354.     if (killed) {
  355.         putchar ('\n');
  356.         fflush (stdout);
  357.         exit (killed);
  358.     }
  359. }
  360.