11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ----------------------------------------------------------------------------
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * "THE BEER-WARE LICENSE" (Revision 42):
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * <phk@login.dknet.dk> wrote this file.  As long as you retain this
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * notice you can do whatever you want with this stuff. If we meet some
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * day, and you think this stuff is worth it, you can buy me a beer in
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * return.   Poul-Henning Kamp
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ----------------------------------------------------------------------------
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT)
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/md5.h>
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 0 ... 63 => ascii - 64 */
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic unsigned char itoa64[] =
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *magic = "$1$";
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodto64(unsigned long v, int n)
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static char buf[5];
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *s = buf;
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (n > 4)
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (NULL);
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(buf, '\0', sizeof(buf));
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (--n >= 0) {
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*s++ = itoa64[v&0x3f];
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		v >>= 6;
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (buf);
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodis_md5_salt(const char *salt)
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (strncmp(salt, magic, strlen(magic)) == 0);
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmd5_crypt(const char *pw, const char *salt)
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static char passwd[120], salt_copy[9], *p;
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static const char *sp, *ep;
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	unsigned char final[16];
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int sl, pl, i, j;
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_CTX	ctx, ctx1;
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	unsigned long l;
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Refine the Salt first */
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sp = salt;
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* If it starts with the magic string, then skip that */
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if(strncmp(sp, magic, strlen(magic)) == 0)
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sp += strlen(magic);
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* It stops at the first '$', max 8 chars */
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (ep = sp; *ep != '$'; ep++) {
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*ep == '\0' || ep >= (sp + 8))
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (NULL);
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* get the length of the true salt */
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sl = ep - sp;
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Stash the salt */
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memcpy(salt_copy, sp, sl);
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	salt_copy[sl] = '\0';
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_Init(&ctx);
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* The password first, since that is what is most unknown */
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_Update(&ctx, pw, strlen(pw));
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Then our magic string */
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_Update(&ctx, magic, strlen(magic));
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Then the raw salt */
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_Update(&ctx, sp, sl);
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Then just as many characters of the MD5(pw, salt, pw) */
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_Init(&ctx1);
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_Update(&ctx1, pw, strlen(pw));
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_Update(&ctx1, sp, sl);
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_Update(&ctx1, pw, strlen(pw));
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_Final(final, &ctx1);
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(pl = strlen(pw); pl > 0; pl -= 16)
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		MD5_Update(&ctx, final, pl > 16 ? 16 : pl);
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Don't leave anything around in vm they could use. */
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(final, '\0', sizeof final);
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Then something really weird... */
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (j = 0, i = strlen(pw); i != 0; i >>= 1)
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (i & 1)
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			MD5_Update(&ctx, final + j, 1);
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			MD5_Update(&ctx, pw + j, 1);
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Now make the output string */
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(passwd, sizeof(passwd), "%s%s$", magic, salt_copy);
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_Final(final, &ctx);
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * and now, just to make sure things don't run too fast
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * On a 60 Mhz Pentium this takes 34 msec, so you would
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * need 30 seconds to build a 1000 entry dictionary...
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; i < 1000; i++) {
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		MD5_Init(&ctx1);
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (i & 1)
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			MD5_Update(&ctx1, pw, strlen(pw));
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			MD5_Update(&ctx1, final, 16);
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (i % 3)
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			MD5_Update(&ctx1, sp, sl);
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (i % 7)
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			MD5_Update(&ctx1, pw, strlen(pw));
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (i & 1)
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			MD5_Update(&ctx1, final, 16);
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			MD5_Update(&ctx1, pw, strlen(pw));
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		MD5_Final(final, &ctx1);
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p = passwd + strlen(passwd);
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	l = (final[ 0]<<16) | (final[ 6]<<8) | final[12];
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	strlcat(passwd, to64(l, 4), sizeof(passwd));
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	l = (final[ 1]<<16) | (final[ 7]<<8) | final[13];
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	strlcat(passwd, to64(l, 4), sizeof(passwd));
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	l = (final[ 2]<<16) | (final[ 8]<<8) | final[14];
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	strlcat(passwd, to64(l, 4), sizeof(passwd));
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	l = (final[ 3]<<16) | (final[ 9]<<8) | final[15];
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	strlcat(passwd, to64(l, 4), sizeof(passwd));
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	l = (final[ 4]<<16) | (final[10]<<8) | final[ 5];
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	strlcat(passwd, to64(l, 4), sizeof(passwd));
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	l =                    final[11]                ;
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	strlcat(passwd, to64(l, 2), sizeof(passwd));
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Don't leave anything around in vm they could use. */
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(final, 0, sizeof(final));
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(salt_copy, 0, sizeof(salt_copy));
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(&ctx, 0, sizeof(ctx));
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(&ctx1, 0, sizeof(ctx1));
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	(void)to64(0, 4);
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (passwd);
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) */
168