198937Sdes/*
298937Sdes * ----------------------------------------------------------------------------
398937Sdes * "THE BEER-WARE LICENSE" (Revision 42):
4126274Sdes * <phk@login.dknet.dk> wrote this file.  As long as you retain this
5126274Sdes * notice you can do whatever you want with this stuff. If we meet some
6126274Sdes * day, and you think this stuff is worth it, you can buy me a beer in
7124208Sdes * return.   Poul-Henning Kamp
898937Sdes * ----------------------------------------------------------------------------
998937Sdes */
1098937Sdes
1198937Sdes#include "includes.h"
1298937Sdes
1398937Sdes#if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT)
14162852Sdes#include <sys/types.h>
15162852Sdes
16162852Sdes#include <string.h>
17162852Sdes
1898937Sdes#include <openssl/md5.h>
1998937Sdes
20124208Sdes/* 0 ... 63 => ascii - 64 */
21124208Sdesstatic unsigned char itoa64[] =
22124208Sdes    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
2398937Sdes
24124208Sdesstatic char *magic = "$1$";
25124208Sdes
26124208Sdesstatic char *
27124208Sdesto64(unsigned long v, int n)
2898937Sdes{
29124208Sdes	static char buf[5];
30124208Sdes	char *s = buf;
31124208Sdes
32124208Sdes	if (n > 4)
33124208Sdes		return (NULL);
34124208Sdes
35124208Sdes	memset(buf, '\0', sizeof(buf));
3698937Sdes	while (--n >= 0) {
3798937Sdes		*s++ = itoa64[v&0x3f];
3898937Sdes		v >>= 6;
3998937Sdes	}
40126274Sdes
41124208Sdes	return (buf);
4298937Sdes}
4398937Sdes
4498937Sdesint
4598937Sdesis_md5_salt(const char *salt)
4698937Sdes{
47124208Sdes	return (strncmp(salt, magic, strlen(magic)) == 0);
4898937Sdes}
4998937Sdes
5098937Sdeschar *
5198937Sdesmd5_crypt(const char *pw, const char *salt)
5298937Sdes{
53124208Sdes	static char passwd[120], salt_copy[9], *p;
54124208Sdes	static const char *sp, *ep;
55124208Sdes	unsigned char final[16];
56124208Sdes	int sl, pl, i, j;
57124208Sdes	MD5_CTX	ctx, ctx1;
5898937Sdes	unsigned long l;
5998937Sdes
6098937Sdes	/* Refine the Salt first */
6198937Sdes	sp = salt;
6298937Sdes
6398937Sdes	/* If it starts with the magic string, then skip that */
64124208Sdes	if(strncmp(sp, magic, strlen(magic)) == 0)
6598937Sdes		sp += strlen(magic);
6698937Sdes
6798937Sdes	/* It stops at the first '$', max 8 chars */
68124208Sdes	for (ep = sp; *ep != '$'; ep++) {
69124208Sdes		if (*ep == '\0' || ep >= (sp + 8))
70124208Sdes			return (NULL);
71124208Sdes	}
7298937Sdes
7398937Sdes	/* get the length of the true salt */
7498937Sdes	sl = ep - sp;
7598937Sdes
76124208Sdes	/* Stash the salt */
77124208Sdes	memcpy(salt_copy, sp, sl);
78124208Sdes	salt_copy[sl] = '\0';
79124208Sdes
8098937Sdes	MD5_Init(&ctx);
8198937Sdes
8298937Sdes	/* The password first, since that is what is most unknown */
83124208Sdes	MD5_Update(&ctx, pw, strlen(pw));
8498937Sdes
8598937Sdes	/* Then our magic string */
86124208Sdes	MD5_Update(&ctx, magic, strlen(magic));
8798937Sdes
8898937Sdes	/* Then the raw salt */
89124208Sdes	MD5_Update(&ctx, sp, sl);
9098937Sdes
91124208Sdes	/* Then just as many characters of the MD5(pw, salt, pw) */
9298937Sdes	MD5_Init(&ctx1);
93124208Sdes	MD5_Update(&ctx1, pw, strlen(pw));
94124208Sdes	MD5_Update(&ctx1, sp, sl);
95124208Sdes	MD5_Update(&ctx1, pw, strlen(pw));
96124208Sdes	MD5_Final(final, &ctx1);
97124208Sdes
9898937Sdes	for(pl = strlen(pw); pl > 0; pl -= 16)
99124208Sdes		MD5_Update(&ctx, final, pl > 16 ? 16 : pl);
10098937Sdes
10198937Sdes	/* Don't leave anything around in vm they could use. */
102124208Sdes	memset(final, '\0', sizeof final);
10398937Sdes
10498937Sdes	/* Then something really weird... */
105124208Sdes	for (j = 0, i = strlen(pw); i != 0; i >>= 1)
106124208Sdes		if (i & 1)
107124208Sdes			MD5_Update(&ctx, final + j, 1);
10898937Sdes		else
109124208Sdes			MD5_Update(&ctx, pw + j, 1);
11098937Sdes
11198937Sdes	/* Now make the output string */
112124208Sdes	snprintf(passwd, sizeof(passwd), "%s%s$", magic, salt_copy);
11398937Sdes
114124208Sdes	MD5_Final(final, &ctx);
11598937Sdes
11698937Sdes	/*
11798937Sdes	 * and now, just to make sure things don't run too fast
11898937Sdes	 * On a 60 Mhz Pentium this takes 34 msec, so you would
11998937Sdes	 * need 30 seconds to build a 1000 entry dictionary...
12098937Sdes	 */
121124208Sdes	for(i = 0; i < 1000; i++) {
12298937Sdes		MD5_Init(&ctx1);
123124208Sdes		if (i & 1)
124124208Sdes			MD5_Update(&ctx1, pw, strlen(pw));
12598937Sdes		else
126124208Sdes			MD5_Update(&ctx1, final, 16);
12798937Sdes
128124208Sdes		if (i % 3)
129124208Sdes			MD5_Update(&ctx1, sp, sl);
13098937Sdes
131124208Sdes		if (i % 7)
132124208Sdes			MD5_Update(&ctx1, pw, strlen(pw));
13398937Sdes
134124208Sdes		if (i & 1)
135124208Sdes			MD5_Update(&ctx1, final, 16);
13698937Sdes		else
137124208Sdes			MD5_Update(&ctx1, pw, strlen(pw));
138124208Sdes
139124208Sdes		MD5_Final(final, &ctx1);
14098937Sdes	}
14198937Sdes
14298937Sdes	p = passwd + strlen(passwd);
14398937Sdes
144124208Sdes	l = (final[ 0]<<16) | (final[ 6]<<8) | final[12];
145124208Sdes	strlcat(passwd, to64(l, 4), sizeof(passwd));
146124208Sdes	l = (final[ 1]<<16) | (final[ 7]<<8) | final[13];
147124208Sdes	strlcat(passwd, to64(l, 4), sizeof(passwd));
148124208Sdes	l = (final[ 2]<<16) | (final[ 8]<<8) | final[14];
149124208Sdes	strlcat(passwd, to64(l, 4), sizeof(passwd));
150124208Sdes	l = (final[ 3]<<16) | (final[ 9]<<8) | final[15];
151124208Sdes	strlcat(passwd, to64(l, 4), sizeof(passwd));
152124208Sdes	l = (final[ 4]<<16) | (final[10]<<8) | final[ 5];
153124208Sdes	strlcat(passwd, to64(l, 4), sizeof(passwd));
154124208Sdes	l =                    final[11]                ;
155124208Sdes	strlcat(passwd, to64(l, 2), sizeof(passwd));
15698937Sdes
15798937Sdes	/* Don't leave anything around in vm they could use. */
158124208Sdes	memset(final, 0, sizeof(final));
159124208Sdes	memset(salt_copy, 0, sizeof(salt_copy));
160124208Sdes	memset(&ctx, 0, sizeof(ctx));
161124208Sdes	memset(&ctx1, 0, sizeof(ctx1));
162124208Sdes	(void)to64(0, 4);
16398937Sdes
164124208Sdes	return (passwd);
16598937Sdes}
16698937Sdes
16798937Sdes#endif /* defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) */
168