1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
* contributor license agreements. See the NOTICE file distributed with
3
* this work for additional information regarding copyright ownership.
4
* The ASF licenses this file to You under the Apache License, Version 2.0
5
* (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
#include "apr_strings.h"
21
#include "apu_config.h"
22
#include "crypt_blowfish.h"
33
#if APR_HAVE_PTHREAD_H
40
static const char * const apr1_id = "$apr1$";
42
#if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
43
#if defined(APU_CRYPT_THREADSAFE) || !APR_HAS_THREADS || \
44
defined(CRYPT_R_CRYPTD) || defined(CRYPT_R_STRUCT_CRYPT_DATA)
46
#define crypt_mutex_lock()
47
#define crypt_mutex_unlock()
49
#elif APR_HAVE_PTHREAD_H && defined(PTHREAD_MUTEX_INITIALIZER)
51
static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
52
static void crypt_mutex_lock(void)
54
pthread_mutex_lock(&crypt_mutex);
57
static void crypt_mutex_unlock(void)
59
pthread_mutex_unlock(&crypt_mutex);
64
#error apr_password_validate() is not threadsafe. rebuild APR without thread support.
70
* Validate a plaintext password against a smashed one. Uses either
71
* crypt() (if available) or apr_md5_encode() or apr_sha1_base64(), depending
72
* upon the format of the smashed input password. Returns APR_SUCCESS if
73
* they match, or APR_EMISMATCH if they don't. If the platform doesn't
74
* support crypt, then the default check is against a clear text string.
76
APU_DECLARE(apr_status_t) apr_password_validate(const char *passwd,
80
#if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
85
&& (hash[2] == 'a' || hash[2] == 'y')
87
if (_crypt_blowfish_rn(passwd, hash, sample, sizeof(sample)) == NULL)
88
return APR_FROM_OS_ERROR(errno);
90
else if (!strncmp(hash, apr1_id, strlen(apr1_id))) {
92
* The hash was created using our custom algorithm.
94
apr_md5_encode(passwd, hash, sample, sizeof(sample));
96
else if (!strncmp(hash, APR_SHA1PW_ID, APR_SHA1PW_IDLEN)) {
97
apr_sha1_base64(passwd, (int)strlen(passwd), sample);
101
* It's not our algorithm, so feed it to crypt() if possible.
103
#if defined(WIN32) || defined(BEOS) || defined(NETWARE)
104
return (strcmp(passwd, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
105
#elif defined(CRYPT_R_CRYPTD)
107
CRYPTD *buffer = malloc(sizeof(*buffer));
111
crypt_pw = crypt_r(passwd, hash, buffer);
115
rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
118
#elif defined(CRYPT_R_STRUCT_CRYPT_DATA)
120
struct crypt_data *buffer = malloc(sizeof(*buffer));
125
#ifdef __GLIBC_PREREQ
127
* For not too old glibc (>= 2.3.2), it's enough to set
128
* buffer.initialized = 0. For < 2.3.2 and for other platforms,
129
* we need to zero the whole struct.
131
#if __GLIBC_PREREQ(2,4)
132
#define USE_CRYPT_DATA_INITALIZED
136
#ifdef USE_CRYPT_DATA_INITALIZED
137
buffer->initialized = 0;
139
memset(buffer, 0, sizeof(*buffer));
142
crypt_pw = crypt_r(passwd, hash, buffer);
146
rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
150
/* Do a bit of sanity checking since we know that crypt_r()
151
* should always be used for threaded builds on AIX, and
152
* problems in configure logic can result in the wrong
155
#if defined(_AIX) && APR_HAS_THREADS
156
#error Configuration error! crypt_r() should have been selected!
161
/* Handle thread safety issues by holding a mutex around the
165
crypt_pw = crypt(passwd, hash);
170
rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
172
crypt_mutex_unlock();
177
return (strcmp(sample, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
180
static const char * const bcrypt_id = "$2y$";
181
APU_DECLARE(apr_status_t) apr_bcrypt_encode(const char *pw,
183
const unsigned char *salt,
185
char *out, apr_size_t out_len)
188
if (_crypt_gensalt_blowfish_rn(bcrypt_id, count, (const char *)salt,
189
salt_len, setting, sizeof(setting)) == NULL)
190
return APR_FROM_OS_ERROR(errno);
191
if (_crypt_blowfish_rn(pw, setting, out, out_len) == NULL)
192
return APR_FROM_OS_ERROR(errno);