]> git.ipfire.org Git - thirdparty/squid.git/blame - src/auth/basic/NCSA/crypt_md5.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / auth / basic / NCSA / crypt_md5.cc
CommitLineData
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 32static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
363a8ce8 33 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
34
35static 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
54char *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
183char *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