diff --git a/plugins/password/drivers/ldap_ppolicy.php b/plugins/password/drivers/ldap_ppolicy.php new file mode 100644 index 000000000..b926734af --- /dev/null +++ b/plugins/password/drivers/ldap_ppolicy.php @@ -0,0 +1,93 @@ + + * + + */ + +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'); + $uri = $rcmail->config->get('password_ldap_uri'); + $baseDN = $rcmail->config->get('password_ldap_basedn'); + $filter = $rcmail->config->get('password_ldap_search_filter'); + $bindDN = $rcmail->config->get('password_ldap_searchDN'); + $bindPW = $rcmail->config->get('password_ldap_searchPW'); + $cafile = $rcmail->config->get('password_ldap_cafile'); + + $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", "/tmp/ppolicy_ldap.err", "a") // stderr is a file to write to + ); + + $cwd = 'plugins/password/drivers/'; + $cmd = $cwd.$cmd; + $this->_debug('CWD: '. $cwd); + $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; + } + } + + private function _debug($str) + { + if ($this->debug) { + rcube::write_log('ldap_ppolicy', $str); + } + } + +} diff --git a/plugins/password/helpers/change_ldap_pass.pl b/plugins/password/helpers/change_ldap_pass.pl new file mode 100644 index 000000000..85c19ca76 --- /dev/null +++ b/plugins/password/helpers/change_ldap_pass.pl @@ -0,0 +1,89 @@ +#!/usr/bin/perl +=pod +Script to change the LDAP password using the set_password method +to proper setting the password policy attributes +author: Zbigniew Szmyd (zbigniew.szmyd@linseco.pl) +version 1.0 2016-02-22 +=cut + +use Net::LDAP; +use Net::LDAP::Extension::SetPassword; +use URI; +use utf8; +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; +} + +foreach my $param ('uri','base','filter','binddn','bindpw','user','pass','new_pass','ca'){ + $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); +} + +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"; +}