home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / passwd+ / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  6.3 KB  |  287 lines

  1. /*
  2.  * PASSWD -- a program to change passwords
  3.  *
  4.  * This program will change a password, but will do so
  5.  * only after the proposed password passes a series of tests.
  6.  */
  7. #include "passwd.h"
  8.  
  9. /*
  10.  * globals
  11.  */
  12. char runner[BUFSIZ];        /* who is running this program */
  13. char user[BUFSIZ];        /* name of user */
  14. char password[BUFSIZ];        /* new password */
  15. char oldpassword[BUFSIZ];    /* current password */
  16. struct passwd *pwinfo;        /* associated password structure */
  17. char *progname = "passwd";    /* program name */
  18. char *pwdfile = DEFPWFILE;    /* password file */
  19. char pwtest[BUFSIZ] = PWTESTFILE;    /* password test file */
  20. int pwsig = PWSIGCHARS;        /* number of significant chars in password */
  21. #ifdef lint
  22. int errno;            /* system error number */
  23. int sys_nerr;            /* number of system errors */
  24. char *sys_errlist[1];        /* descriptions of system errors */
  25. #endif
  26.  
  27. /*
  28.  * main routine
  29.  */
  30. main(argc, argv)
  31. int argc;
  32. char **argv;
  33. {
  34.     register int i;        /* counter in a for loop */
  35.     register char *cp;    /* pointer to various things */
  36.     char saltc[2];        /* the password's salt */
  37.     char ermsg[BUFSIZ];    /* returned message from test routine */
  38. #ifdef CHFN
  39.     int dogecos = 0;    /* 1 to change user's finger info */
  40. #endif
  41. #ifdef GETUSERSHELL
  42.     int doshell = 0;    /* 1 to change user's shell */
  43. #endif
  44. #ifdef UID_TYPE
  45.     UID_TYPE getuid();    /* return user's real UID */
  46.     union {
  47.         UID_TYPE tuid;        /* uid as returned by system */
  48.         int iuid;        /* uid as integer */
  49.     } uuid;            /* uid as union */
  50. #define uidget    uuid.iuid
  51. #define uidset    uuid.tuid
  52. #else
  53.     int uuid;        /* uid as returned by system */
  54. #define uidget    uuid
  55. #define uidset    uuid
  56. #endif
  57.  
  58.     /*
  59.      * don't produce core dumps
  60.      */
  61.     initsig();
  62.     nocore();
  63.     name_pwd(pwdfile);
  64.  
  65.     /*
  66.      * walk the argument list and process the arguments
  67.      */
  68.     progname = argv[0];
  69.     for(i = 1; i < argc; i++){
  70.         if (strncmp(argv[i], "-t", 2) == 0){/* new test file */
  71.             if (argv[i][2] == '\0')
  72.                 (void) strcpy(pwtest, argv[++i]);
  73.             else
  74.                 (void) strcpy(pwtest, &argv[i][2]);
  75.         }
  76. #ifndef NOSETPWFILE
  77.         else if (strncmp(argv[i], "-F", 2) == 0){/* new password file */
  78.             if (argv[i][2] == '\0')
  79.                 name_pwd(pwdfile = argv[++i]);
  80.             else
  81.                 name_pwd(pwdfile = &argv[i][2]);
  82.         }
  83. #endif
  84. #ifdef CHFN
  85.         else if (strcmp(argv[i], "-f") == 0)    /* change gecos */
  86.             dogecos = 1;
  87. #endif
  88. #ifdef GETUSERSHELL
  89.         else if (strcmp(argv[i], "-s") == 0)    /* change shell */
  90.             doshell = 1;
  91. #endif
  92.         else if (*argv[i] == '-'){        /* bad option */
  93.             SPRINTF(user, "%s: unknown option.", argv[i]);
  94.             pwexit(user);
  95.         }
  96.         else if (user[0] != '\0')        /* too many args */
  97.             pwexit("one user at a time");
  98.         else                    /* change user */
  99.             (void) strcpy(user, argv[i]);
  100.     }
  101.  
  102.     /*
  103.      * figure out who is using the program
  104.      */
  105.     uidset = getuid();
  106.     if ((pwinfo = mgpwuid(uidget)) == NULL)
  107.         pwexit("you're not in the password file");
  108.     else
  109.         (void) strcpy(runner, pwinfo->pw_name);
  110.  
  111.     /*
  112.      * if a user is named he/she/it better be the current one ...
  113.      * grab the password information
  114.      */
  115.     if (user[0] != '\0'){
  116.         /*
  117.          * be sure the user exists
  118.          */
  119.         if ((pwinfo = mgpwnam(user)) == NULL){
  120.             if (uidget == ROOTID)
  121.                 pwexit("no such user");
  122.             else
  123.                 pwexit("only superuser can change another's password");
  124.             exit(1);
  125.         }
  126.         if (uidget != ROOTID && pwinfo->pw_uid != uidget){
  127.             pwexit("only superuser can change another's password");
  128.             exit(1);
  129.         }
  130.     }
  131.     else
  132.         (void) strcpy(user, pwinfo->pw_name);
  133.  
  134. #ifdef CHFN
  135. #ifdef GETUSERSHELL
  136.     /*
  137.      * you can only change one of these at a time
  138.      */
  139.     if (doshell && dogecos)
  140.         pwexit("Only one of -f and -s allowed.");
  141. #endif
  142.     /*
  143.      * if to change user info, do so
  144.      * you never return from this routine
  145.      */
  146.     if (dogecos)
  147.         chfn(pwinfo);
  148. #endif
  149. #ifdef GETUSERSHELL
  150.     /*
  151.      * if to change user shell, do so
  152.      * you never return from this routine
  153.      */
  154.     if (doshell)
  155.         chsh(pwinfo);
  156. #endif
  157.  
  158.     /*
  159.      * if an alternate test file is named
  160.      * the ROOTID must be running this program
  161.      */
  162.     if (strcmp(PWTESTFILE, pwtest) != 0 && uidget != ROOTID){
  163.         pwexit("only superuser can change the test file");
  164.         exit(1);
  165.     }
  166.  
  167.     /*
  168.      * if logging, initialize
  169.      */
  170.     initlog();
  171.  
  172.     /*
  173.      * attempt to verify
  174.      */
  175.     if (uidget != ROOTID && (cp = getpass("Current password: ")) == NULL)
  176.         pwexit("EOF in password -- no change");
  177.  
  178.     /*
  179.      * now do the verification
  180.      */
  181.     if (uidget != ROOTID){
  182.         if (!check_age(pwinfo))
  183.             pwexit("too soon to change password -- no change");
  184.         {
  185.             char *s;
  186.  
  187.         s = crypt(cp, pwinfo->pw_passwd);
  188.         printf("crypt password is %s, string is %s, comp hash is %s\n",
  189.                 pwinfo->pw_passwd, cp, s);
  190.         }
  191.         if (strcmp(pwinfo->pw_passwd, crypt(cp, pwinfo->pw_passwd)) != 0)
  192.             pwexit("password incorrect -- no change");
  193.         (void) strcpy(oldpassword, cp);
  194.     }
  195.     else
  196.         (void) strcpy(oldpassword, "xxxxxxxx");
  197.  
  198.     /*
  199.      * verified -- set the salt and ask for new password
  200.      */
  201.     makesalt(saltc);
  202.     if ((cp = getpass("New password: ")) == NULL)
  203.         pwexit("EOF in password -- no change");
  204.  
  205.     /*
  206.      * got it -- now the encrypted form into memory
  207.      */
  208.     (void) strcpy(password, cp);
  209.  
  210.     /*
  211.      * ask for it again (to catch typos)
  212.      */
  213.     if ((cp = getpass("Repeat new password: ")) == NULL)
  214.         pwexit("EOF in password -- no change");
  215.  
  216.     /*
  217.      * verify it
  218.      */
  219.     if (strcmp(password, cp) != 0)
  220.         pwexit("typographical error in new password -- no change");
  221.  
  222.     /*
  223.      * now see if it's an invalid password
  224.      */
  225.     if (!verify(ermsg)){
  226.         /*
  227.          * nope -- reject it
  228.          */
  229.         LOG0(LG_RESULT, "password unchanged");
  230.         if (ermsg[0] == '\0')
  231.             pwexit("password invalid -- no change");
  232.         pwexit(ermsg);
  233.     }
  234.  
  235.     /*
  236.      * valid -- update the record
  237.      */
  238.     LOG0(LG_RESULT, "password to be changed");
  239.     pwinfo->pw_passwd = crypt(password, saltc);
  240.     if (update_pwd(pwinfo) < 0){
  241.         errno = pf_errno;
  242.         if (pf_errno < sys_nerr){
  243.             (void) sprintf(ermsg, "%s: %s",
  244.                     pwdfile, sys_errlist[pf_errno]);
  245.         }
  246.         else
  247.             (void) sprintf(ermsg, "%s: unknown error #%d",
  248.                             pwdfile, pf_errno);
  249.         LOG0(LG_SYSTEM, ermsg);
  250.         pwexit(ermsg);
  251.     }
  252.  
  253.     /*
  254.      * clean up and exit
  255.      */
  256.     exit(0);
  257. }
  258.  
  259. /*
  260.  * generate a salt
  261.  */
  262. makesalt(c)
  263. char c[2];            /* salt characters */
  264. {
  265.     register long salt;        /* used to compute a salt */
  266.     register int i;            /* counter in a for loop */
  267.  
  268.     /*
  269.      * just mix a few things up for the salt ...
  270.      * no rhyme or reason here
  271.      */
  272.     salt = (((long) time(TI_NULL))&0x3f) | (getpid() << 5);
  273.  
  274.     /*
  275.      * use the bottom 12 bits and map them into the legal alphabet
  276.      */
  277.     for(i = 0; i < 2; i++){
  278.         c[i] = (salt & 0x3f) + '.';
  279.         if (c[i] > '9')
  280.             c[i] += 7;
  281.         if (c[i] > 'Z')
  282.             c[i] += 6;
  283.         salt >>= 6;
  284.     }
  285. }
  286.  
  287.