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

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