/[Apache-SVN]/apr/apr/trunk/crypto/apr_md5.c
ViewVC logotype

Contents of /apr/apr/trunk/crypto/apr_md5.c

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native

apache@apache.org
ViewVC Help
Powered by ViewVC 1.1.2