[ Index ] |
PHP Cross Reference of YOURLS |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Auth functions other than login and logout 5 * 6 * @group auth 7 */ 8 class Auth_Func_Tests extends PHPUnit\Framework\TestCase { 9 10 protected static $random_password; 11 12 protected static $yourls_user_passwords_copy; 13 14 public static function setUpBeforeClass(): void { 15 global $yourls_user_passwords; 16 self::$yourls_user_passwords_copy = $yourls_user_passwords; 17 18 self::$random_password = rand_str(); 19 20 $salt = rand( 10000, 99999 ); 21 $md5 = 'md5:' . $salt . ':' . md5( $salt . self::$random_password ); 22 $phpassword_1 = 'phpass:' . str_replace( '$', '!', yourls_phpass_hash( self::$random_password ) ); 23 $phpassword_2 = 'phpass:' . yourls_phpass_hash( self::$random_password ); 24 25 $yourls_user_passwords['random_md5'] = $md5; 26 $yourls_user_passwords['random_phpass1'] = $phpassword_1; 27 $yourls_user_passwords['random_phpass2'] = $phpassword_2; 28 } 29 30 public static function tearDownAfterClass(): void { 31 global $yourls_user_passwords; 32 $yourls_user_passwords = self::$yourls_user_passwords_copy; 33 } 34 35 /** 36 * Check that we have some password in clear text 37 */ 38 public function test_has_cleartext() { 39 $this->assertTrue( yourls_has_cleartext_passwords() ); 40 } 41 42 /** 43 * Check that we have no password in clear text 44 */ 45 public function test_has_no_cleartext() { 46 global $yourls_user_passwords; 47 48 $copy = $yourls_user_passwords; 49 50 $yourls_user_passwords = array(); 51 $yourls_user_passwords['md5'] = $copy['md5']; 52 $yourls_user_passwords['phpass'] = $copy['phpass']; 53 $yourls_user_passwords['phpass2'] = $copy['phpass2']; 54 55 $this->assertFalse( yourls_has_cleartext_passwords() ); 56 57 $yourls_user_passwords = $copy; 58 } 59 60 /** 61 * Check that user md5 has a MD5 hashed password 62 */ 63 public function test_has_md5() { 64 $this->assertTrue( yourls_has_md5_password('md5') ); 65 $this->assertTrue( yourls_has_md5_password('random_md5') ); 66 $this->assertFalse( yourls_has_md5_password(rand_str()) ); 67 } 68 69 /** 70 * Check that users phpass and phpass2 have PHPass'd passwords 71 */ 72 public function test_has_phpass() { 73 $this->assertTrue( yourls_has_phpass_password('phpass') ); 74 $this->assertTrue( yourls_has_phpass_password('phpass2') ); 75 $this->assertTrue( yourls_has_phpass_password('random_phpass1') ); 76 $this->assertTrue( yourls_has_phpass_password('random_phpass2') ); 77 $this->assertFalse( yourls_has_phpass_password(rand_str()) ); 78 } 79 80 /** 81 * Provide strings to hash 82 */ 83 public function strings_to_hash() { 84 85 return array( 86 array( rand_str() ), 87 array( 'lol .\+*?[^]$(){}=!<>|:-/' . "'" . '"' ), 88 array( 'أنا أحب النقانق' ), 89 array( '"double quotes"' ), 90 array( "'single quotes'" ), 91 array( '@$*' ), 92 array( 'أنا أحب النقانق' ), 93 ); 94 } 95 96 /** 97 * Check that a hash can be verified 98 * 99 * @dataProvider strings_to_hash 100 */ 101 public function test_hash_and_check( $string ) { 102 $hash = yourls_phpass_hash( $string ); 103 $this->assertTrue( yourls_phpass_check( $string, $hash ) ); 104 } 105 106 /** 107 * Check that valid login / clear text password is deemed valid 108 */ 109 public function test_valid_cleartext() { 110 $this->assertTrue( yourls_check_password_hash( 'clear', 'somepassword' ) ); 111 $this->assertFalse( yourls_check_password_hash( 'unknown', 'somepassword' ) ); 112 $this->assertFalse( yourls_check_password_hash( 'clear', 'wrongpassword' ) ); 113 } 114 115 /** 116 * Check that valid login / md5 password is deemed valid 117 */ 118 public function test_valid_md5() { 119 // Check if users have md5'd passwords 120 $this->assertTrue( yourls_has_md5_password( 'random_md5' ) ); 121 122 // Check that md5 hashed passwords match the password 123 $this->assertTrue( yourls_check_password_hash( 'random_md5', self::$random_password ) ); 124 125 // Unknown user, existing password 126 $this->assertFalse( yourls_check_password_hash( rand_str(), self::$random_password ) ); 127 128 // Known user, invalid password 129 $this->assertFalse( yourls_check_password_hash( 'md5', rand_str() ) ); 130 } 131 132 /** 133 * Check that valid login / phpass password is deemed valid 134 */ 135 public function test_valid_phpass() { 136 // Check that phpass hashed passwords match the password 137 $this->assertTrue( yourls_check_password_hash( 'random_phpass1', self::$random_password ) ); 138 $this->assertTrue( yourls_check_password_hash( 'random_phpass2', self::$random_password ) ); 139 140 // unknown user, existing valid password 141 $this->assertFalse( yourls_check_password_hash( rand_str(), self::$random_password ) ); 142 143 // known users, invalid passwords 144 $this->assertFalse( yourls_check_password_hash( 'phpass', rand_str() ) ); 145 $this->assertFalse( yourls_check_password_hash( 'phpass2', rand_str() ) ); 146 } 147 148 /** 149 * Check that in-file password encryption works as expected 150 */ 151 public function test_hash_passwords_now() { 152 // If local: make a copy of user/config-sample.php to user/config-test.php in case tests not run on a clean install 153 // on Github: just proceed with user/config-sample.php since there's always a `git clone` first 154 if( yut_is_local() ) { 155 if( !copy( YOURLS_USERDIR . '/config-sample.php', YOURLS_USERDIR . '/config-test.php' ) ) { 156 // Copy failed, we cannot run this test. 157 $this->markTestSkipped( 'Could not copy file (write permissions?) -- cannot run test' ); 158 return; 159 } else { 160 $config_file = YOURLS_USERDIR . '/config-test.php'; 161 } 162 } else { 163 $config_file = YOURLS_USERDIR . '/config-sample.php'; 164 } 165 166 // Encrypt file 167 $this->assertTrue( yourls_hash_passwords_now( $config_file ) ); 168 169 // Make sure encrypted file is still valid PHP with no syntax error 170 if( !defined( 'YOURLS_PHP_BIN' ) ) { 171 $this->markTestSkipped( 'No PHP binary defined -- cannot check file hashing' ); 172 return; 173 } 174 175 exec( YOURLS_PHP_BIN . ' -l ' . escapeshellarg( $config_file ), $output, $return ); 176 $this->assertEquals( 0, $return ); 177 } 178 179 /** 180 * Check that encrypting un-writable file returns expected error 181 */ 182 public function test_hash_passwords_now_unwritable() { 183 // generate un-writable file 184 $file = YOURLS_TESTDATA_DIR . '/auth/unwritable.php'; 185 touch( $file ); 186 187 if(yourls_is_windows()) { 188 exec( 'attrib +r ' . escapeshellarg( $file ) ); 189 } else { 190 chmod( $file, 0444 ); 191 } 192 193 $this->assertSame('cannot write file', yourls_hash_passwords_now( $file ) ); 194 195 // cleanup 196 if(yourls_is_windows()) { 197 exec( 'attrib -r ' . escapeshellarg( $file ) ); 198 } else { 199 chmod( $file, 0644 ); 200 } 201 unlink( $file ); 202 } 203 204 /** 205 * Check that encrypting non-existent or unreadable file returns expected error 206 */ 207 public function test_hash_passwords_now_non_existent() { 208 $this->assertSame('cannot read file', yourls_hash_passwords_now( rand_str() ) ); 209 } 210 211 /** 212 * Check that encrypting empty file returns expected error 213 */ 214 public function test_hash_passwords_now_empty() { 215 $this->assertSame('could not read file', yourls_hash_passwords_now( YOURLS_TESTDATA_DIR . '/auth/empty.php' ) ); 216 } 217 218 /** 219 * Check that encrypting file with no passwords returns expected error 220 */ 221 public function test_hash_passwords_now_no_pwd() { 222 $this->assertSame('no password found', yourls_hash_passwords_now( YOURLS_TESTDATA_DIR . '/auth/nopassword.php' ) ); 223 } 224 225 /** 226 * Check that encrypting file with incorrect content returns expected error 227 */ 228 public function test_hash_passwords_now_bad_content() { 229 $this->assertSame('preg_replace problem', yourls_hash_passwords_now( YOURLS_TESTDATA_DIR . '/auth/preg_replace_problem.php' ) ); 230 } 231 232 /** 233 * Check that in-file password encryption works as expected with different kinds of passwords 234 * 235 * This test checks that encrypting the config file, with different kinds of pwd, results in a valid 236 * PHP file as expected. It doesn't test that the different kinds of password get correctly hashed 237 * and can be correctly deciphered. This task is covered in test_hash_and_check() 238 */ 239 public function test_hash_passwords_special_chars_now() { 240 241 if( !copy( YOURLS_TESTDATA_DIR . '/auth/config-test-auth.php', YOURLS_TESTDATA_DIR . '/auth/config-test-auth-hashed.php' ) ) { 242 $this->markTestSkipped( 'Could not copy file (write permissions?) -- cannot run test' ); 243 } else { 244 $config_file = YOURLS_TESTDATA_DIR . '/auth/config-test-auth-hashed.php'; 245 } 246 247 // Encrypt file 248 $this->assertTrue( yourls_hash_passwords_now( $config_file ) ); 249 250 // Make sure encrypted file is still valid PHP with no syntax error 251 if( !defined( 'YOURLS_PHP_BIN' ) ) { 252 $this->markTestSkipped( 'No PHP binary defined -- cannot check file hashing' ); 253 return; 254 } 255 256 exec( YOURLS_PHP_BIN . ' -l ' . escapeshellarg( $config_file ), $output, $return ); 257 $this->assertEquals( 0, $return ); 258 } 259 260 /** 261 * Check that we hash passwords by default 262 */ 263 public function test_maybe_hash_passwords_clear_passwords() { 264 global $yourls_user_passwords; 265 $copy = $yourls_user_passwords; 266 267 $yourls_user_passwords = []; 268 $yourls_user_passwords['ozh'] = 'ozh'; 269 270 $this->assertTrue( yourls_maybe_hash_passwords() ); 271 272 $yourls_user_passwords = $copy; 273 } 274 275 /** 276 * Check that we don't hash passwords in config file if there's nothing to hash 277 */ 278 public function test_maybe_hash_passwords_no_clear_password() { 279 global $yourls_user_passwords; 280 $copy = $yourls_user_passwords; 281 282 $yourls_user_passwords = array(); 283 $yourls_user_passwords['md5'] = $copy['md5']; 284 285 $this->assertFalse( yourls_maybe_hash_passwords() ); 286 287 $yourls_user_passwords = $copy; 288 } 289 290 /** 291 * Check that we don't hash passwords in config file if user explicitly doesn't want it 292 * 293 * (Note that we're checking with the filter, it can also be enforced with a constant) 294 */ 295 public function test_maybe_hash_passwords_YOURLS_NO_HASH_PASSWORD() { 296 yourls_add_filter('skip_password_hashing', 'yourls_return_true'); 297 $this->assertFalse( yourls_maybe_hash_passwords() ); 298 yourls_remove_filter('skip_password_hashing', 'yourls_return_true'); 299 } 300 301 /** 302 * Check that we don't hash passwords in config file if USER/PWD provided by env 303 */ 304 public function test_maybe_hash_passwords_via_env() { 305 putenv('YOURLS_USER=ozh'); 306 putenv('YOURLS_PASSWORD=ozh'); 307 308 $this->assertFalse( yourls_maybe_hash_passwords() ); 309 310 putenv('YOURLS_USER'); 311 putenv('YOURLS_PASSWORD'); 312 } 313 314 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Mar 3 05:10:02 2025 | Cross-referenced by PHPXref 0.7.1 |