Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

manager.php

Zuletzt modifiziert: 09.10.2024, 12:52 - Dateigröße: 10.11 KiB


 001  <?php
 002  /**
 003  *
 004  * This file is part of the phpBB Forum Software package.
 005  *
 006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
 007  * @license GNU General Public License, version 2 (GPL-2.0)
 008  *
 009  * For full copyright and license information, please see
 010  * the docs/CREDITS.txt file.
 011  *
 012  */
 013   
 014  namespace phpbb\passwords;
 015   
 016  class manager
 017  {
 018      /**
 019      * Default hashing method
 020      */
 021      protected $type = false;
 022   
 023      /**
 024      * Hashing algorithm type map
 025      * Will be used to map hash prefix to type
 026      */
 027      protected $type_map = false;
 028   
 029      /**
 030      * Service collection of hashing algorithms
 031      * Needs to be public for passwords helper
 032      */
 033      public $algorithms = false;
 034   
 035      /**
 036      * Password convert flag. Signals that password should be converted
 037      */
 038      public $convert_flag = false;
 039   
 040      /**
 041      * Passwords helper
 042      * @var \phpbb\passwords\helper
 043      */
 044      protected $helper;
 045   
 046      /**
 047      * phpBB configuration
 048      * @var \phpbb\config\config
 049      */
 050      protected $config;
 051   
 052      /**
 053       * @var bool Whether or not initialized() has been called
 054       */
 055      private $initialized = false;
 056   
 057      /**
 058       * @var array Hashing driver service collection
 059       */
 060      private $hashing_algorithms;
 061   
 062      /**
 063       * @var array List of default driver types
 064       */
 065      private $defaults;
 066   
 067      /**
 068      * Construct a passwords object
 069      *
 070      * @param \phpbb\config\config        $config                phpBB configuration
 071      * @param array                        $hashing_algorithms    Hashing driver service collection
 072      * @param \phpbb\passwords\helper    $helper                Passwords helper object
 073      * @param array                        $defaults            List of default driver types
 074      */
 075      public function __construct(\phpbb\config\config $config, $hashing_algorithms, helper $helper, $defaults)
 076      {
 077          $this->config = $config;
 078          $this->helper = $helper;
 079          $this->hashing_algorithms = $hashing_algorithms;
 080          $this->defaults = $defaults;
 081      }
 082   
 083      /**
 084       * Initialize the internal state
 085       */
 086      protected function initialize()
 087      {
 088          if (!$this->initialized)
 089          {
 090              $this->initialized = true;
 091              $this->fill_type_map($this->hashing_algorithms);
 092              $this->register_default_type($this->defaults);
 093          }
 094      }
 095   
 096      /**
 097      * Register default type
 098      * Will register the first supported type from the list of default types
 099      *
 100      * @param array $defaults List of default types in order from first to
 101      *            use to last to use
 102      */
 103      protected function register_default_type($defaults)
 104      {
 105          foreach ($defaults as $type)
 106          {
 107              if ($this->algorithms[$type]->is_supported())
 108              {
 109                  $this->type = $this->algorithms[$type]->get_prefix();
 110                  break;
 111              }
 112          }
 113      }
 114   
 115      /**
 116      * Fill algorithm type map
 117      *
 118      * @param \phpbb\di\service_collection $hashing_algorithms
 119      */
 120      protected function fill_type_map($hashing_algorithms)
 121      {
 122          foreach ($hashing_algorithms as $algorithm)
 123          {
 124              if (!isset($this->type_map[$algorithm->get_prefix()]))
 125              {
 126                  $this->type_map[$algorithm->get_prefix()] = $algorithm;
 127              }
 128          }
 129          $this->algorithms = $hashing_algorithms;
 130      }
 131   
 132      /**
 133      * Get the algorithm specified by a specific prefix
 134      *
 135      * @param string $prefix Password hash prefix
 136      *
 137      * @return object|bool The hash type object or false if prefix is not
 138      *            supported
 139      */
 140      protected function get_algorithm($prefix)
 141      {
 142          if (isset($this->type_map[$prefix]))
 143          {
 144              return $this->type_map[$prefix];
 145          }
 146          else
 147          {
 148              return false;
 149          }
 150      }
 151   
 152      /**
 153      * Detect the hash type of the supplied hash
 154      *
 155      * @param string $hash Password hash that should be checked
 156      *
 157      * @return object|bool The hash type object or false if the specified
 158      *            type is not supported
 159      */
 160      public function detect_algorithm($hash)
 161      {
 162          /*
 163          * preg_match() will also show hashing algos like $2a\H$, which
 164          * is a combination of bcrypt and phpass. Legacy algorithms
 165          * like md5 will not be matched by this and need to be treated
 166          * differently.
 167          */
 168          if (!preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match))
 169          {
 170              return false;
 171          }
 172   
 173          $this->initialize();
 174   
 175          // Be on the lookout for multiple hashing algorithms
 176          // 2 is correct: H\2a > 2, H\P > 2
 177          if (strlen($match[1]) > 2 && strpos($match[1], '\\') !== false)
 178          {
 179              $hash_types = explode('\\', $match[1]);
 180              $return_ary = array();
 181              foreach ($hash_types as $type)
 182              {
 183                  // we do not support the same hashing
 184                  // algorithm more than once
 185                  if (isset($return_ary[$type]))
 186                  {
 187                      return false;
 188                  }
 189   
 190                  $return_ary[$type] = $this->get_algorithm('$' . $type . '$');
 191   
 192                  if (empty($return_ary[$type]))
 193                  {
 194                      return false;
 195                  }
 196              }
 197              return $return_ary;
 198          }
 199   
 200          // get_algorithm() will automatically return false if prefix
 201          // is not supported
 202          return $this->get_algorithm($match[0]);
 203      }
 204   
 205      /**
 206      * Hash supplied password
 207      *
 208      * @param string $password Password that should be hashed
 209      * @param string $type Hash type. Will default to standard hash type if
 210      *            none is supplied
 211      * @return string|bool Password hash of supplied password or false if
 212      *            if something went wrong during hashing
 213      */
 214      public function hash($password, $type = '')
 215      {
 216          if (strlen($password) > 4096)
 217          {
 218              // If the password is too huge, we will simply reject it
 219              // and not let the server try to hash it.
 220              return false;
 221          }
 222   
 223          $this->initialize();
 224   
 225          // Try to retrieve algorithm by service name if type doesn't
 226          // start with dollar sign
 227          if (!is_array($type) && strpos($type, '$') !== 0 && isset($this->algorithms[$type]))
 228          {
 229              $type = $this->algorithms[$type]->get_prefix();
 230          }
 231   
 232          $type = ($type === '') ? $this->type : $type;
 233   
 234          if (is_array($type))
 235          {
 236              return $this->combined_hash_password($password, $type);
 237          }
 238   
 239          if (isset($this->type_map[$type]))
 240          {
 241              $hashing_algorithm = $this->type_map[$type];
 242          }
 243          else
 244          {
 245              return false;
 246          }
 247   
 248          return $hashing_algorithm->hash($password);
 249      }
 250   
 251      /**
 252      * Check supplied password against hash and set convert_flag if password
 253      * needs to be converted to different format (preferrably newer one)
 254      *
 255      * @param string $password Password that should be checked
 256      * @param string $hash Stored hash
 257      * @param array    $user_row User's row in users table
 258      * @return string|bool True if password is correct, false if not
 259      */
 260      public function check($password, $hash, $user_row = array())
 261      {
 262          if (strlen($password) > 4096)
 263          {
 264              // If the password is too huge, we will simply reject it
 265              // and not let the server try to hash it.
 266              return false;
 267          }
 268   
 269          // Empty hashes can't be checked
 270          if (empty($hash))
 271          {
 272              return false;
 273          }
 274   
 275          $this->initialize();
 276   
 277          // First find out what kind of hash we're dealing with
 278          $stored_hash_type = $this->detect_algorithm($hash);
 279          if ($stored_hash_type == false)
 280          {
 281              // Still check MD5 hashes as that is what the installer
 282              // will default to for the admin user
 283              return $this->get_algorithm('$H$')->check($password, $hash);
 284          }
 285   
 286          // Multiple hash passes needed
 287          if (is_array($stored_hash_type))
 288          {
 289              $correct = $this->check_combined_hash($password, $stored_hash_type, $hash);
 290              $this->convert_flag = ($correct === true) ? true : false;
 291              return $correct;
 292          }
 293   
 294          if ($stored_hash_type->get_prefix() !== $this->type)
 295          {
 296              $this->convert_flag = true;
 297          }
 298          else
 299          {
 300              if ($stored_hash_type instanceof driver\rehashable_driver_interface)
 301              {
 302                  $this->convert_flag = $stored_hash_type->needs_rehash($hash);
 303              }
 304              else
 305              {
 306                  $this->convert_flag = false;
 307              }
 308          }
 309   
 310          // Check all legacy hash types if prefix is $CP$
 311          if ($stored_hash_type->get_prefix() === '$CP$')
 312          {
 313              // Remove $CP$ prefix for proper checking
 314              $hash = substr($hash, 4);
 315   
 316              foreach ($this->type_map as $algorithm)
 317              {
 318                  if ($algorithm->is_legacy() && $algorithm->check($password, $hash, $user_row) === true)
 319                  {
 320                      return true;
 321                  }
 322              }
 323          }
 324   
 325          return $stored_hash_type->check($password, $hash);
 326      }
 327   
 328      /**
 329      * Create combined hash from already hashed password
 330      *
 331      * @param string $password_hash Complete current password hash
 332      * @param string $type Type of the hashing algorithm the password hash
 333      *        should be combined with
 334      * @return string|bool Combined password hash if combined hashing was
 335      *        successful, else false
 336      */
 337      public function combined_hash_password($password_hash, $type)
 338      {
 339          $this->initialize();
 340   
 341          $data = array(
 342              'prefix' => '$',
 343              'settings' => '$',
 344          );
 345          $hash_settings = $this->helper->get_combined_hash_settings($password_hash);
 346          $hash = $hash_settings[0];
 347   
 348          // Put settings of current hash into data array
 349          $stored_hash_type = $this->detect_algorithm($password_hash);
 350          $this->helper->combine_hash_output($data, 'prefix', $stored_hash_type->get_prefix());
 351          $this->helper->combine_hash_output($data, 'settings', $stored_hash_type->get_settings_only($password_hash));
 352   
 353          // Hash current hash with the defined types
 354          foreach ($type as $cur_type)
 355          {
 356              if (isset($this->algorithms[$cur_type]))
 357              {
 358                  $new_hash_type = $this->algorithms[$cur_type];
 359              }
 360              else
 361              {
 362                  $new_hash_type = $this->get_algorithm($cur_type);
 363              }
 364   
 365              if (!$new_hash_type)
 366              {
 367                  return false;
 368              }
 369   
 370              $new_hash = $new_hash_type->hash(str_replace($stored_hash_type->get_settings_only($password_hash), '', $hash));
 371              $this->helper->combine_hash_output($data, 'prefix', $new_hash_type->get_prefix());
 372              $this->helper->combine_hash_output($data, 'settings', substr(str_replace('$', '\\', $new_hash_type->get_settings_only($new_hash, true)), 0));
 373              $hash = str_replace($new_hash_type->get_settings_only($new_hash), '', $this->helper->obtain_hash_only($new_hash));
 374          }
 375          return $this->helper->combine_hash_output($data, 'hash', $hash);
 376      }
 377   
 378      /**
 379      * Check combined password hash against the supplied password
 380      *
 381      * @param string $password Password entered by user
 382      * @param array $stored_hash_type An array containing the hash types
 383      *                as described by stored password hash
 384      * @param string $hash Stored password hash
 385      *
 386      * @return bool True if password is correct, false if not
 387      */
 388      public function check_combined_hash($password, $stored_hash_type, $hash)
 389      {
 390          $i = 0;
 391          $data = array(
 392              'prefix' => '$',
 393              'settings' => '$',
 394          );
 395          $hash_settings = $this->helper->get_combined_hash_settings($hash);
 396          foreach ($stored_hash_type as $key => $hash_type)
 397          {
 398              $rebuilt_hash = $this->helper->rebuild_hash($hash_type->get_prefix(), $hash_settings[$i]);
 399              $this->helper->combine_hash_output($data, 'prefix', $key);
 400              $this->helper->combine_hash_output($data, 'settings', $hash_settings[$i]);
 401              $cur_hash = $hash_type->hash($password, $rebuilt_hash);
 402              $password = str_replace($rebuilt_hash, '', $cur_hash);
 403              $i++;
 404          }
 405          return ($hash === $this->helper->combine_hash_output($data, 'hash', $password));
 406      }
 407  }
 408