~ubuntu-branches/ubuntu/trusty/apr-util/trusty-proposed

« back to all changes in this revision

Viewing changes to crypto/apr_passwd.c

  • Committer: Package Import Robot
  • Author(s): Stefan Fritsch
  • Date: 2013-05-05 15:43:34 UTC
  • mfrom: (1.3.4)
  • Revision ID: package-import@ubuntu.com-20130505154334-ljd2tn8515nf96mo
Tags: 1.5.2-1
* New upstream release.
* Ship find_apu.m4 in libaprutil1-dev. Closes: #699327

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
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.
 
15
 */
 
16
 
 
17
#include "apr_strings.h"
 
18
#include "apr_md5.h"
 
19
#include "apr_lib.h"
 
20
#include "apr_sha1.h"
 
21
#include "apu_config.h"
 
22
#include "crypt_blowfish.h"
 
23
 
 
24
#if APR_HAVE_STRING_H
 
25
#include <string.h>
 
26
#endif
 
27
#if APR_HAVE_CRYPT_H
 
28
#include <crypt.h>
 
29
#endif
 
30
#if APR_HAVE_UNISTD_H
 
31
#include <unistd.h>
 
32
#endif
 
33
#if APR_HAVE_PTHREAD_H
 
34
#include <pthread.h>
 
35
#endif
 
36
#if APR_HAVE_STDLIB_H
 
37
#include <stdlib.h>
 
38
#endif
 
39
 
 
40
static const char * const apr1_id = "$apr1$";
 
41
 
 
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)
 
45
 
 
46
#define crypt_mutex_lock()
 
47
#define crypt_mutex_unlock()
 
48
 
 
49
#elif APR_HAVE_PTHREAD_H && defined(PTHREAD_MUTEX_INITIALIZER)
 
50
 
 
51
static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
 
52
static void crypt_mutex_lock(void)
 
53
{
 
54
    pthread_mutex_lock(&crypt_mutex);
 
55
}
 
56
 
 
57
static void crypt_mutex_unlock(void)
 
58
{
 
59
    pthread_mutex_unlock(&crypt_mutex);
 
60
}
 
61
 
 
62
#else
 
63
 
 
64
#error apr_password_validate() is not threadsafe.  rebuild APR without thread support.
 
65
 
 
66
#endif
 
67
#endif
 
68
 
 
69
/*
 
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.
 
75
 */
 
76
APU_DECLARE(apr_status_t) apr_password_validate(const char *passwd, 
 
77
                                                const char *hash)
 
78
{
 
79
    char sample[200];
 
80
#if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
 
81
    char *crypt_pw;
 
82
#endif
 
83
    if (hash[0] == '$'
 
84
        && hash[1] == '2'
 
85
        && (hash[2] == 'a' || hash[2] == 'y')
 
86
        && hash[3] == '$') {
 
87
        if (_crypt_blowfish_rn(passwd, hash, sample, sizeof(sample)) == NULL)
 
88
            return APR_FROM_OS_ERROR(errno);
 
89
    }
 
90
    else if (!strncmp(hash, apr1_id, strlen(apr1_id))) {
 
91
        /*
 
92
         * The hash was created using our custom algorithm.
 
93
         */
 
94
        apr_md5_encode(passwd, hash, sample, sizeof(sample));
 
95
    }
 
96
    else if (!strncmp(hash, APR_SHA1PW_ID, APR_SHA1PW_IDLEN)) {
 
97
         apr_sha1_base64(passwd, (int)strlen(passwd), sample);
 
98
    }
 
99
    else {
 
100
        /*
 
101
         * It's not our algorithm, so feed it to crypt() if possible.
 
102
         */
 
103
#if defined(WIN32) || defined(BEOS) || defined(NETWARE)
 
104
        return (strcmp(passwd, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
 
105
#elif defined(CRYPT_R_CRYPTD)
 
106
        apr_status_t rv;
 
107
        CRYPTD *buffer = malloc(sizeof(*buffer));
 
108
 
 
109
        if (buffer == NULL)
 
110
            return APR_ENOMEM;
 
111
        crypt_pw = crypt_r(passwd, hash, buffer);
 
112
        if (!crypt_pw)
 
113
            rv = APR_EMISMATCH;
 
114
        else
 
115
            rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
 
116
        free(buffer);
 
117
        return rv;
 
118
#elif defined(CRYPT_R_STRUCT_CRYPT_DATA)
 
119
        apr_status_t rv;
 
120
        struct crypt_data *buffer = malloc(sizeof(*buffer));
 
121
 
 
122
        if (buffer == NULL)
 
123
            return APR_ENOMEM;
 
124
 
 
125
#ifdef __GLIBC_PREREQ
 
126
        /*
 
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.
 
130
         */
 
131
#if __GLIBC_PREREQ(2,4)
 
132
#define USE_CRYPT_DATA_INITALIZED
 
133
#endif
 
134
#endif
 
135
 
 
136
#ifdef USE_CRYPT_DATA_INITALIZED
 
137
        buffer->initialized = 0;
 
138
#else
 
139
        memset(buffer, 0, sizeof(*buffer));
 
140
#endif
 
141
 
 
142
        crypt_pw = crypt_r(passwd, hash, buffer);
 
143
        if (!crypt_pw)
 
144
            rv = APR_EMISMATCH;
 
145
        else
 
146
            rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
 
147
        free(buffer);
 
148
        return rv;
 
149
#else
 
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
 
153
         * choice being made.
 
154
         */
 
155
#if defined(_AIX) && APR_HAS_THREADS
 
156
#error Configuration error!  crypt_r() should have been selected!
 
157
#endif
 
158
        {
 
159
            apr_status_t rv;
 
160
 
 
161
            /* Handle thread safety issues by holding a mutex around the
 
162
             * call to crypt().
 
163
             */
 
164
            crypt_mutex_lock();
 
165
            crypt_pw = crypt(passwd, hash);
 
166
            if (!crypt_pw) {
 
167
                rv = APR_EMISMATCH;
 
168
            }
 
169
            else {
 
170
                rv = (strcmp(crypt_pw, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
 
171
            }
 
172
            crypt_mutex_unlock();
 
173
            return rv;
 
174
        }
 
175
#endif
 
176
    }
 
177
    return (strcmp(sample, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
 
178
}
 
179
 
 
180
static const char * const bcrypt_id = "$2y$";
 
181
APU_DECLARE(apr_status_t) apr_bcrypt_encode(const char *pw,
 
182
                                            unsigned int count,
 
183
                                            const unsigned char *salt,
 
184
                                            apr_size_t salt_len,
 
185
                                            char *out, apr_size_t out_len)
 
186
{
 
187
    char setting[40];
 
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);
 
193
    return APR_SUCCESS;
 
194
}