diff options
| author | ad <ad@NetBSD.org> | 2000-07-06 11:12:42 +0000 |
|---|---|---|
| committer | ad <ad@NetBSD.org> | 2000-07-06 11:12:42 +0000 |
| commit | 49de2aa1ceac28cb2e48685980740e6f3d5ba3ec (patch) | |
| tree | 3b1709b77c7daebeae7dd813132e4c479ba07a27 /lib/libcrypt | |
| parent | 05ca1d33936b576b0053cacf7dc8e1f85dd8d6ad (diff) | |
Add __md5crypt(), for internal use by libcrypt. This behaves for the most
part like crypt() but uses a proprietry encryption scheme that utilises MD5.
From FreeBSD via OpenBSD.
Diffstat (limited to 'lib/libcrypt')
| -rw-r--r-- | lib/libcrypt/Makefile | 4 | ||||
| -rw-r--r-- | lib/libcrypt/md5crypt.c | 157 |
2 files changed, 159 insertions, 2 deletions
diff --git a/lib/libcrypt/Makefile b/lib/libcrypt/Makefile index 8a01de22f2c..21bb1445e59 100644 --- a/lib/libcrypt/Makefile +++ b/lib/libcrypt/Makefile @@ -1,8 +1,8 @@ -# $NetBSD: Makefile,v 1.9 2000/06/16 16:29:35 thorpej Exp $ +# $NetBSD: Makefile,v 1.10 2000/07/06 11:12:42 ad Exp $ LIB= crypt -SRCS= crypt.c +SRCS= crypt.c md5crypt.c MAN= crypt.3 MLINKS= crypt.3 encrypt.3 crypt.3 setkey.3 diff --git a/lib/libcrypt/md5crypt.c b/lib/libcrypt/md5crypt.c new file mode 100644 index 00000000000..59f7c529f09 --- /dev/null +++ b/lib/libcrypt/md5crypt.c @@ -0,0 +1,157 @@ +/* $NetBSD: md5crypt.c,v 1.1 2000/07/06 11:12:42 ad 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 + * ---------------------------------------------------------------------------- + * + * from FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp + * via OpenBSD: md5crypt.c,v 1.9 1997/07/23 20:58:27 kstailey Exp + * + */ + +#include <sys/cdefs.h> +#if !defined(lint) +__RCSID("$NetBSD: md5crypt.c,v 1.1 2000/07/06 11:12:42 ad Exp $"); +#endif /* not lint */ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <md5.h> +#include <string.h> + +#define MD5_MAGIC "$1$" +#define MD5_MAGIC_LEN 3 + +char *__md5crypt(const char *pw, const char *salt); /* XXX */ + +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static void to64(char *, u_int32_t, int); + +static void +to64(char *s, u_int32_t v, int n) +{ + + while (--n >= 0) { + *s++ = itoa64[v & 0x3f]; + v >>= 6; + } +} + +/* + * MD5 password encryption. + * + * XXX This is dumb. NetBSD includes it for NIS compatibility. [ad] + */ +char * +__md5crypt(const char *pw, const char *salt) +{ + static char passwd[120], *p; + const char *sp, *ep; + unsigned char final[16]; + unsigned int i, sl, pwl; + MD5_CTX ctx, ctx1; + u_int32_t l; + int pl; + + pwl = strlen(pw); + + /* Refine the salt first */ + sp = salt; + + /* If it starts with the magic string, then skip that */ + if(strncmp(sp, MD5_MAGIC, MD5_MAGIC_LEN) == 0) + sp += MD5_MAGIC_LEN; + + /* It stops at the first '$', max 8 chars */ + for(ep = sp; *ep != '\0' && *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, (const unsigned char *)pw, pwl); + + /* Then our magic string */ + MD5Update(&ctx, (const unsigned char *)MD5_MAGIC, MD5_MAGIC_LEN); + + /* Then the raw salt */ + MD5Update(&ctx, (const unsigned char *)sp, sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + MD5Init(&ctx1); + MD5Update(&ctx1, (const unsigned char *)pw, pwl); + MD5Update(&ctx1, (const unsigned char *)sp, sl); + MD5Update(&ctx1, (const unsigned char *)pw, pwl); + MD5Final(final, &ctx1); + + for(pl = pwl; pl > 0; pl -= 16) + MD5Update(&ctx, final, (unsigned int)(pl > 16 ? 16 : pl)); + + /* Don't leave anything around in vm they could use. */ + memset(final, 0, sizeof(final)); + + /* Then something really weird... */ + for (i = pwl; i != 0; i >>= 1) + if((i & 1) != 0) + MD5Update(&ctx, final, 1); + else + MD5Update(&ctx, (const unsigned char *)pw, 1); + + /* Now make the output string */ + memcpy(passwd, MD5_MAGIC, MD5_MAGIC_LEN); + strncpy(passwd + MD5_MAGIC_LEN, 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) != 0) + MD5Update(&ctx1, (const unsigned char *)pw, pwl); + else + MD5Update(&ctx1, final, 16); + + if((i % 3) != 0) + MD5Update(&ctx1, (const unsigned char *)sp, sl); + + if((i % 7) != 0) + MD5Update(&ctx1, (const unsigned char *)pw, pwl); + + if((i & 1) != 0) + MD5Update(&ctx1, final, 16); + else + MD5Update(&ctx1, (const unsigned char *)pw, pwl); + + MD5Final(final, &ctx1); + } + + p = passwd + sl + MD5_MAGIC_LEN + 1; + + l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4; + l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4; + l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4; + l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4; + l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4; + l = final[11] ; to64(p,l,2); p += 2; + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final, 0, sizeof(final)); + return (passwd); +} |
