diff --git a/CHANGELOG b/CHANGELOG index d1ffacc6d..0e6983073 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Password: Added LDAP PPolicy driver (#5364) - Implement separate action to mark all messages in a folder as \Seen (#5006) - Implement marking as \Seen in all folders or in a folder and its subfolders (#5076) - Archive: Don't reload messages list when it's not needed (#5225) diff --git a/plugins/password/drivers/ldap_ppolicy.php b/plugins/password/drivers/ldap_ppolicy.php index 667be2f4f..c62a873bd 100644 --- a/plugins/password/drivers/ldap_ppolicy.php +++ b/plugins/password/drivers/ldap_ppolicy.php @@ -6,95 +6,91 @@ * Driver that adds functionality to change the user password via * the 'change_ldap_pass.pl' command respecting password policy (history) in LDAP. * - * * @version 1.0 * @author Zbigniew Szmyd * - */ class rcube_ldap_ppolicy_password { public function save($currpass, $newpass) { - $rcmail = rcmail::get_instance(); - $this->debug = $rcmail->config->get('ldap_debug'); - - $cmd = $rcmail->config->get('password_ldap_ppolicy_cmd'); + $rcmail = rcmail::get_instance(); + $this->debug = $rcmail->config->get('ldap_debug'); + + $cmd = $rcmail->config->get('password_ldap_ppolicy_cmd'); $uri = $rcmail->config->get('password_ldap_ppolicy_uri'); - $baseDN = $rcmail->config->get('password_ldap_ppolicy_basedn'); + $baseDN = $rcmail->config->get('password_ldap_ppolicy_basedn'); $filter = $rcmail->config->get('password_ldap_ppolicy_search_filter'); $bindDN = $rcmail->config->get('password_ldap_ppolicy_searchDN'); $bindPW = $rcmail->config->get('password_ldap_ppolicy_searchPW'); $cafile = $rcmail->config->get('password_ldap_ppolicy_cafile'); - $log_dir = $rcmail->config->get('log_dir'); - - if (empty($log_dir)) { - $log_dir = RCUBE_INSTALL_PATH . 'logs'; - } - - // try to open specific log file for writing - $logfile = $log_dir.'/password_ldap_ppolicy.err'; - + $log_dir = $rcmail->config->get('log_dir'); + + if (empty($log_dir)) { + $log_dir = RCUBE_INSTALL_PATH . 'logs'; + } + + // try to open specific log file for writing + $logfile = $log_dir.'/password_ldap_ppolicy.err'; + $descriptorspec = array( - 0 => array("pipe", "r"), // stdin is a pipe that the child will read from - 1 => array("pipe", "w"), // stdout is a pipe that the child will write to - 2 => array("file", $logfile, "a") // stderr is a file to write to + 0 => array("pipe", "r"), // stdin is a pipe that the child will read from + 1 => array("pipe", "w"), // stdout is a pipe that the child will write to + 2 => array("file", $logfile, "a") // stderr is a file to write to ); - + $cmd = 'plugins/password/helpers/'. $cmd; $this->_debug("parameters:\ncmd:$cmd\nuri:$uri\nbaseDN:$baseDN\nfilter:$filter"); $process = proc_open($cmd, $descriptorspec, $pipes); - + if (is_resource($process)) { - // $pipes now looks like this: - // 0 => writeable handle connected to child stdin - // 1 => readable handle connected to child stdout - // Any error output will be appended to /tmp/error-output.txt - - fwrite($pipes[0], $uri."\n"); - fwrite($pipes[0], $baseDN."\n"); - fwrite($pipes[0], $filter."\n"); - fwrite($pipes[0], $bindDN."\n"); - fwrite($pipes[0], $bindPW."\n"); - fwrite($pipes[0], $_SESSION['username']."\n"); - fwrite($pipes[0], $currpass."\n"); - fwrite($pipes[0], $newpass."\n"); - fwrite($pipes[0], $cafile); - fclose($pipes[0]); - - $result = stream_get_contents($pipes[1]); - fclose($pipes[1]); - - $this->_debug('Result:'.$result); - - switch ($result) { - case "OK": - return PASSWORD_SUCCESS; - case "Password is in history of old passwords": - return PASSWORD_IN_HISTORY; - - case "Cannot connect to any server": - return PASSWORD_CONNECT_ERROR; - default: - rcube::raise_error(array( - 'code' => 600, - 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => $result - ), true, false); - } - - return PASSWORD_ERROR; - } + // $pipes now looks like this: + // 0 => writeable handle connected to child stdin + // 1 => readable handle connected to child stdout + // Any error output will be appended to /tmp/error-output.txt + + fwrite($pipes[0], $uri."\n"); + fwrite($pipes[0], $baseDN."\n"); + fwrite($pipes[0], $filter."\n"); + fwrite($pipes[0], $bindDN."\n"); + fwrite($pipes[0], $bindPW."\n"); + fwrite($pipes[0], $_SESSION['username']."\n"); + fwrite($pipes[0], $currpass."\n"); + fwrite($pipes[0], $newpass."\n"); + fwrite($pipes[0], $cafile); + fclose($pipes[0]); + + $result = stream_get_contents($pipes[1]); + fclose($pipes[1]); + + $this->_debug('Result:'.$result); + + switch ($result) { + case "OK": + return PASSWORD_SUCCESS; + case "Password is in history of old passwords": + return PASSWORD_IN_HISTORY; + case "Cannot connect to any server": + return PASSWORD_CONNECT_ERROR; + default: + rcube::raise_error(array( + 'code' => 600, + 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => $result + ), true, false); + } + + return PASSWORD_ERROR; + } } - + private function _debug($str) { - if ($this->debug) { - rcube::write_log('password_ldap_ppolicy', $str); - } + if ($this->debug) { + rcube::write_log('password_ldap_ppolicy', $str); + } } - } diff --git a/plugins/password/helpers/change_ldap_pass.pl b/plugins/password/helpers/change_ldap_pass.pl index 85c19ca76..c304ff84d 100644 --- a/plugins/password/helpers/change_ldap_pass.pl +++ b/plugins/password/helpers/change_ldap_pass.pl @@ -14,76 +14,74 @@ binmode(STDOUT, ':utf8'); my %PAR = (); if (my $param = shift @ARGV){ - print "Password change in LDAP\n\n"; - print "Run script without any parameter and pass the following data:\n"; - print "URI\nbaseDN\nFilter\nbindDN\nbindPW\nLogin\nuserPass\nnewPass\nCAfile\n"; - exit; + print "Password change in LDAP\n\n"; + print "Run script without any parameter and pass the following data:\n"; + print "URI\nbaseDN\nFilter\nbindDN\nbindPW\nLogin\nuserPass\nnewPass\nCAfile\n"; + exit; } foreach my $param ('uri','base','filter','binddn','bindpw','user','pass','new_pass','ca'){ - $PAR{$param} = <>; - $PAR{$param} =~ s/\r|\n//g; + $PAR{$param} = <>; + $PAR{$param} =~ s/\r|\n//g; } my @servers = split (/\s+/, $PAR{'uri'}); my $active_server = 0; my $ldap; -while ((my $serwer = shift @servers) && !($active_server)){ - my $ldap_uri = URI->new($serwer); - if ($ldap_uri->secure){ - $ldap = Net::LDAP->new($ldap_uri->as_string, - version => 3, - verify => 'require', - sslversion => 'tlsv1', - cafile => $PAR{'ca'}); - } else { - $ldap = Net::LDAP->new($ldap_uri->as_string, version => 3); - } - $active_server = 1 if ($ldap); +while ((my $serwer = shift @servers) && !($active_server)) { + my $ldap_uri = URI->new($serwer); + if ($ldap_uri->secure) { + $ldap = Net::LDAP->new($ldap_uri->as_string, + version => 3, + verify => 'require', + sslversion => 'tlsv1', + cafile => $PAR{'ca'}); + } else { + $ldap = Net::LDAP->new($ldap_uri->as_string, version => 3); + } + $active_server = 1 if ($ldap); } -if ($active_server){ - my $mesg = $ldap->bind( $PAR{'binddn'}, password => $PAR{'bindpw'} ); - if ($mesg->code != 0){ - print "Cannot login: ". $mesg->error; - } else { - # Wyszukanie usera wg filtra - $PAR{'filter'} =~ s/\%login/$PAR{'user'}/; - my @search_args = (base => $PAR{'base'}, - scope => 'sub', - filter => $PAR{'filter'}, - attrs => ['1.1'], - ); - my $result = $ldap->search( @search_args ); - if ($result->code){ - print $result->error; - } else { - my $count = $result->count; - if ($count == 1){ - my @users = $result->entries; - my $dn = $users[0]->dn(); - $result = $ldap->bind($dn, password => $PAR{'pass'}); - if ($result->code){ - print $result->error; - } else { - $result = $ldap->set_password( - newpasswd => $PAR{'new_pass'}, - ); - if ($result->code){ - print $result->error; - } else { - print "OK"; - } - } - } else { - print "User not found in LDAP\n" if $count == 0; - print "Found $count users\n"; - } - - } - } - $ldap->unbind(); +if ($active_server) { + my $mesg = $ldap->bind($PAR{'binddn'}, password => $PAR{'bindpw'}); + if ($mesg->code != 0) { + print "Cannot login: ". $mesg->error; + } else { + # Wyszukanie usera wg filtra + $PAR{'filter'} =~ s/\%login/$PAR{'user'}/; + my @search_args = ( + base => $PAR{'base'}, + scope => 'sub', + filter => $PAR{'filter'}, + attrs => ['1.1'], + ); + my $result = $ldap->search(@search_args); + if ($result->code) { + print $result->error; + } else { + my $count = $result->count; + if ($count == 1) { + my @users = $result->entries; + my $dn = $users[0]->dn(); + $result = $ldap->bind($dn, password => $PAR{'pass'}); + if ($result->code){ + print $result->error; + } else { + $result = $ldap->set_password(newpasswd => $PAR{'new_pass'}); + if ($result->code) { + print $result->error; + } else { + print "OK"; + } + } + } else { + print "User not found in LDAP\n" if $count == 0; + print "Found $count users\n"; + } + } + } + $ldap->unbind(); } else { - print "Cannot connect to any server"; + print "Cannot connect to any server"; }