00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 */
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 package require critcl
00024 package provide md5cryptc 1.0
00025 
00026 critcl::cheaders ../md5/md5.h
00027 
00028 
00029 namespace ::md5crypt {
00030     critcl::ccode {
00031 
00032 
00033 
00034 
00035         static unsigned char itoa64[] =
00036             "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
00037         
00038         static void to64(char *s, unsigned int v, int n)
00039         {
00040             while (--n >= 0) {
00041                 *s++ = itoa64[v&0x3f];
00042                 v >>= 6;
00043             }
00044         }
00045         
00046         static void dump(const char *s, unsigned int len) 
00047         {
00048             unsigned int i;
00049             for (i = 0; i < len; i++)
00050                 printf("%02X", s[i]&0xFF);
00051             putchar('\n');
00052         }
00053         
00054         static char * md5crypt(const char *pw,
00055                                const char *salt,
00056                                const char *magic)
00057         {
00058             static char     passwd[120], *p;
00059             static const unsigned char *sp,*ep;
00060             unsigned char   final[16];
00061             int sl,pl,i;
00062             MD5_CTX ctx,ctx1;
00063             unsigned long l;
00064             
00065             
00066             sp = (const unsigned char *)salt;
00067             
00068             
00069             if(!strncmp((const char *)sp,(const char *)magic,strlen((const char *)magic)))
00070                 sp += strlen((const char *)magic);
00071             
00072             
00073             for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
00074                 continue;
00075             
00076             
00077             sl = ep - sp;
00078             
00079             MD5Init(&ctx);
00080             
00081             
00082             MD5Update(&ctx,(const unsigned char *)pw,strlen(pw));
00083             
00084             
00085             MD5Update(&ctx,magic,strlen((const char *)magic));
00086             
00087             
00088             MD5Update(&ctx,sp,sl);
00089             
00090             
00091             MD5Init(&ctx1);
00092             MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
00093             MD5Update(&ctx1,sp,sl);
00094             MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
00095             MD5Final(final,&ctx1);
00096             
00097             for(pl = strlen(pw); pl > 0; pl -= 16) {
00098                 int tl = pl > 16 ? 16 : pl;
00099                 MD5Update(&ctx,final,pl>16 ? 16 : pl);
00100             }
00101             
00102             
00103             mem(final = ,0,sizeof final);
00104             
00105             
00106             for (i = strlen(pw); i ; i >>= 1) {
00107                 if(i&1)
00108                     MD5Update(&ctx, final, 1);
00109                 else
00110                     MD5Update(&ctx, (const unsigned char *)pw, 1);
00111             }
00112             
00113             
00114             snprintf(passwd, sizeof(passwd), "%s%.*s$", (char *)magic,
00115                     sl, (const char *)sp);
00116             
00117             MD5Final(final,&ctx);
00118             
00119             
00120 
00121 
00122 
00123 
00124             for(i=0;i<1000;i++) {
00125                 MD5Init(&ctx1);
00126                 if(i & 1)
00127                     MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
00128                 else
00129                     MD5Update(&ctx1,final,16);
00130                 
00131                 if(i % 3)
00132                     MD5Update(&ctx1,sp,sl);
00133                 
00134                 if(i % 7)
00135                     MD5Update(&ctx1,pw,strlen(pw));
00136                 
00137                 if(i & 1)
00138                     MD5Update(&ctx1,final,16);
00139                 else
00140                     MD5Update(&ctx1,pw,strlen(pw));
00141                 MD5Final(final,&ctx1);
00142             }
00143 
00144             p = passwd + strlen(passwd);
00145             
00146             l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
00147             l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
00148             l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
00149             l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
00150             l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
00151             l =            final[11]        ; to64(p,l,2); p += 2;
00152             *p = '\0';
00153             
00154             
00155             mem(final = ,0,sizeof final);
00156             
00157             return passwd;
00158         }            
00159     }
00160     critcl::cret  to64_c (type Tcl_, type Interp* , type interp , type int , type v , type int , type n) ok {
00161         char s[5];
00162         to64(s, (unsigned int)v, n); 
00163         Tcl_SetStringObj(Tcl_GetObjResult(interp), s, n);
00164         return TCL_OK;
00165     }
00166 
00167     critcl::cret  md5crypt_c (type Tcl_, type Interp* , type interp , type char* , type magic , type char* , type pw , type char* , type salt) ok {
00168         char* s = md5crypt(pw, salt, magic);
00169         Tcl_SetStringObj(Tcl_GetObjResult(interp), s, strlen(s));
00170         return TCL_OK;
00171     }
00172 }
00173