aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_unix/md5.c')
-rw-r--r--modules/pam_unix/md5.c158
1 files changed, 151 insertions, 7 deletions
diff --git a/modules/pam_unix/md5.c b/modules/pam_unix/md5.c
index a9377f1..94d3dd4 100644
--- a/modules/pam_unix/md5.c
+++ b/modules/pam_unix/md5.c
@@ -17,6 +17,8 @@
#include <sys/types.h>
#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "md5.h"
#define PUT_64BIT_LE(cp, value) do { \
@@ -35,6 +37,10 @@
(cp)[1] = (value) >> 8; \
(cp)[0] = (value); } while (0)
+
+static void to64(char* , long , int );
+
+
static u_int8_t PADDING[MD5_BLOCK_LENGTH] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -244,20 +250,158 @@ MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
state[2] += c;
state[3] += d;
}
+
+
/*
* MD5String: takes a string as an argument and returns the
* digest for this string.
*/
-char * MD5String(const char * string) {
+char * MD5Hash(const char * string, const char * salt) {
+
+ int i,j,passl,saltl,pl;
+ unsigned long l;
+ MD5_CTX mdContext, mdContext2;
+ unsigned char digest[16];
+ const char *magic = "$1$";
+ const char *sp , *tsp; /*sp: salt pointer / tsp : true salt pointer*/
+ char * md5hash, *passwd;
+
+ md5hash = (char *) malloc (sizeof(char)*120);
+ passwd = md5hash;
+ sp = salt;
+
+ /* skip magic string if it's in salt --
+ * this can't happen here, since we create the
+ * salt without a magic string but someone may use
+ * this for something else one day */
+ if (!strncmp(sp, magic, strlen(magic)))
+ sp += strlen(magic);
+
+ /* stop salt at '$' or after 8 chars */
+ for (tsp = sp; *tsp && *tsp != '$' && tsp < (sp + 8); tsp++)
+ continue;
+ /* Define salt and pass length */
+ saltl = tsp - sp ;
+ passl = strlen(string);
+
+ /* Init the condext */
+ MD5Init(&mdContext);
+ /* Update with the password first */
+ MD5Update(&mdContext, (unsigned const char *)string, passl);
+ /* Then use the magic string */
+ MD5Update(&mdContext, (unsigned const char *)magic, strlen(magic));
+ /* Then use the salt */
+ MD5Update(&mdContext, (unsigned const char *)salt, saltl);
+
+ /* Update original using characters from MD5Hash of pwd,salt,pwd */
+ MD5Init(&mdContext2);
+ MD5Update(&mdContext2, (unsigned const char *)string, passl);
+ MD5Update(&mdContext2, (unsigned const char *)salt, saltl);
+ MD5Update(&mdContext2, (unsigned const char *)string, passl);
+ MD5Final (digest, &mdContext2);
+
+ /* Cool, huh? */
+ for (pl = passl; pl > 0; pl -= 16)
+ MD5Update(&mdContext,(unsigned const char *)digest,pl>16 ? 16 : pl);
+
+ /* Don't leave behind sensitive data */
+ memset(digest, 0, sizeof digest);
+
+ /* Weird stuff... */
+ for (j = 0, i = passl; i; i >>= 1) {
+ if (i & 1)
+ MD5Update(&mdContext,(unsigned const char *)digest+j,1);
+ else
+ MD5Update(&mdContext,(unsigned const char *)string+j,1);
+ }
+
+ /* Update hash with magic + salt + $ */
+ strcpy(passwd, magic);
+ strncat(passwd, salt, saltl);
+ strcat(passwd,"$");
+ passwd += strlen(md5hash);
+
+ MD5Final(digest,&mdContext);
+
+ /* Ensure that it can't go too fast (not sure why we need this) */
+ for (i = 0; i < 1000; i++) {
+ MD5Init(&mdContext2);
+ if (i & 1)
+ MD5Update(&mdContext2,(unsigned const char *)string,passl);
+ else
+ MD5Update(&mdContext2,(unsigned const char *)digest,16);
+ if (i % 3)
+ MD5Update(&mdContext2,(unsigned const char *)salt,saltl);
+
+ if (i % 7)
+ MD5Update(&mdContext2,(unsigned const char *)string,passl);
+
+ if (i & 1)
+ MD5Update(&mdContext2,(unsigned const char *)digest,16);
+ else
+ MD5Update(&mdContext2,(unsigned const char *)string,passl);
+
+ MD5Final(digest,&mdContext2);
+
+ }
+
+ /* Do some binary permutations */
+ l = (digest[0] << 16) | (digest[6] << 8) | digest[12];
+ to64(passwd, l, 4);
+ passwd += 4;
+ l = (digest[1] << 16) | (digest[7] << 8) | digest[13];
+ to64(passwd, l, 4);
+ passwd += 4;
+ l = (digest[2] << 16) | (digest[8] << 8) | digest[14];
+ to64(passwd, l, 4);
+ passwd += 4;
+ l = (digest[3] << 16) | (digest[9] << 8) | digest[15];
+ to64(passwd, l, 4);
+ passwd += 4;
+ l = (digest[4] << 16) | (digest[10] << 8) | digest[5];
+ to64(passwd, l, 4);
+ passwd += 4;
+ l = digest[11];
+ to64(passwd, l, 2);
+ passwd += 2;
+ *passwd = '\0';
+
+ /* Don't leave behind sensitive data */
+ memset(digest, 0, sizeof digest);
+ puts(md5hash);
+ return (md5hash);
+}
- MD5_CTX mdContext;
- unsigned int length = strlen(string);
- MD5Init(&mdContext);
- MD5Update(&mdContext, string, length);
- MD5Final (&mdContext);
- return (mdContext->digest);
+/*
+ * Mostly stolen from freebsd-lib's pam_unix module which was mostly
+ * stolen from passwd(1)'s local_passwd.c
+ *
+ * Good ideas are meant to be reused ;)
+ */
+
+static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static void to64(char *s, long v, int n) {
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+/* Salt suitable for traditional DES and MD5 */
+void makesalt(char salt[SALTSIZE]) {
+ int i;
+ /* These are not really random numbers, they are just
+ * numbers that change to thwart construction of a
+ * dictionary. This is exposed to the public.
+ */
+
+ for (i = 0; i < SALTSIZE; i += 4)
+ to64(&salt[i], random(), 4);
+
+ salt[SALTSIZE] = '\0';
}