Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

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: 9.30 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      * Construct a passwords object
 054      *
 055      * @param \phpbb\config\config $config phpBB configuration
 056      * @param array $hashing_algorithms Hashing driver
 057      *            service collection
 058      * @param \phpbb\passwords\helper $helper Passwords helper object
 059      * @param string $defaults List of default driver types
 060      */
 061      public function __construct(\phpbb\config\config $config, $hashing_algorithms, helper $helper, $defaults)
 062      {
 063          $this->config = $config;
 064          $this->helper = $helper;
 065   
 066          $this->fill_type_map($hashing_algorithms);
 067          $this->register_default_type($defaults);
 068      }
 069   
 070      /**
 071      * Register default type
 072      * Will register the first supported type from the list of default types
 073      *
 074      * @param array $defaults List of default types in order from first to
 075      *            use to last to use
 076      */
 077      protected function register_default_type($defaults)
 078      {
 079          foreach ($defaults as $type)
 080          {
 081              if ($this->algorithms[$type]->is_supported())
 082              {
 083                  $this->type = $this->algorithms[$type]->get_prefix();
 084                  break;
 085              }
 086          }
 087      }
 088   
 089      /**
 090      * Fill algorithm type map
 091      *
 092      * @param \phpbb\di\service_collection $hashing_algorithms
 093      */
 094      protected function fill_type_map($hashing_algorithms)
 095      {
 096          foreach ($hashing_algorithms as $algorithm)
 097          {
 098              if (!isset($this->type_map[$algorithm->get_prefix()]))
 099              {
 100                  $this->type_map[$algorithm->get_prefix()] = $algorithm;
 101              }
 102          }
 103          $this->algorithms = $hashing_algorithms;
 104      }
 105   
 106      /**
 107      * Get the algorithm specified by a specific prefix
 108      *
 109      * @param string $prefix Password hash prefix
 110      *
 111      * @return object|bool The hash type object or false if prefix is not
 112      *            supported
 113      */
 114      protected function get_algorithm($prefix)
 115      {
 116          if (isset($this->type_map[$prefix]))
 117          {
 118              return $this->type_map[$prefix];
 119          }
 120          else
 121          {
 122              return false;
 123          }
 124      }
 125   
 126      /**
 127      * Detect the hash type of the supplied hash
 128      *
 129      * @param string $hash Password hash that should be checked
 130      *
 131      * @return object|bool The hash type object or false if the specified
 132      *            type is not supported
 133      */
 134      public function detect_algorithm($hash)
 135      {
 136          /*
 137          * preg_match() will also show hashing algos like $2a\H$, which
 138          * is a combination of bcrypt and phpass. Legacy algorithms
 139          * like md5 will not be matched by this and need to be treated
 140          * differently.
 141          */
 142          if (!preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match))
 143          {
 144              return false;
 145          }
 146   
 147          // Be on the lookout for multiple hashing algorithms
 148          // 2 is correct: H\2a > 2, H\P > 2
 149          if (strlen($match[1]) > 2)
 150          {
 151              $hash_types = explode('\\', $match[1]);
 152              $return_ary = array();
 153              foreach ($hash_types as $type)
 154              {
 155                  // we do not support the same hashing
 156                  // algorithm more than once
 157                  if (isset($return_ary[$type]))
 158                  {
 159                      return false;
 160                  }
 161   
 162                  $return_ary[$type] = $this->get_algorithm('$' . $type . '$');
 163   
 164                  if (empty($return_ary[$type]))
 165                  {
 166                      return false;
 167                  }
 168              }
 169              return $return_ary;
 170          }
 171   
 172          // get_algorithm() will automatically return false if prefix
 173          // is not supported
 174          return $this->get_algorithm($match[0]);
 175      }
 176   
 177      /**
 178      * Hash supplied password
 179      *
 180      * @param string $password Password that should be hashed
 181      * @param string $type Hash type. Will default to standard hash type if
 182      *            none is supplied
 183      * @return string|bool Password hash of supplied password or false if
 184      *            if something went wrong during hashing
 185      */
 186      public function hash($password, $type = '')
 187      {
 188          if (strlen($password) > 4096)
 189          {
 190              // If the password is too huge, we will simply reject it
 191              // and not let the server try to hash it.
 192              return false;
 193          }
 194   
 195          // Try to retrieve algorithm by service name if type doesn't
 196          // start with dollar sign
 197          if (!is_array($type) && strpos($type, '$') !== 0 && isset($this->algorithms[$type]))
 198          {
 199              $type = $this->algorithms[$type]->get_prefix();
 200          }
 201   
 202          $type = ($type === '') ? $this->type : $type;
 203   
 204          if (is_array($type))
 205          {
 206              return $this->combined_hash_password($password, $type);
 207          }
 208   
 209          if (isset($this->type_map[$type]))
 210          {
 211              $hashing_algorithm = $this->type_map[$type];
 212          }
 213          else
 214          {
 215              return false;
 216          }
 217   
 218          return $hashing_algorithm->hash($password);
 219      }
 220   
 221      /**
 222      * Check supplied password against hash and set convert_flag if password
 223      * needs to be converted to different format (preferrably newer one)
 224      *
 225      * @param string $password Password that should be checked
 226      * @param string $hash Stored hash
 227      * @param array    $user_row User's row in users table
 228      * @return string|bool True if password is correct, false if not
 229      */
 230      public function check($password, $hash, $user_row = array())
 231      {
 232          if (strlen($password) > 4096)
 233          {
 234              // If the password is too huge, we will simply reject it
 235              // and not let the server try to hash it.
 236              return false;
 237          }
 238   
 239          // Empty hashes can't be checked
 240          if (empty($hash))
 241          {
 242              return false;
 243          }
 244   
 245          // First find out what kind of hash we're dealing with
 246          $stored_hash_type = $this->detect_algorithm($hash);
 247          if ($stored_hash_type == false)
 248          {
 249              // Still check MD5 hashes as that is what the installer
 250              // will default to for the admin user
 251              return $this->get_algorithm('$H$')->check($password, $hash);
 252          }
 253   
 254          // Multiple hash passes needed
 255          if (is_array($stored_hash_type))
 256          {
 257              $correct = $this->check_combined_hash($password, $stored_hash_type, $hash);
 258              $this->convert_flag = ($correct === true) ? true : false;
 259              return $correct;
 260          }
 261   
 262          if ($stored_hash_type->get_prefix() !== $this->type)
 263          {
 264              $this->convert_flag = true;
 265          }
 266          else
 267          {
 268              $this->convert_flag = false;
 269          }
 270   
 271          // Check all legacy hash types if prefix is $CP$
 272          if ($stored_hash_type->get_prefix() === '$CP$')
 273          {
 274              // Remove $CP$ prefix for proper checking
 275              $hash = substr($hash, 4);
 276   
 277              foreach ($this->type_map as $algorithm)
 278              {
 279                  if ($algorithm->is_legacy() && $algorithm->check($password, $hash, $user_row) === true)
 280                  {
 281                      return true;
 282                  }
 283              }
 284          }
 285   
 286          return $stored_hash_type->check($password, $hash);
 287      }
 288   
 289      /**
 290      * Create combined hash from already hashed password
 291      *
 292      * @param string $password_hash Complete current password hash
 293      * @param string $type Type of the hashing algorithm the password hash
 294      *        should be combined with
 295      * @return string|bool Combined password hash if combined hashing was
 296      *        successful, else false
 297      */
 298      public function combined_hash_password($password_hash, $type)
 299      {
 300          $data = array(
 301              'prefix' => '$',
 302              'settings' => '$',
 303          );
 304          $hash_settings = $this->helper->get_combined_hash_settings($password_hash);
 305          $hash = $hash_settings[0];
 306   
 307          // Put settings of current hash into data array
 308          $stored_hash_type = $this->detect_algorithm($password_hash);
 309          $this->helper->combine_hash_output($data, 'prefix', $stored_hash_type->get_prefix());
 310          $this->helper->combine_hash_output($data, 'settings', $stored_hash_type->get_settings_only($password_hash));
 311   
 312          // Hash current hash with the defined types
 313          foreach ($type as $cur_type)
 314          {
 315              if (isset($this->algorithms[$cur_type]))
 316              {
 317                  $new_hash_type = $this->algorithms[$cur_type];
 318              }
 319              else
 320              {
 321                  $new_hash_type = $this->get_algorithm($cur_type);
 322              }
 323   
 324              if (!$new_hash_type)
 325              {
 326                  return false;
 327              }
 328   
 329              $new_hash = $new_hash_type->hash(str_replace($stored_hash_type->get_settings_only($password_hash), '', $hash));
 330              $this->helper->combine_hash_output($data, 'prefix', $new_hash_type->get_prefix());
 331              $this->helper->combine_hash_output($data, 'settings', substr(str_replace('$', '\\', $new_hash_type->get_settings_only($new_hash, true)), 0));
 332              $hash = str_replace($new_hash_type->get_settings_only($new_hash), '', $this->helper->obtain_hash_only($new_hash));
 333          }
 334          return $this->helper->combine_hash_output($data, 'hash', $hash);
 335      }
 336   
 337      /**
 338      * Check combined password hash against the supplied password
 339      *
 340      * @param string $password Password entered by user
 341      * @param array $stored_hash_type An array containing the hash types
 342      *                as described by stored password hash
 343      * @param string $hash Stored password hash
 344      *
 345      * @return bool True if password is correct, false if not
 346      */
 347      public function check_combined_hash($password, $stored_hash_type, $hash)
 348      {
 349          $i = 0;
 350          $data = array(
 351              'prefix' => '$',
 352              'settings' => '$',
 353          );
 354          $hash_settings = $this->helper->get_combined_hash_settings($hash);
 355          foreach ($stored_hash_type as $key => $hash_type)
 356          {
 357              $rebuilt_hash = $this->helper->rebuild_hash($hash_type->get_prefix(), $hash_settings[$i]);
 358              $this->helper->combine_hash_output($data, 'prefix', $key);
 359              $this->helper->combine_hash_output($data, 'settings', $hash_settings[$i]);
 360              $cur_hash = $hash_type->hash($password, $rebuilt_hash);
 361              $password = str_replace($rebuilt_hash, '', $cur_hash);
 362              $i++;
 363          }
 364          return ($hash === $this->helper->combine_hash_output($data, 'hash', $password));
 365      }
 366  }
 367