Back to index

courier  0.68.2
redhat-crypt-md5.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 1999 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #define       MD5_INTERNAL
00007 #include      "md5.h"
00008 #include      <string.h>
00009 
00010 
00011 static char base64[]=
00012         "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
00013 
00014 char *md5_crypt_redhat(const char *pw, const char *salt)
00015 {
00016 struct MD5_CONTEXT outer_context, inner_context;
00017 MD5_DIGEST digest;
00018 unsigned pwl=strlen(pw);
00019 unsigned l;
00020 unsigned i, j;
00021 char   *p;
00022 static char buffer[100];
00023 
00024        if (*salt == '$' && salt[1] == '1' && salt[2] == '$')
00025               salt += 3;
00026 
00027        for (l=0; l<8 && salt[l] && salt[l] != '$'; l++)
00028               ;
00029 
00030        md5_context_init(&inner_context);
00031        md5_context_hashstream(&inner_context, pw, pwl);
00032        md5_context_hashstream(&inner_context, salt, l);
00033        md5_context_hashstream(&inner_context, pw, pwl);
00034        md5_context_endstream(&inner_context, pwl*2+l);
00035        md5_context_digest(&inner_context, digest);
00036 
00037        md5_context_init(&outer_context);
00038        md5_context_hashstream(&outer_context, pw, pwl);
00039        md5_context_hashstream(&outer_context, "$1$", 3);
00040        md5_context_hashstream(&outer_context, salt, l);
00041 
00042        for (i=pwl; i; )
00043        {
00044               j=i;
00045               if (j > 16)   j=16;
00046               md5_context_hashstream(&outer_context, digest, j);
00047               i -= j;
00048        }
00049 
00050        j=pwl*2+l+3;
00051 
00052        for (i=pwl; i; i >>= 1)
00053        {
00054               md5_context_hashstream(&outer_context, (i & 1) ? "": pw, 1);
00055               ++j;
00056        }
00057 
00058 
00059        md5_context_endstream(&outer_context, j);
00060        md5_context_digest(&outer_context, digest);
00061 
00062        for (i=0; i<1000; i++)
00063        {
00064               j=0;
00065 
00066               md5_context_init(&outer_context);
00067               if (i & 1)
00068               {
00069                      md5_context_hashstream(&outer_context, pw, pwl);
00070                      j += pwl;
00071               }
00072               else
00073               {
00074                      md5_context_hashstream(&outer_context, digest, 16);
00075                      j += 16;
00076               }
00077     
00078               if (i % 3)
00079               {
00080                      md5_context_hashstream(&outer_context, salt, l);
00081                      j += l;
00082               }
00083     
00084               if (i % 7)
00085               {
00086                      md5_context_hashstream(&outer_context, pw, pwl);
00087                      j += pwl;
00088               }
00089     
00090               if (i & 1)
00091               {
00092                      md5_context_hashstream(&outer_context, digest, 16);
00093                      j += 16;
00094               }
00095               else
00096               {
00097                      md5_context_hashstream(&outer_context, pw, pwl);
00098                      j += pwl;
00099               }
00100 
00101               md5_context_endstream(&outer_context, j);
00102               md5_context_digest(&outer_context, digest);
00103        }
00104 
00105        strcpy(buffer, "$1$");
00106        strncat(buffer, salt, l);
00107        strcat(buffer, "$");
00108 
00109        p=buffer+strlen(buffer);
00110        for (i=0; i<5; i++)
00111        {
00112        unsigned char *d=digest;
00113 
00114               j= (d[i] << 16) | (d[i+6] << 8) | d[i == 4 ? 5:12+i];
00115               *p++= base64[j & 63] ; j=j >> 6;
00116               *p++= base64[j & 63] ; j=j >> 6;
00117               *p++= base64[j & 63] ; j=j >> 6;
00118               *p++= base64[j & 63];
00119        }
00120        j=digest[11];
00121        *p++ = base64[j & 63]; j=j >> 6;
00122        *p++ = base64[j & 63];
00123        *p=0;
00124        return (buffer);
00125 }