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