upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr-util / crypto / apr_md5.c
1 /*
2  * This is work is derived from material Copyright RSA Data Security, Inc.
3  *
4  * The RSA copyright statement and Licence for that original material is
5  * included below. This is followed by the Apache copyright statement and
6  * licence for the modifications made to that material.
7  */
8
9 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
10  */
11
12 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
13    rights reserved.
14
15    License to copy and use this software is granted provided that it
16    is identified as the "RSA Data Security, Inc. MD5 Message-Digest
17    Algorithm" in all material mentioning or referencing this software
18    or this function.
19
20    License is also granted to make and use derivative works provided
21    that such works are identified as "derived from the RSA Data
22    Security, Inc. MD5 Message-Digest Algorithm" in all material
23    mentioning or referencing the derived work.
24
25    RSA Data Security, Inc. makes no representations concerning either
26    the merchantability of this software or the suitability of this
27    software for any particular purpose. It is provided "as is"
28    without express or implied warranty of any kind.
29
30    These notices must be retained in any copies of any part of this
31    documentation and/or software.
32  */
33
34 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
35  * applicable.
36  *
37  * Licensed under the Apache License, Version 2.0 (the "License");
38  * you may not use this file except in compliance with the License.
39  * You may obtain a copy of the License at
40  *
41  *     http://www.apache.org/licenses/LICENSE-2.0
42  *
43  * Unless required by applicable law or agreed to in writing, software
44  * distributed under the License is distributed on an "AS IS" BASIS,
45  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
46  * See the License for the specific language governing permissions and
47  * limitations under the License.
48  */
49
50 /*
51  * The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0
52  * MD5 crypt() function, which is licenced as follows:
53  * ----------------------------------------------------------------------------
54  * "THE BEER-WARE LICENSE" (Revision 42):
55  * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
56  * can do whatever you want with this stuff. If we meet some day, and you think
57  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
58  * ----------------------------------------------------------------------------
59  */
60 #include "apr_strings.h"
61 #include "apr_md5.h"
62 #include "apr_sha1.h" /* needed by apr_password_validate */
63 #include "apr_lib.h"
64 #include "apu_config.h"
65
66 #if APR_HAVE_STRING_H
67 #include <string.h>
68 #endif
69 #if APR_HAVE_CRYPT_H
70 #include <crypt.h>
71 #endif
72 #if APR_HAVE_UNISTD_H
73 #include <unistd.h>
74 #endif
75 #if APR_HAVE_PTHREAD_H
76 #include <pthread.h>
77 #endif
78
79 /* Constants for MD5Transform routine.
80  */
81
82 #define S11 7
83 #define S12 12
84 #define S13 17
85 #define S14 22
86 #define S21 5
87 #define S22 9
88 #define S23 14
89 #define S24 20
90 #define S31 4
91 #define S32 11
92 #define S33 16
93 #define S34 23
94 #define S41 6
95 #define S42 10
96 #define S43 15
97 #define S44 21
98
99 static void MD5Transform(apr_uint32_t state[4], const unsigned char block[64]);
100 static void Encode(unsigned char *output, const apr_uint32_t *input,
101                    unsigned int len);
102 static void Decode(apr_uint32_t *output, const unsigned char *input,
103                    unsigned int len);
104
105 static unsigned char PADDING[64] =
106 {
107     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
110 };
111
112 #if APR_CHARSET_EBCDIC
113 static apr_xlate_t *xlate_ebcdic_to_ascii; /* used in apr_md5_encode() */
114 #endif
115
116 /* F, G, H and I are basic MD5 functions.
117  */
118 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
119 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
120 #define H(x, y, z) ((x) ^ (y) ^ (z))
121 #define I(x, y, z) ((y) ^ ((x) | (~z)))
122
123 /* ROTATE_LEFT rotates x left n bits.
124  */
125 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
126
127 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
128  * Rotation is separate from addition to prevent recomputation.
129  */
130 #define FF(a, b, c, d, x, s, ac) { \
131  (a) += F ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
132  (a) = ROTATE_LEFT ((a), (s)); \
133  (a) += (b); \
134   }
135 #define GG(a, b, c, d, x, s, ac) { \
136  (a) += G ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
137  (a) = ROTATE_LEFT ((a), (s)); \
138  (a) += (b); \
139   }
140 #define HH(a, b, c, d, x, s, ac) { \
141  (a) += H ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
142  (a) = ROTATE_LEFT ((a), (s)); \
143  (a) += (b); \
144   }
145 #define II(a, b, c, d, x, s, ac) { \
146  (a) += I ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
147  (a) = ROTATE_LEFT ((a), (s)); \
148  (a) += (b); \
149   }
150
151 /* MD5 initialization. Begins an MD5 operation, writing a new context.
152  */
153 APU_DECLARE(apr_status_t) apr_md5_init(apr_md5_ctx_t *context)
154 {
155     context->count[0] = context->count[1] = 0;
156     
157     /* Load magic initialization constants. */
158     context->state[0] = 0x67452301;
159     context->state[1] = 0xefcdab89;
160     context->state[2] = 0x98badcfe;
161     context->state[3] = 0x10325476;
162     context->xlate = NULL;
163     
164     return APR_SUCCESS;
165 }
166
167 /* MD5 translation setup.  Provides the APR translation handle
168  * to be used for translating the content before calculating the
169  * digest.
170  */
171 APU_DECLARE(apr_status_t) apr_md5_set_xlate(apr_md5_ctx_t *context, 
172                                             apr_xlate_t *xlate)
173 {
174 #if APR_HAS_XLATE
175     apr_status_t rv;
176     int is_sb;
177
178     /* TODO: remove the single-byte-only restriction from this code
179      */
180     rv = apr_xlate_sb_get(xlate, &is_sb);
181     if (rv != APR_SUCCESS) {
182         return rv;
183     }
184     if (!is_sb) {
185         return APR_EINVAL;
186     }
187     context->xlate = xlate;
188     return APR_SUCCESS;
189 #else
190     return APR_ENOTIMPL;
191 #endif /* APR_HAS_XLATE */
192 }
193
194 /* MD5 block update operation. Continues an MD5 message-digest
195  * operation, processing another message block, and updating the
196  * context.
197  */
198 APU_DECLARE(apr_status_t) apr_md5_update(apr_md5_ctx_t *context,
199                                          const void *_input,
200                                          apr_size_t inputLen)
201 {
202     const unsigned char *input = _input;
203     unsigned int i, idx, partLen;
204 #if APR_HAS_XLATE
205     apr_size_t inbytes_left, outbytes_left;
206 #endif
207
208     /* Compute number of bytes mod 64 */
209     idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
210
211     /* Update number of bits */
212     if ((context->count[0] += ((apr_uint32_t)inputLen << 3)) 
213             < ((apr_uint32_t)inputLen << 3))
214         context->count[1]++;
215     context->count[1] += (apr_uint32_t)inputLen >> 29;
216
217     partLen = 64 - idx;
218
219     /* Transform as many times as possible. */
220 #if !APR_HAS_XLATE
221     if (inputLen >= partLen) {
222         memcpy(&context->buffer[idx], input, partLen);
223         MD5Transform(context->state, context->buffer);
224
225         for (i = partLen; i + 63 < inputLen; i += 64)
226             MD5Transform(context->state, &input[i]);
227
228         idx = 0;
229     }
230     else
231         i = 0;
232
233     /* Buffer remaining input */
234     memcpy(&context->buffer[idx], &input[i], inputLen - i);
235 #else /*APR_HAS_XLATE*/
236     if (inputLen >= partLen) {
237         if (context->xlate) {
238             inbytes_left = outbytes_left = partLen;
239             apr_xlate_conv_buffer(context->xlate, (const char *)input, 
240                                   &inbytes_left,
241                                   (char *)&context->buffer[idx], 
242                                   &outbytes_left);
243         }
244         else {
245             memcpy(&context->buffer[idx], input, partLen);
246         }
247         MD5Transform(context->state, context->buffer);
248
249         for (i = partLen; i + 63 < inputLen; i += 64) {
250             if (context->xlate) {
251                 unsigned char inp_tmp[64];
252                 inbytes_left = outbytes_left = 64;
253                 apr_xlate_conv_buffer(context->xlate, (const char *)&input[i], 
254                                       &inbytes_left, (char *)inp_tmp, 
255                                       &outbytes_left);
256                 MD5Transform(context->state, inp_tmp);
257             }
258             else {
259                 MD5Transform(context->state, &input[i]);
260             }
261         }
262
263         idx = 0;
264     }
265     else
266         i = 0;
267
268     /* Buffer remaining input */
269     if (context->xlate) {
270         inbytes_left = outbytes_left = inputLen - i;
271         apr_xlate_conv_buffer(context->xlate, (const char *)&input[i], 
272                               &inbytes_left, (char *)&context->buffer[idx], 
273                               &outbytes_left);
274     }
275     else {
276         memcpy(&context->buffer[idx], &input[i], inputLen - i);
277     }
278 #endif /*APR_HAS_XLATE*/
279     return APR_SUCCESS;
280 }
281
282 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
283  * the message digest and zeroizing the context.
284  */
285 APU_DECLARE(apr_status_t) apr_md5_final(unsigned char digest[APR_MD5_DIGESTSIZE],
286                                         apr_md5_ctx_t *context)
287 {
288     unsigned char bits[8];
289     unsigned int idx, padLen;
290
291     /* Save number of bits */
292     Encode(bits, context->count, 8);
293
294 #if APR_HAS_XLATE
295     /* apr_md5_update() should not translate for this final round. */
296     context->xlate = NULL;
297 #endif /*APR_HAS_XLATE*/
298
299     /* Pad out to 56 mod 64. */
300     idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
301     padLen = (idx < 56) ? (56 - idx) : (120 - idx);
302     apr_md5_update(context, PADDING, padLen);
303
304     /* Append length (before padding) */
305     apr_md5_update(context, bits, 8);
306
307     /* Store state in digest */
308     Encode(digest, context->state, APR_MD5_DIGESTSIZE);
309
310     /* Zeroize sensitive information. */
311     memset(context, 0, sizeof(*context));
312     
313     return APR_SUCCESS;
314 }
315
316 /* MD5 in one step (init, update, final)
317  */
318 APU_DECLARE(apr_status_t) apr_md5(unsigned char digest[APR_MD5_DIGESTSIZE],
319                                   const void *_input,
320                                   apr_size_t inputLen)
321 {
322     const unsigned char *input = _input;
323     apr_md5_ctx_t ctx;
324     apr_status_t rv;
325
326     apr_md5_init(&ctx);
327
328     if ((rv = apr_md5_update(&ctx, input, inputLen)) != APR_SUCCESS)
329         return rv;
330
331     return apr_md5_final(digest, &ctx);
332 }
333
334 /* MD5 basic transformation. Transforms state based on block. */
335 static void MD5Transform(apr_uint32_t state[4], const unsigned char block[64])
336 {
337     apr_uint32_t a = state[0], b = state[1], c = state[2], d = state[3],
338                  x[APR_MD5_DIGESTSIZE];
339
340     Decode(x, block, 64);
341
342     /* Round 1 */
343     FF(a, b, c, d, x[0],  S11, 0xd76aa478); /* 1 */
344     FF(d, a, b, c, x[1],  S12, 0xe8c7b756); /* 2 */
345     FF(c, d, a, b, x[2],  S13, 0x242070db); /* 3 */
346     FF(b, c, d, a, x[3],  S14, 0xc1bdceee); /* 4 */
347     FF(a, b, c, d, x[4],  S11, 0xf57c0faf); /* 5 */
348     FF(d, a, b, c, x[5],  S12, 0x4787c62a); /* 6 */
349     FF(c, d, a, b, x[6],  S13, 0xa8304613); /* 7 */
350     FF(b, c, d, a, x[7],  S14, 0xfd469501); /* 8 */
351     FF(a, b, c, d, x[8],  S11, 0x698098d8); /* 9 */
352     FF(d, a, b, c, x[9],  S12, 0x8b44f7af); /* 10 */
353     FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
354     FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
355     FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
356     FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
357     FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
358     FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
359
360     /* Round 2 */
361     GG(a, b, c, d, x[1],  S21, 0xf61e2562); /* 17 */
362     GG(d, a, b, c, x[6],  S22, 0xc040b340); /* 18 */
363     GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
364     GG(b, c, d, a, x[0],  S24, 0xe9b6c7aa); /* 20 */
365     GG(a, b, c, d, x[5],  S21, 0xd62f105d); /* 21 */
366     GG(d, a, b, c, x[10], S22, 0x2441453);  /* 22 */
367     GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
368     GG(b, c, d, a, x[4],  S24, 0xe7d3fbc8); /* 24 */
369     GG(a, b, c, d, x[9],  S21, 0x21e1cde6); /* 25 */
370     GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
371     GG(c, d, a, b, x[3],  S23, 0xf4d50d87); /* 27 */
372     GG(b, c, d, a, x[8],  S24, 0x455a14ed); /* 28 */
373     GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
374     GG(d, a, b, c, x[2],  S22, 0xfcefa3f8); /* 30 */
375     GG(c, d, a, b, x[7],  S23, 0x676f02d9); /* 31 */
376     GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
377
378     /* Round 3 */
379     HH(a, b, c, d, x[5],  S31, 0xfffa3942); /* 33 */
380     HH(d, a, b, c, x[8],  S32, 0x8771f681); /* 34 */
381     HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
382     HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
383     HH(a, b, c, d, x[1],  S31, 0xa4beea44); /* 37 */
384     HH(d, a, b, c, x[4],  S32, 0x4bdecfa9); /* 38 */
385     HH(c, d, a, b, x[7],  S33, 0xf6bb4b60); /* 39 */
386     HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
387     HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
388     HH(d, a, b, c, x[0],  S32, 0xeaa127fa); /* 42 */
389     HH(c, d, a, b, x[3],  S33, 0xd4ef3085); /* 43 */
390     HH(b, c, d, a, x[6],  S34, 0x4881d05);  /* 44 */
391     HH(a, b, c, d, x[9],  S31, 0xd9d4d039); /* 45 */
392     HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
393     HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
394     HH(b, c, d, a, x[2],  S34, 0xc4ac5665); /* 48 */
395
396     /* Round 4 */
397     II(a, b, c, d, x[0],  S41, 0xf4292244); /* 49 */
398     II(d, a, b, c, x[7],  S42, 0x432aff97); /* 50 */
399     II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
400     II(b, c, d, a, x[5],  S44, 0xfc93a039); /* 52 */
401     II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
402     II(d, a, b, c, x[3],  S42, 0x8f0ccc92); /* 54 */
403     II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
404     II(b, c, d, a, x[1],  S44, 0x85845dd1); /* 56 */
405     II(a, b, c, d, x[8],  S41, 0x6fa87e4f); /* 57 */
406     II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
407     II(c, d, a, b, x[6],  S43, 0xa3014314); /* 59 */
408     II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
409     II(a, b, c, d, x[4],  S41, 0xf7537e82); /* 61 */
410     II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
411     II(c, d, a, b, x[2],  S43, 0x2ad7d2bb); /* 63 */
412     II(b, c, d, a, x[9],  S44, 0xeb86d391); /* 64 */
413
414     state[0] += a;
415     state[1] += b;
416     state[2] += c;
417     state[3] += d;
418
419     /* Zeroize sensitive information. */
420     memset(x, 0, sizeof(x));
421 }
422
423 /* Encodes input (apr_uint32_t) into output (unsigned char). Assumes len is
424  * a multiple of 4.
425  */
426 static void Encode(unsigned char *output, const apr_uint32_t *input,
427                    unsigned int len)
428 {
429     unsigned int i, j;
430     apr_uint32_t k;
431
432     for (i = 0, j = 0; j < len; i++, j += 4) {
433         k = input[i];
434         output[j]     = (unsigned char)(k & 0xff);
435         output[j + 1] = (unsigned char)((k >> 8) & 0xff);
436         output[j + 2] = (unsigned char)((k >> 16) & 0xff);
437         output[j + 3] = (unsigned char)((k >> 24) & 0xff);
438     }
439 }
440
441 /* Decodes input (unsigned char) into output (apr_uint32_t). Assumes len is
442  * a multiple of 4.
443  */
444 static void Decode(apr_uint32_t *output, const unsigned char *input,
445                    unsigned int len)
446 {
447     unsigned int i, j;
448
449     for (i = 0, j = 0; j < len; i++, j += 4)
450         output[i] = ((apr_uint32_t)input[j])             |
451                     (((apr_uint32_t)input[j + 1]) << 8)  |
452                     (((apr_uint32_t)input[j + 2]) << 16) |
453                     (((apr_uint32_t)input[j + 3]) << 24);
454 }
455
456 #if APR_CHARSET_EBCDIC
457 APU_DECLARE(apr_status_t) apr_MD5InitEBCDIC(apr_xlate_t *xlate)
458 {
459     xlate_ebcdic_to_ascii = xlate;
460     return APR_SUCCESS;
461 }
462 #endif
463
464 /*
465  * Define the Magic String prefix that identifies a password as being
466  * hashed using our algorithm.
467  */
468 static const char *apr1_id = "$apr1$";
469
470 /*
471  * The following MD5 password encryption code was largely borrowed from
472  * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
473  * licenced as stated at the top of this file.
474  */
475
476 static void to64(char *s, unsigned long v, int n)
477 {
478     static unsigned char itoa64[] =         /* 0 ... 63 => ASCII - 64 */
479         "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
480
481     while (--n >= 0) {
482         *s++ = itoa64[v&0x3f];
483         v >>= 6;
484     }
485 }
486
487 APU_DECLARE(apr_status_t) apr_md5_encode(const char *pw, const char *salt,
488                              char *result, apr_size_t nbytes)
489 {
490     /*
491      * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
492      * plus 4 for the '$' separators, plus the password hash itself.
493      * Let's leave a goodly amount of leeway.
494      */
495
496     char passwd[120], *p;
497     const char *sp, *ep;
498     unsigned char final[APR_MD5_DIGESTSIZE];
499     apr_ssize_t sl, pl, i;
500     apr_md5_ctx_t ctx, ctx1;
501     unsigned long l;
502
503     /* 
504      * Refine the salt first.  It's possible we were given an already-hashed
505      * string as the salt argument, so extract the actual salt value from it
506      * if so.  Otherwise just use the string up to the first '$' as the salt.
507      */
508     sp = salt;
509
510     /*
511      * If it starts with the magic string, then skip that.
512      */
513     if (!strncmp(sp, apr1_id, strlen(apr1_id))) {
514         sp += strlen(apr1_id);
515     }
516
517     /*
518      * It stops at the first '$' or 8 chars, whichever comes first
519      */
520     for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
521         continue;
522     }
523
524     /*
525      * Get the length of the true salt
526      */
527     sl = ep - sp;
528
529     /*
530      * 'Time to make the doughnuts..'
531      */
532     apr_md5_init(&ctx);
533 #if APR_CHARSET_EBCDIC
534     apr_md5_set_xlate(&ctx, xlate_ebcdic_to_ascii);
535 #endif
536     
537     /*
538      * The password first, since that is what is most unknown
539      */
540     apr_md5_update(&ctx, (unsigned char *)pw, strlen(pw));
541
542     /*
543      * Then our magic string
544      */
545     apr_md5_update(&ctx, (unsigned char *)apr1_id, strlen(apr1_id));
546
547     /*
548      * Then the raw salt
549      */
550     apr_md5_update(&ctx, (unsigned char *)sp, sl);
551
552     /*
553      * Then just as many characters of the MD5(pw, salt, pw)
554      */
555     apr_md5_init(&ctx1);
556     apr_md5_update(&ctx1, (unsigned char *)pw, strlen(pw));
557     apr_md5_update(&ctx1, (unsigned char *)sp, sl);
558     apr_md5_update(&ctx1, (unsigned char *)pw, strlen(pw));
559     apr_md5_final(final, &ctx1);
560     for (pl = strlen(pw); pl > 0; pl -= APR_MD5_DIGESTSIZE) {
561         apr_md5_update(&ctx, final, 
562                       (pl > APR_MD5_DIGESTSIZE) ? APR_MD5_DIGESTSIZE : pl);
563     }
564
565     /*
566      * Don't leave anything around in vm they could use.
567      */
568     memset(final, 0, sizeof(final));
569
570     /*
571      * Then something really weird...
572      */
573     for (i = strlen(pw); i != 0; i >>= 1) {
574         if (i & 1) {
575             apr_md5_update(&ctx, final, 1);
576         }
577         else {
578             apr_md5_update(&ctx, (unsigned char *)pw, 1);
579         }
580     }
581
582     /*
583      * Now make the output string.  We know our limitations, so we
584      * can use the string routines without bounds checking.
585      */
586     strcpy(passwd, apr1_id);
587     strncat(passwd, sp, sl);
588     strcat(passwd, "$");
589
590     apr_md5_final(final, &ctx);
591
592     /*
593      * And now, just to make sure things don't run too fast..
594      * On a 60 Mhz Pentium this takes 34 msec, so you would
595      * need 30 seconds to build a 1000 entry dictionary...
596      */
597     for (i = 0; i < 1000; i++) {
598         apr_md5_init(&ctx1);
599         if (i & 1) {
600             apr_md5_update(&ctx1, (unsigned char *)pw, strlen(pw));
601         }
602         else {
603             apr_md5_update(&ctx1, final, APR_MD5_DIGESTSIZE);
604         }
605         if (i % 3) {
606             apr_md5_update(&ctx1, (unsigned char *)sp, sl);
607         }
608
609         if (i % 7) {
610             apr_md5_update(&ctx1, (unsigned char *)pw, strlen(pw));
611         }
612
613         if (i & 1) {
614             apr_md5_update(&ctx1, final, APR_MD5_DIGESTSIZE);
615         }
616         else {
617             apr_md5_update(&ctx1, (unsigned char *)pw, strlen(pw));
618         }
619         apr_md5_final(final,&ctx1);
620     }
621
622     p = passwd + strlen(passwd);
623
624     l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p, l, 4); p += 4;
625     l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p, l, 4); p += 4;
626     l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p, l, 4); p += 4;
627     l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p, l, 4); p += 4;
628     l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p, l, 4); p += 4;
629     l =                    final[11]                ; to64(p, l, 2); p += 2;
630     *p = '\0';
631
632     /*
633      * Don't leave anything around in vm they could use.
634      */
635     memset(final, 0, sizeof(final));
636
637     apr_cpystrn(result, passwd, nbytes - 1);
638     return APR_SUCCESS;
639 }
640
641 #if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
642 #if defined(APU_CRYPT_THREADSAFE) || !APR_HAS_THREADS || \
643     defined(CRYPT_R_CRYPTD) || defined(CRYPT_R_STRUCT_CRYPT_DATA)
644
645 #define crypt_mutex_lock()
646 #define crypt_mutex_unlock()
647
648 #elif APR_HAVE_PTHREAD_H && defined(PTHREAD_MUTEX_INITIALIZER)
649
650 static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
651 static void crypt_mutex_lock(void)
652 {
653     pthread_mutex_lock(&crypt_mutex);
654 }
655
656 static void crypt_mutex_unlock(void)
657 {
658     pthread_mutex_unlock(&crypt_mutex);
659 }
660
661 #else
662
663 #error apr_password_validate() is not threadsafe.  rebuild APR without thread support.
664
665 #endif
666 #endif
667
668 /*
669  * Validate a plaintext password against a smashed one.  Use either
670  * crypt() (if available) or apr_md5_encode(), depending upon the format
671  * of the smashed input password.  Return APR_SUCCESS if they match, or
672  * APR_EMISMATCH if they don't.
673  */
674
675 APU_DECLARE(apr_status_t) apr_password_validate(const char *passwd, 
676                                                 const char *hash)
677 {
678     char sample[120];
679 #if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
680     char *crypt_pw;
681 #endif
682     if (!strncmp(hash, apr1_id, strlen(apr1_id))) {
683         /*
684          * The hash was created using our custom algorithm.
685          */
686         apr_md5_encode(passwd, hash, sample, sizeof(sample));
687     }
688     else if (!strncmp(hash, APR_SHA1PW_ID, APR_SHA1PW_IDLEN)) {
689         apr_sha1_base64(passwd, strlen(passwd), sample);
690     }
691     else {
692         /*
693          * It's not our algorithm, so feed it to crypt() if possible.
694          */
695 #if defined(WIN32) || defined(BEOS) || defined(NETWARE)
696         apr_cpystrn(sample, passwd, sizeof(sample) - 1);
697 #elif defined(CRYPT_R_CRYPTD)
698         CRYPTD buffer;
699
700         crypt_pw = crypt_r(passwd, hash, &buffer);
701         apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
702 #elif defined(CRYPT_R_STRUCT_CRYPT_DATA)
703         struct crypt_data buffer;
704
705         /* having to clear this seems bogus... GNU doc is
706          * confusing...  user report found from google says
707          * the crypt_data struct had to be cleared to get
708          * the same result as plain crypt()
709          */
710         memset(&buffer, 0, sizeof(buffer));
711         crypt_pw = crypt_r(passwd, hash, &buffer);
712         apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
713 #else
714         /* Do a bit of sanity checking since we know that crypt_r()
715          * should always be used for threaded builds on AIX, and
716          * problems in configure logic can result in the wrong
717          * choice being made.
718          */
719 #if defined(_AIX) && APR_HAS_THREADS
720 #error Configuration error!  crypt_r() should have been selected!
721 #endif
722
723         /* Handle thread safety issues by holding a mutex around the
724          * call to crypt().
725          */
726         crypt_mutex_lock();
727         crypt_pw = crypt(passwd, hash);
728         apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
729         crypt_mutex_unlock();
730 #endif
731     }
732     return (strcmp(sample, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
733 }