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