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