]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Imported MD5 hash support for NCSA auth, supporting both shadow and
authorhno <>
Thu, 29 May 2003 04:42:32 +0000 (04:42 +0000)
committerhno <>
Thu, 29 May 2003 04:42:32 +0000 (04:42 +0000)
Apache htpasswd MD5 hases (same algorithms, different permutation strings)

helpers/basic_auth/NCSA/Makefile.am
helpers/basic_auth/NCSA/crypt_md5.c [new file with mode: 0644]
helpers/basic_auth/NCSA/crypt_md5.h [new file with mode: 0644]
helpers/basic_auth/NCSA/ncsa_auth.c

index e4d292aab53bb7672f364a6fa87945d2dc5495d5..0f63d35ff36b061efe01b2f22d7d46d33a618d7b 100644 (file)
@@ -1,12 +1,12 @@
 #
 #  Makefile for the Squid Object Cache server
 #
-#  $Id: Makefile.am,v 1.3 2003/01/23 00:35:30 robertc Exp $
+#  $Id: Makefile.am,v 1.4 2003/05/28 22:42:32 hno Exp $
 #
 #  Uncomment and customize the following to suit your needs:
 #
 
 libexec_PROGRAMS       = ncsa_auth
-ncsa_auth_SOURCES      = ncsa_auth.c
-LDADD                  = -L$(top_builddir)/lib -lmiscutil $(CRYPTLIB) $(XTRA_LIBS)
+ncsa_auth_SOURCES      = ncsa_auth.c crypt_md5.c crtpe_md5.h
+LDADD                  = -L$(top_builddir)/lib -lmiscutil $(CRYPTLIB) $(XTRA_LIBS) $(SSLLIB)
 INCLUDES      = -I$(top_srcdir)/include
