Mercurial > hg > rc1
comparison plugins/password/password.php @ 0:1e000243b222
vanilla 1.3.3 distro, I hope
author | Charlie Root |
---|---|
date | Thu, 04 Jan 2018 15:50:29 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e000243b222 |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * Password Plugin for Roundcube | |
5 * | |
6 * @author Aleksander Machniak <alec@alec.pl> | |
7 * | |
8 * Copyright (C) 2005-2015, The Roundcube Dev Team | |
9 * | |
10 * This program is free software: you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation, either version 3 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * This program is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this program. If not, see http://www.gnu.org/licenses/. | |
22 */ | |
23 | |
24 define('PASSWORD_CRYPT_ERROR', 1); | |
25 define('PASSWORD_ERROR', 2); | |
26 define('PASSWORD_CONNECT_ERROR', 3); | |
27 define('PASSWORD_IN_HISTORY', 4); | |
28 define('PASSWORD_CONSTRAINT_VIOLATION', 5); | |
29 define('PASSWORD_SUCCESS', 0); | |
30 | |
31 /** | |
32 * Change password plugin | |
33 * | |
34 * Plugin that adds functionality to change a users password. | |
35 * It provides common functionality and user interface and supports | |
36 * several backends to finally update the password. | |
37 * | |
38 * For installation and configuration instructions please read the README file. | |
39 * | |
40 * @author Aleksander Machniak | |
41 */ | |
42 class password extends rcube_plugin | |
43 { | |
44 public $task = 'settings|login'; | |
45 public $noframe = true; | |
46 public $noajax = true; | |
47 | |
48 private $newuser = false; | |
49 | |
50 function init() | |
51 { | |
52 $rcmail = rcmail::get_instance(); | |
53 | |
54 $this->load_config(); | |
55 | |
56 if ($rcmail->task == 'settings') { | |
57 if (!$this->check_host_login_exceptions()) { | |
58 return; | |
59 } | |
60 | |
61 $this->add_texts('localization/'); | |
62 | |
63 $this->add_hook('settings_actions', array($this, 'settings_actions')); | |
64 | |
65 $this->register_action('plugin.password', array($this, 'password_init')); | |
66 $this->register_action('plugin.password-save', array($this, 'password_save')); | |
67 } | |
68 else if ($rcmail->config->get('password_force_new_user')) { | |
69 $this->add_hook('user_create', array($this, 'user_create')); | |
70 $this->add_hook('login_after', array($this, 'login_after')); | |
71 } | |
72 } | |
73 | |
74 function settings_actions($args) | |
75 { | |
76 // register as settings action | |
77 $args['actions'][] = array( | |
78 'action' => 'plugin.password', | |
79 'class' => 'password', | |
80 'label' => 'password', | |
81 'title' => 'changepasswd', | |
82 'domain' => 'password', | |
83 ); | |
84 | |
85 return $args; | |
86 } | |
87 | |
88 function password_init() | |
89 { | |
90 $this->register_handler('plugin.body', array($this, 'password_form')); | |
91 | |
92 $rcmail = rcmail::get_instance(); | |
93 $rcmail->output->set_pagetitle($this->gettext('changepasswd')); | |
94 | |
95 if (rcube_utils::get_input_value('_first', rcube_utils::INPUT_GET)) { | |
96 $rcmail->output->command('display_message', $this->gettext('firstloginchange'), 'notice'); | |
97 } | |
98 else if (!empty($_SESSION['password_expires'])) { | |
99 if ($_SESSION['password_expires'] == 1) { | |
100 $rcmail->output->command('display_message', $this->gettext('passwdexpired'), 'error'); | |
101 } | |
102 else { | |
103 $rcmail->output->command('display_message', $this->gettext(array( | |
104 'name' => 'passwdexpirewarning', | |
105 'vars' => array('expirationdatetime' => $_SESSION['password_expires']) | |
106 )), 'warning'); | |
107 } | |
108 } | |
109 | |
110 $rcmail->output->send('plugin'); | |
111 } | |
112 | |
113 function password_save() | |
114 { | |
115 $this->register_handler('plugin.body', array($this, 'password_form')); | |
116 | |
117 $rcmail = rcmail::get_instance(); | |
118 $rcmail->output->set_pagetitle($this->gettext('changepasswd')); | |
119 | |
120 $form_disabled = $rcmail->config->get('password_disabled'); | |
121 $confirm = $rcmail->config->get('password_confirm_current'); | |
122 $required_length = intval($rcmail->config->get('password_minimum_length')); | |
123 $check_strength = $rcmail->config->get('password_require_nonalpha'); | |
124 | |
125 if (($confirm && !isset($_POST['_curpasswd'])) || !isset($_POST['_newpasswd'])) { | |
126 $rcmail->output->command('display_message', $this->gettext('nopassword'), 'error'); | |
127 } | |
128 else { | |
129 $charset = strtoupper($rcmail->config->get('password_charset', 'ISO-8859-1')); | |
130 $rc_charset = strtoupper($rcmail->output->get_charset()); | |
131 | |
132 $sespwd = $rcmail->decrypt($_SESSION['password']); | |
133 $curpwd = $confirm ? rcube_utils::get_input_value('_curpasswd', rcube_utils::INPUT_POST, true, $charset) : $sespwd; | |
134 $newpwd = rcube_utils::get_input_value('_newpasswd', rcube_utils::INPUT_POST, true); | |
135 $conpwd = rcube_utils::get_input_value('_confpasswd', rcube_utils::INPUT_POST, true); | |
136 | |
137 // check allowed characters according to the configured 'password_charset' option | |
138 // by converting the password entered by the user to this charset and back to UTF-8 | |
139 $orig_pwd = $newpwd; | |
140 $chk_pwd = rcube_charset::convert($orig_pwd, $rc_charset, $charset); | |
141 $chk_pwd = rcube_charset::convert($chk_pwd, $charset, $rc_charset); | |
142 | |
143 // WARNING: Default password_charset is ISO-8859-1, so conversion will | |
144 // change national characters. This may disable possibility of using | |
145 // the same password in other MUA's. | |
146 // We're doing this for consistence with Roundcube core | |
147 $newpwd = rcube_charset::convert($newpwd, $rc_charset, $charset); | |
148 $conpwd = rcube_charset::convert($conpwd, $rc_charset, $charset); | |
149 | |
150 if ($chk_pwd != $orig_pwd) { | |
151 $rcmail->output->command('display_message', $this->gettext('passwordforbidden'), 'error'); | |
152 } | |
153 // other passwords validity checks | |
154 else if ($conpwd != $newpwd) { | |
155 $rcmail->output->command('display_message', $this->gettext('passwordinconsistency'), 'error'); | |
156 } | |
157 else if ($confirm && $sespwd != $curpwd) { | |
158 $rcmail->output->command('display_message', $this->gettext('passwordincorrect'), 'error'); | |
159 } | |
160 else if ($required_length && strlen($newpwd) < $required_length) { | |
161 $rcmail->output->command('display_message', $this->gettext( | |
162 array('name' => 'passwordshort', 'vars' => array('length' => $required_length))), 'error'); | |
163 } | |
164 else if ($check_strength && (!preg_match("/[0-9]/", $newpwd) || !preg_match("/[^A-Za-z0-9]/", $newpwd))) { | |
165 $rcmail->output->command('display_message', $this->gettext('passwordweak'), 'error'); | |
166 } | |
167 // password is the same as the old one, warn user, return error | |
168 else if ($sespwd == $newpwd && !$rcmail->config->get('password_force_save')) { | |
169 $rcmail->output->command('display_message', $this->gettext('samepasswd'), 'error'); | |
170 } | |
171 // try to save the password | |
172 else if (!($res = $this->_save($curpwd, $newpwd))) { | |
173 $rcmail->output->command('display_message', $this->gettext('successfullysaved'), 'confirmation'); | |
174 | |
175 // allow additional actions after password change (e.g. reset some backends) | |
176 $plugin = $rcmail->plugins->exec_hook('password_change', array( | |
177 'old_pass' => $curpwd, 'new_pass' => $newpwd)); | |
178 | |
179 // Reset session password | |
180 $_SESSION['password'] = $rcmail->encrypt($plugin['new_pass']); | |
181 | |
182 // Log password change | |
183 if ($rcmail->config->get('password_log')) { | |
184 rcube::write_log('password', sprintf('Password changed for user %s (ID: %d) from %s', | |
185 $rcmail->get_user_name(), $rcmail->user->ID, rcube_utils::remote_ip())); | |
186 } | |
187 | |
188 // Remove expiration date/time | |
189 $rcmail->session->remove('password_expires'); | |
190 } | |
191 else { | |
192 $rcmail->output->command('display_message', $res, 'error'); | |
193 } | |
194 } | |
195 | |
196 $rcmail->overwrite_action('plugin.password'); | |
197 $rcmail->output->send('plugin'); | |
198 } | |
199 | |
200 function password_form() | |
201 { | |
202 $rcmail = rcmail::get_instance(); | |
203 | |
204 // add some labels to client | |
205 $rcmail->output->add_label( | |
206 'password.nopassword', | |
207 'password.nocurpassword', | |
208 'password.passwordinconsistency' | |
209 ); | |
210 | |
211 $form_disabled = $rcmail->config->get('password_disabled'); | |
212 | |
213 $rcmail->output->set_env('product_name', $rcmail->config->get('product_name')); | |
214 $rcmail->output->set_env('password_disabled', !empty($form_disabled)); | |
215 | |
216 $table = new html_table(array('cols' => 2)); | |
217 | |
218 if ($rcmail->config->get('password_confirm_current')) { | |
219 // show current password selection | |
220 $field_id = 'curpasswd'; | |
221 $input_curpasswd = new html_passwordfield(array( | |
222 'name' => '_curpasswd', | |
223 'id' => $field_id, | |
224 'size' => 20, | |
225 'autocomplete' => 'off', | |
226 )); | |
227 | |
228 $table->add('title', html::label($field_id, rcube::Q($this->gettext('curpasswd')))); | |
229 $table->add(null, $input_curpasswd->show()); | |
230 } | |
231 | |
232 // show new password selection | |
233 $field_id = 'newpasswd'; | |
234 $input_newpasswd = new html_passwordfield(array( | |
235 'name' => '_newpasswd', | |
236 'id' => $field_id, | |
237 'size' => 20, | |
238 'autocomplete' => 'off', | |
239 )); | |
240 | |
241 $table->add('title', html::label($field_id, rcube::Q($this->gettext('newpasswd')))); | |
242 $table->add(null, $input_newpasswd->show()); | |
243 | |
244 // show confirm password selection | |
245 $field_id = 'confpasswd'; | |
246 $input_confpasswd = new html_passwordfield(array( | |
247 'name' => '_confpasswd', | |
248 'id' => $field_id, | |
249 'size' => 20, | |
250 'autocomplete' => 'off', | |
251 )); | |
252 | |
253 $table->add('title', html::label($field_id, rcube::Q($this->gettext('confpasswd')))); | |
254 $table->add(null, $input_confpasswd->show()); | |
255 | |
256 $rules = ''; | |
257 | |
258 $required_length = intval($rcmail->config->get('password_minimum_length')); | |
259 if ($required_length > 0) { | |
260 $rules .= html::tag('li', array('id' => 'required-length'), $this->gettext(array( | |
261 'name' => 'passwordshort', | |
262 'vars' => array('length' => $required_length) | |
263 ))); | |
264 } | |
265 | |
266 if ($rcmail->config->get('password_require_nonalpha')) { | |
267 $rules .= html::tag('li', array('id' => 'require-nonalpha'), $this->gettext('passwordweak')); | |
268 } | |
269 | |
270 if (!empty($rules)) { | |
271 $rules = html::tag('ul', array('id' => 'ruleslist'), $rules); | |
272 } | |
273 | |
274 $disabled_msg = ''; | |
275 if ($form_disabled) { | |
276 $disabled_msg = is_string($form_disabled) ? $form_disabled : $this->gettext('disablednotice'); | |
277 $disabled_msg = html::div(array('class' => 'boxwarning', 'id' => 'password-notice'), $disabled_msg); | |
278 } | |
279 | |
280 $submit_button = $rcmail->output->button(array( | |
281 'command' => 'plugin.password-save', | |
282 'type' => 'input', | |
283 'class' => 'button mainaction', | |
284 'label' => 'save', | |
285 )); | |
286 $form_buttons = html::p(array('class' => 'formbuttons'), $submit_button); | |
287 | |
288 $out = html::div(array('class' => 'box'), | |
289 html::div(array('id' => 'prefs-title', 'class' => 'boxtitle'), $this->gettext('changepasswd')) | |
290 . html::div(array('class' => 'boxcontent'), | |
291 $disabled_msg . $table->show() . $rules . $form_buttons)); | |
292 | |
293 $rcmail->output->add_gui_object('passform', 'password-form'); | |
294 | |
295 $this->include_script('password.js'); | |
296 | |
297 return $rcmail->output->form_tag(array( | |
298 'id' => 'password-form', | |
299 'name' => 'password-form', | |
300 'method' => 'post', | |
301 'action' => './?_task=settings&_action=plugin.password-save', | |
302 ), $out); | |
303 } | |
304 | |
305 private function _save($curpass, $passwd) | |
306 { | |
307 $config = rcmail::get_instance()->config; | |
308 $driver = $config->get('password_driver', 'sql'); | |
309 $class = "rcube_{$driver}_password"; | |
310 $file = $this->home . "/drivers/$driver.php"; | |
311 | |
312 if (!file_exists($file)) { | |
313 rcube::raise_error(array( | |
314 'code' => 600, | |
315 'type' => 'php', | |
316 'file' => __FILE__, 'line' => __LINE__, | |
317 'message' => "Password plugin: Unable to open driver file ($file)" | |
318 ), true, false); | |
319 return $this->gettext('internalerror'); | |
320 } | |
321 | |
322 include_once $file; | |
323 | |
324 if (!class_exists($class, false) || !method_exists($class, 'save')) { | |
325 rcube::raise_error(array( | |
326 'code' => 600, | |
327 'type' => 'php', | |
328 'file' => __FILE__, 'line' => __LINE__, | |
329 'message' => "Password plugin: Broken driver $driver" | |
330 ), true, false); | |
331 return $this->gettext('internalerror'); | |
332 } | |
333 | |
334 $object = new $class; | |
335 $result = $object->save($curpass, $passwd); | |
336 $message = ''; | |
337 | |
338 if (is_array($result)) { | |
339 $message = $result['message']; | |
340 $result = $result['code']; | |
341 } | |
342 | |
343 switch ($result) { | |
344 case PASSWORD_SUCCESS: | |
345 return; | |
346 case PASSWORD_CRYPT_ERROR: | |
347 $reason = $this->gettext('crypterror'); | |
348 break; | |
349 case PASSWORD_CONNECT_ERROR: | |
350 $reason = $this->gettext('connecterror'); | |
351 break; | |
352 case PASSWORD_IN_HISTORY: | |
353 $reason = $this->gettext('passwdinhistory'); | |
354 break; | |
355 case PASSWORD_CONSTRAINT_VIOLATION: | |
356 $reason = $this->gettext('passwdconstraintviolation'); | |
357 break; | |
358 case PASSWORD_ERROR: | |
359 default: | |
360 $reason = $this->gettext('internalerror'); | |
361 } | |
362 | |
363 if ($message) { | |
364 $reason .= ' ' . $message; | |
365 } | |
366 | |
367 return $reason; | |
368 } | |
369 | |
370 function user_create($args) | |
371 { | |
372 $this->newuser = true; | |
373 return $args; | |
374 } | |
375 | |
376 function login_after($args) | |
377 { | |
378 if ($this->newuser && $this->check_host_login_exceptions()) { | |
379 $args['_task'] = 'settings'; | |
380 $args['_action'] = 'plugin.password'; | |
381 $args['_first'] = 'true'; | |
382 } | |
383 | |
384 return $args; | |
385 } | |
386 | |
387 // Check if host and login is allowed to change the password, false = not allowed, true = not allowed | |
388 private function check_host_login_exceptions() | |
389 { | |
390 $rcmail = rcmail::get_instance(); | |
391 | |
392 // Host exceptions | |
393 $hosts = $rcmail->config->get('password_hosts'); | |
394 if (!empty($hosts) && !in_array($_SESSION['storage_host'], (array) $hosts)) { | |
395 return false; | |
396 } | |
397 | |
398 // Login exceptions | |
399 if ($exceptions = $rcmail->config->get('password_login_exceptions')) { | |
400 $exceptions = array_map('trim', (array) $exceptions); | |
401 $exceptions = array_filter($exceptions); | |
402 $username = $_SESSION['username']; | |
403 | |
404 foreach ($exceptions as $ec) { | |
405 if ($username === $ec) { | |
406 return false; | |
407 } | |
408 } | |
409 } | |
410 | |
411 return true; | |
412 } | |
413 | |
414 /** | |
415 * Hashes a password and returns the hash based on the specified method | |
416 * | |
417 * Parts of the code originally from the phpLDAPadmin development team | |
418 * http://phpldapadmin.sourceforge.net/ | |
419 * | |
420 * @param string Clear password | |
421 * @param string Hashing method | |
422 * @param bool|string Prefix string or TRUE to add a default prefix | |
423 * | |
424 * @return string Hashed password | |
425 */ | |
426 static function hash_password($password, $method = '', $prefixed = true) | |
427 { | |
428 $method = strtolower($method); | |
429 $rcmail = rcmail::get_instance(); | |
430 $prefix = ''; | |
431 $crypted = ''; | |
432 $default = false; | |
433 | |
434 if (empty($method) || $method == 'default') { | |
435 $method = $rcmail->config->get('password_algorithm'); | |
436 $prefixed = $rcmail->config->get('password_algorithm_prefix'); | |
437 $default = true; | |
438 } | |
439 else if ($method == 'crypt') { // deprecated | |
440 if (!($method = $rcmail->config->get('password_crypt_hash'))) { | |
441 $method = 'md5'; | |
442 } | |
443 | |
444 if (!strpos($method, '-crypt')) { | |
445 $method .= '-crypt'; | |
446 } | |
447 } | |
448 | |
449 switch ($method) { | |
450 case 'des': | |
451 case 'des-crypt': | |
452 $crypted = crypt($password, rcube_utils::random_bytes(2)); | |
453 $prefix = '{CRYPT}'; | |
454 break; | |
455 | |
456 case 'ext_des': // for BC | |
457 case 'ext-des-crypt': | |
458 $crypted = crypt($password, '_' . rcube_utils::random_bytes(8)); | |
459 $prefix = '{CRYPT}'; | |
460 break; | |
461 | |
462 case 'md5crypt': // for BC | |
463 case 'md5-crypt': | |
464 $crypted = crypt($password, '$1$' . rcube_utils::random_bytes(9)); | |
465 $prefix = '{CRYPT}'; | |
466 break; | |
467 | |
468 case 'sha256-crypt': | |
469 $rounds = (int) $rcmail->config->get('password_crypt_rounds'); | |
470 $prefix = '$5$'; | |
471 | |
472 if ($rounds > 1000) { | |
473 $prefix .= 'rounds=' . $rounds . '$'; | |
474 } | |
475 | |
476 $crypted = crypt($password, $prefix . rcube_utils::random_bytes(16)); | |
477 $prefix = '{CRYPT}'; | |
478 break; | |
479 | |
480 case 'sha512-crypt': | |
481 $rounds = (int) $rcmail->config->get('password_crypt_rounds'); | |
482 $prefix = '$6$'; | |
483 | |
484 if ($rounds > 1000) { | |
485 $prefix .= 'rounds=' . $rounds . '$'; | |
486 } | |
487 | |
488 $crypted = crypt($password, $prefix . rcube_utils::random_bytes(16)); | |
489 $prefix = '{CRYPT}'; | |
490 break; | |
491 | |
492 case 'blowfish': // for BC | |
493 case 'blowfish-crypt': | |
494 $cost = (int) $rcmail->config->get('password_blowfish_cost'); | |
495 $cost = $cost < 4 || $cost > 31 ? 12 : $cost; | |
496 $prefix = sprintf('$2a$%02d$', $cost); | |
497 | |
498 $crypted = crypt($password, $prefix . rcube_utils::random_bytes(22)); | |
499 $prefix = '{CRYPT}'; | |
500 break; | |
501 | |
502 case 'md5': | |
503 $crypted = base64_encode(pack('H*', md5($password))); | |
504 $prefix = '{MD5}'; | |
505 break; | |
506 | |
507 case 'sha': | |
508 if (function_exists('sha1')) { | |
509 $crypted = pack('H*', sha1($password)); | |
510 } | |
511 else if (function_exists('hash')) { | |
512 $crypted = hash('sha1', $password, true); | |
513 } | |
514 else if (function_exists('mhash')) { | |
515 $crypted = mhash(MHASH_SHA1, $password); | |
516 } | |
517 else { | |
518 rcube::raise_error(array( | |
519 'code' => 600, 'file' => __FILE__, 'line' => __LINE__, | |
520 'message' => "Password plugin: Your PHP install does not have the mhash()/hash() nor sha1() function" | |
521 ), true, true); | |
522 } | |
523 | |
524 $crypted = base64_encode($crypted); | |
525 $prefix = '{SHA}'; | |
526 break; | |
527 | |
528 case 'ssha': | |
529 $salt = rcube_utils::random_bytes(8); | |
530 | |
531 if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) { | |
532 $salt = mhash_keygen_s2k(MHASH_SHA1, $password, $salt, 4); | |
533 $crypted = mhash(MHASH_SHA1, $password . $salt); | |
534 } | |
535 else if (function_exists('sha1')) { | |
536 $salt = substr(pack("H*", sha1($salt . $password)), 0, 4); | |
537 $crypted = sha1($password . $salt, true); | |
538 } | |
539 else if (function_exists('hash')) { | |
540 $salt = substr(pack("H*", hash('sha1', $salt . $password)), 0, 4); | |
541 $crypted = hash('sha1', $password . $salt, true); | |
542 } | |
543 else { | |
544 rcube::raise_error(array( | |
545 'code' => 600, 'file' => __FILE__, 'line' => __LINE__, | |
546 'message' => "Password plugin: Your PHP install does not have the mhash()/hash() nor sha1() function" | |
547 ), true, true); | |
548 } | |
549 | |
550 $crypted = base64_encode($crypted . $salt); | |
551 $prefix = '{SSHA}'; | |
552 break; | |
553 | |
554 case 'smd5': | |
555 $salt = rcube_utils::random_bytes(8); | |
556 | |
557 if (function_exists('mhash') && function_exists('mhash_keygen_s2k')) { | |
558 $salt = mhash_keygen_s2k(MHASH_MD5, $password, $salt, 4); | |
559 $crypted = mhash(MHASH_MD5, $password . $salt); | |
560 } | |
561 else if (function_exists('hash')) { | |
562 $salt = substr(pack("H*", hash('md5', $salt . $password)), 0, 4); | |
563 $crypted = hash('md5', $password . $salt, true); | |
564 } | |
565 else { | |
566 $salt = substr(pack("H*", md5($salt . $password)), 0, 4); | |
567 $crypted = md5($password . $salt, true); | |
568 } | |
569 | |
570 $crypted = base64_encode($crypted . $salt); | |
571 $prefix = '{SMD5}'; | |
572 break; | |
573 | |
574 case 'samba': | |
575 if (function_exists('hash')) { | |
576 $crypted = hash('md4', rcube_charset::convert($password, RCUBE_CHARSET, 'UTF-16LE')); | |
577 $crypted = strtoupper($crypted); | |
578 } | |
579 else { | |
580 rcube::raise_error(array( | |
581 'code' => 600, 'file' => __FILE__, 'line' => __LINE__, | |
582 'message' => "Password plugin: Your PHP install does not have hash() function" | |
583 ), true, true); | |
584 } | |
585 break; | |
586 | |
587 case 'ad': | |
588 $crypted = rcube_charset::convert('"' . $password . '"', RCUBE_CHARSET, 'UTF-16LE'); | |
589 break; | |
590 | |
591 case 'cram-md5': // deprecated | |
592 require_once __DIR__ . '/../helpers/dovecot_hmacmd5.php'; | |
593 $crypted = dovecot_hmacmd5($password); | |
594 $prefix = '{CRAM-MD5}'; | |
595 break; | |
596 | |
597 case 'dovecot': | |
598 if (!($dovecotpw = $rcmail->config->get('password_dovecotpw'))) { | |
599 $dovecotpw = 'dovecotpw'; | |
600 } | |
601 if (!($method = $rcmail->config->get('password_dovecotpw_method'))) { | |
602 $method = 'CRAM-MD5'; | |
603 } | |
604 | |
605 $spec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('file', '/dev/null', 'a')); | |
606 $pipe = proc_open("$dovecotpw -s '$method'", $spec, $pipes); | |
607 | |
608 if (!is_resource($pipe)) { | |
609 return false; | |
610 } | |
611 | |
612 fwrite($pipes[0], $password . "\n", 1+strlen($password)); | |
613 usleep(1000); | |
614 fwrite($pipes[0], $password . "\n", 1+strlen($password)); | |
615 | |
616 $crypted = trim(stream_get_contents($pipes[1]), "\n"); | |
617 | |
618 fclose($pipes[0]); | |
619 fclose($pipes[1]); | |
620 proc_close($pipe); | |
621 | |
622 if (!preg_match('/^\{' . $method . '\}/', $crypted)) { | |
623 return false; | |
624 } | |
625 | |
626 if (!$default) { | |
627 $prefixed = (bool) $rcmail->config->get('password_dovecotpw_with_method'); | |
628 } | |
629 | |
630 if (!$prefixed) { | |
631 $crypted = trim(str_replace('{' . $method . '}', '', $crypted)); | |
632 } | |
633 | |
634 $prefixed = false; | |
635 | |
636 break; | |
637 | |
638 case 'hash': // deprecated | |
639 if (!extension_loaded('hash')) { | |
640 rcube::raise_error(array( | |
641 'code' => 600, 'file' => __FILE__, 'line' => __LINE__, | |
642 'message' => "Password plugin: 'hash' extension not loaded!" | |
643 ), true, true); | |
644 } | |
645 | |
646 if (!($hash_algo = strtolower($rcmail->config->get('password_hash_algorithm')))) { | |
647 $hash_algo = 'sha1'; | |
648 } | |
649 | |
650 $crypted = hash($hash_algo, $password); | |
651 | |
652 if ($rcmail->config->get('password_hash_base64')) { | |
653 $crypted = base64_encode(pack('H*', $crypted)); | |
654 } | |
655 | |
656 break; | |
657 | |
658 case 'clear': | |
659 $crypted = $password; | |
660 } | |
661 | |
662 if ($crypted === null || $crypted === false) { | |
663 return false; | |
664 } | |
665 | |
666 if ($prefixed && $prefixed !== true) { | |
667 $prefix = $prefixed; | |
668 $prefixed = true; | |
669 } | |
670 | |
671 if ($prefixed === true && $prefix) { | |
672 $crypted = $prefix . $crypted; | |
673 } | |
674 | |
675 return $crypted; | |
676 } | |
677 } |