@ -49,18 +49,21 @@ class password extends rcube_plugin
private $newuser = false;
private $newuser = false;
private $drivers = array();
private $drivers = array();
private $rc;
function init()
function init()
{
{
$rcmail = rcmail::get_instance();
$this-> rc = rcmail::get_instance();
$this->load_config();
$this->load_config();
// update deprecated password_require_nonalpha option removed 20181007
// update deprecated password_require_nonalpha option removed 20181007
if ($rcmail->config->get('password_check_strength') === null ) {
if ($this->rc->config->get('password_minimum_score') === null & & $this->rc->config->get('password_require_nonalpha') ) {
$rcmail->config->set('password_check_strength', $rcmail->config->get('password_require_nonalpha') );
$this->rc->config->set('password_minimum_score', 2 );
}
}
if ($rcmail ->task == 'settings') {
if ($this-> rc->task == 'settings') {
if (!$this->check_host_login_exceptions()) {
if (!$this->check_host_login_exceptions()) {
return;
return;
}
}
@ -73,10 +76,10 @@ class password extends rcube_plugin
$this->register_action('plugin.password-save', array($this, 'password_save'));
$this->register_action('plugin.password-save', array($this, 'password_save'));
}
}
if ($rcmail ->config->get('password_force_new_user')) {
if ($this-> rc->config->get('password_force_new_user')) {
if ($rcmail ->config->get('newuserpassword') & & $this->check_host_login_exceptions()) {
if ($this-> rc->config->get('newuserpassword') & & $this->check_host_login_exceptions()) {
if (!($rcmail ->task == 'settings' & & strpos($rcmail ->action, 'plugin.password') === 0)) {
if (!($this-> rc->task == 'settings' & & strpos($this-> rc->action, 'plugin.password') === 0)) {
$rcmail ->output->command('redirect', '?_task=settings& _action=plugin.password& _first=1', false);
$this-> rc->output->command('redirect', '?_task=settings& _action=plugin.password& _first=1', false);
}
}
}
}
@ -103,48 +106,45 @@ class password extends rcube_plugin
{
{
$this->register_handler('plugin.body', array($this, 'password_form'));
$this->register_handler('plugin.body', array($this, 'password_form'));
$rcmail = rcmail::get_instance();
$this->rc->output->set_pagetitle($this->gettext('changepasswd'));
$rcmail->output->set_pagetitle($this->gettext('changepasswd'));
if (rcube_utils::get_input_value('_first', rcube_utils::INPUT_GET)) {
if (rcube_utils::get_input_value('_first', rcube_utils::INPUT_GET)) {
$rcmail ->output->command('display_message', $this->gettext('firstloginchange'), 'notice');
$this-> rc->output->command('display_message', $this->gettext('firstloginchange'), 'notice');
}
}
else if (!empty($_SESSION['password_expires'])) {
else if (!empty($_SESSION['password_expires'])) {
if ($_SESSION['password_expires'] == 1) {
if ($_SESSION['password_expires'] == 1) {
$rcmail ->output->command('display_message', $this->gettext('passwdexpired'), 'error');
$this-> rc->output->command('display_message', $this->gettext('passwdexpired'), 'error');
}
}
else {
else {
$rcmail ->output->command('display_message', $this->gettext(array(
$this-> rc->output->command('display_message', $this->gettext(array(
'name' => 'passwdexpirewarning',
'name' => 'passwdexpirewarning',
'vars' => array('expirationdatetime' => $_SESSION['password_expires'])
'vars' => array('expirationdatetime' => $_SESSION['password_expires'])
)), 'warning');
)), 'warning');
}
}
}
}
$rcmail ->output->send('plugin');
$this-> rc->output->send('plugin');
}
}
function password_save()
function password_save()
{
{
$this->register_handler('plugin.body', array($this, 'password_form'));
$this->register_handler('plugin.body', array($this, 'password_form'));
$rcmail = rcmail::get_instance();
$this->rc->output->set_pagetitle($this->gettext('changepasswd'));
$rcmail->output->set_pagetitle($this->gettext('changepasswd'));
$form_disabled = $rcmail->config->get('password_disabled');
$form_disabled = $this->rc->config->get('password_disabled');
$confirm = $rcmail->config->get('password_confirm_current');
$confirm = $this->rc->config->get('password_confirm_current');
$required_length = intval($rcmail->config->get('password_minimum_length'));
$required_length = intval($this->rc->config->get('password_minimum_length'));
$check_strength = $rcmail->config->get('password_check_strength');
$force_save = $this->rc->config->get('password_force_save');
$force_save = $rcmail->config->get('password_force_save');
if (($confirm & & !isset($_POST['_curpasswd'])) || !isset($_POST['_newpasswd']) || !strlen($_POST['_newpasswd'])) {
if (($confirm & & !isset($_POST['_curpasswd'])) || !isset($_POST['_newpasswd']) || !strlen($_POST['_newpasswd'])) {
$rcmail ->output->command('display_message', $this->gettext('nopassword'), 'error');
$this-> rc->output->command('display_message', $this->gettext('nopassword'), 'error');
}
}
else {
else {
$charset = strtoupper($rcmail ->config->get('password_charset', 'ISO-8859-1'));
$charset = strtoupper($this-> rc->config->get('password_charset', 'ISO-8859-1'));
$rc_charset = strtoupper($rcmail ->output->get_charset());
$rc_charset = strtoupper($this-> rc->output->get_charset());
$sespwd = $rcmail ->decrypt($_SESSION['password']);
$sespwd = $this-> rc->decrypt($_SESSION['password']);
$curpwd = $confirm ? rcube_utils::get_input_value('_curpasswd', rcube_utils::INPUT_POST, true, $charset) : $sespwd;
$curpwd = $confirm ? rcube_utils::get_input_value('_curpasswd', rcube_utils::INPUT_POST, true, $charset) : $sespwd;
$newpwd = rcube_utils::get_input_value('_newpasswd', rcube_utils::INPUT_POST, true);
$newpwd = rcube_utils::get_input_value('_newpasswd', rcube_utils::INPUT_POST, true);
$conpwd = rcube_utils::get_input_value('_confpasswd', rcube_utils::INPUT_POST, true);
$conpwd = rcube_utils::get_input_value('_confpasswd', rcube_utils::INPUT_POST, true);
@ -163,78 +163,76 @@ class password extends rcube_plugin
$conpwd = rcube_charset::convert($conpwd, $rc_charset, $charset);
$conpwd = rcube_charset::convert($conpwd, $rc_charset, $charset);
if ($chk_pwd != $orig_pwd) {
if ($chk_pwd != $orig_pwd) {
$rcmail ->output->command('display_message', $this->gettext('passwordforbidden'), 'error');
$this-> rc->output->command('display_message', $this->gettext('passwordforbidden'), 'error');
}
}
// other passwords validity checks
// other passwords validity checks
else if ($conpwd != $newpwd) {
else if ($conpwd != $newpwd) {
$rcmail ->output->command('display_message', $this->gettext('passwordinconsistency'), 'error');
$this-> rc->output->command('display_message', $this->gettext('passwordinconsistency'), 'error');
}
}
else if ($confirm & & ($res = $this->_compare($sespwd, $curpwd, PASSWORD_COMPARE_CURRENT))) {
else if ($confirm & & ($res = $this->_compare($sespwd, $curpwd, PASSWORD_COMPARE_CURRENT))) {
$rcmail ->output->command('display_message', $res, 'error');
$this-> rc->output->command('display_message', $res, 'error');
}
}
else if ($required_length & & strlen($newpwd) < $required_length) {
else if ($required_length & & strlen($newpwd) < $required_length) {
$rcmail ->output->command('display_message', $this->gettext(
$this-> rc->output->command('display_message', $this->gettext(
array('name' => 'passwordshort', 'vars' => array('length' => $required_length))), 'error');
array('name' => 'passwordshort', 'vars' => array('length' => $required_length))), 'error');
}
}
else if ($check_strength & & ($ res = $this->_check_strength($newpwd) )) {
else if ($res = $this->_check_strength($newpwd)) {
$rcmail ->output->command('display_message', $res, 'error');
$this-> rc->output->command('display_message', $res, 'error');
}
}
// password is the same as the old one, warn user, return error
// password is the same as the old one, warn user, return error
else if (!$force_save & & ($res = $this->_compare($sespwd, $newpwd, PASSWORD_COMPARE_NEW))) {
else if (!$force_save & & ($res = $this->_compare($sespwd, $newpwd, PASSWORD_COMPARE_NEW))) {
$rcmail ->output->command('display_message', $res, 'error');
$this-> rc->output->command('display_message', $res, 'error');
}
}
// try to save the password
// try to save the password
else if (!($res = $this->_save($curpwd, $newpwd))) {
else if (!($res = $this->_save($curpwd, $newpwd))) {
$rcmail ->output->command('display_message', $this->gettext('successfullysaved'), 'confirmation');
$this-> rc->output->command('display_message', $this->gettext('successfullysaved'), 'confirmation');
// allow additional actions after password change (e.g. reset some backends)
// allow additional actions after password change (e.g. reset some backends)
$plugin = $rcmail ->plugins->exec_hook('password_change', array(
$plugin = $this-> rc->plugins->exec_hook('password_change', array(
'old_pass' => $curpwd, 'new_pass' => $newpwd));
'old_pass' => $curpwd, 'new_pass' => $newpwd));
// Reset session password
// Reset session password
$_SESSION['password'] = $rcmail ->encrypt($plugin['new_pass']);
$_SESSION['password'] = $this-> rc->encrypt($plugin['new_pass']);
if ($rcmail ->config->get('newuserpassword')) {
if ($this-> rc->config->get('newuserpassword')) {
$rcmail ->user->save_prefs(array('newuserpassword' => false));
$this-> rc->user->save_prefs(array('newuserpassword' => false));
}
}
// Log password change
// Log password change
if ($rcmail ->config->get('password_log')) {
if ($this-> rc->config->get('password_log')) {
rcube::write_log('password', sprintf('Password changed for user %s (ID: %d) from %s',
rcube::write_log('password', sprintf('Password changed for user %s (ID: %d) from %s',
$rcmail ->get_user_name(), $rcmail ->user->ID, rcube_utils::remote_ip()));
$this-> rc->get_user_name(), $this-> rc->user->ID, rcube_utils::remote_ip()));
}
}
// Remove expiration date/time
// Remove expiration date/time
$rcmail ->session->remove('password_expires');
$this-> rc->session->remove('password_expires');
}
}
else {
else {
$rcmail ->output->command('display_message', $res, 'error');
$this-> rc->output->command('display_message', $res, 'error');
}
}
}
}
$rcmail ->overwrite_action('plugin.password');
$this-> rc->overwrite_action('plugin.password');
$rcmail ->output->send('plugin');
$this-> rc->output->send('plugin');
}
}
function password_form()
function password_form()
{
{
$rcmail = rcmail::get_instance();
// add some labels to client
// add some labels to client
$rcmail ->output->add_label(
$this->rc->output->add_label(
'password.nopassword',
'password.nopassword',
'password.nocurpassword',
'password.nocurpassword',
'password.passwordinconsistency'
'password.passwordinconsistency'
);
);
$form_disabled = $rcmail ->config->get('password_disabled');
$form_disabled = $this-> rc->config->get('password_disabled');
$rcmail ->output->set_env('product_name', $rcmail ->config->get('product_name'));
$this-> rc->output->set_env('product_name', $this-> rc->config->get('product_name'));
$rcmail ->output->set_env('password_disabled', !empty($form_disabled));
$this-> rc->output->set_env('password_disabled', !empty($form_disabled));
$table = new html_table(array('cols' => 2, 'class' => 'propform'));
$table = new html_table(array('cols' => 2, 'class' => 'propform'));
if ($rcmail ->config->get('password_confirm_current')) {
if ($this-> rc->config->get('password_confirm_current')) {
// show current password selection
// show current password selection
$field_id = 'curpasswd';
$field_id = 'curpasswd';
$input_curpasswd = new html_passwordfield(array(
$input_curpasswd = new html_passwordfield(array(
@ -274,7 +272,7 @@ class password extends rcube_plugin
$rules = '';
$rules = '';
$required_length = intval($rcmail ->config->get('password_minimum_length'));
$required_length = intval($this-> rc->config->get('password_minimum_length'));
if ($required_length > 0) {
if ($required_length > 0) {
$rules .= html::tag('li', array('class' => 'required-length'), $this->gettext(array(
$rules .= html::tag('li', array('class' => 'required-length'), $this->gettext(array(
'name' => 'passwordshort',
'name' => 'passwordshort',
@ -282,7 +280,7 @@ class password extends rcube_plugin
)));
)));
}
}
if ($rcmail->config->get('password_check_strength') & & ($ msgs = $this->_strength_rules() )) {
if ($msgs = $this->_strength_rules()) {
foreach ($msgs as $msg) {
foreach ($msgs as $msg) {
$rules .= html::tag('li', array('class' => 'strength-rule'), $msg);
$rules .= html::tag('li', array('class' => 'strength-rule'), $msg);
}
}
@ -298,18 +296,18 @@ class password extends rcube_plugin
$disabled_msg = html::div(array('class' => 'boxwarning', 'id' => 'password-notice'), $disabled_msg);
$disabled_msg = html::div(array('class' => 'boxwarning', 'id' => 'password-notice'), $disabled_msg);
}
}
$submit_button = $rcmail ->output->button(array(
$submit_button = $this-> rc->output->button(array(
'command' => 'plugin.password-save',
'command' => 'plugin.password-save',
'class' => 'button mainaction submit',
'class' => 'button mainaction submit',
'label' => 'save',
'label' => 'save',
));
));
$form_buttons = html::p(array('class' => 'formbuttons footerleft'), $submit_button);
$form_buttons = html::p(array('class' => 'formbuttons footerleft'), $submit_button);
$rcmail ->output->add_gui_object('passform', 'password-form');
$this-> rc->output->add_gui_object('passform', 'password-form');
$this->include_script('password.js');
$this->include_script('password.js');
$form = $rcmail ->output->form_tag(array(
$form = $this-> rc->output->form_tag(array(
'id' => 'password-form',
'id' => 'password-form',
'name' => 'password-form',
'name' => 'password-form',
'method' => 'post',
'method' => 'post',
@ -350,15 +348,10 @@ class password extends rcube_plugin
private function _strength_rules()
private function _strength_rules()
{
{
$driver = $this->_load_driver('strength');
if (($driver = $this->_load_driver('strength')) & & method_exists($driver, 'strength_rules')) {
if (!$driver) {
$result = null;
}
else if (method_exists($driver, 'strength_rules')) {
$result = $driver->strength_rules();
$result = $driver->strength_rules();
}
}
else {
else if ($this->rc->config->get('password_minimum_score') > 1) {
$result = $this->gettext('passwordweak');
$result = $this->gettext('passwordweak');
}
}
@ -371,17 +364,22 @@ class password extends rcube_plugin
private function _check_strength($passwd)
private function _check_strength($passwd)
{
{
$driver = $this->_load_driver('strength ');
$min_score = $this->rc->config->get('password_minimum_score ');
if (!$driver ) {
if (!$min_score ) {
return $this->gettext('internalerror') ;
return;
}
}
if (method_exists($driver, 'check_strength')) {
if (($driver = $this->_load_driver('strength')) & & method_exists($driver, 'check_strength')) {
return $driver->check_strength($passwd);
list($score, $reason) = $driver->check_strength($passwd);
}
else {
$score = (!preg_match("/[0-9]/", $passwd) || !preg_match("/[^A-Za-z0-9]/", $passwd)) ? 1 : 5;
}
}
return (!preg_match("/[0-9]/", $passwd) || !preg_match("/[^A-Za-z0-9]/", $passwd)) ? $this->gettext('passwordweak') : null;
if ($score < $min_score) {
return $this->gettext('passwordtooweak') . (!empty($reason) ? " $reason" : '');
}
}
}
private function _save($curpass, $passwd)
private function _save($curpass, $passwd)
@ -427,8 +425,8 @@ class password extends rcube_plugin
private function _load_driver($type = 'password')
private function _load_driver($type = 'password')
{
{
if (!($type & & $driver = rcmail::get_instance() ->config->get('password_' . $type . '_driver'))) {
if (!($type & & $driver = $this->rc ->config->get('password_' . $type . '_driver'))) {
$driver = rcmail::get_instance() ->config->get('password_driver', 'sql');
$driver = $this->rc ->config->get('password_driver', 'sql');
}
}
if (!$this->drivers[$type]) {
if (!$this->drivers[$type]) {
@ -472,8 +470,7 @@ class password extends rcube_plugin
function login_after($args)
function login_after($args)
{
{
if ($this->newuser & & $this->check_host_login_exceptions()) {
if ($this->newuser & & $this->check_host_login_exceptions()) {
$rcmail = rcmail::get_instance();
$this->rc->user->save_prefs(array('newuserpassword' => true));
$rcmail->user->save_prefs(array('newuserpassword' => true));
$args['_task'] = 'settings';
$args['_task'] = 'settings';
$args['_action'] = 'plugin.password';
$args['_action'] = 'plugin.password';
@ -486,16 +483,14 @@ class password extends rcube_plugin
// Check if host and login is allowed to change the password, false = not allowed, true = not allowed
// Check if host and login is allowed to change the password, false = not allowed, true = not allowed
private function check_host_login_exceptions()
private function check_host_login_exceptions()
{
{
$rcmail = rcmail::get_instance();
// Host exceptions
// Host exceptions
$hosts = $rcmail ->config->get('password_hosts');
$hosts = $this->rc->config->get('password_hosts');
if (!empty($hosts) & & !in_array($_SESSION['storage_host'], (array) $hosts)) {
if (!empty($hosts) & & !in_array($_SESSION['storage_host'], (array) $hosts)) {
return false;
return false;
}
}
// Login exceptions
// Login exceptions
if ($exceptions = $rcmail ->config->get('password_login_exceptions')) {
if ($exceptions = $this-> rc->config->get('password_login_exceptions')) {
$exceptions = array_map('trim', (array) $exceptions);
$exceptions = array_map('trim', (array) $exceptions);
$exceptions = array_filter($exceptions);
$exceptions = array_filter($exceptions);
$username = $_SESSION['username'];
$username = $_SESSION['username'];