home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / shadow-3.1.4 / dpmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-26  |  4.2 KB  |  228 lines

  1. /*
  2.  * Copyright 1990, 1991 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.  
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <stdio.h>
  15. #include <fcntl.h>
  16. #ifdef    BSD
  17. #include <strings.h>
  18. #else
  19. #include <string.h>
  20. #endif
  21. #include "dialup.h"
  22.  
  23. #ifndef    lint
  24. static    char    sccsid[] = "@(#)dpmain.c    3.4    17:31:55    8/4/91";
  25. #endif
  26.  
  27. #ifdef    USG
  28. #define    bzero(p,l)    memset(p, 0, l)
  29. #endif
  30.  
  31. #define    DTMP    "/etc/d_passwd.tmp"
  32.  
  33. /*
  34.  * Prompts and messages go here.
  35.  */
  36.  
  37. #define    PASS1    "Shell password:"
  38. #define    PASS2    "re-enter Shell password:"
  39. #define    NOMATCH    "%s: Passwords do not match, try again.\n"
  40. #define    NOFOUND    "%s: Shell %s not found.\n"
  41.  
  42. int    aflg;
  43. int    dflg;
  44. char    *Prog;
  45.  
  46. extern    char    *pw_encrypt();
  47. extern    char    *getpass();
  48.  
  49. usage ()
  50. {
  51.     fprintf (stderr, "Usage: %s [ -(a|d) ] shell\n", Prog);
  52.     exit (1);
  53. }
  54.  
  55. main (argc, argv)
  56. int    argc;
  57. char    **argv;
  58. {
  59.     struct    dialup    *dial;
  60.     struct    dialup    dent;
  61.     struct    stat    sb;
  62.     FILE    *fp;
  63.     char    *shell;
  64.     char    *cp;
  65.     char    pass[BUFSIZ];
  66.     int    fd;
  67.     int    found = 0;
  68.     int    opt;
  69.     extern    int    optind;
  70.     extern    char    *optarg;
  71.  
  72.     if (Prog = strrchr (argv[0], '/'))
  73.         Prog++;
  74.     else
  75.         Prog = argv[0];
  76.  
  77.     while ((opt = getopt (argc, argv, "a:d:")) != EOF) {
  78.         switch (opt) {
  79.             case 'a':
  80.                 aflg++;
  81.                 shell = optarg;
  82.                 break;
  83.             case 'd':
  84.                 dflg++;
  85.                 shell = optarg;
  86.                 break;
  87.             default:
  88.                 usage ();
  89.         }
  90.     }
  91.     if (! aflg && ! dflg)
  92.         aflg++;
  93.  
  94.     if (! shell) {
  95.         if (optind >= argc)
  96.             usage ();
  97.         else
  98.             shell = argv[optind];
  99.     }
  100.     if (aflg + dflg != 1)
  101.         usage ();
  102.  
  103.     /*
  104.      * Add a new shell to the password file, or update an existing
  105.      * entry.  Begin by getting an encrypted password for this
  106.      * shell.
  107.      */
  108.  
  109.     if (aflg) {
  110.         int    tries = 3;
  111.  
  112.         dent.du_shell = shell;
  113.         dent.du_passwd = "";
  114.  
  115. again:
  116.         if (! (cp = getpass (PASS1)))
  117.             exit (1);
  118.  
  119.         strcpy (pass, cp);
  120.         bzero (cp, strlen (cp));
  121.  
  122.         if (! (cp = getpass (PASS2)))
  123.             exit (1);
  124.  
  125.         if (strcmp (pass, cp)) {
  126.             bzero (pass, strlen (pass));
  127.             bzero (cp, strlen (cp));
  128.             fprintf (stderr, NOMATCH, Prog);
  129.  
  130.             if (--tries)
  131.                 goto again;
  132.  
  133.             exit (1);
  134.         }
  135.         bzero (cp, strlen (cp));
  136.         dent.du_passwd = pw_encrypt (pass, (char *) 0);
  137.         bzero (pass, strlen (pass));
  138.     }
  139.  
  140.     /*
  141.      * Create the temporary file for the updated dialup password
  142.      * information to be placed into.  Turn it into a (FILE *)
  143.      * for use by putduent().
  144.      */
  145.  
  146.     if ((fd = open (DTMP, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0) {
  147.         sprintf (pass, "%s: can't create %s", Prog, DTMP);
  148.         perror (pass);
  149.         exit (1);
  150.     }
  151.     if (! (fp = fdopen (fd, "r+"))) {
  152.         sprintf (pass, "%s: can't open %s", Prog, DTMP);
  153.         perror (pass);
  154.         exit (1);
  155.     }
  156.  
  157.     /*
  158.      * Scan the dialup password file for the named entry,
  159.      * copying out other entries along the way.  Copying
  160.      * stops when a match is found or the file runs out.
  161.      */
  162.  
  163.     while (dial = getduent ()) {
  164.         if (strcmp (dial->du_shell, shell) == 0) {
  165.             found = 1;
  166.             break;
  167.         }
  168.         if (putduent (dial, fp))
  169.             goto failure;
  170.     }
  171.  
  172.     /*
  173.      * To delete the entry, just don't copy it.  To update
  174.      * the entry, output the modified version - works with
  175.      * new entries as well.
  176.      */
  177.  
  178.     if (dflg && ! found) {
  179.         fprintf (stderr, NOMATCH, Prog, shell);
  180.         exit (1);
  181.     }
  182.     if (aflg)
  183.         if (putduent (&dent, fp))
  184.             goto failure;
  185.  
  186.     /*
  187.      * Now copy out the remaining entries.  Flush and close the
  188.      * new file before doing anything nasty to the existing
  189.      * file.
  190.      */
  191.  
  192.  
  193.     while (dial = getduent ())
  194.         if (putduent (dial, fp))
  195.             goto failure;
  196.  
  197.     if (fflush (fp))
  198.         goto failure;
  199.  
  200.     fclose (fp);
  201.  
  202.     /*
  203.      * If the original file did not exist, we must create a new
  204.      * file with owner "root" and mode 400.  Otherwise we copy
  205.      * the modes from the existing file to the new file.
  206.      *
  207.      * After this is done the new file will replace the old file.
  208.      */
  209.  
  210.     if (! stat (DIALPWD, &sb)) {
  211.         chown (DTMP, sb.st_uid, sb.st_gid);
  212.         chmod (DTMP, sb.st_mode);
  213.         unlink (DIALPWD);
  214.     } else {
  215.         chown (DTMP, 0, 0);
  216.         chmod (DTMP, 0400);
  217.     }
  218.     link (DTMP, DIALPWD);
  219.     unlink (DTMP);
  220.  
  221.     sync ();
  222.     exit (0);
  223.  
  224. failure:
  225.     unlink (DTMP);
  226.     exit (1);
  227. }
  228.