2 * This is work is derived from material Copyright RSA Data Security, Inc.
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.
9 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
12 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
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
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.
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.
30 These notices must be retained in any copies of any part of this
31 documentation and/or software.
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
41 * http://www.apache.org/licenses/LICENSE-2.0
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.
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 * ----------------------------------------------------------------------------
60 #include "apr_strings.h"
63 #include "apu_config.h"
75 #if APR_HAVE_PTHREAD_H
79 /* Constants for MD5Transform routine.
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
,
102 static void Decode(apr_uint32_t
*output
, const unsigned char *input
,
105 static const unsigned char PADDING
[64] =
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
112 #if APR_CHARSET_EBCDIC
113 static apr_xlate_t
*xlate_ebcdic_to_ascii
; /* used in apr_md5_encode() */
118 /* F, G, H and I are basic MD5 functions.
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)))
125 /* ROTATE_LEFT rotates x left n bits.
127 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
129 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
130 * Rotation is separate from addition to prevent recomputation.
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)); \
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)); \
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)); \
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)); \
153 /* MD5 initialization. Begins an MD5 operation, writing a new context.
155 APU_DECLARE(apr_status_t
) apr_md5_init(apr_md5_ctx_t
*context
)
157 context
->count
[0] = context
->count
[1] = 0;
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
;
169 /* MD5 translation setup. Provides the APR translation handle
170 * to be used for translating the content before calculating the
173 APU_DECLARE(apr_status_t
) apr_md5_set_xlate(apr_md5_ctx_t
*context
,
180 /* TODO: remove the single-byte-only restriction from this code
182 rv
= apr_xlate_sb_get(xlate
, &is_sb
);
183 if (rv
!= APR_SUCCESS
) {
189 context
->xlate
= xlate
;
193 #endif /* APR_HAS_XLATE */
196 /* MD5 block update operation. Continues an MD5 message-digest
197 * operation, processing another message block, and updating the
200 static apr_status_t
md5_update_buffer(apr_md5_ctx_t
*context
,
205 const unsigned char *input
= vinput
;
206 unsigned int i
, idx
, partLen
;
208 apr_size_t inbytes_left
, outbytes_left
;
211 /* Compute number of bytes mod 64 */
212 idx
= (unsigned int)((context
->count
[0] >> 3) & 0x3F);
214 /* Update number of bits */
215 if ((context
->count
[0] += ((apr_uint32_t
)inputLen
<< 3))
216 < ((apr_uint32_t
)inputLen
<< 3))
218 context
->count
[1] += (apr_uint32_t
)inputLen
>> 29;
222 /* Transform as many times as possible. */
224 if (inputLen
>= partLen
) {
225 memcpy(&context
->buffer
[idx
], input
, partLen
);
226 MD5Transform(context
->state
, context
->buffer
);
228 for (i
= partLen
; i
+ 63 < inputLen
; i
+= 64)
229 MD5Transform(context
->state
, &input
[i
]);
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
,
244 (char *)&context
->buffer
[idx
],
248 memcpy(&context
->buffer
[idx
], input
, partLen
);
250 MD5Transform(context
->state
, context
->buffer
);
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
,
259 MD5Transform(context
->state
, inp_tmp
);
262 MD5Transform(context
->state
, &input
[i
]);
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
],
279 memcpy(&context
->buffer
[idx
], &input
[i
], inputLen
- i
);
281 #endif /*APR_HAS_XLATE*/
285 /* MD5 block update operation. API with the default setting
286 * for EBCDIC translations
288 APU_DECLARE(apr_status_t
) apr_md5_update(apr_md5_ctx_t
*context
,
292 return md5_update_buffer(context
, input
, inputLen
, DO_XLATE
);
295 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
296 * the message digest and zeroizing the context.
298 APU_DECLARE(apr_status_t
) apr_md5_final(unsigned char digest
[APR_MD5_DIGESTSIZE
],
299 apr_md5_ctx_t
*context
)
301 unsigned char bits
[8];
302 unsigned int idx
, padLen
;
304 /* Save number of bits */
305 Encode(bits
, context
->count
, 8);
308 /* apr_md5_update() should not translate for this final round. */
309 context
->xlate
= NULL
;
310 #endif /*APR_HAS_XLATE*/
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
);
317 /* Append length (before padding) */
318 apr_md5_update(context
, bits
, 8);
320 /* Store state in digest */
321 Encode(digest
, context
->state
, APR_MD5_DIGESTSIZE
);
323 /* Zeroize sensitive information. */
324 memset(context
, 0, sizeof(*context
));
329 /* MD5 in one step (init, update, final)
331 APU_DECLARE(apr_status_t
) apr_md5(unsigned char digest
[APR_MD5_DIGESTSIZE
],
335 const unsigned char *input
= _input
;
341 if ((rv
= apr_md5_update(&ctx
, input
, inputLen
)) != APR_SUCCESS
)
344 return apr_md5_final(digest
, &ctx
);
347 /* MD5 basic transformation. Transforms state based on block. */
348 static void MD5Transform(apr_uint32_t state
[4], const unsigned char block
[64])
350 apr_uint32_t a
= state
[0], b
= state
[1], c
= state
[2], d
= state
[3],
351 x
[APR_MD5_DIGESTSIZE
];
353 Decode(x
, block
, 64);
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 */
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 */
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 */
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 */
432 /* Zeroize sensitive information. */
433 memset(x
, 0, sizeof(x
));
436 /* Encodes input (apr_uint32_t) into output (unsigned char). Assumes len is
439 static void Encode(unsigned char *output
, const apr_uint32_t
*input
,
445 for (i
= 0, j
= 0; j
< len
; i
++, j
+= 4) {
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);
454 /* Decodes input (unsigned char) into output (apr_uint32_t). Assumes len is
457 static void Decode(apr_uint32_t
*output
, const unsigned char *input
,
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);
469 #if APR_CHARSET_EBCDIC
470 APU_DECLARE(apr_status_t
) apr_MD5InitEBCDIC(apr_xlate_t
*xlate
)
472 xlate_ebcdic_to_ascii
= xlate
;
478 * Define the Magic String prefix that identifies a password as being
479 * hashed using our algorithm.
481 static const char *apr1_id
= "$apr1$";
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.
489 static void to64(char *s
, unsigned long v
, int n
)
491 static unsigned char itoa64
[] = /* 0 ... 63 => ASCII - 64 */
492 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
495 *s
++ = itoa64
[v
&0x3f];
500 APU_DECLARE(apr_status_t
) apr_md5_encode(const char *pw
, const char *salt
,
501 char *result
, apr_size_t nbytes
)
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.
509 char passwd
[120], *p
;
511 unsigned char final
[APR_MD5_DIGESTSIZE
];
512 apr_ssize_t sl
, pl
, i
;
513 apr_md5_ctx_t ctx
, ctx1
;
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.
524 * If it starts with the magic string, then skip that.
526 if (!strncmp(sp
, apr1_id
, strlen(apr1_id
))) {
527 sp
+= strlen(apr1_id
);
531 * It stops at the first '$' or 8 chars, whichever comes first
533 for (ep
= sp
; (*ep
!= '\0') && (*ep
!= '$') && (ep
< (sp
+ 8)); ep
++) {
538 * Get the length of the true salt
543 * 'Time to make the doughnuts..'
546 #if APR_CHARSET_EBCDIC
547 apr_md5_set_xlate(&ctx
, xlate_ebcdic_to_ascii
);
551 * The password first, since that is what is most unknown
553 apr_md5_update(&ctx
, pw
, strlen(pw
));
556 * Then our magic string
558 apr_md5_update(&ctx
, apr1_id
, strlen(apr1_id
));
563 apr_md5_update(&ctx
, sp
, sl
);
566 * Then just as many characters of the MD5(pw, salt, pw)
569 #if APR_CHARSET_EBCDIC
570 apr_md5_set_xlate(&ctx1
, xlate_ebcdic_to_ascii
);
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
);
582 * Don't leave anything around in vm they could use.
584 memset(final
, 0, sizeof(final
));
587 * Then something really weird...
589 for (i
= strlen(pw
); i
!= 0; i
>>= 1) {
591 md5_update_buffer(&ctx
, final
, 1, SKIP_XLATE
);
594 apr_md5_update(&ctx
, pw
, 1);
599 * Now make the output string. We know our limitations, so we
600 * can use the string routines without bounds checking.
602 strcpy(passwd
, apr1_id
);
603 strncat(passwd
, sp
, sl
);
606 apr_md5_final(final
, &ctx
);
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...
613 for (i
= 0; i
< 1000; i
++) {
616 * apr_md5_final clears out ctx1.xlate at the end of each loop,
617 * so need to to set it each time through
619 #if APR_CHARSET_EBCDIC
620 apr_md5_set_xlate(&ctx1
, xlate_ebcdic_to_ascii
);
623 apr_md5_update(&ctx1
, pw
, strlen(pw
));
626 md5_update_buffer(&ctx1
, final
, APR_MD5_DIGESTSIZE
, SKIP_XLATE
);
629 apr_md5_update(&ctx1
, sp
, sl
);
633 apr_md5_update(&ctx1
, pw
, strlen(pw
));
637 md5_update_buffer(&ctx1
, final
, APR_MD5_DIGESTSIZE
, SKIP_XLATE
);
640 apr_md5_update(&ctx1
, pw
, strlen(pw
));
642 apr_md5_final(final
,&ctx1
);
645 p
= passwd
+ strlen(passwd
);
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;
656 * Don't leave anything around in vm they could use.
658 memset(final
, 0, sizeof(final
));
660 apr_cpystrn(result
, passwd
, nbytes
- 1);
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)
668 #define crypt_mutex_lock()
669 #define crypt_mutex_unlock()
671 #elif APR_HAVE_PTHREAD_H && defined(PTHREAD_MUTEX_INITIALIZER)
673 static pthread_mutex_t crypt_mutex
= PTHREAD_MUTEX_INITIALIZER
;
674 static void crypt_mutex_lock(void)
676 pthread_mutex_lock(&crypt_mutex
);
679 static void crypt_mutex_unlock(void)
681 pthread_mutex_unlock(&crypt_mutex
);
686 #error apr_password_validate() is not threadsafe. rebuild APR without thread support.
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.
698 APU_DECLARE(apr_status_t
) apr_password_validate(const char *passwd
,
702 #if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
705 if (!strncmp(hash
, apr1_id
, strlen(apr1_id
))) {
707 * The hash was created using our custom algorithm.
709 apr_md5_encode(passwd
, hash
, sample
, sizeof(sample
));
711 else if (!strncmp(hash
, APR_SHA1PW_ID
, APR_SHA1PW_IDLEN
)) {
712 apr_sha1_base64(passwd
, (int)strlen(passwd
), sample
);
716 * It's not our algorithm, so feed it to crypt() if possible.
718 #if defined(WIN32) || defined(BEOS) || defined(NETWARE)
719 apr_cpystrn(sample
, passwd
, sizeof(sample
) - 1);
720 #elif defined(CRYPT_R_CRYPTD)
723 crypt_pw
= crypt_r(passwd
, hash
, &buffer
);
724 apr_cpystrn(sample
, crypt_pw
, sizeof(sample
) - 1);
725 #elif defined(CRYPT_R_STRUCT_CRYPT_DATA)
726 struct crypt_data buffer
;
728 /* having to clear this seems bogus... GNU doc is
729 * confusing... user report found from google says
730 * the crypt_data struct had to be cleared to get
731 * the same result as plain crypt()
733 memset(&buffer
, 0, sizeof(buffer
));
734 crypt_pw
= crypt_r(passwd
, hash
, &buffer
);
735 apr_cpystrn(sample
, crypt_pw
, sizeof(sample
) - 1);
737 /* Do a bit of sanity checking since we know that crypt_r()
738 * should always be used for threaded builds on AIX, and
739 * problems in configure logic can result in the wrong
742 #if defined(_AIX) && APR_HAS_THREADS
743 #error Configuration error! crypt_r() should have been selected!
746 /* Handle thread safety issues by holding a mutex around the
750 crypt_pw
= crypt(passwd
, hash
);
751 apr_cpystrn(sample
, crypt_pw
, sizeof(sample
) - 1);
752 crypt_mutex_unlock();
755 return (strcmp(sample
, hash
) == 0) ? APR_SUCCESS
: APR_EMISMATCH
;