diff --git a/helpers/basic_auth/NCSA/crypt_md5.c b/helpers/basic_auth/NCSA/crypt_md5.c
new file mode 100644 (file)
index 0000000..d781a02
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Shamelessly stolen from linux-pam, and adopted to work with
+ * OpenSSL md5 implementation and any magic string
+ *
+ * Origin2: md5_crypt.c,v 1.1.1.1 2000/01/03 17:34:46 gafton Exp
+ *
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ * Origin: Id: crypt.c,v 1.3 1995/05/30 05:42:22 rgrimes Exp
+ *
+ */
+
+#include <string.h>
+#include "config.h"
+#include "md5.h"
+
+#include "crypt_md5.h"
+
+static unsigned char itoa64[] =        /* 0 ... 63 => ascii - 64 */
+    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static void md5to64(char *s, unsigned long v, int n)
+{
+    while (--n >= 0) {
+       *s++ = itoa64[v & 0x3f];
+       v >>= 6;
+    }
+}
+
+/*
+ * MD5 hash a password
+ *
+ * Use MD5 for what it is best at...
+ *
+ * If salt begins with $ then it is assumed to be on the form
+ *   $magic$salt$...
+ * If not the normal UNIX magic $1$ is used.
+ */
+
+char *crypt_md5(const char *pw, const char *salt)
+{
+    const char *magic = "$1$";
+    int magiclen = 3;
+    static char passwd[120], *p;
+    static const char *sp, *ep;
+    unsigned char final[16];
+    int sl, pl, i, j;
+    MD5_CTX ctx, ctx1;
+    unsigned long l;
+
+    if (*salt == '$') {
+       magic = salt++;
+       while(*salt && *salt != '$')
+           salt++;
+       if (*salt == '$') {
+           salt++;
+           magiclen = salt - magic;
+       } else {
+           salt = magic;
+           magic = "$1$";
+       }
+    }
+
+    /* Refine the Salt first */
+    sp = salt;
+
+    /* It stops at the first '$', max 8 chars */
+    for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
+       continue;
+
+    /* get the length of the true salt */
+    sl = ep - sp;
+
+    MD5Init(&ctx);
+
+    /* The password first, since that is what is most unknown */
+    MD5Update(&ctx, (unsigned const char *) pw, strlen(pw));
+
+    /* Then our magic string */
+    MD5Update(&ctx, (unsigned const char *) magic, magiclen);
+
+    /* Then the raw salt */
+    MD5Update(&ctx, (unsigned const char *) sp, sl);
+
+    /* Then just as many characters of the MD5(pw,salt,pw) */
+    MD5Init(&ctx1);
+    MD5Update(&ctx1, (unsigned const char *) pw, strlen(pw));
+    MD5Update(&ctx1, (unsigned const char *) sp, sl);
+    MD5Update(&ctx1, (unsigned const char *) pw, strlen(pw));
+    MD5Final(final, &ctx1);
+    for (pl = strlen(pw); pl > 0; pl -= 16)
+       MD5Update(&ctx, (unsigned const char *) final, pl > 16 ? 16 : pl);
+
+    /* Don't leave anything around in vm they could use. */
+    memset(final, 0, sizeof final);
+
+    /* Then something really weird... */
+    for (j = 0, i = strlen(pw); i; i >>= 1)
+       if (i & 1)
+           MD5Update(&ctx, (unsigned const char *) final + j, 1);
+       else
+           MD5Update(&ctx, (unsigned const char *) pw + j, 1);
+
+    /* Now make the output string */
+    memset(passwd, 0, sizeof(passwd));
+    strncat(passwd, magic, magiclen);
+    strncat(passwd, sp, sl);
+    strcat(passwd, "$");
+
+    MD5Final(final, &ctx);
+
+    /*
+     * and now, just to make sure things don't run too fast
+     * On a 60 Mhz Pentium this takes 34 msec, so you would
+     * need 30 seconds to build a 1000 entry dictionary...
+     */
+    for (i = 0; i < 1000; i++) {
+       MD5Init(&ctx1);
+       if (i & 1)
+           MD5Update(&ctx1, (unsigned const char *) pw, strlen(pw));
+       else
+           MD5Update(&ctx1, (unsigned const char *) final, 16);
+
+       if (i % 3)
+           MD5Update(&ctx1, (unsigned const char *) sp, sl);
+
+       if (i % 7)
+           MD5Update(&ctx1, (unsigned const char *) pw, strlen(pw));
+
+       if (i & 1)
+           MD5Update(&ctx1, (unsigned const char *) final, 16);
+       else
+           MD5Update(&ctx1, (unsigned const char *) pw, strlen(pw));
+       MD5Final(final, &ctx1);
+    }
+
+    p = passwd + strlen(passwd);
+
+    l = (final[0] << 16) | (final[6] << 8) | final[12];
+    md5to64(p, l, 4);
+    p += 4;
+    l = (final[1] << 16) | (final[7] << 8) | final[13];
+    md5to64(p, l, 4);
+    p += 4;
+    l = (final[2] << 16) | (final[8] << 8) | final[14];
+    md5to64(p, l, 4);
+    p += 4;
+    l = (final[3] << 16) | (final[9] << 8) | final[15];
+    md5to64(p, l, 4);
+    p += 4;
+    l = (final[4] << 16) | (final[10] << 8) | final[5];
+    md5to64(p, l, 4);
+    p += 4;
+    l = final[11];
+    md5to64(p, l, 2);
+    p += 2;
+    *p = '\0';
+
+    /* Don't leave anything around in vm they could use. */
+    memset(final, 0, sizeof final);
+
+    return passwd;
+}
diff --git a/helpers/basic_auth/NCSA/crypt_md5.h b/helpers/basic_auth/NCSA/crypt_md5.h
new file mode 100644 (file)
index 0000000..2e27d82
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Creates a MD5 based hash of a password
+ *
+ * To validate a entered password, use the previously calculated
+ * password hash as salt, and then compare the result. If identical
+ * then the password matches.
+ *
+ * While encoding a password the salt should be 8 randomly selected
+ * characters from the base64 alphabet, for example generated as follows:
+ *    char salt[9];
+ *    to64(salt, rand(), 4);
+ *    to64(salt+4, rand(), 4);
+ *    salt[0] = '\0';
+ */
+char *crypt_md5(const char *pw, const char *salt);
index 419cdb48c889ab6bbc8f11e3681f2975b32e849a..3bc43afb76aad9c58100a6551bc3e4f523171b2b 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "util.h"
 #include "hash.h"
+#include "crypt_md5.h"
 
 static hash_table *hash = NULL;
 static HASHFREE my_free;
@@ -135,10 +136,12 @@ main(int argc, char **argv)
        u = (user_data *)hash_lookup(hash, user);
        if (u == NULL) {
            printf("ERR\n");
-       } else if (strcmp(u->passwd, (char *) crypt(passwd, u->passwd))) {
-           printf("ERR\n");
-       } else {
+       } else if (strcmp(u->passwd, (char *) crypt(passwd, u->passwd)) == 0) {
+           printf("OK\n");
+       } else if (strcmp(u->passwd, (char *) crypt_md5(passwd, u->passwd)) == 0) {
            printf("OK\n");
+       } else {
+           printf("ERR\n");
        }
     }
     exit(0);