testpass.c revision 262253
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 <stdio.h> 18#include <stdlib.h> 19 20#include "apr_errno.h" 21#include "apr_strings.h" 22#include "apr_file_io.h" 23#include "apr_thread_pool.h" 24#include "apr_md5.h" 25#include "apr_sha1.h" 26 27#include "abts.h" 28#include "testutil.h" 29 30#if defined(WIN32) || defined(BEOS) || defined(NETWARE) 31#define CRYPT_ALGO_SUPPORTED 0 32#else 33#define CRYPT_ALGO_SUPPORTED 1 34#endif 35 36#if defined __GLIBC_PREREQ 37#if __GLIBC_PREREQ(2,7) 38#define GLIBCSHA_ALGO_SUPPORTED 39#endif 40#endif 41 42#if CRYPT_ALGO_SUPPORTED 43 44static struct { 45 const char *password; 46 const char *hash; 47} passwords[] = 48{ 49/* 50 passwords and hashes created with Apache's htpasswd utility like this: 51 52 htpasswd -c -b passwords pass1 pass1 53 htpasswd -b passwords pass2 pass2 54 htpasswd -b passwords pass3 pass3 55 htpasswd -b passwords pass4 pass4 56 htpasswd -b passwords pass5 pass5 57 htpasswd -b passwords pass6 pass6 58 htpasswd -b passwords pass7 pass7 59 htpasswd -b passwords pass8 pass8 60 (insert Perl one-liner to convert to initializer :) ) 61 */ 62 {"pass1", "1fWDc9QWYCWrQ"}, 63 {"pass2", "1fiGx3u7QoXaM"}, 64 {"pass3", "1fzijMylTiwCs"}, 65 {"pass4", "nHUYc8U2UOP7s"}, 66 {"pass5", "nHpETGLGPwAmA"}, 67 {"pass6", "nHbsbWmJ3uyhc"}, 68 {"pass7", "nHQ3BbF0Y9vpI"}, 69 {"pass8", "nHZA1rViSldQk"} 70}; 71static int num_passwords = sizeof(passwords) / sizeof(passwords[0]); 72 73static void test_crypt(abts_case *tc, void *data) 74{ 75 int i; 76 77 for (i = 0; i < num_passwords; i++) { 78 apr_assert_success(tc, "check for valid password", 79 apr_password_validate(passwords[i].password, 80 passwords[i].hash)); 81 } 82} 83 84#if APR_HAS_THREADS 85 86static void * APR_THREAD_FUNC testing_thread(apr_thread_t *thd, 87 void *data) 88{ 89 abts_case *tc = data; 90 int i; 91 92 for (i = 0; i < 100; i++) { 93 test_crypt(tc, NULL); 94 } 95 96 return APR_SUCCESS; 97} 98 99#define NUM_THR 20 100 101/* test for threadsafe crypt() */ 102static void test_threadsafe(abts_case *tc, void *data) 103{ 104 int i; 105 apr_status_t rv; 106 apr_thread_pool_t *thrp; 107 108 rv = apr_thread_pool_create(&thrp, NUM_THR/2, NUM_THR, p); 109 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 110 111 for (i = 0; i < NUM_THR; i++) { 112 rv = apr_thread_pool_push(thrp, testing_thread, tc, 0, NULL); 113 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 114 } 115 116 apr_thread_pool_destroy(thrp); 117} 118#endif 119 120#endif /* CRYPT_ALGO_SUPPORTED */ 121 122static void test_shapass(abts_case *tc, void *data) 123{ 124 const char *pass = "hellojed"; 125 const char *pass2 = "hellojed2"; 126 char hash[100]; 127 128 apr_sha1_base64(pass, strlen(pass), hash); 129 130 apr_assert_success(tc, "SHA1 password validated", 131 apr_password_validate(pass, hash)); 132 APR_ASSERT_FAILURE(tc, "wrong SHA1 password should not validate", 133 apr_password_validate(pass2, hash)); 134} 135 136static void test_md5pass(abts_case *tc, void *data) 137{ 138 const char *pass = "hellojed", *salt = "sardine"; 139 const char *pass2 = "hellojed2"; 140 char hash[100]; 141 142 apr_md5_encode(pass, salt, hash, sizeof hash); 143 144 apr_assert_success(tc, "MD5 password validated", 145 apr_password_validate(pass, hash)); 146 APR_ASSERT_FAILURE(tc, "wrong MD5 password should not validate", 147 apr_password_validate(pass2, hash)); 148} 149 150#ifdef GLIBCSHA_ALGO_SUPPORTED 151 152static struct { 153 const char *password; 154 const char *hash; 155} glibc_sha_pws[] = { 156 /* SHA256 */ 157 { "secret1", "$5$0123456789abcdef$SFX.CooXBS8oXsbAPgU/UyiCodhrLQ19sBgvcA3Zh1D" }, 158 { "secret2", "$5$rounds=100000$0123456789abcdef$dLXfO5m4d.xv8G66kpz2LyL0.Mi5wjLlH0m7rtgyhyB" }, 159 /* SHA512 */ 160 { "secret3", "$6$0123456789abcdef$idOsOfoWwnCQkJm9hd2hxS4NnEs9nBA9poOFXsvtrYSoSHaOToCfyUoZwKe.ZCZnq7D95tGVoi2jxZZMyVwTL1" }, 161 { "secret4", "$6$rounds=100000$0123456789abcdef$ZiAMjbeA.iIGTWxq2oks9Bvz9sfxaoGPgAtpwimPEwFwkSNMTK7lLwABzzldds/n4UgCQ16HqawPrCrePr4YX1" }, 162 { NULL, NULL } 163}; 164 165static void test_glibc_shapass(abts_case *tc, void *data) 166{ 167 int i = 0; 168 while (glibc_sha_pws[i].password) { 169 apr_assert_success(tc, "check for valid glibc crypt-sha password", 170 apr_password_validate(glibc_sha_pws[i].password, 171 glibc_sha_pws[i].hash)); 172 i++; 173 } 174} 175#endif 176 177static void test_bcryptpass(abts_case *tc, void *data) 178{ 179 const char *pass = "hellojed"; 180 const char *pass2 = "hellojed2"; 181 unsigned char salt[] = "sardine_sardine"; 182 char hash[100]; 183 const char *hash2 = "$2a$08$qipUJiI9fySUN38hcbz.lucXvAmtgowKOWYtB9y3CXyl6lTknruou"; 184 const char *pass3 = "foobar"; 185 186 apr_assert_success(tc, "bcrypt encode password", 187 apr_bcrypt_encode(pass, 5, salt, sizeof(salt), hash, 188 sizeof(hash))); 189 190 apr_assert_success(tc, "bcrypt password validated", 191 apr_password_validate(pass, hash)); 192 APR_ASSERT_FAILURE(tc, "wrong bcrypt password should not validate", 193 apr_password_validate(pass2, hash)); 194 apr_assert_success(tc, "bcrypt password validated", 195 apr_password_validate(pass3, hash2)); 196} 197 198 199abts_suite *testpass(abts_suite *suite) 200{ 201 suite = ADD_SUITE(suite); 202 203#if CRYPT_ALGO_SUPPORTED 204 abts_run_test(suite, test_crypt, NULL); 205#if APR_HAS_THREADS 206 abts_run_test(suite, test_threadsafe, NULL); 207#endif 208#endif /* CRYPT_ALGO_SUPPORTED */ 209 abts_run_test(suite, test_shapass, NULL); 210 abts_run_test(suite, test_md5pass, NULL); 211 abts_run_test(suite, test_bcryptpass, NULL); 212#ifdef GLIBCSHA_ALGO_SUPPORTED 213 abts_run_test(suite, test_glibc_shapass, NULL); 214#endif 215 216 return suite; 217} 218