[ Index ]

PHP Cross Reference of YOURLS

title

Body

[close]

/tests/tests/auth/ -> auth.php (source)

   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  }


Generated: Mon Mar 3 05:10:02 2025 Cross-referenced by PHPXref 0.7.1