home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / security / login_1 / c / passwd < prev   
Text File  |  1995-08-29  |  3KB  |  150 lines

  1. /* vi:tabstop=4:shiftwidth=4:smartindent
  2.  *
  3.  * passwd.c - Change password for a user.
  4.  *
  5.  */
  6. #include <time.h>
  7. #include "login.h"
  8.  
  9. #define PASSWD        "/etc/passwd"
  10. #define PASSWD_NEW    "/etc/passwd.new"
  11. #define PASSWD_OLD    "/etc/passwd.old"
  12.  
  13. /* Old and new passwords.
  14.  */
  15. char pass1[1024], pass2[1024];
  16.  
  17. /* Run at exit to blank any plaintext password. Running it as
  18.  * an atexit function should protect them in all circumstances.
  19.  */
  20. void splange(void)
  21. {
  22.     int i;
  23.     for (i=0; i<1024; i++)
  24.     {
  25.         pass1[i] = pass2[i] = '\0';
  26.     }
  27. }
  28.  
  29. /* Characters we allow in the salt.
  30.  */
  31. char *saltchars =
  32.         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  33.  
  34. int    main(void)
  35. {
  36.     struct passwd *pw;
  37.     char salt[3], *pass;
  38.     int  uid;
  39.     FILE *fp;
  40.  
  41. #ifdef crypt
  42.     init_des();
  43. #endif
  44.  
  45.     /* Make sure that any plaintext passwords get zapped.
  46.      */
  47.     atexit(splange);
  48.     
  49.     /* Disable escape.
  50.      */
  51.     signal(SIGINT, SIG_IGN);
  52.  
  53.     /* Find out who is running the program.
  54.      */
  55.     pw = getpwnam(getenv("USER"));
  56.     if (pw == NULL)
  57.     {
  58.         fprintf(stderr, "Can't get your passwd entry\n");
  59.         exit(1);
  60.     }
  61.  
  62.     /* If they have a password, ask them for it.
  63.      */
  64.     if (pw->pw_passwd[0])
  65.     {
  66.         get("Old Password: ", pass1, 0);
  67.  
  68.         /* If they enter the wrong password then don't let them
  69.          * change it.
  70.          */
  71.         strncpy(salt, pw->pw_passwd, 2);
  72.         salt[2] = '\0';
  73.         if (strcmp(pw->pw_passwd, crypt(pass1, salt)))
  74.         {
  75.             fprintf(stderr, "Sorry\n");
  76.             exit(1);
  77.         }
  78.     }
  79.  
  80.     /* OK, they knew their old password. Ask them for a new one.
  81.      */
  82.     get("New Password: ", pass1, 0);
  83.     if (strlen(pass1) < 6)
  84.     {
  85.         fprintf(stderr, "Your password must be six or more characters long\n");
  86.         exit(1);
  87.     }
  88.  
  89.     /* Twice, just to make sure.
  90.      */
  91.     get("Again: ", pass2, 0);
  92.     if (strcmp(pass1, pass2))
  93.     {
  94.         fprintf(stderr, "The new passwords didn't match\n");
  95.         exit(1);
  96.     }
  97.  
  98.     /* Generate a salt for the new password. I don't know the criterion
  99.      * for generating these under Unix, but we should be safe if it's 
  100.      * limited to letters and numbers.
  101.      */
  102.     srand(time(NULL));
  103.     salt[0] = saltchars[rand() % strlen(saltchars)];
  104.     salt[1] = saltchars[rand() % strlen(saltchars)];
  105.     strcpy(pass1, crypt(pass2, salt));
  106.  
  107.     /* Copy the password file, making the relevant change.
  108.      */
  109.     fp = fopen(PASSWD_NEW, "w");
  110.     if (fp == NULL)
  111.     {
  112.         fprintf(stderr, "Can't open new password file\n");
  113.         exit(1);
  114.     }
  115.  
  116.     /* Remember the uid for searching.
  117.      */
  118.     uid = pw->pw_uid;
  119.  
  120.     setpwent();
  121.     while (pw = getpwent())
  122.     {
  123.         if ((pw->pw_uid != uid) || (strcmp(pw->pw_name, getenv("USER"))))
  124.         {
  125.             pass = pw->pw_passwd;
  126.         }
  127.         else
  128.         {
  129.             pass = pass1;
  130.         }
  131.  
  132.         /* Output the current record to the new file.
  133.          */
  134.         fprintf(fp, "%s:%s:%d:%d:%s:%s:%s\n", pw->pw_name, pass, 
  135.             pw->pw_uid, pw->pw_gid, pw->pw_gecos, pw->pw_dir, 
  136.             pw->pw_shell);
  137.     }
  138.     endpwent();
  139.  
  140.     fclose(fp);
  141.  
  142.     /* Finally shuffle the files.
  143.      */
  144.     remove(PASSWD_OLD);
  145.     rename(PASSWD, PASSWD_OLD);
  146.     rename(PASSWD_NEW, PASSWD);
  147.  
  148.     exit(0);
  149. }
  150.