Changeset View
Changeset View
Standalone View
Standalone View
head/lib/libcrypt/crypt-md5.c
Show All 35 Lines | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#include "crypt.h" | #include "crypt.h" | ||||
/* | /* | ||||
* UNIX password | * UNIX password | ||||
*/ | */ | ||||
char * | int | ||||
crypt_md5(const char *pw, const char *salt) | crypt_md5(const char *pw, const char *salt, char *buffer) | ||||
{ | { | ||||
MD5_CTX ctx,ctx1; | MD5_CTX ctx,ctx1; | ||||
unsigned long l; | unsigned long l; | ||||
int sl, pl; | int sl, pl; | ||||
u_int i; | u_int i; | ||||
u_char final[MD5_SIZE]; | u_char final[MD5_SIZE]; | ||||
static const char *sp, *ep; | const char *ep; | ||||
static char passwd[120], *p; | |||||
static const char *magic = "$1$"; | static const char *magic = "$1$"; | ||||
/* Refine the Salt first */ | /* If the salt starts with the magic string, skip that. */ | ||||
sp = salt; | if (!strncmp(salt, magic, strlen(magic))) | ||||
salt += strlen(magic); | |||||
/* If it starts with the magic string, then skip that */ | |||||
if(!strncmp(sp, magic, strlen(magic))) | |||||
sp += strlen(magic); | |||||
/* It stops at the first '$', max 8 chars */ | /* It stops at the first '$', max 8 chars */ | ||||
for(ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) | for (ep = salt; *ep && *ep != '$' && ep < salt + 8; ep++) | ||||
continue; | continue; | ||||
/* get the length of the true salt */ | /* get the length of the true salt */ | ||||
sl = ep - sp; | sl = ep - salt; | ||||
MD5Init(&ctx); | MD5Init(&ctx); | ||||
/* The password first, since that is what is most unknown */ | /* The password first, since that is what is most unknown */ | ||||
MD5Update(&ctx, (const u_char *)pw, strlen(pw)); | MD5Update(&ctx, (const u_char *)pw, strlen(pw)); | ||||
/* Then our magic string */ | /* Then our magic string */ | ||||
MD5Update(&ctx, (const u_char *)magic, strlen(magic)); | MD5Update(&ctx, (const u_char *)magic, strlen(magic)); | ||||
/* Then the raw salt */ | /* Then the raw salt */ | ||||
MD5Update(&ctx, (const u_char *)sp, (u_int)sl); | MD5Update(&ctx, (const u_char *)salt, (u_int)sl); | ||||
/* Then just as many characters of the MD5(pw,salt,pw) */ | /* Then just as many characters of the MD5(pw,salt,pw) */ | ||||
MD5Init(&ctx1); | MD5Init(&ctx1); | ||||
MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); | MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); | ||||
MD5Update(&ctx1, (const u_char *)sp, (u_int)sl); | MD5Update(&ctx1, (const u_char *)salt, (u_int)sl); | ||||
MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); | MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); | ||||
MD5Final(final, &ctx1); | MD5Final(final, &ctx1); | ||||
for(pl = (int)strlen(pw); pl > 0; pl -= MD5_SIZE) | for(pl = (int)strlen(pw); pl > 0; pl -= MD5_SIZE) | ||||
MD5Update(&ctx, (const u_char *)final, | MD5Update(&ctx, (const u_char *)final, | ||||
(u_int)(pl > MD5_SIZE ? MD5_SIZE : pl)); | (u_int)(pl > MD5_SIZE ? MD5_SIZE : pl)); | ||||
/* Don't leave anything around in vm they could use. */ | /* Don't leave anything around in vm they could use. */ | ||||
memset(final, 0, sizeof(final)); | memset(final, 0, sizeof(final)); | ||||
/* Then something really weird... */ | /* Then something really weird... */ | ||||
for (i = strlen(pw); i; i >>= 1) | for (i = strlen(pw); i; i >>= 1) | ||||
if(i & 1) | if(i & 1) | ||||
MD5Update(&ctx, (const u_char *)final, 1); | MD5Update(&ctx, (const u_char *)final, 1); | ||||
else | else | ||||
MD5Update(&ctx, (const u_char *)pw, 1); | MD5Update(&ctx, (const u_char *)pw, 1); | ||||
/* Now make the output string */ | /* Now make the output string */ | ||||
strcpy(passwd, magic); | buffer = stpcpy(buffer, magic); | ||||
strncat(passwd, sp, (u_int)sl); | buffer = stpncpy(buffer, salt, (u_int)sl); | ||||
strcat(passwd, "$"); | *buffer++ = '$'; | ||||
MD5Final(final, &ctx); | MD5Final(final, &ctx); | ||||
/* | /* | ||||
* and now, just to make sure things don't run too fast | * and now, just to make sure things don't run too fast | ||||
* On a 60 Mhz Pentium this takes 34 msec, so you would | * On a 60 Mhz Pentium this takes 34 msec, so you would | ||||
* need 30 seconds to build a 1000 entry dictionary... | * need 30 seconds to build a 1000 entry dictionary... | ||||
*/ | */ | ||||
for(i = 0; i < 1000; i++) { | for(i = 0; i < 1000; i++) { | ||||
MD5Init(&ctx1); | MD5Init(&ctx1); | ||||
if(i & 1) | if(i & 1) | ||||
MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); | MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); | ||||
else | else | ||||
MD5Update(&ctx1, (const u_char *)final, MD5_SIZE); | MD5Update(&ctx1, (const u_char *)final, MD5_SIZE); | ||||
if(i % 3) | if(i % 3) | ||||
MD5Update(&ctx1, (const u_char *)sp, (u_int)sl); | MD5Update(&ctx1, (const u_char *)salt, (u_int)sl); | ||||
if(i % 7) | if(i % 7) | ||||
MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); | MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); | ||||
if(i & 1) | if(i & 1) | ||||
MD5Update(&ctx1, (const u_char *)final, MD5_SIZE); | MD5Update(&ctx1, (const u_char *)final, MD5_SIZE); | ||||
else | else | ||||
MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); | MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); | ||||
MD5Final(final, &ctx1); | MD5Final(final, &ctx1); | ||||
} | } | ||||
p = passwd + strlen(passwd); | |||||
l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; | l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; | ||||
_crypt_to64(p, l, 4); p += 4; | _crypt_to64(buffer, l, 4); buffer += 4; | ||||
l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; | l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; | ||||
_crypt_to64(p, l, 4); p += 4; | _crypt_to64(buffer, l, 4); buffer += 4; | ||||
l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; | l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; | ||||
_crypt_to64(p, l, 4); p += 4; | _crypt_to64(buffer, l, 4); buffer += 4; | ||||
l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; | l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; | ||||
_crypt_to64(p, l, 4); p += 4; | _crypt_to64(buffer, l, 4); buffer += 4; | ||||
l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; | l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; | ||||
_crypt_to64(p, l, 4); p += 4; | _crypt_to64(buffer, l, 4); buffer += 4; | ||||
l = final[11]; | l = final[11]; | ||||
_crypt_to64(p, l, 2); p += 2; | _crypt_to64(buffer, l, 2); buffer += 2; | ||||
*p = '\0'; | *buffer = '\0'; | ||||
/* Don't leave anything around in vm they could use. */ | /* Don't leave anything around in vm they could use. */ | ||||
memset(final, 0, sizeof(final)); | memset(final, 0, sizeof(final)); | ||||
return (passwd); | return (0); | ||||
} | } |