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. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
manager.php
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