crypt_md5.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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 
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  */
25 
26 #include "squid.h"
28 #include "md5.h"
29 
30 #include <cstring>
31 
32 static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
33  "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
34 
35 static void md5to64(char *s, unsigned long v, int n)
36 {
37  while (--n >= 0) {
38  *s = itoa64[v & 0x3f];
39  ++s;
40  v >>= 6;
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;
62  SquidMD5_CTX ctx, ctx1;
63  unsigned long l;
64 
65  if (*salt == '$') {
66  magic = salt;
67  ++salt;
68  while (*salt && *salt != '$')
69  ++salt;
70  if (*salt == '$') {
71  ++salt;
72  magiclen = salt - magic;
73  } else {
74  salt = magic;
75  magic = "$1$";
76  }
77  }
78 
79  /* Refine the Salt first */
80  sp = salt;
81 
82  /* It stops at the first '$', max 8 chars */
83  for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ++ep)
84  continue;
85 
86  /* get the length of the true salt */
87  sl = ep - sp;
88 
89  SquidMD5Init(&ctx);
90 
91  /* The password first, since that is what is most unknown */
92  SquidMD5Update(&ctx, (unsigned const char *) pw, strlen(pw));
93 
94  /* Then our magic string */
95  SquidMD5Update(&ctx, (unsigned const char *) magic, magiclen);
96 
97  /* Then the raw salt */
98  SquidMD5Update(&ctx, (unsigned const char *) sp, sl);
99 
100  /* Then just as many characters of the MD5(pw,salt,pw) */
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);
106  for (pl = strlen(pw); pl > 0; pl -= 16)
107  SquidMD5Update(&ctx, (unsigned const char *) final, pl > 16 ? 16 : pl);
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)
114  if (i & 1)
115  SquidMD5Update(&ctx, (unsigned const char *) final + j, 1);
116  else
117  SquidMD5Update(&ctx, (unsigned const char *) pw + j, 1);
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 
125  SquidMD5Final(final, &ctx);
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  */
132  for (i = 0; i < 1000; ++i) {
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);
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 }
179 
180 /* Created by Ramon de Carvalho <ramondecarvalho@yahoo.com.br>
181  Refined by Rodrigo Rubira Branco <rodrigo@kernelhacking.com>
182 */
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];
189 
190  memset(digest,0,16);
191 
192  SquidMD5Init(&ctx);
193  SquidMD5Update(&ctx,(const unsigned char *)s,strlen(s));
194  SquidMD5Final(digest,&ctx);
195 
196  for (idx=0; idx<16; ++idx)
197  snprintf(&sum[idx*2],(33-(idx*2)),"%02x",digest[idx]);
198 
199  sum[32]='\0';
200 
201  /* Don't leave anything around in vm they could use. */
202  memset(digest, 0, sizeof digest);
203 
204  return sum;
205 }
206 
SQUIDCEXTERN void SquidMD5Init(struct SquidMD5Context *context)
Definition: md5.c:73
SQUIDCEXTERN void SquidMD5Final(uint8_t digest[16], struct SquidMD5Context *context)
static void md5to64(char *s, unsigned long v, int n)
Definition: crypt_md5.cc:35
char * crypt_md5(const char *pw, const char *salt)
Definition: crypt_md5.cc:54
char * md5sum(const char *s)
Definition: crypt_md5.cc:183
struct _sp sp
static unsigned char itoa64[]
Definition: crypt_md5.cc:32
SQUIDCEXTERN void SquidMD5Update(struct SquidMD5Context *context, const void *buf, unsigned len)
Definition: md5.c:89

 

Introduction

Documentation

Support

Miscellaneous