home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / msdos / lynx / source / www / library / implemen / htpasswd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-25  |  7.8 KB  |  301 lines

  1.  
  2. /* MODULE                            HTPasswd.c
  3. **        PASSWORD FILE ROUTINES
  4. **
  5. ** AUTHORS:
  6. **    AL    Ari Luotonen    luotonen@dxcern.cern.ch
  7. **    MD    Mark Donszelmann    duns@vxdeop.cern.ch
  8. **
  9. ** HISTORY:
  10. **     7 Nov 93     MD     free for crypt taken out (static data returned) 
  11. **
  12. **
  13. ** BUGS:
  14. **
  15. **
  16. */
  17.  
  18.  
  19. #include <string.h>
  20.  
  21. #include "HTUtils.h"
  22. #include "HTAAUtil.h"    /* Common parts of AA    */
  23. #include "HTAAFile.h"    /* File routines    */
  24. #include "HTPasswd.h"    /* Implemented here    */
  25. #include "tcp.h"    /* FROMASCII()        */
  26.  
  27. extern char *crypt();
  28.  
  29.  
  30. PRIVATE char salt_chars [65] =
  31.     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
  32.  
  33.  
  34. /* PRIVATE                        next_rec()
  35. **        GO TO THE BEGINNING OF THE NEXT RECORD
  36. **        Otherwise like HTAAFile_nextRec() but
  37. **        does not handle continuation lines
  38. **        (because password file has none).
  39. ** ON ENTRY:
  40. **    fp    is the password file from which records are read from.
  41. **
  42. ** ON EXIT:
  43. **    returns    nothing. File read pointer is located at the beginning
  44. **        of the next record.
  45. */
  46. PRIVATE void next_rec ARGS1(FILE *, fp)
  47. {
  48.     int ch = getc(fp);
  49.  
  50.     while (ch != EOF  &&  ch != CR  &&  ch != LF)
  51.     ch = getc(fp);        /* Skip until end-of-line */
  52.  
  53.     while (ch != EOF &&
  54.        (ch == CR  ||  ch == LF))    /*Skip carriage returns and linefeeds*/
  55.     ch = getc(fp);
  56.  
  57.     if (ch != EOF)
  58.     ungetc(ch, fp);
  59. }
  60.  
  61.  
  62. /* PUBLIC                        HTAA_encryptPasswd()
  63. **        ENCRYPT PASSWORD TO THE FORM THAT IT IS SAVED
  64. **        IN THE PASSWORD FILE.
  65. ** ON ENTRY:
  66. **    password    is a string of arbitrary lenght.
  67. **
  68. ** ON EXIT:
  69. **    returns        password in one-way encrypted form.
  70. **
  71. ** NOTE:
  72. **    Uses currently the C library function crypt(), which
  73. **    only accepts at most 8 characters long strings and produces
  74. **    always 13 characters long strings. This function is
  75. **    called repeatedly so that longer strings can be encrypted.
  76. **    This is of course not as safe as encrypting the entire
  77. **    string at once, but then again, we are not that paranoid
  78. **    about the security inside the machine.
  79. **
  80. */
  81. PUBLIC char *HTAA_encryptPasswd ARGS1(CONST char *, password)
  82. {
  83.     char salt[3];
  84.     char chunk[9];
  85.     char *result;
  86.     char *tmp;
  87.     CONST char *cur = password;
  88.     int len = strlen(password);
  89.     extern time_t theTime;
  90.     int random = (int)theTime;    /* This is random enough */
  91.  
  92.     if (!(result = (char*)malloc(13*((strlen(password)+7)/8) + 1)))
  93.     outofmem(__FILE__, "HTAA_encryptPasswd");
  94.  
  95.     *result = (char)0;
  96.     while (len > 0) {
  97.     salt[0] = salt_chars[random%64];
  98.     salt[1] = salt_chars[(random/64)%64];
  99.     salt[2] = (char)0;
  100.  
  101.     strncpy(chunk, cur, 8);
  102.     chunk[8] = (char)0;
  103.  
  104.     tmp = crypt((char*)password, salt);  /*crypt() doesn't change its args*/
  105.     strcat(result, tmp);
  106.  
  107.     cur += 8;
  108.     len -= 8;
  109.     } /* while */
  110.  
  111.     return result;
  112. }
  113.  
  114.  
  115.  
  116. /* PUBLIC                        HTAA_passwdMatch()
  117. **        VERIFY THE CORRECTNESS OF A GIVEN PASSWORD
  118. **        AGAINST A ONE-WAY ENCRYPTED FORM OF PASSWORD.
  119. ** ON ENTRY:
  120. **    password    is cleartext password.
  121. **    encrypted    is one-way encrypted password, as returned
  122. **            by function HTAA_encryptPasswd().
  123. **            This is typically read from the password
  124. **            file.
  125. **
  126. ** ON EXIT:
  127. **    returns        YES, if password matches the encrypted one.
  128. **            NO, if not, or if either parameter is NULL.
  129. ** FIX:
  130. **    Only the length of original encrypted password is
  131. **    checked -- longer given passwords are accepted if
  132. **    common length is correct (but not shorter).
  133. **    This is to allow interoperation of servers and clients
  134. **    who have a hard-coded limit of 8 to password.
  135. */
  136. PUBLIC BOOL HTAA_passwdMatch ARGS2(CONST char *, password,
  137.                    CONST char *, encrypted)
  138. {
  139.     char *result;
  140.     int len;
  141.     int status;
  142.  
  143.     if (!password || !encrypted)
  144.     return NO;
  145.  
  146.     len = 13*((strlen(password)+7)/8);
  147.     if (len < strlen(encrypted))
  148.     return NO;
  149.  
  150.     if (!(result = (char*)malloc(len + 1)))
  151.     outofmem(__FILE__, "HTAA_encryptPasswd");
  152.  
  153.     *result = (char)0;
  154.     while (len > 0) {
  155.     char salt[3];
  156.     char chunk[9];
  157.     CONST char *cur1 = password;
  158.     CONST char *cur2 = encrypted;
  159.     char *tmp;
  160.  
  161.     salt[0] = *cur2;
  162.     salt[1] = *(cur2+1);
  163.     salt[2] = (char)0;
  164.  
  165.     strncpy(chunk, cur1, 8);
  166.     chunk[8] = (char)0;
  167.  
  168.     tmp = crypt((char*)password, salt);
  169.     strcat(result, tmp);
  170.  
  171.     cur1 += 8;
  172.     cur2 += 13;
  173.     len -= 13;
  174.     } /* while */
  175.  
  176.     status = strncmp(result, encrypted, strlen(encrypted));
  177.  
  178.     if (TRACE)
  179.     fprintf(stderr,
  180.         "%s `%s' (encrypted: `%s') with: `%s' => %s\n",
  181.         "HTAA_passwdMatch: Matching password:",
  182.         password, result, encrypted,
  183.         (status==0 ? "OK" : "INCORRECT"));
  184.  
  185.     free(result);
  186.  
  187.     if (status==0)
  188.     return YES;
  189.     else
  190.     return NO;
  191. }
  192.  
  193.  
  194. /* PUBLIC                    HTAAFile_readPasswdRec()
  195. **            READ A RECORD FROM THE PASSWORD FILE
  196. ** ON ENTRY:
  197. **    fp        open password file
  198. **    out_username    buffer to put the read username, must be at
  199. **            least MAX_USERNAME_LEN+1 characters long.
  200. **    out_passwd    buffer to put the read password, must be at
  201. **            least MAX_PASSWORD_LEN+1 characters long.
  202. ** ON EXIT:
  203. **    returns        EOF on end of file,
  204. **            otherwise the number of read fields
  205. **            (i.e. in a correct case returns 2).
  206. **    out_username    contains the null-terminated read username.
  207. **    out_password    contains the null-terminated read password.
  208. **
  209. ** FORMAT OF PASSWORD FILE:
  210. **    username:password:maybe real name or other stuff
  211. **                (may include even colons)
  212. **
  213. **    There may be whitespace (blanks or tabs) in the beginning and
  214. **    the end of each field. They are ignored.
  215. */
  216. PUBLIC int HTAAFile_readPasswdRec ARGS3(FILE *, fp,
  217.                     char *, out_username,
  218.                     char *, out_password)
  219. {
  220.     char terminator;
  221.     
  222.     terminator = HTAAFile_readField(fp, out_username, MAX_USERNAME_LEN);
  223.  
  224.     if (terminator == EOF) {                /* End of file */
  225.     return EOF;
  226.     }
  227.     else if (terminator == CR  ||  terminator == LF) {    /* End of line */
  228.     next_rec(fp);
  229.     return 1;
  230.     }
  231.     else {
  232.     HTAAFile_readField(fp, out_password, MAX_PASSWORD_LEN);
  233.     next_rec(fp);
  234.     return 2;
  235.     }
  236. }
  237.  
  238.  
  239.  
  240. /* PUBLIC                        HTAA_checkPassword()
  241. **        CHECK A USERNAME-PASSWORD PAIR
  242. ** ON ENTRY:
  243. **    username    is a null-terminated string containing
  244. **            the client's username.
  245. **    password    is a null-terminated string containing
  246. **            the client's corresponding password.
  247. **    filename    is a null-terminated absolute filename
  248. **            for password file.
  249. **            If NULL or empty, the value of
  250. **            PASSWD_FILE is used.
  251. ** ON EXIT:
  252. **    returns        YES, if the username-password pair was correct.
  253. **            NO, otherwise; also, if open fails.
  254. */
  255. PUBLIC BOOL HTAA_checkPassword ARGS3(CONST char *, username,
  256.                      CONST char *, password,
  257.                      CONST char *, filename)
  258. {
  259.     FILE *fp = NULL;
  260.     char user[MAX_USERNAME_LEN+1];
  261.     char pw[MAX_PASSWORD_LEN+1];
  262.     int status;
  263.     
  264.     if (filename && *filename)  fp = fopen(filename,"r");
  265.     else            fp = fopen(PASSWD_FILE,"r");
  266.  
  267.     if (!fp) {
  268.     if (TRACE) fprintf(stderr, "%s `%s'\n",
  269.                "HTAA_checkPassword: Unable to open password file",
  270.                (filename && *filename ? filename : PASSWD_FILE));
  271.     return NO;
  272.     }
  273.     do {
  274.     if (2 == (status = HTAAFile_readPasswdRec(fp,user,pw))) {
  275.         if (TRACE)
  276.         fprintf(stderr,
  277.             "HTAAFile_validateUser: %s \"%s\" %s \"%s:%s\"\n",
  278.             "Matching username:", username,
  279.             "against passwd record:", user, pw);
  280.         if (username  &&  user  &&  !strcmp(username,user)) {
  281.         /* User's record found */
  282.         if (pw) { /* So password is required for this user */
  283.             if (!password ||
  284.             !HTAA_passwdMatch(password,pw)) /* Check the password */
  285.             status = EOF;    /* If wrong, indicate it with EOF */
  286.         }
  287.         break;  /* exit loop */
  288.         }  /* if username found */
  289.     }  /* if record is ok */
  290.     } while (status != EOF);
  291.  
  292.     fclose(fp);
  293.     
  294.     if (TRACE) fprintf(stderr, "HTAAFile_checkPassword: (%s,%s) %scorrect\n",
  295.                username, password, ((status != EOF) ? "" : "in"));
  296.  
  297.     if (status == EOF)  return NO;  /* We traversed to the end without luck */
  298.     else                return YES; /* The user was found */
  299. }
  300.  
  301.