]>
Commit | Line | Data |
---|---|---|
363a8ce8 | 1 | /* |
2 | * Shamelessly stolen from linux-pam, and adopted to work with | |
3 | * OpenSSL md5 implementation and any magic string | |
4 | * | |
5 | * Origin2: md5_crypt.c,v 1.1.1.1 2000/01/03 17:34:46 gafton Exp | |
6 | * | |
7 | * ---------------------------------------------------------------------------- | |
8 | * "THE BEER-WARE LICENSE" (Revision 42): | |
9 | * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you | |
10 | * can do whatever you want with this stuff. If we meet some day, and you think | |
11 | * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp | |
12 | * ---------------------------------------------------------------------------- | |
13 | * | |
14 | * Origin: Id: crypt.c,v 1.3 1995/05/30 05:42:22 rgrimes Exp | |
15 | * | |
16 | */ | |
81951d76 | 17 | #include "config.h" |
363a8ce8 | 18 | |
81951d76 | 19 | #if HAVE_STRING_H |
363a8ce8 | 20 | #include <string.h> |
81951d76 AJ |
21 | #endif |
22 | #if HAVE_STDIO_H | |
8655ee19 | 23 | #include <stdio.h> |
81951d76 | 24 | #endif |
363a8ce8 | 25 | |
81951d76 | 26 | #include "md5.h" |
363a8ce8 | 27 | #include "crypt_md5.h" |
28 | ||
29 | static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ | |
30 | "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |
31 | ||
32 | static void md5to64(char *s, unsigned long v, int n) | |
33 | { | |
34 | while (--n >= 0) { | |
26ac0430 AJ |
35 | *s++ = itoa64[v & 0x3f]; |
36 | v >>= 6; | |
363a8ce8 | 37 | } |
38 | } | |
39 | ||
40 | /* | |
41 | * MD5 hash a password | |
42 | * | |
43 | * Use MD5 for what it is best at... | |
44 | * | |
45 | * If salt begins with $ then it is assumed to be on the form | |
46 | * $magic$salt$... | |
47 | * If not the normal UNIX magic $1$ is used. | |
48 | */ | |
49 | ||
50 | char *crypt_md5(const char *pw, const char *salt) | |
51 | { | |
52 | const char *magic = "$1$"; | |
53 | int magiclen = 3; | |
54 | static char passwd[120], *p; | |
55 | static const char *sp, *ep; | |
56 | unsigned char final[16]; | |
57 | int sl, pl, i, j; | |
c3031d67 | 58 | SquidMD5_CTX ctx, ctx1; |
363a8ce8 | 59 | unsigned long l; |
60 | ||
61 | if (*salt == '$') { | |
26ac0430 AJ |
62 | magic = salt++; |
63 | while (*salt && *salt != '$') | |
64 | salt++; | |
65 | if (*salt == '$') { | |
66 | salt++; | |
67 | magiclen = salt - magic; | |
68 | } else { | |
69 | salt = magic; | |
70 | magic = "$1$"; | |
71 | } | |
363a8ce8 | 72 | } |
73 | ||
74 | /* Refine the Salt first */ | |
75 | sp = salt; | |
76 | ||
77 | /* It stops at the first '$', max 8 chars */ | |
78 | for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) | |
26ac0430 | 79 | continue; |
363a8ce8 | 80 | |
81 | /* get the length of the true salt */ | |
82 | sl = ep - sp; | |
83 | ||
c3031d67 | 84 | SquidMD5Init(&ctx); |
363a8ce8 | 85 | |
86 | /* The password first, since that is what is most unknown */ | |
c3031d67 | 87 | SquidMD5Update(&ctx, (unsigned const char *) pw, strlen(pw)); |
363a8ce8 | 88 | |
89 | /* Then our magic string */ | |
c3031d67 | 90 | SquidMD5Update(&ctx, (unsigned const char *) magic, magiclen); |
363a8ce8 | 91 | |
92 | /* Then the raw salt */ | |
c3031d67 | 93 | SquidMD5Update(&ctx, (unsigned const char *) sp, sl); |
363a8ce8 | 94 | |
95 | /* Then just as many characters of the MD5(pw,salt,pw) */ | |
c3031d67 | 96 | SquidMD5Init(&ctx1); |
97 | SquidMD5Update(&ctx1, (unsigned const char *) pw, strlen(pw)); | |
98 | SquidMD5Update(&ctx1, (unsigned const char *) sp, sl); | |
99 | SquidMD5Update(&ctx1, (unsigned const char *) pw, strlen(pw)); | |
100 | SquidMD5Final(final, &ctx1); | |
363a8ce8 | 101 | for (pl = strlen(pw); pl > 0; pl -= 16) |
26ac0430 | 102 | SquidMD5Update(&ctx, (unsigned const char *) final, pl > 16 ? 16 : pl); |
363a8ce8 | 103 | |
104 | /* Don't leave anything around in vm they could use. */ | |
105 | memset(final, 0, sizeof final); | |
106 | ||
107 | /* Then something really weird... */ | |
108 | for (j = 0, i = strlen(pw); i; i >>= 1) | |
26ac0430 AJ |
109 | if (i & 1) |
110 | SquidMD5Update(&ctx, (unsigned const char *) final + j, 1); | |
111 | else | |
112 | SquidMD5Update(&ctx, (unsigned const char *) pw + j, 1); | |
363a8ce8 | 113 | |
114 | /* Now make the output string */ | |
115 | memset(passwd, 0, sizeof(passwd)); | |
116 | strncat(passwd, magic, magiclen); | |
117 | strncat(passwd, sp, sl); | |
118 | strcat(passwd, "$"); | |
119 | ||
c3031d67 | 120 | SquidMD5Final(final, &ctx); |
363a8ce8 | 121 | |
122 | /* | |
123 | * and now, just to make sure things don't run too fast | |
124 | * On a 60 Mhz Pentium this takes 34 msec, so you would | |
125 | * need 30 seconds to build a 1000 entry dictionary... | |
126 | */ | |
127 | for (i = 0; i < 1000; i++) { | |
26ac0430 AJ |
128 | SquidMD5Init(&ctx1); |
129 | if (i & 1) | |
130 | SquidMD5Update(&ctx1, (unsigned const char *) pw, strlen(pw)); | |
131 | else | |
132 | SquidMD5Update(&ctx1, (unsigned const char *) final, 16); | |
133 | ||
134 | if (i % 3) | |
135 | SquidMD5Update(&ctx1, (unsigned const char *) sp, sl); | |
136 | ||
137 | if (i % 7) | |
138 | SquidMD5Update(&ctx1, (unsigned const char *) pw, strlen(pw)); | |
139 | ||
140 | if (i & 1) | |
141 | SquidMD5Update(&ctx1, (unsigned const char *) final, 16); | |
142 | else | |
143 | SquidMD5Update(&ctx1, (unsigned const char *) pw, strlen(pw)); | |
144 | SquidMD5Final(final, &ctx1); | |
363a8ce8 | 145 | } |
146 | ||
147 | p = passwd + strlen(passwd); | |
148 | ||
149 | l = (final[0] << 16) | (final[6] << 8) | final[12]; | |
150 | md5to64(p, l, 4); | |
151 | p += 4; | |
152 | l = (final[1] << 16) | (final[7] << 8) | final[13]; | |
153 | md5to64(p, l, 4); | |
154 | p += 4; | |
155 | l = (final[2] << 16) | (final[8] << 8) | final[14]; | |
156 | md5to64(p, l, 4); | |
157 | p += 4; | |
158 | l = (final[3] << 16) | (final[9] << 8) | final[15]; | |
159 | md5to64(p, l, 4); | |
160 | p += 4; | |
161 | l = (final[4] << 16) | (final[10] << 8) | final[5]; | |
162 | md5to64(p, l, 4); | |
163 | p += 4; | |
164 | l = final[11]; | |
165 | md5to64(p, l, 2); | |
166 | p += 2; | |
167 | *p = '\0'; | |
168 | ||
169 | /* Don't leave anything around in vm they could use. */ | |
170 | memset(final, 0, sizeof final); | |
171 | ||
172 | return passwd; | |
173 | } | |
8655ee19 | 174 | |
175 | /* Created by Ramon de Carvalho <ramondecarvalho@yahoo.com.br> | |
176 | Refined by Rodrigo Rubira Branco <rodrigo@kernelhacking.com> | |
177 | */ | |
26ac0430 AJ |
178 | char *md5sum(const char *s) |
179 | { | |
180 | static unsigned char digest[16]; | |
181 | SquidMD5_CTX ctx; | |
182 | int idx; | |
183 | static char sum[33]; | |
8655ee19 | 184 | |
26ac0430 | 185 | memset(digest,0,16); |
8655ee19 | 186 | |
26ac0430 AJ |
187 | SquidMD5Init(&ctx); |
188 | SquidMD5Update(&ctx,(const unsigned char *)s,strlen(s)); | |
189 | SquidMD5Final(digest,&ctx); | |
8655ee19 | 190 | |
e1381638 | 191 | for (idx=0; idx<16; idx++) |
26ac0430 | 192 | sprintf(&sum[idx*2],"%02x",digest[idx]); |
8655ee19 | 193 | |
26ac0430 | 194 | sum[32]='\0'; |
8655ee19 | 195 | |
26ac0430 AJ |
196 | /* Don't leave anything around in vm they could use. */ |
197 | memset(digest, 0, sizeof digest); | |
8655ee19 | 198 | |
26ac0430 | 199 | return sum; |
8655ee19 | 200 | } |
201 |