httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From c...@hyperreal.org
Subject cvs commit: apache-1.3/src/support htpasswd.1 htpasswd.c
Date Mon, 25 Jan 1999 22:55:42 GMT
coar        99/01/25 14:55:41

  Modified:    .        STATUS
               src      CHANGES
               src/ap   ap_md5c.c
               src/include ap_md5.h
               src/modules/standard mod_auth.c mod_auth_db.c mod_auth_dbm.c
               src/support htpasswd.1 htpasswd.c
  Log:
  	Enhance the authentication password handling so that stored
  	passwords can be encrypted with either DES or MD5.  htpasswd can
  	now generate either on systems that allow both, and MD5 on
  	Win32.   .htpasswd files can contain both types; usernames
  	with passwords encrypted with MD5 and usernames with DES
  	passwords can appear in the same file.  The authentication
  	modules (mod_auth, mod_auth_db, mod_auth_dbm) autosense the
  	correct algorithm from the stored password.
  
  	This gives us encrypted passwords on Win32 at last.  This is
  	only the first part of the patch; some changes to allow the
  	Win32 side to build properly are being fixed and should be
  	committed to-morrow.  However, Unix systems can build with
  	and use these immediately.
  
  Submitted by:	Ryan Bloom <rbb@Raleigh.IBM.Com>
  Reviewed by:	Ken Coar
  
  Revision  Changes    Path
  1.607     +1 -5      apache-1.3/STATUS
  
  Index: STATUS
  ===================================================================
  RCS file: /home/cvs/apache-1.3/STATUS,v
  retrieving revision 1.606
  retrieving revision 1.607
  diff -u -r1.606 -r1.607
  --- STATUS	1999/01/20 03:38:18	1.606
  +++ STATUS	1999/01/25 22:55:31	1.607
  @@ -1,5 +1,5 @@
     1.3 STATUS:
  -  Last modified at [$Date: 1999/01/20 03:38:18 $]
  +  Last modified at [$Date: 1999/01/25 22:55:31 $]
   
   Release:
   
  @@ -385,10 +385,6 @@
   
         That _really_ sucks.  Can we recommend running Apache as some 
         other user?
  -
  -    * need a crypt() of some sort.
  -	- sources are easy; problem is export restrictions on DES
  -	- if we don't do DES, can do md5
   
       * modules that need to be made to work on win32
           - mod_example isn't multithreadreded
  
  
  
  1.1223    +3 -0      apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.1222
  retrieving revision 1.1223
  diff -u -r1.1222 -r1.1223
  --- CHANGES	1999/01/25 18:12:36	1.1222
  +++ CHANGES	1999/01/25 22:55:33	1.1223
  @@ -1,5 +1,8 @@
   Changes with Apache 1.3.5
   
  +  *) Add ability to handle DES or MD5 authentication passwords.
  +     [Ryan Bloom <rbb@Raleigh.IBM.Com>]
  +
     *) Fix O(n^2) memory consumption in mod_speling.  [Dean Gaudet]
   
     *) SECURITY: Avoid some buffer overflow problems when escaping
  
  
  
  1.18      +45 -0     apache-1.3/src/ap/ap_md5c.c
  
  Index: ap_md5c.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/ap/ap_md5c.c,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- ap_md5c.c	1999/01/01 19:04:53	1.17
  +++ ap_md5c.c	1999/01/25 22:55:36	1.18
  @@ -92,6 +92,7 @@
   
   #include "ap_config.h"
   #include "ap_md5.h"
  +#include "ap.h"
   #ifdef CHARSET_EBCDIC
   #include "ebcdic.h"
   #endif /*CHARSET_EBCDIC*/
  @@ -389,4 +390,48 @@
       for (i = 0, j = 0; j < len; i++, j += 4)
   	output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
   	    (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
  +}
  +
  +API_EXPORT(char *) ap_MD5Encode(const char *password, const char * salt) {
  +/* salt has size 2, md5 hash size 22, plus 1 for trailing NUL, plus 4 for
  +   '$' separators between md5 distinguisher, salt, and password.*/
  +
  +    static unsigned char ret[2+22+1+4];
  +    AP_MD5_CTX my_md5;
  +    unsigned char hash[16], *cp;
  +    register int i;
  +    static const char *alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
  + 
  +    /*
  +     * Take the MD5 hash of the string argument.
  +    */
  + 
  +    sprintf(ret, "$1$%s$", salt); 
  + 
  +    /* If the salt is shorter than 2, pad with random characters */
  +    for (cp = &ret[strlen(ret)]; cp < &ret[2]; ++cp) {
  +        *cp = alphabet[rand() & 0x3F];
  +    }
  +    ap_MD5Init(&my_md5);
  +    ap_MD5Update(&my_md5, salt, 2);
  +    ap_MD5Update(&my_md5, password, strlen(password));
  +    ap_MD5Final(hash, &my_md5);
  + 
  +    /* Take 3*8 bits (3 bytes) and store them as 4 base64 bytes (of 6 bit each) */
  +    /* Copy first 15 bytes in loop (producing 20 result bytes) */
  +    for (i = 0, cp = &ret[6]; i < 15; i += 3, cp += 4) {
  +        long l = hash[i] | (hash[i+1] << 8) | (hash[i+2] << 16);
  + 
  +        cp[0] = alphabet[l&0x3F];
  +        cp[1] = alphabet[(l>>6)&0x3F];
  +        cp[2] = alphabet[(l>>12)&0x3F];
  +        cp[3] = alphabet[(l>>18)&0x3F];
  +    }
  +    cp[0] = alphabet[hash[i]&0x3F]; /* Use 16th byte as 21st result byte */
  +    cp[1] = alphabet[(hash[i]>>6)&0x3F]; /* Last 2 bits of 16th byte are 22nd
result byte */
  +    cp[2] = '\0';
  + 
  +    /*ap_assert(&cp[2] == &ret[(sizeof ret)-1]);*/
  + 
  +    return (char *)ret;
   }
  
  
  
  1.3       +1 -0      apache-1.3/src/include/ap_md5.h
  
  Index: ap_md5.h
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/include/ap_md5.h,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ap_md5.h	1999/01/01 19:04:39	1.2
  +++ ap_md5.h	1999/01/25 22:55:37	1.3
  @@ -108,6 +108,7 @@
   API_EXPORT(void) ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input,
   			   unsigned int inputLen);
   API_EXPORT(void) ap_MD5Final(unsigned char digest[16], AP_MD5_CTX * context);
  +API_EXPORT(char *) ap_MD5Encode(const char *, const char *);
   
   #ifdef __cplusplus
   }
  
  
  
  1.43      +12 -2     apache-1.3/src/modules/standard/mod_auth.c
  
  Index: mod_auth.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_auth.c,v
  retrieving revision 1.42
  retrieving revision 1.43
  diff -u -r1.42 -r1.43
  --- mod_auth.c	1999/01/01 19:05:07	1.42
  +++ mod_auth.c	1999/01/25 22:55:38	1.43
  @@ -74,6 +74,7 @@
   #include "http_core.h"
   #include "http_log.h"
   #include "http_protocol.h"
  +#include "ap_md5.h"
   #if defined(HAVE_CRYPT_H)
   #include <crypt.h>
   #endif
  @@ -220,9 +221,18 @@
   	return AUTH_REQUIRED;
       }
       /* anyone know where the prototype for crypt is? */
  -    if (strcmp(real_pw, (char *) crypt(sent_pw, real_pw))) {
  +    if (real_pw[0] == '$' && real_pw[1] == '1') {
  +        const char *salt = real_pw + 3;
  +        salt = ap_getword(r->pool, &salt, '$');
  +        res = strcmp(real_pw, ap_MD5Encode(sent_pw, salt));
  +    }
  +    else {
  +        res = strcmp(real_pw, crypt(sent_pw, real_pw));
  +    }
  +
  +    if (res != 0) {
   	ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  -		    "user %s: password mismatch: %s", c->user, r->uri);
  +		      "user %s: password mismatch: %s", c->user, r->uri);
   	ap_note_basic_auth_failure(r);
   	return AUTH_REQUIRED;
       }
  
  
  
  1.37      +17 -3     apache-1.3/src/modules/standard/mod_auth_db.c
  
  Index: mod_auth_db.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_auth_db.c,v
  retrieving revision 1.36
  retrieving revision 1.37
  diff -u -r1.36 -r1.37
  --- mod_auth_db.c	1999/01/01 19:05:07	1.36
  +++ mod_auth_db.c	1999/01/25 22:55:38	1.37
  @@ -96,6 +96,10 @@
   #include "http_log.h"
   #include "http_protocol.h"
   #include <db.h>
  +#include "ap_md5.h";
  +#if defined(HAVE_CRYPT_H)
  +#include <crypt.h>
  +#endif
   
   #if defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 2)
   #define DB2
  @@ -244,12 +248,22 @@
       }
       /* Password is up to first : if exists */
       colon_pw = strchr(real_pw, ':');
  -    if (colon_pw)
  +    if (colon_pw) {
   	*colon_pw = '\0';
  +    }
       /* anyone know where the prototype for crypt is? */
  -    if (strcmp(real_pw, (char *) crypt(sent_pw, real_pw))) {
  +    if (real_pw[0] == '$' && real_pw[1] == '1') {
  +        char *salt = real_pw + 3;
  +        salt = ap_getword(r->pool, &salt, '$');
  +        res = strcmp(real_pw, ap_MD5Encode(sent_pw, salt));
  +    }
  +    else {
  +        res = strcmp(real_pw, crypt(sent_pw, real_pw));
  +    }
  +
  +    if (res != 0) {
   	ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  -		    "DB user %s: password mismatch: %s", c->user, r->uri);
  +		      "DB user %s: password mismatch: %s", c->user, r->uri);
   	ap_note_basic_auth_failure(r);
   	return AUTH_REQUIRED;
       }
  
  
  
  1.42      +15 -2     apache-1.3/src/modules/standard/mod_auth_dbm.c
  
  Index: mod_auth_dbm.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_auth_dbm.c,v
  retrieving revision 1.41
  retrieving revision 1.42
  diff -u -r1.41 -r1.42
  --- mod_auth_dbm.c	1999/01/01 19:05:07	1.41
  +++ mod_auth_dbm.c	1999/01/25 22:55:39	1.42
  @@ -75,6 +75,10 @@
   #include "http_log.h"
   #include "http_protocol.h"
   #include <ndbm.h>
  +#include "ap_md5.h";
  +#if defined(HAVE_CRYPT_H)
  +#include <crypt.h>
  +#endif
   
   /*
    * Module definition information - the part between the -START and -END
  @@ -229,9 +233,18 @@
       if (colon_pw)
   	*colon_pw = '\0';
       /* anyone know where the prototype for crypt is? */
  -    if (strcmp(real_pw, (char *) crypt(sent_pw, real_pw))) {
  +    if (real_pw[0] == '$' && real_pw[1] == '1') {
  +        char *salt = real_pw + 3;
  +        salt = ap_getword(r->pool, &salt, '$');
  +        res = strcmp(real_pw, ap_MD5Encode(sent_pw, salt));
  +    }
  +    else {
  +        res = strcmp(real_pw, crypt(sent_pw, real_pw));
  +    }
  +
  +    if (res != 0) {
   	ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  -		    "user %s: password mismatch: %s", c->user, r->uri);
  +		      "user %s: password mismatch: %s", c->user, r->uri);
   	ap_note_basic_auth_failure(r);
   	return AUTH_REQUIRED;
       }
  
  
  
  1.8       +3 -0      apache-1.3/src/support/htpasswd.1
  
  Index: htpasswd.1
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/support/htpasswd.1,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- htpasswd.1	1999/01/01 19:05:34	1.7
  +++ htpasswd.1	1999/01/25 22:55:40	1.8
  @@ -85,6 +85,9 @@
   .IP \-c 
   Create the \fIpasswdfile\fP. If \fIpasswdfile\fP already exists, it
   is deleted first. 
  +.IP \-m 
  +Use MD5 encryption for passwords.  On Windows, this is the only format 
  +supported.
   .IP \fB\fIpasswdfile\fP
   Name of the file to contain the user name and password. If \-c
   is given, this file is created if it does not already exist,
  
  
  
  1.19      +111 -29   apache-1.3/src/support/htpasswd.c
  
  Index: htpasswd.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/support/htpasswd.c,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- htpasswd.c	1999/01/19 22:35:45	1.18
  +++ htpasswd.c	1999/01/25 22:55:41	1.19
  @@ -13,7 +13,14 @@
   #include "ap_config.h"
   #include <sys/types.h>
   #include <signal.h>
  +#include "ap_md5.h"
   
  +#ifdef WIN32
  +#include <conio.h>
  +#include "../os/win32/getopt.h"
  +#define unlink _unlink
  +#endif
  +
   #ifndef CHARSET_EBCDIC
   #define LF 10
   #define CR 13
  @@ -116,8 +123,42 @@
   
   #endif
   
  -static void add_password(char *user, FILE *f)
  +#ifdef WIN32
  +/* Windows lacks getpass().  So we'll re-implement it here.
  + */
  +
  +static char *getpass(const char *prompt)
   {
  +    static char password[81];
  +    int n = 0;
  +
  +    fputs(prompt, stderr);
  +    
  +    while ((password[n] = _getch()) != '\r') {
  +        if (password[n] >= ' ' && password[n] <= '~') {
  +            n++;
  +            printf("*");
  +        }
  +	else {
  +            printf("\n");
  +            fputs(prompt, stderr);
  +            n = 0;
  +        }
  +    }
  + 
  +    password[n] = '\0';
  +    printf("\n");
  +
  +    if (n > 8) {
  +        password[8] = '\0';
  +    }
  +
  +    return (char *) &password;
  +}
  +#endif
  +
  +static void add_password(char *user, FILE *f, int use_md5)
  +{
       char *pw, *cpw, salt[3];
   
       pw = strd((char *) getpass("New password:"));
  @@ -131,15 +172,23 @@
       (void) srand((int) time((time_t *) NULL));
       to64(&salt[0], rand(), 2);
       salt[2] = '\0';
  -    cpw = (char *)crypt(pw, salt);
  +
  +    if (use_md5) {
  +        cpw = (char *)ap_MD5Encode(pw, salt);
  +    }
  +    else {
  +	cpw = (char *)crypt(pw, salt);
  +    }
       free(pw);
       fprintf(f, "%s:%s\n", user, cpw);
   }
   
   static void usage(void)
   {
  -    fprintf(stderr, "Usage: htpasswd [-c] passwordfile username\n");
  +    fprintf(stderr, "Usage: htpasswd [-cm] passwordfile username\n");
       fprintf(stderr, "The -c flag creates a new file.\n");
  +    fprintf(stderr, "The -m flag creates a md5 encrypted file.\n");
  +    fprintf(stderr, "On Windows systems the -m flag is used by default.\n");
       exit(1);
   }
   
  @@ -160,27 +209,58 @@
       char l[MAX_STRING_LEN];
       char w[MAX_STRING_LEN];
       char command[MAX_STRING_LEN];
  +    char filename[MAX_STRING_LEN];
       int found;
  +    int use_md5 = 0;
  +    int newfile = 0;
   
       tn = NULL;
  -    signal(SIGINT, (void (*)()) interrupted);
  -    if (argc == 4) {
  -	if (strcmp(argv[1], "-c")) {
  +    signal(SIGINT, (void (*)(int)) interrupted);
  +
  +    /* preliminary check to make sure they provided at least
  +     * three arguments, we'll do better argument checking as 
  +     * we parse the command line.
  +     */
  +    if (argc < 3) {
   	    usage();
  -	}
  -	if (!(tfp = fopen(argv[2], "w+"))) {
  -	    fprintf(stderr, "Could not open passwd file %s for writing.\n",
  -		    argv[2]);
  +    }
  +    else {
  +        strcpy(filename, argv[argc - 2]);
  +    }
  +
  +    /* I would rather use getopt, but Windows and UNIX seem to handle getopt
  +     * differently, so I am doing the argument checking by hand.
  +     */
  +    
  +    if (!strcmp(argv[1],"-c") || !strcmp(argv[2],"-c")) {
  +        newfile = 1;
  +    }
  +    if (!strcmp(argv[1],"-m") || !strcmp(argv[2],"-m")) {
  +        use_md5 = 1;
  +    }
  +
  +    if (!strcmp(argv[1], "-cm") || !strcmp(argv[2], "-mc")) {
  +        use_md5 = 1;
  +        newfile = 1;
  +    }
  +
  +#ifdef WIN32
  +    if (!use_md5) {
  +	use_md5 = 1;
  +	fprintf(stderr,"Automatically using md5 format on Windows.\n");
  +    }
  +#endif
  +    if (newfile) {
  +        if (!(tfp = fopen(filename, "w+"))) {
  +            fprintf(stderr, "Could not open password file %s for writing.\n",
  +                    filename);
   	    perror("fopen");
   	    exit(1);
   	}
  -	printf("Adding password for %s.\n", argv[3]);
  -	add_password(argv[3], tfp);
  +	printf("Adding password for %s.\n", argv[argc-1]);
  +	add_password(argv[argc - 1], tfp, use_md5);
   	fclose(tfp);
  -	exit(0);
  -    }
  -    else if (argc != 3) {
  -	usage();
  +	return(0);
       }
   
       tn = tmpnam(NULL);
  @@ -189,13 +269,15 @@
   	exit(1);
       }
   
  -    if (!(f = fopen(argv[1], "r+"))) {
  -	fprintf(stderr,
  -		"Could not open passwd file %s for reading.\n", argv[1]);
  -	fprintf(stderr, "Use -c option to create new one.\n");
  +    if (!(f = fopen(argv[argc - 2], "r+"))) {
  +        fprintf(stderr, "Could not open password file %s for reading.\n",
  +                argv[argc - 2]);
  +        fprintf(stderr, "Use -c option to create a new one\n");
  +	fclose(tfp);
  +	unlink(tn);
   	exit(1);
       }
  -    strcpy(user, argv[2]);
  +    strcpy(user, argv[argc - 1]);
   
       found = 0;
       while (!(getline(line, MAX_STRING_LEN, f))) {
  @@ -208,28 +290,28 @@
   	if (strcmp(user, w)) {
   	    putline(tfp, line);
   	    continue;
  -	}
  +        }
   	else {
   	    printf("Changing password for user %s\n", user);
  -	    add_password(user, tfp);
  +            add_password(user, tfp, use_md5);
   	    found = 1;
   	}
       }
       if (!found) {
   	printf("Adding user %s\n", user);
  -	add_password(user, tfp);
  +        add_password(user, tfp, use_md5);
       }
   /*
    * make a copy from the tmp file to the actual file
    */  
  -    rewind(f);
  +    f = fopen(filename, "w+");
       rewind(tfp);
  -    while ( fgets(command,MAX_STRING_LEN,tfp) != NULL) {
  -	fputs(command,f);
  -    } 
  +    while (fgets(command, MAX_STRING_LEN, tfp) != NULL) {
  +	fputs(command, f);
  +    }
   
       fclose(f);
       fclose(tfp);
       unlink(tn);
  -    exit(0);
  +    return(0);
   }
  
  
  

Mime
View raw message