Import initial du site depuis le serveur
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* chpasswd driver
|
||||
*
|
||||
* Driver that adds functionality to change the systems user password via
|
||||
* the 'chpasswd' command.
|
||||
*
|
||||
* For installation instructions please read the README file.
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Alex Cartwright <acartwright@mutinydesign.co.uk>
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_chpasswd_password
|
||||
{
|
||||
public function save($currpass, $newpass, $username)
|
||||
{
|
||||
$cmd = rcmail::get_instance()->config->get('password_chpasswd_cmd');
|
||||
|
||||
$handle = popen($cmd, "w");
|
||||
fwrite($handle, "$username:$newpass\n");
|
||||
|
||||
if (pclose($handle) == 0) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to execute $cmd"
|
||||
], true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* cPanel Password Driver
|
||||
*
|
||||
* It uses Cpanel's Webmail UAPI to change the users password.
|
||||
*
|
||||
* This driver has been tested successfully with Digital Pacific hosting.
|
||||
*
|
||||
* @author Maikel Linke <maikel@email.org.au>
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_cpanel_password
|
||||
{
|
||||
/**
|
||||
* Changes the user's password. It is called by password.php.
|
||||
* See "Driver API" README and password.php for the interface details.
|
||||
*
|
||||
* @param string $curpas Current (old) password
|
||||
* @param string $newpass New password
|
||||
*
|
||||
* @return int|array Error code or assoc array with 'code' and 'message', see
|
||||
* "Driver API" README and password.php
|
||||
*/
|
||||
public function save($curpas, $newpass)
|
||||
{
|
||||
$url = self::url();
|
||||
$user = password::username();
|
||||
$userpwd = "$user:$curpas";
|
||||
$data = [
|
||||
'email' => password::username('%l'),
|
||||
'password' => $newpass
|
||||
];
|
||||
|
||||
$response = $this->curl_auth_post($userpwd, $url, $data);
|
||||
|
||||
return self::decode_response($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the UAPI URL of the Email::passwd_pop function.
|
||||
*
|
||||
* @return string HTTPS URL
|
||||
*/
|
||||
public static function url()
|
||||
{
|
||||
$config = rcmail::get_instance()->config;
|
||||
$storage_host = $_SESSION['storage_host'];
|
||||
|
||||
$host = $config->get('password_cpanel_host', $storage_host);
|
||||
$port = $config->get('password_cpanel_port', 2096);
|
||||
|
||||
return "https://$host:$port/execute/Email/passwd_pop";
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a UAPI response to a password driver response.
|
||||
*
|
||||
* @param string $response JSON response by the Cpanel UAPI
|
||||
*
|
||||
* @return mixed Response code or array, see <code>save</code>
|
||||
*/
|
||||
public static function decode_response($response)
|
||||
{
|
||||
if (!$response) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
// $result should be `null` or `stdClass` object
|
||||
$result = json_decode($response);
|
||||
|
||||
// The UAPI may return HTML instead of JSON on missing authentication
|
||||
if ($result && isset($result->status) && $result->status === 1) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
if ($result && !empty($result->errors) && is_array($result->errors)) {
|
||||
return [
|
||||
'code' => PASSWORD_ERROR,
|
||||
'message' => $result->errors[0],
|
||||
];
|
||||
}
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post data to the given URL using basic authentication.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <code>
|
||||
* curl_auth_post('john:Secr3t', 'https://example.org', [
|
||||
* 'param' => 'value',
|
||||
* 'param' => 'value'
|
||||
* ]);
|
||||
* </code>
|
||||
*
|
||||
* @param string $userpwd User name and password separated by a colon
|
||||
* <code>:</code>
|
||||
* @param string $url The URL to post data to
|
||||
* @param array $postdata The data to post
|
||||
*
|
||||
* @return string|false The body of the reply, False on error
|
||||
*/
|
||||
private function curl_auth_post($userpwd, $url, $postdata)
|
||||
{
|
||||
$ch = curl_init();
|
||||
$postfields = http_build_query($postdata, '', '&');
|
||||
|
||||
// see http://php.net/manual/en/function.curl-setopt.php
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_BUFFERSIZE, 131072);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
|
||||
curl_setopt($ch, CURLOPT_USERPWD, $userpwd);
|
||||
|
||||
$result = curl_exec($ch);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($result === false) {
|
||||
rcube::raise_error("curl error: $error", true, false);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* DBMail Password Driver
|
||||
*
|
||||
* Driver that adds functionality to change the users DBMail password.
|
||||
* The code is derived from the Squirrelmail "Change SASL Password" Plugin
|
||||
* by Galen Johnson.
|
||||
*
|
||||
* It only works with dbmail-users on the same host where Roundcube runs
|
||||
* and requires shell access and gcc in order to compile the binary.
|
||||
*
|
||||
* For installation instructions please read the README file.
|
||||
*
|
||||
* @version 1.0
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_dbmail_password
|
||||
{
|
||||
function save($currpass, $newpass, $username)
|
||||
{
|
||||
$curdir = RCUBE_PLUGINS_DIR . 'password/helpers';
|
||||
$username = escapeshellarg($username);
|
||||
$password = escapeshellarg($newpass);
|
||||
$args = rcmail::get_instance()->config->get('password_dbmail_args', '');
|
||||
$command = "$curdir/chgdbmailusers -c $username -w $password $args";
|
||||
|
||||
exec($command, $output, $return_value);
|
||||
|
||||
if ($return_value == 0) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to execute $curdir/chgdbmailusers"
|
||||
], true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,456 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* DirectAdmin Password Driver
|
||||
*
|
||||
* Driver to change passwords via DirectAdmin Control Panel
|
||||
*
|
||||
* @version 2.2
|
||||
* @author Victor Benincasa <vbenincasa @ gmail.com>
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_directadmin_password
|
||||
{
|
||||
public function save($curpass, $passwd)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$Socket = new HTTPSocket;
|
||||
|
||||
$da_user = $_SESSION['username'];
|
||||
$da_curpass = $curpass;
|
||||
$da_newpass = $passwd;
|
||||
$da_host = $rcmail->config->get('password_directadmin_host');
|
||||
$da_port = $rcmail->config->get('password_directadmin_port');
|
||||
|
||||
if (strpos($da_user, '@') === false) {
|
||||
return ['code' => PASSWORD_ERROR, 'message' => 'Change the SYSTEM user password through control panel!'];
|
||||
}
|
||||
|
||||
$da_host = str_replace('%h', $_SESSION['imap_host'], $da_host);
|
||||
$da_host = str_replace('%d', $rcmail->user->get_username('domain'), $da_host);
|
||||
|
||||
$Socket->connect($da_host,$da_port);
|
||||
$Socket->set_method('POST');
|
||||
$Socket->query('/CMD_CHANGE_EMAIL_PASSWORD', [
|
||||
'email' => $da_user,
|
||||
'oldpassword' => $da_curpass,
|
||||
'password1' => $da_newpass,
|
||||
'password2' => $da_newpass,
|
||||
'api' => '1'
|
||||
]);
|
||||
|
||||
$response = $Socket->fetch_parsed_body();
|
||||
|
||||
//DEBUG
|
||||
//rcube::console("Password Plugin: [USER: $da_user] [HOST: $da_host] - Response: [SOCKET: ".$Socket->result_status_code."] [DA ERROR: ".strip_tags($response['error'])."] [TEXT: ".$response[text]."]");
|
||||
|
||||
if ($Socket->result_status_code != 200) {
|
||||
return ['code' => PASSWORD_CONNECT_ERROR, 'message' => $Socket->error[0]];
|
||||
}
|
||||
|
||||
if ($response['error'] == 1) {
|
||||
return ['code' => PASSWORD_ERROR, 'message' => strip_tags($response['text'])];
|
||||
}
|
||||
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Socket communication class.
|
||||
*
|
||||
* Originally designed for use with DirectAdmin's API, this class will fill any HTTP socket need.
|
||||
*
|
||||
* Very, very basic usage:
|
||||
* $Socket = new HTTPSocket;
|
||||
* echo $Socket->get('http://user:pass@somesite.com/somedir/some.file?query=string&this=that');
|
||||
*
|
||||
* @author Phi1 'l0rdphi1' Stier <l0rdphi1@liquenox.net>
|
||||
* @package HTTPSocket
|
||||
* @version 3.0.2
|
||||
*/
|
||||
class HTTPSocket
|
||||
{
|
||||
var $version = '3.0.2';
|
||||
|
||||
// all vars are private except $error, $query_cache, and $doFollowLocationHeader
|
||||
|
||||
var $method = 'GET';
|
||||
|
||||
var $remote_host;
|
||||
var $remote_port;
|
||||
var $remote_uname;
|
||||
var $remote_passwd;
|
||||
|
||||
var $result;
|
||||
var $result_header;
|
||||
var $result_body;
|
||||
var $result_status_code;
|
||||
|
||||
var $lastTransferSpeed;
|
||||
var $bind_host;
|
||||
var $error = [];
|
||||
var $warn = [];
|
||||
var $query_cache = [];
|
||||
var $doFollowLocationHeader = true;
|
||||
var $redirectURL;
|
||||
var $max_redirects = 5;
|
||||
var $ssl_setting_message = 'DirectAdmin appears to be using SSL. Change your script to connect to ssl://';
|
||||
var $extra_headers = [];
|
||||
|
||||
/**
|
||||
* Create server "connection".
|
||||
*
|
||||
*/
|
||||
function connect($host, $port = '')
|
||||
{
|
||||
if (!is_numeric($port)) {
|
||||
$port = 2222;
|
||||
}
|
||||
|
||||
$this->remote_host = $host;
|
||||
$this->remote_port = $port;
|
||||
}
|
||||
|
||||
function bind($ip = '')
|
||||
{
|
||||
if ($ip == '') {
|
||||
$ip = $_SERVER['SERVER_ADDR'];
|
||||
}
|
||||
|
||||
$this->bind_host = $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the method being used to communicate.
|
||||
*
|
||||
* @param string|null request method. supports GET, POST, and HEAD. default is GET
|
||||
*/
|
||||
function set_method($method = 'GET')
|
||||
{
|
||||
$this->method = strtoupper($method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a username and password.
|
||||
*
|
||||
* @param string|null username. default is null
|
||||
* @param string|null password. default is null
|
||||
*/
|
||||
function set_login($uname = '', $passwd = '')
|
||||
{
|
||||
if (strlen($uname) > 0) {
|
||||
$this->remote_uname = $uname;
|
||||
}
|
||||
|
||||
if (strlen($passwd) > 0) {
|
||||
$this->remote_passwd = $passwd;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the server
|
||||
*
|
||||
* @param string containing properly formatted server API. See DA API docs and examples. Http:// URLs O.K. too.
|
||||
* @param string|array query to pass to url
|
||||
*/
|
||||
function query($request, $content = '')
|
||||
{
|
||||
$this->error = $this->warn = [];
|
||||
$this->result_status_code = null;
|
||||
|
||||
$is_ssl = false;
|
||||
|
||||
// is our request a http:// ... ?
|
||||
if (preg_match('!^http://!i',$request) || preg_match('!^https://!i',$request)) {
|
||||
$location = parse_url($request);
|
||||
if (preg_match('!^https://!i',$request)) {
|
||||
$this->connect('https://'.$location['host'],$location['port']);
|
||||
}
|
||||
else {
|
||||
$this->connect('http://'.$location['host'],$location['port']);
|
||||
}
|
||||
|
||||
$this->set_login($location['user'], $location['pass']);
|
||||
|
||||
$request = $location['path'];
|
||||
|
||||
if ($content == '') {
|
||||
$content = $location['query'];
|
||||
}
|
||||
|
||||
if (strlen($request) < 1) {
|
||||
$request = '/';
|
||||
}
|
||||
}
|
||||
|
||||
if (preg_match('!^ssl://!i', $this->remote_host)) {
|
||||
$this->remote_host = 'https://'.substr($this->remote_host, 6);
|
||||
}
|
||||
|
||||
if (preg_match('!^tcp://!i', $this->remote_host)) {
|
||||
$this->remote_host = 'http://'.substr($this->remote_host, 6);
|
||||
}
|
||||
|
||||
if (preg_match('!^https://!i', $this->remote_host)) {
|
||||
$is_ssl = true;
|
||||
}
|
||||
|
||||
$array_headers = [
|
||||
'Host' => $this->remote_port == 80 ? $this->remote_host : "$this->remote_host:$this->remote_port",
|
||||
'Accept' => '*/*',
|
||||
'Connection' => 'Close'
|
||||
];
|
||||
|
||||
foreach ($this->extra_headers as $key => $value) {
|
||||
$array_headers[$key] = $value;
|
||||
}
|
||||
|
||||
$this->result = $this->result_header = $this->result_body = '';
|
||||
|
||||
// was content sent as an array? if so, turn it into a string
|
||||
if (is_array($content)) {
|
||||
$pairs = [];
|
||||
|
||||
foreach ($content as $key => $value) {
|
||||
$pairs[] = "$key=".urlencode($value);
|
||||
}
|
||||
|
||||
$content = join('&',$pairs);
|
||||
unset($pairs);
|
||||
}
|
||||
|
||||
$OK = true;
|
||||
|
||||
if ($this->method == 'GET') {
|
||||
$request .= '?'.$content;
|
||||
}
|
||||
|
||||
$ch = curl_init($this->remote_host.':'.$this->remote_port.$request);
|
||||
|
||||
if ($is_ssl) {
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //1
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //2
|
||||
//curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, "HTTPSocket/$this->version");
|
||||
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
|
||||
curl_setopt($ch, CURLOPT_LOW_SPEED_LIMIT, 512);
|
||||
curl_setopt($ch, CURLOPT_LOW_SPEED_TIME, 120);
|
||||
|
||||
// instance connection
|
||||
if ($this->bind_host) {
|
||||
curl_setopt($ch, CURLOPT_INTERFACE, $this->bind_host);
|
||||
}
|
||||
|
||||
// if we have a username and password, add the header
|
||||
if (isset($this->remote_uname) && isset($this->remote_passwd)) {
|
||||
curl_setopt($ch, CURLOPT_USERPWD, $this->remote_uname.':'.$this->remote_passwd);
|
||||
}
|
||||
|
||||
// for DA skins: if $this->remote_passwd is NULL, try to use the login key system
|
||||
if (isset($this->remote_uname) && $this->remote_passwd == NULL) {
|
||||
$array_headers['Cookie'] = "session={$_SERVER['SESSION_ID']}; key={$_SERVER['SESSION_KEY']}";
|
||||
}
|
||||
|
||||
// if method is POST, add content length & type headers
|
||||
if ($this->method == 'POST') {
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
|
||||
|
||||
//$array_headers['Content-type'] = 'application/x-www-form-urlencoded';
|
||||
$array_headers['Content-length'] = strlen($content);
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $array_headers);
|
||||
|
||||
if (!($this->result = curl_exec($ch))) {
|
||||
$this->error[] = curl_error($ch);
|
||||
$OK = false;
|
||||
}
|
||||
|
||||
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||
$this->result_header = substr($this->result, 0, $header_size);
|
||||
$this->result_body = substr($this->result, $header_size);
|
||||
$this->result_status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$this->lastTransferSpeed = curl_getinfo($ch, CURLINFO_SPEED_DOWNLOAD) / 1024;
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
$this->query_cache[] = $this->remote_host.':'.$this->remote_port.$request;
|
||||
|
||||
$headers = $this->fetch_header();
|
||||
|
||||
// did we get the full file?
|
||||
if (!empty($headers['content-length']) && $headers['content-length'] != strlen($this->result_body)) {
|
||||
$this->result_status_code = 206;
|
||||
}
|
||||
|
||||
// now, if we're being passed a location header, should we follow it?
|
||||
if ($this->doFollowLocationHeader) {
|
||||
//dont bother if we didn't even setup the script correctly
|
||||
if (isset($headers['x-use-https']) && $headers['x-use-https'] == 'yes') {
|
||||
die($this->ssl_setting_message);
|
||||
}
|
||||
|
||||
if (isset($headers['location'])) {
|
||||
if ($this->max_redirects <= 0) {
|
||||
die("Too many redirects on: ".$headers['location']);
|
||||
}
|
||||
|
||||
$this->max_redirects--;
|
||||
$this->redirectURL = $headers['location'];
|
||||
$this->query($headers['location'], $content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getTransferSpeed()
|
||||
{
|
||||
return $this->lastTransferSpeed;
|
||||
}
|
||||
|
||||
/**
|
||||
* The quick way to get a URL's content :)
|
||||
*
|
||||
* @param string $location URL
|
||||
* @param bool $asArray return as array? (like PHP's file() command)
|
||||
*
|
||||
* @return string result body
|
||||
*/
|
||||
function get($location, $asArray = false)
|
||||
{
|
||||
$this->query($location);
|
||||
|
||||
if ($this->get_status_code() == 200) {
|
||||
if ($asArray) {
|
||||
return preg_split("/\n/", $this->fetch_body());
|
||||
}
|
||||
|
||||
return $this->fetch_body();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last status code.
|
||||
* 200 = OK;
|
||||
* 403 = FORBIDDEN;
|
||||
* etc.
|
||||
*
|
||||
* @return int status code
|
||||
*/
|
||||
function get_status_code()
|
||||
{
|
||||
return $this->result_status_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a header, sent with the next query.
|
||||
*
|
||||
* @param string header name
|
||||
* @param string header value
|
||||
*/
|
||||
function add_header($key, $value)
|
||||
{
|
||||
$this->extra_headers[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any extra headers.
|
||||
*
|
||||
*/
|
||||
function clear_headers()
|
||||
{
|
||||
$this->extra_headers = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the result of a query.
|
||||
*
|
||||
* @return string result
|
||||
*/
|
||||
function fetch_result()
|
||||
{
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the header of result (stuff before body).
|
||||
*
|
||||
* @param string (optional) header to return
|
||||
* @return array result header
|
||||
*/
|
||||
function fetch_header($header = '')
|
||||
{
|
||||
$array_headers = preg_split("/\r\n/", $this->result_header);
|
||||
|
||||
$array_return = [0 => $array_headers[0]];
|
||||
unset($array_headers[0]);
|
||||
|
||||
foreach ($array_headers as $pair) {
|
||||
if ($pair == '' || $pair == "\r\n") continue;
|
||||
list($key,$value) = preg_split("/: /", $pair, 2);
|
||||
$array_return[strtolower($key)] = $value;
|
||||
}
|
||||
|
||||
if ($header != '') {
|
||||
return $array_return[strtolower($header)];
|
||||
}
|
||||
|
||||
return $array_return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the body of result (stuff after header).
|
||||
*
|
||||
* @return string result body
|
||||
*/
|
||||
function fetch_body()
|
||||
{
|
||||
return $this->result_body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return parsed body in array format.
|
||||
*
|
||||
* @return array result parsed
|
||||
*/
|
||||
function fetch_parsed_body()
|
||||
{
|
||||
parse_str($this->result_body, $x);
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a specific message on how to change the SSL setting, in the event that it's not set correctly.
|
||||
*/
|
||||
function set_ssl_setting_message($str)
|
||||
{
|
||||
$this->ssl_setting_message = $str;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* domainFACTORY Password Driver
|
||||
*
|
||||
* Driver to change passwords with the hosting provider domainFACTORY.
|
||||
* http://www.df.eu/
|
||||
*
|
||||
* @version 2.1
|
||||
* @author Till Krüss <me@tillkruess.com>
|
||||
* @link http://tillkruess.com/projects/roundcube/
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_domainfactory_password
|
||||
{
|
||||
function save($curpass, $passwd, $username)
|
||||
{
|
||||
if ($ch = curl_init()) {
|
||||
// initial login
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_URL => 'https://ssl.df.eu/chmail.php',
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => http_build_query([
|
||||
'login' => $username,
|
||||
'pwd' => $curpass,
|
||||
'action' => 'change'
|
||||
])
|
||||
]);
|
||||
|
||||
if ($result = curl_exec($ch)) {
|
||||
// login successful, get token!
|
||||
$postfields = [
|
||||
'pwd1' => $passwd,
|
||||
'pwd2' => $passwd,
|
||||
'action[update]' => 'Speichern'
|
||||
];
|
||||
|
||||
preg_match_all('~<input name="(.+?)" type="hidden" value="(.+?)">~i', $result, $fields);
|
||||
foreach ($fields[1] as $field_key => $field_name) {
|
||||
$postfields[$field_name] = $fields[2][$field_key];
|
||||
}
|
||||
|
||||
// change password
|
||||
$ch = curl_copy_handle($ch);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields));
|
||||
if ($result = curl_exec($ch)) {
|
||||
// has the password been changed?
|
||||
if (strpos($result, 'Einstellungen erfolgreich') !== false) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
// show error message(s) if possible
|
||||
if (strpos($result, '<div class="d-msg-text">') !== false) {
|
||||
preg_match_all('#<div class="d-msg-text">(.*?)</div>#s', $result, $errors);
|
||||
if (isset($errors[1])) {
|
||||
$error_message = '';
|
||||
foreach ($errors[1] as $error) {
|
||||
$error_message .= trim(rcube_charset::convert($error, 'ISO-8859-15')).' ';
|
||||
}
|
||||
return ['code' => PASSWORD_ERROR, 'message' => $error_message];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Dovecot passwdfile Password Driver
|
||||
*
|
||||
* Driver that adds functionality to change the passwords in dovecot v2 passwd-file files.
|
||||
* The code is derived from the Plugin examples by The Roundcube Dev Team
|
||||
*
|
||||
* On vanilla dovecot v2 environments, use the correct values for these config settings, too:
|
||||
*
|
||||
* $config['password_dovecot_passwdfile_path']: The path of your dovecot passwd-file '/path/to/filename'
|
||||
* $config['password_dovecotpw']: Full path and 'pw' command of doveadm binary - like '/usr/local/bin/doveadm pw'
|
||||
* $config['password_dovecotpw_method']: Dovecot hashing algo (http://wiki2.dovecot.org/Authentication/PasswordSchemes)
|
||||
* $config['password_dovecotpw_with_method']: True if you want the hashing algo as prefix in your passwd-file
|
||||
*
|
||||
* @version 1.1
|
||||
*
|
||||
* Copyright (C) 2017, hostNET Medien GmbH, www.hostnet.de
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_dovecot_passwdfile_password
|
||||
{
|
||||
public function save($currpass, $newpass, $username)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$mailuserfile = $rcmail->config->get('password_dovecot_passwdfile_path') ?: '/etc/mail/imap.passwd';
|
||||
|
||||
$password = password::hash_password($newpass);
|
||||
$username = escapeshellcmd($username); // FIXME: Do we need this?
|
||||
$content = '';
|
||||
|
||||
// read the entire mail user file
|
||||
$fp = fopen($mailuserfile, 'r');
|
||||
|
||||
if (empty($fp)) {
|
||||
rcube::raise_error([
|
||||
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to read password file $mailuserfile."
|
||||
],
|
||||
true, false
|
||||
);
|
||||
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
if (flock($fp, LOCK_EX)) {
|
||||
// Read the file and replace the user password
|
||||
while (($line = fgets($fp, 40960)) !== false) {
|
||||
if (strpos($line, "$username:") === 0) {
|
||||
$pos = strpos($line, ':', strlen("$username:") + 1);
|
||||
$line = "$username:$password" . substr($line, $pos);
|
||||
}
|
||||
|
||||
$content .= $line;
|
||||
}
|
||||
|
||||
// Write back the entire file
|
||||
if (file_put_contents($mailuserfile, $content)) {
|
||||
flock($fp, LOCK_UN);
|
||||
fclose($fp);
|
||||
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Password plugin: Failed to save file $mailuserfile."
|
||||
],
|
||||
true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* expect driver
|
||||
*
|
||||
* Driver that adds functionality to change the systems user password via
|
||||
* the 'expect' command.
|
||||
*
|
||||
* For installation instructions please read the README file.
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Andy Theuninck <gohanman@gmail.com)
|
||||
*
|
||||
* Based on chpasswd roundcubemail password driver by
|
||||
* @author Alex Cartwright <acartwright@mutinydesign.co.uk)
|
||||
* and expect horde passwd driver by
|
||||
* @author Gaudenz Steinlin <gaudenz@soziologie.ch>
|
||||
*
|
||||
* Configuration settings:
|
||||
* password_expect_bin => location of expect (e.g. /usr/bin/expect)
|
||||
* password_expect_script => path to "password-expect" file
|
||||
* password_expect_params => arguments for the expect script
|
||||
* see the password-expect file for details. This is probably
|
||||
* a good starting default:
|
||||
* -telnet -host localhost -output /tmp/passwd.log -log /tmp/passwd.log
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_expect_password
|
||||
{
|
||||
public function save($currpass, $newpass, $username)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$bin = $rcmail->config->get('password_expect_bin');
|
||||
$script = $rcmail->config->get('password_expect_script');
|
||||
$params = $rcmail->config->get('password_expect_params');
|
||||
|
||||
$cmd = $bin . ' -f ' . $script . ' -- ' . $params;
|
||||
$handle = popen($cmd, "w");
|
||||
fwrite($handle, "$username\n");
|
||||
fwrite($handle, "$currpass\n");
|
||||
fwrite($handle, "$newpass\n");
|
||||
|
||||
if (pclose($handle) == 0) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to execute $cmd"
|
||||
], true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Gearman Password Driver
|
||||
*
|
||||
* Payload is json string containing username, oldPassword and newPassword
|
||||
* Return value is a json string saying result: true if success.
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Mohammad Anwari <mdamt@mdamt.net>
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_gearman_password
|
||||
{
|
||||
function save($currpass, $newpass, $username)
|
||||
{
|
||||
if (extension_loaded('gearman')) {
|
||||
$rcmail = rcmail::get_instance();
|
||||
$payload = [
|
||||
'username' => $username,
|
||||
'oldPassword' => $currpass,
|
||||
'newPassword' => $newpass,
|
||||
];
|
||||
|
||||
$gmc = new GearmanClient();
|
||||
$gmc->addServer($rcmail->config->get('password_gearman_host', 'localhost'));
|
||||
|
||||
$result = $gmc->doNormal('setPassword', json_encode($payload));
|
||||
$success = json_decode($result);
|
||||
|
||||
if ($success && $success->result == 1) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Gearman authentication failed for user $username"
|
||||
], true, false
|
||||
);
|
||||
}
|
||||
else {
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: PECL Gearman module not loaded"
|
||||
], true, false
|
||||
);
|
||||
}
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* hMailserver password driver
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Roland 'rosali' Liebl <myroundcube@mail4us.net>
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_hmail_password
|
||||
{
|
||||
public function save($curpass, $passwd, $username)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
try {
|
||||
$remote = $rcmail->config->get('hmailserver_remote_dcom', false);
|
||||
if ($remote) {
|
||||
$obApp = new COM("hMailServer.Application", $rcmail->config->get('hmailserver_server'));
|
||||
}
|
||||
else {
|
||||
$obApp = new COM("hMailServer.Application");
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
rcube::write_log('errors', "Plugin password (hmail driver): " . trim(strip_tags($e->getMessage())));
|
||||
rcube::write_log('errors', "Plugin password (hmail driver): This problem is often caused by DCOM permissions not being set.");
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
if (strstr($username,'@')) {
|
||||
list(, $domain) = explode('@', $username);
|
||||
}
|
||||
else {
|
||||
$domain = $rcmail->config->get('username_domain',false);
|
||||
if (!$domain) {
|
||||
rcube::write_log('errors','Plugin password (hmail driver): $config[\'username_domain\'] is not defined.');
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
$username = $username . "@" . $domain;
|
||||
}
|
||||
|
||||
try {
|
||||
$obApp->Authenticate($username, $curpass);
|
||||
|
||||
$obDomain = $obApp->Domains->ItemByName($domain);
|
||||
$obAccount = $obDomain->Accounts->ItemByAddress($username);
|
||||
$obAccount->Password = $passwd;
|
||||
$obAccount->Save();
|
||||
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
rcube::write_log('errors', "Plugin password (hmail driver): " . trim(strip_tags($e->getMessage())));
|
||||
rcube::write_log('errors', "Plugin password (hmail driver): This problem is often caused by DCOM permissions not being set.");
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Roundcube password driver for generic HTTP APIs.
|
||||
*
|
||||
* This driver changes the e-mail password via any generic HTTP/HTTPS API.
|
||||
*
|
||||
* @author David Croft
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* Config variables:
|
||||
* $config['password_httpapi_url'] = 'https://passwordserver.example.org'; // required
|
||||
* $config['password_httpapi_method'] = 'POST'; // default
|
||||
* $config['password_httpapi_var_user'] = 'user'; // optional
|
||||
* $config['password_httpapi_var_curpass'] = 'curpass'; // optional
|
||||
* $config['password_httpapi_var_newpass'] = 'newpass'; // optional
|
||||
* $config['password_httpapi_expect'] = '/^ok$/i'; // optional
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_httpapi_password
|
||||
{
|
||||
/**
|
||||
* This method is called from roundcube to change the password
|
||||
*
|
||||
* roundcube already validated the old password so we just need to change it at this point
|
||||
*
|
||||
* @param string $curpass Current password
|
||||
* @param string $newpass New password
|
||||
* @param string $username Login username
|
||||
*
|
||||
* @return int PASSWORD_SUCCESS|PASSWORD_ERROR|PASSWORD_CONNECT_ERROR
|
||||
*/
|
||||
function save($curpass, $newpass, $username)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$client = password::get_http_client();
|
||||
|
||||
// Get configuration with defaults
|
||||
$url = $rcmail->config->get('password_httpapi_url');
|
||||
$method = $rcmail->config->get('password_httpapi_method', 'POST');
|
||||
$var_user = $rcmail->config->get('password_httpapi_var_user');
|
||||
$var_curpass = $rcmail->config->get('password_httpapi_var_curpass');
|
||||
$var_newpass = $rcmail->config->get('password_httpapi_var_newpass');
|
||||
$expect = $rcmail->config->get('password_httpapi_expect');
|
||||
|
||||
// Set the variables on the GET query string or POST vars
|
||||
$vars = [];
|
||||
|
||||
if ($var_user) {
|
||||
$vars[$var_user] = $username;
|
||||
}
|
||||
|
||||
if ($var_curpass) {
|
||||
$vars[$var_curpass] = $curpass;
|
||||
}
|
||||
|
||||
if ($var_newpass) {
|
||||
$vars[$var_newpass] = $newpass;
|
||||
}
|
||||
|
||||
$method = strtoupper($method);
|
||||
$params = [];
|
||||
|
||||
if ($method == 'POST') {
|
||||
$params['form_params'] = $vars;
|
||||
}
|
||||
else if ($method == 'GET') {
|
||||
$params['query'] = $vars;
|
||||
}
|
||||
else {
|
||||
rcube::raise_error([
|
||||
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Password plugin: Invalid httpapi method",
|
||||
],
|
||||
true, false
|
||||
);
|
||||
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $client->request($method, $url, $params);
|
||||
|
||||
$response_code = $response->getStatusCode();
|
||||
$result = $response->getBody();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
rcube::raise_error([
|
||||
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Password plugin: " . $e->getMessage()
|
||||
],
|
||||
true, false
|
||||
);
|
||||
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
// Non-2xx response codes mean the password change failed
|
||||
if ($response_code < 200 || $response_code > 299) {
|
||||
rcube::raise_error([
|
||||
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Password plugin: Unexpected response code {$response_code}: "
|
||||
. substr($result, 0, 1024)
|
||||
],
|
||||
true, false
|
||||
);
|
||||
|
||||
return ($response_code == 404 || $response_code > 499) ? PASSWORD_CONNECT_ERROR : PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
// If configured, check the body of the response
|
||||
if ($expect && !preg_match($expect, $result)) {
|
||||
rcube::raise_error([
|
||||
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Password plugin: Unexpected response body: " . substr($result, 0, 1024)
|
||||
],
|
||||
true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* kpasswd Driver
|
||||
*
|
||||
* Driver that adds functionality to change the systems user password via
|
||||
* the 'kpasswd' command.
|
||||
*
|
||||
* For installation instructions please read the README file.
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Peter Allgeyer <peter.allgeyer@salzburgresearch.at>
|
||||
*
|
||||
* Based on chpasswd roundcubemail password driver by
|
||||
* @author Alex Cartwright <acartwright@mutinydesign.co.uk>
|
||||
*/
|
||||
|
||||
class rcube_kpasswd_password
|
||||
{
|
||||
public function save($currpass, $newpass, $username)
|
||||
{
|
||||
$bin = rcmail::get_instance()->config->get('password_kpasswd_cmd', '/usr/bin/kpasswd');
|
||||
$cmd = $bin . ' ' . escapeshellarg($username) . ' 2>&1';
|
||||
|
||||
$handle = popen($cmd, "w");
|
||||
fwrite($handle, $currpass."\n");
|
||||
fwrite($handle, $newpass."\n");
|
||||
fwrite($handle, $newpass."\n");
|
||||
|
||||
if (pclose($handle) == 0) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to execute $cmd"
|
||||
], true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* LDAP Password Driver
|
||||
*
|
||||
* Driver for passwords stored in LDAP
|
||||
* This driver use the PEAR Net_LDAP2 class (http://pear.php.net/package/Net_LDAP2).
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Edouard MOREAU <edouard.moreau@ensma.fr>
|
||||
*
|
||||
* method hashPassword based on code from the phpLDAPadmin development team (http://phpldapadmin.sourceforge.net/).
|
||||
* method randomSalt based on code from the phpLDAPadmin development team (http://phpldapadmin.sourceforge.net/).
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_ldap_password
|
||||
{
|
||||
public function save($curpass, $passwd)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
require_once 'Net/LDAP2.php';
|
||||
require_once __DIR__ . '/ldap_simple.php';
|
||||
|
||||
// Building user DN
|
||||
if ($userDN = $rcmail->config->get('password_ldap_userDN_mask')) {
|
||||
$userDN = rcube_ldap_simple_password::substitute_vars($userDN);
|
||||
}
|
||||
else {
|
||||
$userDN = $this->search_userdn($rcmail);
|
||||
}
|
||||
|
||||
if (empty($userDN)) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
// Connection Method
|
||||
switch ($rcmail->config->get('password_ldap_method')) {
|
||||
case 'admin':
|
||||
$binddn = $rcmail->config->get('password_ldap_adminDN');
|
||||
$bindpw = $rcmail->config->get('password_ldap_adminPW');
|
||||
break;
|
||||
case 'user':
|
||||
default:
|
||||
$binddn = $userDN;
|
||||
$bindpw = $curpass;
|
||||
break;
|
||||
}
|
||||
|
||||
// Configuration array
|
||||
$ldapConfig = [
|
||||
'binddn' => $binddn,
|
||||
'bindpw' => $bindpw,
|
||||
'basedn' => $rcmail->config->get('password_ldap_basedn'),
|
||||
'host' => $rcmail->config->get('password_ldap_host', 'localhost'),
|
||||
'port' => $rcmail->config->get('password_ldap_port', '389'),
|
||||
'starttls' => $rcmail->config->get('password_ldap_starttls'),
|
||||
'version' => $rcmail->config->get('password_ldap_version', '3'),
|
||||
];
|
||||
|
||||
// Connecting using the configuration array
|
||||
$ldap = Net_LDAP2::connect($ldapConfig);
|
||||
|
||||
// Checking for connection error
|
||||
if (is_a($ldap, 'PEAR_Error')) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
$force = $rcmail->config->get('password_ldap_force_replace', true);
|
||||
$pwattr = $rcmail->config->get('password_ldap_pwattr', 'userPassword');
|
||||
$lchattr = $rcmail->config->get('password_ldap_lchattr');
|
||||
$smbpwattr = $rcmail->config->get('password_ldap_samba_pwattr');
|
||||
$smblchattr = $rcmail->config->get('password_ldap_samba_lchattr');
|
||||
$samba = $rcmail->config->get('password_ldap_samba');
|
||||
$encodage = $rcmail->config->get('password_ldap_encodage', 'md5-crypt');
|
||||
|
||||
// Support multiple userPassword values where desired.
|
||||
// multiple encodings can be specified separated by '+' (e.g. "cram-md5+ssha")
|
||||
$encodages = explode('+', $encodage);
|
||||
$crypted_pass = [];
|
||||
|
||||
foreach ($encodages as $enc) {
|
||||
if ($cpw = password::hash_password($passwd, $enc)) {
|
||||
$crypted_pass[] = $cpw;
|
||||
}
|
||||
}
|
||||
|
||||
// Support password_ldap_samba option for backward compat.
|
||||
if ($samba && !$smbpwattr) {
|
||||
$smbpwattr = 'sambaNTPassword';
|
||||
$smblchattr = 'sambaPwdLastSet';
|
||||
}
|
||||
|
||||
// Crypt new password
|
||||
if (empty($crypted_pass)) {
|
||||
return PASSWORD_CRYPT_ERROR;
|
||||
}
|
||||
|
||||
// Crypt new samba password
|
||||
if ($smbpwattr && !($samba_pass = password::hash_password($passwd, 'samba'))) {
|
||||
return PASSWORD_CRYPT_ERROR;
|
||||
}
|
||||
|
||||
// Writing new crypted password to LDAP
|
||||
$userEntry = $ldap->getEntry($userDN);
|
||||
if (Net_LDAP2::isError($userEntry)) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
if (!$userEntry->replace([$pwattr => $crypted_pass], $force)) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
// Updating PasswordLastChange Attribute if desired
|
||||
if ($lchattr) {
|
||||
$current_day = (int) (time() / 86400);
|
||||
if (!$userEntry->replace([$lchattr => $current_day], $force)) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Update Samba password and last change fields
|
||||
if ($smbpwattr) {
|
||||
$userEntry->replace([$smbpwattr => $samba_pass], $force);
|
||||
}
|
||||
// Update Samba password last change field
|
||||
if ($smblchattr) {
|
||||
$userEntry->replace([$smblchattr => time()], $force);
|
||||
}
|
||||
|
||||
if (Net_LDAP2::isError($userEntry->update())) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
// All done, no error
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind with searchDN and searchPW and search for the user's DN.
|
||||
* Use search_base and search_filter defined in config file.
|
||||
* Return the found DN.
|
||||
*/
|
||||
function search_userdn($rcmail)
|
||||
{
|
||||
$binddn = $rcmail->config->get('password_ldap_searchDN');
|
||||
$bindpw = $rcmail->config->get('password_ldap_searchPW');
|
||||
|
||||
$ldapConfig = [
|
||||
'basedn' => $rcmail->config->get('password_ldap_basedn'),
|
||||
'host' => $rcmail->config->get('password_ldap_host', 'localhost'),
|
||||
'port' => $rcmail->config->get('password_ldap_port', '389'),
|
||||
'starttls' => $rcmail->config->get('password_ldap_starttls'),
|
||||
'version' => $rcmail->config->get('password_ldap_version', '3'),
|
||||
];
|
||||
|
||||
// allow anonymous searches
|
||||
if (!empty($binddn)) {
|
||||
$ldapConfig['binddn'] = $binddn;
|
||||
$ldapConfig['bindpw'] = $bindpw;
|
||||
}
|
||||
|
||||
$ldap = Net_LDAP2::connect($ldapConfig);
|
||||
|
||||
if (is_a($ldap, 'PEAR_Error')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$base = rcube_ldap_simple_password::substitute_vars($rcmail->config->get('password_ldap_search_base'));
|
||||
$filter = rcube_ldap_simple_password::substitute_vars($rcmail->config->get('password_ldap_search_filter'));
|
||||
$options = [
|
||||
'scope' => 'sub',
|
||||
'attributes' => [],
|
||||
];
|
||||
|
||||
$result = $ldap->search($base, $filter, $options);
|
||||
|
||||
if (is_a($result, 'PEAR_Error') || ($result->count() != 1)) {
|
||||
$ldap->done();
|
||||
return '';
|
||||
}
|
||||
|
||||
$userDN = $result->current()->dn();
|
||||
$ldap->done();
|
||||
|
||||
return $userDN;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* LDAP - Password Modify Extended Operation Driver
|
||||
*
|
||||
* Driver for passwords stored in LDAP
|
||||
* This driver is based on Simple LDAP Password Driver, but uses
|
||||
* Password Modify Extended Operation
|
||||
* PHP >= 7.2 required
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Peter Kubica <peter@kubica.ch>
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/ldap_simple.php';
|
||||
|
||||
class rcube_ldap_exop_password extends rcube_ldap_simple_password
|
||||
{
|
||||
function save($curpass, $passwd)
|
||||
{
|
||||
if (!function_exists('ldap_exop_passwd')) {
|
||||
rcube::raise_error([
|
||||
'code' => 100, 'type' => 'ldap',
|
||||
'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "ldap_exop_passwd not supported"
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
// Connect and bind
|
||||
$ret = $this->connect($curpass);
|
||||
if ($ret !== true) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if (!ldap_exop_passwd($this->conn, $this->user, $curpass, $passwd)) {
|
||||
$this->_debug("S: ".ldap_error($this->conn));
|
||||
|
||||
$errno = ldap_errno($this->conn);
|
||||
|
||||
ldap_unbind($this->conn);
|
||||
|
||||
if ($errno == 0x13) {
|
||||
return PASSWORD_CONSTRAINT_VIOLATION;
|
||||
}
|
||||
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
$this->_debug("S: OK");
|
||||
|
||||
// All done, no error
|
||||
ldap_unbind($this->conn);
|
||||
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ldap_ppolicy driver
|
||||
*
|
||||
* 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 <zbigniew.szmyd@linseco.pl>
|
||||
*/
|
||||
|
||||
class rcube_ldap_ppolicy_password
|
||||
{
|
||||
protected $debug = false;
|
||||
|
||||
public function save($currpass, $newpass, $username)
|
||||
{
|
||||
$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');
|
||||
$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';
|
||||
}
|
||||
|
||||
$descriptorspec = [
|
||||
0 => ["pipe", "r"], // stdin is a pipe that the child will read from
|
||||
1 => ["pipe", "w"], // stdout is a pipe that the child will write to
|
||||
2 => ["pipe", "w"] // stderr is a pipe that the child will write to
|
||||
];
|
||||
|
||||
$cmd = 'plugins/password/helpers/'. $cmd;
|
||||
|
||||
$this->_debug('Policy request: ' . json_encode([
|
||||
'user' => $username,
|
||||
'cmd' => $cmd,
|
||||
'uri' => $uri,
|
||||
'baseDN' => $baseDN,
|
||||
'filter' => $filter,
|
||||
]));
|
||||
|
||||
$process = proc_open($cmd, $descriptorspec, $pipes);
|
||||
|
||||
if ($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], $username."\n");
|
||||
fwrite($pipes[0], $currpass."\n");
|
||||
fwrite($pipes[0], $newpass."\n");
|
||||
fwrite($pipes[0], $cafile);
|
||||
|
||||
$result = trim(stream_get_contents($pipes[1]));
|
||||
$stderr = trim(stream_get_contents($pipes[2]));
|
||||
|
||||
fclose($pipes[0]);
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
proc_close($process);
|
||||
|
||||
$this->_debug('Policy 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([
|
||||
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Password plugin: Failed to execute command: $cmd. Output: $result. Error: $stderr"
|
||||
], true, false);
|
||||
}
|
||||
}
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
private function _debug($str)
|
||||
{
|
||||
if ($this->debug) {
|
||||
rcube::write_log('ldap', $str);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Simple LDAP Password Driver
|
||||
*
|
||||
* Driver for passwords stored in LDAP
|
||||
* This driver is based on Edouard's LDAP Password Driver, but does not
|
||||
* require PEAR's Net_LDAP2 to be installed
|
||||
*
|
||||
* @version 2.1
|
||||
* @author Wout Decre <wout@canodus.be>
|
||||
* @author Aleksander Machniak <machniak@kolabsys.com>
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_ldap_simple_password
|
||||
{
|
||||
protected $debug = false;
|
||||
protected $user;
|
||||
protected $conn;
|
||||
|
||||
|
||||
public function save($curpass, $passwd)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
$lchattr = $rcmail->config->get('password_ldap_lchattr');
|
||||
$pwattr = $rcmail->config->get('password_ldap_pwattr', 'userPassword');
|
||||
$smbpwattr = $rcmail->config->get('password_ldap_samba_pwattr');
|
||||
$smblchattr = $rcmail->config->get('password_ldap_samba_lchattr');
|
||||
$samba = $rcmail->config->get('password_ldap_samba');
|
||||
$pass_mode = $rcmail->config->get('password_ldap_encodage', 'md5-crypt');
|
||||
$crypted_pass = password::hash_password($passwd, $pass_mode);
|
||||
|
||||
// Support password_ldap_samba option for backward compat.
|
||||
if ($samba && !$smbpwattr) {
|
||||
$smbpwattr = 'sambaNTPassword';
|
||||
$smblchattr = 'sambaPwdLastSet';
|
||||
}
|
||||
|
||||
// Crypt new password
|
||||
if (!$crypted_pass) {
|
||||
return PASSWORD_CRYPT_ERROR;
|
||||
}
|
||||
|
||||
// Crypt new Samba password
|
||||
if ($smbpwattr && !($samba_pass = password::hash_password($passwd, 'samba'))) {
|
||||
return PASSWORD_CRYPT_ERROR;
|
||||
}
|
||||
|
||||
// Connect and bind
|
||||
$ret = $this->connect($curpass);
|
||||
if ($ret !== true) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$entry[$pwattr] = $crypted_pass;
|
||||
|
||||
// Update PasswordLastChange Attribute if desired
|
||||
if ($lchattr) {
|
||||
$entry[$lchattr] = (int)(time() / 86400);
|
||||
}
|
||||
|
||||
// Update Samba password
|
||||
if ($smbpwattr) {
|
||||
$entry[$smbpwattr] = $samba_pass;
|
||||
}
|
||||
|
||||
// Update Samba password last change
|
||||
if ($smblchattr) {
|
||||
$entry[$smblchattr] = time();
|
||||
}
|
||||
|
||||
$this->_debug("C: Modify {$this->user}: " . print_r($entry, true));
|
||||
|
||||
if (!ldap_modify($this->conn, $this->user, $entry)) {
|
||||
$this->_debug("S: ".ldap_error($this->conn));
|
||||
|
||||
$errno = ldap_errno($this->conn);
|
||||
|
||||
ldap_unbind($this->conn);
|
||||
|
||||
if ($errno == 0x13) {
|
||||
return PASSWORD_CONSTRAINT_VIOLATION;
|
||||
}
|
||||
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
$this->_debug("S: OK");
|
||||
|
||||
// All done, no error
|
||||
ldap_unbind($this->conn);
|
||||
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect and bind to LDAP server
|
||||
*/
|
||||
function connect($curpass)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
$this->debug = $rcmail->config->get('ldap_debug');
|
||||
$ldap_host = $rcmail->config->get('password_ldap_host', 'localhost');
|
||||
$ldap_port = $rcmail->config->get('password_ldap_port', '389');
|
||||
$ldap_uri = $this->_host2uri($ldap_host, $ldap_port);
|
||||
|
||||
$this->_debug("C: Connect [{$ldap_uri}]");
|
||||
|
||||
// Connect
|
||||
if (!($ds = ldap_connect($ldap_uri))) {
|
||||
$this->_debug("S: NOT OK");
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 100, 'type' => 'ldap',
|
||||
'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Could not connect to LDAP server"
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
$this->_debug("S: OK");
|
||||
|
||||
// Set protocol version
|
||||
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION,
|
||||
$rcmail->config->get('password_ldap_version', '3'));
|
||||
|
||||
// Start TLS
|
||||
if ($rcmail->config->get('password_ldap_starttls')) {
|
||||
if (!ldap_start_tls($ds)) {
|
||||
ldap_unbind($ds);
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// other plugins might want to modify user DN
|
||||
$plugin = $rcmail->plugins->exec_hook('password_ldap_bind',
|
||||
['user_dn' => '', 'conn' => $ds]
|
||||
);
|
||||
|
||||
// Build user DN
|
||||
if (!empty($plugin['user_dn'])) {
|
||||
$user_dn = $plugin['user_dn'];
|
||||
}
|
||||
else if ($user_dn = $rcmail->config->get('password_ldap_userDN_mask')) {
|
||||
$user_dn = self::substitute_vars($user_dn);
|
||||
}
|
||||
else {
|
||||
$user_dn = $this->search_userdn($rcmail, $ds);
|
||||
}
|
||||
|
||||
if (empty($user_dn)) {
|
||||
ldap_unbind($ds);
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
// Connection method
|
||||
switch ($rcmail->config->get('password_ldap_method')) {
|
||||
case 'admin':
|
||||
$binddn = $rcmail->config->get('password_ldap_adminDN');
|
||||
$bindpw = $rcmail->config->get('password_ldap_adminPW');
|
||||
break;
|
||||
case 'user':
|
||||
default:
|
||||
$binddn = $user_dn;
|
||||
$bindpw = $curpass;
|
||||
break;
|
||||
}
|
||||
|
||||
$this->_debug("C: Bind $binddn, pass: **** [" . strlen($bindpw) . "]");
|
||||
|
||||
// Bind
|
||||
if (!ldap_bind($ds, $binddn, $bindpw)) {
|
||||
$this->_debug("S: ".ldap_error($ds));
|
||||
|
||||
ldap_unbind($ds);
|
||||
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
$this->_debug("S: OK");
|
||||
|
||||
$this->conn = $ds;
|
||||
$this->user = $user_dn;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind with searchDN and searchPW and search for the user's DN
|
||||
* Use search_base and search_filter defined in config file
|
||||
* Return the found DN
|
||||
*/
|
||||
function search_userdn($rcmail, $ds)
|
||||
{
|
||||
$search_user = $rcmail->config->get('password_ldap_searchDN');
|
||||
$search_pass = $rcmail->config->get('password_ldap_searchPW');
|
||||
$search_base = $rcmail->config->get('password_ldap_search_base');
|
||||
$search_filter = $rcmail->config->get('password_ldap_search_filter');
|
||||
|
||||
if (empty($search_filter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->_debug("C: Bind " . ($search_user ? $search_user : '[anonymous]'));
|
||||
|
||||
// Bind
|
||||
if (!ldap_bind($ds, $search_user, $search_pass)) {
|
||||
$this->_debug("S: ".ldap_error($ds));
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->_debug("S: OK");
|
||||
|
||||
$search_base = self::substitute_vars($search_base);
|
||||
$search_filter = self::substitute_vars($search_filter);
|
||||
|
||||
$this->_debug("C: Search $search_base for $search_filter");
|
||||
|
||||
// Search for the DN
|
||||
if (!($sr = ldap_search($ds, $search_base, $search_filter))) {
|
||||
$this->_debug("S: ".ldap_error($ds));
|
||||
return false;
|
||||
}
|
||||
|
||||
$found = ldap_count_entries($ds, $sr);
|
||||
|
||||
$this->_debug("S: OK [found $found records]");
|
||||
|
||||
// If no or more entries were found, return false
|
||||
if ($found != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ldap_get_dn($ds, ldap_first_entry($ds, $sr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitute %login, %name, %domain, %dc in $str
|
||||
* See plugin config for details
|
||||
*/
|
||||
public static function substitute_vars($str)
|
||||
{
|
||||
$str = str_replace('%login', $_SESSION['username'], $str);
|
||||
$str = str_replace('%l', $_SESSION['username'], $str);
|
||||
|
||||
$parts = explode('@', $_SESSION['username']);
|
||||
|
||||
if (count($parts) == 2) {
|
||||
$dc = 'dc='.strtr($parts[1], ['.' => ',dc=']); // hierarchal domain string
|
||||
|
||||
$str = str_replace('%name', $parts[0], $str);
|
||||
$str = str_replace('%n', $parts[0], $str);
|
||||
$str = str_replace('%dc', $dc, $str);
|
||||
$str = str_replace('%domain', $parts[1], $str);
|
||||
$str = str_replace('%d', $parts[1], $str);
|
||||
}
|
||||
else if (count($parts) == 1) {
|
||||
$str = str_replace('%name', $parts[0], $str);
|
||||
$str = str_replace('%n', $parts[0], $str);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints debug info to the log
|
||||
*/
|
||||
protected function _debug($str)
|
||||
{
|
||||
if ($this->debug) {
|
||||
rcube::write_log('ldap', $str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert LDAP host/port into URI
|
||||
*/
|
||||
private static function _host2uri($host, $port = null)
|
||||
{
|
||||
if (stripos($host, 'ldapi://') === 0) {
|
||||
return $host;
|
||||
}
|
||||
|
||||
if (strpos($host, '://') === false) {
|
||||
$host = ($port == 636 ? 'ldaps' : 'ldap') . '://' . $host;
|
||||
}
|
||||
|
||||
if ($port && !preg_match('/:[0-9]+$/', $host)) {
|
||||
$host .= ':' . $port;
|
||||
}
|
||||
|
||||
return $host;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Mailcow Password Driver
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Lukas "Hexaris" Matula <hexaris@gbely.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* It is necessary to set the following variables in plugin/password/config.inc.php
|
||||
* $config['password_driver'] = 'mailcow';
|
||||
* $config['password_mailcow_api_host'] = '';
|
||||
* $config['password_mailcow_api_token'] = '';
|
||||
*/
|
||||
|
||||
class rcube_mailcow_password
|
||||
{
|
||||
function save($curpass, $passwd, $username)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
$host = $rcmail->config->get('password_mailcow_api_host');
|
||||
$token = $rcmail->config->get('password_mailcow_api_token');
|
||||
|
||||
try {
|
||||
$client = password::get_http_client();
|
||||
|
||||
$headers = [
|
||||
'X-API-Key' => $token,
|
||||
'accept' => 'application/json'
|
||||
];
|
||||
|
||||
$cowdata = [
|
||||
'attr' => [
|
||||
'password' => $passwd,
|
||||
'password2' => $passwd
|
||||
],
|
||||
'items' => [ $username ]
|
||||
];
|
||||
|
||||
if (!strpos($host, '://')) {
|
||||
$host = "https://{$host}";
|
||||
}
|
||||
|
||||
$response = $client->post("{$host}/api/v1/edit/mailbox", [
|
||||
'headers' => $headers,
|
||||
'json' => $cowdata
|
||||
]);
|
||||
|
||||
$cowreply = json_decode($response->getBody(),true);
|
||||
|
||||
if ($cowreply[0]['type'] == 'success') {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$result = $e->getMessage();
|
||||
}
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Password plugin: Problem with Mailcow API: $result",
|
||||
],
|
||||
true, false
|
||||
);
|
||||
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Mail-in-a-Box Driver
|
||||
*
|
||||
* Driver that adds functionality to change the user password via the
|
||||
* API endpoint of Mail-in-a-Box (https://mailinabox.email/).
|
||||
*
|
||||
* For installation instructions please read the README file. It requires
|
||||
* following parameters in configuration:
|
||||
*
|
||||
* - password_miab_username - name of the admin user used to access api
|
||||
* - password_miab_password - password of the admin user used to access api
|
||||
* - password_miab_url - the url to the control panel of Mail-in-a-Box
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Alexey Shtokalo <alexey@shtokalo.net>
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_miab_password
|
||||
{
|
||||
public function save($currpass, $newpass, $username)
|
||||
{
|
||||
$config = rcmail::get_instance()->config;
|
||||
$host = rtrim($config->get('password_miab_url'), '/') . '/mail/users/password';
|
||||
|
||||
try {
|
||||
$client = password::get_http_client();
|
||||
|
||||
$request = [
|
||||
'form_params' => [
|
||||
'email' => $username,
|
||||
'password' => $newpass,
|
||||
],
|
||||
'auth' => [
|
||||
$config->get('password_miab_user') ?: $username,
|
||||
$config->get('password_miab_pass') ?: $currpass,
|
||||
],
|
||||
];
|
||||
|
||||
$response = $client->post($host, $request);
|
||||
|
||||
if (
|
||||
$response->getStatusCode() == 200
|
||||
&& trim($result = $response->getBody()) === 'OK'
|
||||
) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$result = $e->getMessage();
|
||||
}
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to change password. $result",
|
||||
],
|
||||
true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Modoboa Password Driver
|
||||
*
|
||||
* Payload is json string containing username, oldPassword and newPassword
|
||||
* Return value is a json string saying result: true if success.
|
||||
*
|
||||
* @version 1.0.1
|
||||
* @author stephane @actionweb.fr
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The driver need modoboa core 1.10.6 or later
|
||||
*
|
||||
* You need to define theses variables in plugin/password/config.inc.php
|
||||
*
|
||||
* $config['password_driver'] = 'modoboa'; // use modoboa as driver
|
||||
* $config['password_modoboa_api_token'] = ''; // put token number from Modoboa server
|
||||
* $config['password_minimum_length'] = 8; // select same number as in Modoboa server
|
||||
*/
|
||||
|
||||
class rcube_modoboa_password
|
||||
{
|
||||
function save($curpass, $passwd)
|
||||
{
|
||||
// Init config access
|
||||
$rcmail = rcmail::get_instance();
|
||||
$ModoboaToken = $rcmail->config->get('password_modoboa_api_token');
|
||||
$RoudCubeUsername = $_SESSION['username'];
|
||||
$IMAPhost = $_SESSION['imap_host'];
|
||||
|
||||
// Call GET to fetch values from modoboa server
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt_array($curl, [
|
||||
CURLOPT_URL => "https://" . $IMAPhost . "/api/v1/accounts/?search=" . urlencode($RoudCubeUsername),
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "GET",
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"Authorization: Token " . $ModoboaToken,
|
||||
"Cache-Control: no-cache",
|
||||
"Content-Type: application/json"
|
||||
],
|
||||
]);
|
||||
|
||||
$response = curl_exec($curl);
|
||||
$err = curl_error($curl);
|
||||
|
||||
curl_close($curl);
|
||||
|
||||
if ($err) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
// Decode json string
|
||||
$decoded = json_decode($response);
|
||||
|
||||
if (!is_array($decoded)) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
// Get user ID (pk)
|
||||
$userid = $decoded[0]->pk;
|
||||
|
||||
// Encode json with new password
|
||||
$ret['username'] = $decoded[0]->username;
|
||||
$ret['mailbox'] = $decoded[0]->mailbox;
|
||||
$ret['role'] = $decoded[0]->role;
|
||||
$ret['password'] = $passwd; // new password
|
||||
$encoded = json_encode($ret);
|
||||
|
||||
// Call HTTP API Modoboa
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt_array($curl, [
|
||||
CURLOPT_URL => "https://" . $IMAPhost . "/api/v1/accounts/" . $userid . "/",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "PUT",
|
||||
CURLOPT_POSTFIELDS => "" . $encoded . "",
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"Authorization: Token " . $ModoboaToken,
|
||||
"Cache-Control: no-cache",
|
||||
"Content-Type: application/json"
|
||||
],
|
||||
]);
|
||||
|
||||
$response = curl_exec($curl);
|
||||
$err = curl_error($curl);
|
||||
|
||||
curl_close($curl);
|
||||
|
||||
if ($err) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PAM Password Driver
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Aleksander Machniak
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_pam_password
|
||||
{
|
||||
function save($currpass, $newpass, $username)
|
||||
{
|
||||
$error = '';
|
||||
|
||||
if (extension_loaded('pam') || extension_loaded('pam_auth')) {
|
||||
if (pam_auth($username, $currpass, $error, false)) {
|
||||
if (pam_chpass($username, $currpass, $newpass)) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: PAM authentication failed for user $username: $error"
|
||||
], true, false
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: PECL-PAM module not loaded"
|
||||
], true, false
|
||||
);
|
||||
}
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Roundcube Password Driver for Plesk-RPC.
|
||||
*
|
||||
* This driver changes a E-Mail-Password via Plesk-RPC
|
||||
* Deps: PHP-Curl, SimpleXML
|
||||
*
|
||||
* @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
|
||||
* @copyright Adfinis SyGroup AG, 2014
|
||||
*
|
||||
* Config needed:
|
||||
* $config['password_plesk_host'] = '10.0.0.5';
|
||||
* $config['password_plesk_user'] = 'admin';
|
||||
* $config['password_plesk_pass'] = 'pass';
|
||||
* $config['password_plesk_rpc_port'] = 8443;
|
||||
* $config['password_plesk_rpc_path'] = enterprise/control/agent.php;
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Roundcube Password Driver Class
|
||||
*
|
||||
* See {ROUNDCUBE_ROOT}/plugins/password/README for API description
|
||||
*
|
||||
* @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
|
||||
*/
|
||||
class rcube_plesk_password
|
||||
{
|
||||
/**
|
||||
* This method is called from roundcube to change the password
|
||||
*
|
||||
* roundcube already validated the old password so we just need to change it at this point
|
||||
*
|
||||
* @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
|
||||
* @param string $curpass Current password
|
||||
* @param string $newpass New password
|
||||
* @returns int PASSWORD_SUCCESS|PASSWORD_ERROR
|
||||
*/
|
||||
function save($currpass, $newpass, $username)
|
||||
{
|
||||
// get config
|
||||
$rcmail = rcmail::get_instance();
|
||||
$host = $rcmail->config->get('password_plesk_host');
|
||||
$user = $rcmail->config->get('password_plesk_user');
|
||||
$pass = $rcmail->config->get('password_plesk_pass');
|
||||
$port = $rcmail->config->get('password_plesk_rpc_port');
|
||||
$path = $rcmail->config->get('password_plesk_rpc_path');
|
||||
|
||||
// create plesk-object
|
||||
$plesk = new plesk_rpc;
|
||||
$plesk->init($host, $port, $path, $user, $pass);
|
||||
|
||||
// try to change password and return the status
|
||||
$result = $plesk->change_mailbox_password($username, $newpass);
|
||||
//$plesk->destroy();
|
||||
|
||||
if ($result == "ok") {
|
||||
return PASSWORD_SUCCESS;
|
||||
} elseif (is_array($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Plesk RPC-Class
|
||||
*
|
||||
* Striped down version of Plesk-RPC-Class
|
||||
* Just functions for changing mail-passwords included
|
||||
*
|
||||
* Documentation of Plesk RPC-API: http://download1.parallels.com/Plesk/PP11/11.0/Doc/en-US/online/plesk-api-rpc/
|
||||
*
|
||||
* @author Cyrill von Wattenwyl <cyrill.vonwattenwyl@adfinis-sygroup.ch>
|
||||
*/
|
||||
class plesk_rpc
|
||||
{
|
||||
protected $old_version = false;
|
||||
protected $curl;
|
||||
|
||||
/**
|
||||
* init plesk-rpc via curl
|
||||
*
|
||||
* @param string $host plesk host
|
||||
* @param string $port plesk rpc port
|
||||
* @param string $path plesk rpc path
|
||||
* @param string $user plesk user
|
||||
* @param string $user plesk password
|
||||
* @returns void
|
||||
*/
|
||||
function init($host, $port, $path, $user, $pass)
|
||||
{
|
||||
$headers = [
|
||||
sprintf("HTTP_AUTH_LOGIN: %s", $user),
|
||||
sprintf("HTTP_AUTH_PASSWD: %s", $pass),
|
||||
"Content-Type: text/xml"
|
||||
];
|
||||
|
||||
$url = sprintf("https://%s:%s/%s", $host, $port, $path);
|
||||
$this->curl = curl_init();
|
||||
|
||||
curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT , 5);
|
||||
curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST , 0);
|
||||
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER , false);
|
||||
curl_setopt($this->curl, CURLOPT_HTTPHEADER , $headers);
|
||||
curl_setopt($this->curl, CURLOPT_URL , $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* send a request to the plesk
|
||||
*
|
||||
* @param string $packet XML-Packet to send to Plesk
|
||||
*
|
||||
* @returns string Response body
|
||||
*/
|
||||
function send_request($packet)
|
||||
{
|
||||
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($this->curl, CURLOPT_POSTFIELDS, $packet);
|
||||
$result = curl_exec($this->curl);
|
||||
|
||||
return $result && strpos($result, '<?xml') === 0 ? $result : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* close curl
|
||||
*/
|
||||
function destroy()
|
||||
{
|
||||
curl_close($this->curl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all hosting-information of a domain
|
||||
*
|
||||
* @param string $domain domain-name
|
||||
* @returns object SimpleXML object
|
||||
*/
|
||||
function domain_info($domain)
|
||||
{
|
||||
// build xml
|
||||
$request = new SimpleXMLElement("<packet></packet>");
|
||||
$site = $request->addChild("site");
|
||||
$get = $site->addChild("get");
|
||||
$filter = $get->addChild("filter");
|
||||
|
||||
$filter->addChild("name", utf8_encode($domain));
|
||||
$dataset = $get->addChild("dataset");
|
||||
|
||||
$dataset->addChild("hosting");
|
||||
$packet = $request->asXML();
|
||||
$xml = null;
|
||||
|
||||
// send the request and make it to simple-xml-object
|
||||
if ($res = $this->send_request($packet)) {
|
||||
$xml = new SimpleXMLElement($res);
|
||||
}
|
||||
|
||||
// Old Plesk versions require version attribute, add it and try again
|
||||
if ($xml && $xml->site->get->result->status == 'error' && $xml->site->get->result->errcode == 1017) {
|
||||
$request->addAttribute("version", "1.6.3.0");
|
||||
$packet = $request->asXML();
|
||||
|
||||
$this->old_version = true;
|
||||
|
||||
// send the request and make it to simple-xml-object
|
||||
if ($res = $this->send_request($packet)) {
|
||||
$xml = new SimpleXMLElement($res);
|
||||
}
|
||||
}
|
||||
|
||||
return $xml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get psa-id of a domain
|
||||
*
|
||||
* @param string $domain domain-name
|
||||
*
|
||||
* @returns int Domain ID
|
||||
*/
|
||||
function get_domain_id($domain)
|
||||
{
|
||||
if ($xml = $this->domain_info($domain)) {
|
||||
return intval($xml->site->get->result->id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Password of a mailbox
|
||||
*
|
||||
* @param string $mailbox full email-address (user@domain.tld)
|
||||
* @param string $newpass new password of mailbox
|
||||
*
|
||||
* @returns bool
|
||||
*/
|
||||
function change_mailbox_password($mailbox, $newpass)
|
||||
{
|
||||
list($user, $domain) = explode("@", $mailbox);
|
||||
$domain_id = $this->get_domain_id($domain);
|
||||
|
||||
// if domain cannot be resolved to an id, do not continue
|
||||
if (!$domain_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// build xml-packet
|
||||
$request = new SimpleXMLElement("<packet></packet>");
|
||||
$mail = $request->addChild("mail");
|
||||
$update = $mail->addChild("update");
|
||||
$add = $update->addChild("set");
|
||||
$filter = $add->addChild("filter");
|
||||
$filter->addChild("site-id", $domain_id);
|
||||
|
||||
$mailname = $filter->addChild("mailname");
|
||||
$mailname->addChild("name", $user);
|
||||
|
||||
$password = $mailname->addChild("password");
|
||||
$password->addChild("value", $newpass);
|
||||
$password->addChild("type", "plain");
|
||||
|
||||
if ($this->old_version) {
|
||||
$request->addAttribute("version", "1.6.3.0");
|
||||
}
|
||||
|
||||
$packet = $request->asXML();
|
||||
|
||||
// send the request to plesk
|
||||
if ($res = $this->send_request($packet)) {
|
||||
$xml = new SimpleXMLElement($res);
|
||||
$res = strval($xml->mail->update->set->result->status);
|
||||
|
||||
if ($res != "ok") {
|
||||
$res = [
|
||||
'code' => PASSWORD_ERROR,
|
||||
'message' => strval($xml->mail->update->set->result->errtext)
|
||||
];
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Poppassd Password Driver
|
||||
*
|
||||
* Driver to change passwords via Poppassd/Courierpassd
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Philip Weir
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_poppassd_password
|
||||
{
|
||||
function format_error_result($code, $line)
|
||||
{
|
||||
if (preg_match('/^\d\d\d\s+(\S.*)\s*$/', $line, $matches)) {
|
||||
return ['code' => $code, 'message' => $matches[1]];
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
function save($curpass, $passwd, $username)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$poppassd = new Net_Socket();
|
||||
|
||||
$port = $rcmail->config->get('password_pop_port', 106);
|
||||
$host = $rcmail->config->get('password_pop_host', 'localhost');
|
||||
$host = rcube_utils::parse_host($host);
|
||||
|
||||
$result = $poppassd->connect($host, $port, null);
|
||||
|
||||
if (is_a($result, 'PEAR_Error')) {
|
||||
return $this->format_error_result(PASSWORD_CONNECT_ERROR, $result->getMessage());
|
||||
}
|
||||
|
||||
$result = $poppassd->readLine();
|
||||
|
||||
if (!preg_match('/^2\d\d/', $result)) {
|
||||
$poppassd->disconnect();
|
||||
return $this->format_error_result(PASSWORD_ERROR, $result);
|
||||
}
|
||||
|
||||
$poppassd->writeLine("user ". $username);
|
||||
$result = $poppassd->readLine();
|
||||
|
||||
if (!preg_match('/^[23]\d\d/', $result)) {
|
||||
$poppassd->disconnect();
|
||||
return $this->format_error_result(PASSWORD_CONNECT_ERROR, $result);
|
||||
}
|
||||
|
||||
$poppassd->writeLine("pass ". $curpass);
|
||||
$result = $poppassd->readLine();
|
||||
|
||||
if (!preg_match('/^[23]\d\d/', $result)) {
|
||||
$poppassd->disconnect();
|
||||
return $this->format_error_result(PASSWORD_ERROR, $result);
|
||||
}
|
||||
|
||||
$poppassd->writeLine("newpass ". $passwd);
|
||||
$result = $poppassd->readLine();
|
||||
$poppassd->disconnect();
|
||||
|
||||
if (!preg_match('/^2\d\d/', $result)) {
|
||||
return $this->format_error_result(PASSWORD_ERROR, $result);
|
||||
}
|
||||
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* pw_usermod Driver
|
||||
*
|
||||
* Driver that adds functionality to change the systems user password via
|
||||
* the 'pw usermod' command.
|
||||
*
|
||||
* For installation instructions please read the README file.
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Alex Cartwright <acartwright@mutinydesign.co.uk>
|
||||
* @author Adamson Huang <adomputer@gmail.com>
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_pw_usermod_password
|
||||
{
|
||||
public function save($currpass, $newpass, $username)
|
||||
{
|
||||
$cmd = rcmail::get_instance()->config->get('password_pw_usermod_cmd', 'sudo /usr/sbin/pw usermod -h 0 -n');
|
||||
$cmd .= ' ' . escapeshellarg($username) . ' > /dev/null';
|
||||
|
||||
$handle = popen($cmd, 'w');
|
||||
fwrite($handle, "$newpass\n");
|
||||
|
||||
if (pclose($handle) == 0) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to execute $cmd"
|
||||
], true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Have I Been Pwned Password Strength Driver
|
||||
*
|
||||
* Driver to check passwords using HIBP:
|
||||
* https://haveibeenpwned.com/Passwords
|
||||
*
|
||||
* This driver will return a strength of:
|
||||
* 3: if the password WAS NOT found in HIBP
|
||||
* 1: if the password WAS found in HIBP
|
||||
* 2: if there was an ERROR retrieving data.
|
||||
*
|
||||
* To use this driver, configure (in ../config.inc.php):
|
||||
*
|
||||
* $config['password_strength_driver'] = 'pwned';
|
||||
* $config['password_minimum_score'] = 3;
|
||||
*
|
||||
* Set the minimum score to 3 if you want to make sure that all
|
||||
* passwords are successfully checked against HIBP (recommended).
|
||||
*
|
||||
* Set it to 2 if you still want to accept passwords in case a
|
||||
* HIBP check fails for some (technical) reason.
|
||||
*
|
||||
* Setting the minimum score to 1 or less effectively renders
|
||||
* the checks useless, as all passwords would be accepted.
|
||||
* Setting it to 4 or more will effectively reject all passwords.
|
||||
*
|
||||
* This driver will only return a maximum score of 3 because not
|
||||
* being listed in HIBP does not necessarily mean that the
|
||||
* password is a good one. It is therefore recommended to also
|
||||
* configure a minimum length for the password.
|
||||
*
|
||||
* Background reading (don't worry, your passwords are not sent anywhere):
|
||||
* https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/#cloudflareprivacyandkanonymity
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Christoph Langguth
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_pwned_password
|
||||
{
|
||||
// API URL. Note: the trailing slash is mandatory.
|
||||
const API_URL = 'https://api.pwnedpasswords.com/range/';
|
||||
|
||||
// See https://www.troyhunt.com/enhancing-pwned-passwords-privacy-with-padding/
|
||||
const ENHANCED_PRIVACY_CURL = 1;
|
||||
|
||||
// Score constants, these directly correspond to the score that is returned.
|
||||
const SCORE_LISTED = 1;
|
||||
const SCORE_ERROR = 2;
|
||||
const SCORE_NOT_LISTED = 3;
|
||||
|
||||
/**
|
||||
* Rule description.
|
||||
*
|
||||
* @return array human-readable description of the check rule.
|
||||
*/
|
||||
function strength_rules()
|
||||
{
|
||||
$rc = rcmail::get_instance();
|
||||
$href = 'https://haveibeenpwned.com/Passwords';
|
||||
|
||||
return [$rc->gettext(['name' => 'password.pwned_mustnotbedisclosed', 'vars' => ['href' => $href]])];
|
||||
}
|
||||
|
||||
/**
|
||||
* Password strength check.
|
||||
* Return values:
|
||||
* 1 - if password is definitely compromised.
|
||||
* 2 - if status for password can't be determined (network failures etc.)
|
||||
* 3 - if password is not publicly known to be compromised.
|
||||
*
|
||||
* @param string $passwd Password
|
||||
*
|
||||
* @return array password score (1 to 3) and (optional) reason message
|
||||
*/
|
||||
function check_strength($passwd)
|
||||
{
|
||||
$score = $this->check_pwned($passwd);
|
||||
$message = null;
|
||||
|
||||
if ($score !== self::SCORE_NOT_LISTED) {
|
||||
$rc = rcmail::get_instance();
|
||||
if ($score === self::SCORE_LISTED) {
|
||||
$message = $rc->gettext('password.pwned_isdisclosed');
|
||||
}
|
||||
else {
|
||||
$message = $rc->gettext('password.pwned_fetcherror');
|
||||
}
|
||||
}
|
||||
|
||||
return [$score, $message];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check password using HIBP.
|
||||
*
|
||||
* @param string $passwd
|
||||
*
|
||||
* @return int score, one of the SCORE_* constants (between 1 and 3).
|
||||
*/
|
||||
function check_pwned($passwd)
|
||||
{
|
||||
// initialize with error score
|
||||
$result = self::SCORE_ERROR;
|
||||
|
||||
if (!$this->can_retrieve()) {
|
||||
// Log the fact that we cannot check because of configuration error.
|
||||
rcube::raise_error("Need curl or allow_url_fopen to check password strength with 'pwned'", true, true);
|
||||
}
|
||||
else {
|
||||
list($prefix, $suffix) = $this->hash_split($passwd);
|
||||
|
||||
$suffixes = $this->retrieve_suffixes(self::API_URL . $prefix);
|
||||
|
||||
if ($suffixes) {
|
||||
$result = $this->check_suffix_in_list($suffix, $suffixes);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function hash_split($passwd)
|
||||
{
|
||||
$hash = strtolower(sha1($passwd));
|
||||
$prefix = substr($hash, 0, 5);
|
||||
$suffix = substr($hash, 5);
|
||||
|
||||
return [$prefix, $suffix];
|
||||
}
|
||||
|
||||
function can_retrieve()
|
||||
{
|
||||
return $this->can_curl() || $this->can_fopen();
|
||||
}
|
||||
|
||||
function can_curl()
|
||||
{
|
||||
return function_exists('curl_init');
|
||||
}
|
||||
|
||||
function can_fopen()
|
||||
{
|
||||
return ini_get('allow_url_fopen');
|
||||
}
|
||||
|
||||
function retrieve_suffixes($url)
|
||||
{
|
||||
if ($this->can_curl()) {
|
||||
return $this->retrieve_curl($url);
|
||||
}
|
||||
else {
|
||||
return $this->retrieve_fopen($url);
|
||||
}
|
||||
}
|
||||
|
||||
function retrieve_curl($url)
|
||||
{
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
if (self::ENHANCED_PRIVACY_CURL == 1) {
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Add-Padding: true']);
|
||||
}
|
||||
$output = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function retrieve_fopen($url)
|
||||
{
|
||||
$output = '';
|
||||
$ch = fopen($url, 'r');
|
||||
while (!feof($ch)) {
|
||||
$output .= fgets($ch);
|
||||
}
|
||||
fclose($ch);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function check_suffix_in_list($candidate, $list)
|
||||
{
|
||||
// initialize to error in case there are no lines at all
|
||||
$result = self::SCORE_ERROR;
|
||||
|
||||
foreach (preg_split('/[\r\n]+/', $list) as $line) {
|
||||
$line = strtolower($line);
|
||||
|
||||
if (preg_match('/^([0-9a-f]{35}):(\d+)$/', $line, $matches)) {
|
||||
if ($matches[2] > 0 && $matches[1] === $candidate) {
|
||||
// more than 0 occurrences, and suffix matches
|
||||
// -> password is compromised
|
||||
return self::SCORE_LISTED;
|
||||
}
|
||||
|
||||
// valid line, not matching the current password
|
||||
$result = self::SCORE_NOT_LISTED;
|
||||
}
|
||||
else {
|
||||
// invalid line
|
||||
return self::SCORE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SASL Password Driver
|
||||
*
|
||||
* Driver that adds functionality to change the users Cyrus/SASL password.
|
||||
* The code is derived from the Squirrelmail "Change SASL Password" Plugin
|
||||
* by Galen Johnson.
|
||||
*
|
||||
* It only works with saslpasswd2 on the same host where Roundcube runs
|
||||
* and requires shell access and gcc in order to compile the binary.
|
||||
*
|
||||
* For installation instructions please read the README file.
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Thomas Bruederli
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_sasl_password
|
||||
{
|
||||
function save($currpass, $newpass, $username)
|
||||
{
|
||||
$curdir = RCUBE_PLUGINS_DIR . 'password/helpers';
|
||||
$username = escapeshellarg($username);
|
||||
$args = rcmail::get_instance()->config->get('password_saslpasswd_args', '');
|
||||
|
||||
if ($fh = popen("$curdir/chgsaslpasswd -p $args $username", 'w')) {
|
||||
fwrite($fh, $newpass."\n");
|
||||
$code = pclose($fh);
|
||||
|
||||
if ($code == 0) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to execute $curdir/chgsaslpasswd"
|
||||
], true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* smb Driver
|
||||
*
|
||||
* Driver that adds functionality to change the systems user password via
|
||||
* the 'smbpasswd' command.
|
||||
*
|
||||
* For installation instructions please read the README file.
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Andy Theuninck <gohanman@gmail.com)
|
||||
*
|
||||
* Based on chpasswd roundcubemail password driver by
|
||||
* @author Alex Cartwright <acartwright@mutinydesign.co.uk)
|
||||
* and smbpasswd horde passwd driver by
|
||||
* @author Rene Lund Jensen <Rene@lundjensen.net>
|
||||
*
|
||||
* Configuration settings:
|
||||
* password_smb_host => samba host (default: localhost)
|
||||
* password_smb_cmd => smbpasswd binary (default: /usr/bin/smbpasswd)
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_smb_password
|
||||
{
|
||||
|
||||
public function save($currpass, $newpass, $username)
|
||||
{
|
||||
$host = rcmail::get_instance()->config->get('password_smb_host', 'localhost');
|
||||
$bin = rcmail::get_instance()->config->get('password_smb_cmd', '/usr/bin/smbpasswd');
|
||||
$host = rcube_utils::parse_host($host);
|
||||
$tmpfile = tempnam(sys_get_temp_dir(), 'smb');
|
||||
$cmd = $bin . ' -r ' . escapeshellarg($host) . ' -s -U ' . escapeshellarg($username) . ' > ' . $tmpfile . ' 2>&1';
|
||||
$handle = @popen($cmd, 'w');
|
||||
|
||||
fwrite($handle, $currpass."\n");
|
||||
fwrite($handle, $newpass."\n");
|
||||
fwrite($handle, $newpass."\n");
|
||||
@pclose($handle);
|
||||
$res = file($tmpfile);
|
||||
unlink($tmpfile);
|
||||
|
||||
if (strstr($res[count($res) - 1], 'Password changed for user') !== false) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to execute $cmd"
|
||||
], true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SQL Password Driver
|
||||
*
|
||||
* Driver for passwords stored in SQL database
|
||||
*
|
||||
* @version 2.1
|
||||
* @author Aleksander Machniak <alec@alec.pl>
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
class rcube_sql_password
|
||||
{
|
||||
/**
|
||||
* Update current user password
|
||||
*
|
||||
* @param string $curpass Current password
|
||||
* @param string $passwd New password
|
||||
*
|
||||
* @return int Result
|
||||
*/
|
||||
function save($curpass, $passwd)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
if (!($sql = $rcmail->config->get('password_query'))) {
|
||||
$sql = 'SELECT update_passwd(%P, %u)';
|
||||
}
|
||||
|
||||
if ($dsn = $rcmail->config->get('password_db_dsn')) {
|
||||
$db = rcube_db::factory(self::parse_dsn($dsn), '', false);
|
||||
$db->set_debug((bool)$rcmail->config->get('sql_debug'));
|
||||
}
|
||||
else {
|
||||
$db = $rcmail->get_dbh();
|
||||
}
|
||||
|
||||
if ($db->is_error()) {
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
// new password - default hash method
|
||||
if (strpos($sql, '%P') !== false) {
|
||||
$password = password::hash_password($passwd);
|
||||
|
||||
if ($password === false) {
|
||||
return PASSWORD_CRYPT_ERROR;
|
||||
}
|
||||
|
||||
$sql = str_replace('%P', $db->quote($password), $sql);
|
||||
}
|
||||
|
||||
// old password - default hash method
|
||||
if (strpos($sql, '%O') !== false) {
|
||||
$password = password::hash_password($curpass);
|
||||
|
||||
if ($password === false) {
|
||||
return PASSWORD_CRYPT_ERROR;
|
||||
}
|
||||
|
||||
$sql = str_replace('%O', $db->quote($password), $sql);
|
||||
}
|
||||
|
||||
// Handle clear text passwords securely (#1487034)
|
||||
$sql_vars = [];
|
||||
if (preg_match_all('/%[p|o]/', $sql, $m)) {
|
||||
foreach ($m[0] as $var) {
|
||||
if ($var == '%p') {
|
||||
$sql = preg_replace('/%p/', '?', $sql, 1);
|
||||
$sql_vars[] = (string) $passwd;
|
||||
}
|
||||
else { // %o
|
||||
$sql = preg_replace('/%o/', '?', $sql, 1);
|
||||
$sql_vars[] = (string) $curpass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$local_part = $rcmail->user->get_username('local');
|
||||
$domain_part = $rcmail->user->get_username('domain');
|
||||
$username = $_SESSION['username'];
|
||||
$host = $_SESSION['imap_host'];
|
||||
|
||||
// convert domains to/from punycode
|
||||
if ($rcmail->config->get('password_idn_ascii')) {
|
||||
$domain_part = rcube_utils::idn_to_ascii($domain_part);
|
||||
$username = rcube_utils::idn_to_ascii($username);
|
||||
$host = rcube_utils::idn_to_ascii($host);
|
||||
}
|
||||
else {
|
||||
$domain_part = rcube_utils::idn_to_utf8($domain_part);
|
||||
$username = rcube_utils::idn_to_utf8($username);
|
||||
$host = rcube_utils::idn_to_utf8($host);
|
||||
}
|
||||
|
||||
// at least we should always have the local part
|
||||
$sql = str_replace('%l', $db->quote($local_part, 'text'), $sql);
|
||||
$sql = str_replace('%d', $db->quote($domain_part, 'text'), $sql);
|
||||
$sql = str_replace('%u', $db->quote($username, 'text'), $sql);
|
||||
$sql = str_replace('%h', $db->quote($host, 'text'), $sql);
|
||||
|
||||
$res = $db->query($sql, $sql_vars);
|
||||
|
||||
if (!$db->is_error()) {
|
||||
if (strtolower(substr(trim($sql),0,6)) == 'select') {
|
||||
if ($db->fetch_array($res)) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Note: Don't be tempted to check affected_rows = 1. For some queries
|
||||
// (e.g. INSERT ... ON DUPLICATE KEY UPDATE) the result can be 2.
|
||||
if ($db->affected_rows($res) > 0) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse DSN string and replace host variables
|
||||
*
|
||||
* @param string $dsn DSN string
|
||||
*
|
||||
* @return string DSN string
|
||||
*/
|
||||
protected static function parse_dsn($dsn)
|
||||
{
|
||||
if (strpos($dsn, '%')) {
|
||||
// parse DSN and replace variables in hostname
|
||||
$parsed = rcube_db::parse_dsn($dsn);
|
||||
$host = rcube_utils::parse_host($parsed['hostspec']);
|
||||
|
||||
// build back the DSN string
|
||||
if ($host != $parsed['hostspec']) {
|
||||
$dsn = str_replace('@' . $parsed['hostspec'], '@' . $host, $dsn);
|
||||
}
|
||||
}
|
||||
|
||||
return $dsn;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* TinyCP driver
|
||||
*
|
||||
* Enable the password driver in Roundcube (https://roundcube.net/) for the
|
||||
* TinyCP Lightweight Linux Control Panel (https://tinycp.com/).
|
||||
* See README for instructions, Connector Required.
|
||||
*
|
||||
* @version 1.2
|
||||
* @author Ricky Mendoza (HelloWorld@rickymendoza.dev)
|
||||
*
|
||||
* Copyright (C) 2020 Ricky Mendoza
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
class rcube_tinycp_password
|
||||
{
|
||||
public function save($currpass, $newpass, $username)
|
||||
{
|
||||
require_once 'TinyCPConnector.php';
|
||||
|
||||
$tinycp_host = rcmail::get_instance()->config->get('password_tinycp_host');
|
||||
$tinycp_port = rcmail::get_instance()->config->get('password_tinycp_port');
|
||||
$tinycp_user = rcmail::get_instance()->config->get('password_tinycp_user');
|
||||
$tinycp_pass = rcmail::get_instance()->config->get('password_tinycp_pass');
|
||||
$error_message = '';
|
||||
|
||||
if ($tinycp_host && $tinycp_port && $tinycp_user && $tinycp_pass) {
|
||||
try {
|
||||
$tcp = new TinyCPConnector($tinycp_host, $tinycp_port);
|
||||
$tcp->Auth($tinycp_user, $tinycp_pass);
|
||||
$tcp->mail___mailserver___email_pass_change2($username, $newpass);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$error_message = $e->getMessage();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$error_message = "Missing configuration value(s). ";
|
||||
}
|
||||
|
||||
if ($error_message) {
|
||||
rcube::raise_error([
|
||||
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Password driver: $error_message",
|
||||
],
|
||||
true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Virtualmin Password Driver
|
||||
*
|
||||
* Driver that adds functionality to change the users Virtualmin password.
|
||||
* The code is derived from the Squirrelmail "Change Cyrus/SASL Password" Plugin
|
||||
* by Thomas Bruederli.
|
||||
*
|
||||
* It only works with virtualmin on the same host where Roundcube runs
|
||||
* and requires shell access and gcc in order to compile the binary.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Martijn de Munnik
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_virtualmin_password
|
||||
{
|
||||
function save($currpass, $newpass, $username)
|
||||
{
|
||||
$curdir = RCUBE_PLUGINS_DIR . 'password/helpers';
|
||||
$username = escapeshellarg($username);
|
||||
|
||||
// Get the domain using virtualmin CLI:
|
||||
exec("$curdir/chgvirtualminpasswd list-domains --mail-user $username --name-only", $output_domain, $returnvalue);
|
||||
|
||||
if ($returnvalue == 0 && count($output_domain) == 1) {
|
||||
$domain = trim($output_domain[0]);
|
||||
}
|
||||
else {
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to execute $curdir/chgvirtualminpasswd "
|
||||
. "or domain for mail-user '$username' not known to Virtualmin"
|
||||
], true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
$domain = escapeshellarg($domain);
|
||||
$newpass = escapeshellarg($newpass);
|
||||
|
||||
exec("$curdir/chgvirtualminpasswd modify-user --domain $domain --user $username --pass $newpass", $output, $returnvalue);
|
||||
|
||||
if ($returnvalue == 0) {
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to execute $curdir/chgvirtualminpasswd"
|
||||
], true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* vpopmail Password Driver
|
||||
*
|
||||
* Driver to change passwords via vpopmaild
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Johannes Hessellund
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_vpopmaild_password
|
||||
{
|
||||
function save($curpass, $passwd, $username)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$vpopmaild = new Net_Socket();
|
||||
$host = $rcmail->config->get('password_vpopmaild_host');
|
||||
$port = $rcmail->config->get('password_vpopmaild_port');
|
||||
|
||||
$result = $vpopmaild->connect($host, $port, null);
|
||||
if (is_a($result, 'PEAR_Error')) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
$vpopmaild->setTimeout($rcmail->config->get('password_vpopmaild_timeout'),0);
|
||||
|
||||
$result = $vpopmaild->readLine();
|
||||
if(!preg_match('/^\+OK/', $result)) {
|
||||
$vpopmaild->disconnect();
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
$vpopmaild->writeLine("slogin ". $username . " " . $curpass);
|
||||
$result = $vpopmaild->readLine();
|
||||
|
||||
if(!preg_match('/^\+OK/', $result) ) {
|
||||
$vpopmaild->writeLine("quit");
|
||||
$vpopmaild->disconnect();
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
$vpopmaild->writeLine("mod_user ". $username);
|
||||
$vpopmaild->writeLine("clear_text_password ". $passwd);
|
||||
$vpopmaild->writeLine(".");
|
||||
$result = $vpopmaild->readLine();
|
||||
$vpopmaild->writeLine("quit");
|
||||
$vpopmaild->disconnect();
|
||||
|
||||
if (!preg_match('/^\+OK/', $result)) {
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* Communigate driver for the Password Plugin for Roundcube
|
||||
*
|
||||
* Tested with Communigate Pro 5.1.2
|
||||
*
|
||||
* Configuration options:
|
||||
* password_ximss_host - Host name of Communigate server
|
||||
* password_ximss_port - XIMSS port on Communigate server
|
||||
*
|
||||
* References:
|
||||
* http://www.communigate.com/WebGuide/XMLAPI.html
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Erik Meitner <erik wanderings.us>
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_ximss_password
|
||||
{
|
||||
function save($pass, $newpass, $username)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
$host = $rcmail->config->get('password_ximss_host');
|
||||
$port = $rcmail->config->get('password_ximss_port');
|
||||
$sock = stream_socket_client("tcp://$host:$port", $errno, $errstr, 30);
|
||||
|
||||
if ($sock === false) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
// send all requests at once(pipelined)
|
||||
fwrite($sock, '<login id="A001" authData="'.$username.'" password="'.$pass.'" />'."\0");
|
||||
fwrite($sock, '<passwordModify id="A002" oldPassword="'.$pass.'" newPassword="'.$newpass.'" />'."\0");
|
||||
fwrite($sock, '<bye id="A003" />'."\0");
|
||||
|
||||
//example responses
|
||||
// <session id="A001" urlID="4815-vN2Txjkggy7gjHRD10jw" userName="user@example.com"/>\0
|
||||
// <response id="A001"/>\0
|
||||
// <response id="A002"/>\0
|
||||
// <response id="A003"/>\0
|
||||
// or an error:
|
||||
// <response id="A001" errorText="incorrect password or account name" errorNum="515"/>\0
|
||||
|
||||
$responseblob = '';
|
||||
while (!feof($sock)) {
|
||||
$responseblob .= fgets($sock, 1024);
|
||||
}
|
||||
|
||||
fclose($sock);
|
||||
|
||||
foreach (explode( "\0", $responseblob) as $response) {
|
||||
$resp = simplexml_load_string("<xml>".$response."</xml>");
|
||||
$id = $resp && !empty($resp->response[0]['id']) ? $resp->response[0]['id'] : null;
|
||||
|
||||
if ($id == 'A001') {
|
||||
if (isset($resp->response[0]['errorNum'])) {
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
else if ($id == 'A002') {
|
||||
if (isset($resp->response[0]['errorNum'])) {
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
}
|
||||
else if ($id == 'A003') {
|
||||
if (isset($resp->response[0]['errorNum'])) {
|
||||
// There was a problem during logout (This is probably harmless)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
/**
|
||||
* XMail Password Driver
|
||||
*
|
||||
* Driver for XMail password
|
||||
*
|
||||
* @version 2.0
|
||||
* @author Helio Cavichiolo Jr <helio@hcsistemas.com.br>
|
||||
*
|
||||
* Setup xmail_host, xmail_user, xmail_pass and xmail_port into
|
||||
* config.inc.php of password plugin as follows:
|
||||
*
|
||||
* $config['xmail_host'] = 'localhost';
|
||||
* $config['xmail_user'] = 'YourXmailControlUser';
|
||||
* $config['xmail_pass'] = 'YourXmailControlPass';
|
||||
* $config['xmail_port'] = 6017;
|
||||
*
|
||||
* Copyright (C) The Roundcube Dev Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_xmail_password
|
||||
{
|
||||
function save($currpass, $newpass)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
list($user, $domain) = explode('@', $_SESSION['username']);
|
||||
|
||||
$xmail = new XMail;
|
||||
|
||||
$xmail->hostname = $rcmail->config->get('xmail_host');
|
||||
$xmail->username = $rcmail->config->get('xmail_user');
|
||||
$xmail->password = $rcmail->config->get('xmail_pass');
|
||||
$xmail->port = $rcmail->config->get('xmail_port');
|
||||
|
||||
if (!$xmail->connect()) {
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to connect to mail server"
|
||||
], true, false
|
||||
);
|
||||
|
||||
return PASSWORD_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
if (!$xmail->send("userpasswd\t".$domain."\t".$user."\t".$newpass."\n")) {
|
||||
$xmail->close();
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Unable to change password"
|
||||
], true, false
|
||||
);
|
||||
|
||||
return PASSWORD_ERROR;
|
||||
}
|
||||
|
||||
$xmail->close();
|
||||
return PASSWORD_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
class XMail {
|
||||
var $socket;
|
||||
var $hostname = 'localhost';
|
||||
var $username = 'xmail';
|
||||
var $password = '';
|
||||
var $port = 6017;
|
||||
|
||||
function send($msg)
|
||||
{
|
||||
socket_write($this->socket,$msg);
|
||||
if (substr(socket_read($this->socket, 512, PHP_BINARY_READ),0,1) != "+") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function connect()
|
||||
{
|
||||
$this->socket = socket_create(AF_INET, SOCK_STREAM, 0);
|
||||
if ($this->socket < 0)
|
||||
return false;
|
||||
|
||||
$result = socket_connect($this->socket, $this->hostname, $this->port);
|
||||
if ($result < 0) {
|
||||
socket_close($this->socket);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (substr(socket_read($this->socket, 512, PHP_BINARY_READ),0,1) != "+") {
|
||||
socket_close($this->socket);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->send("$this->username\t$this->password\n")) {
|
||||
socket_close($this->socket);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function close()
|
||||
{
|
||||
$this->send("quit\n");
|
||||
socket_close($this->socket);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Zxcvb Password Strength Driver
|
||||
*
|
||||
* Driver to check password strength using Zxcvbn-PHP
|
||||
*
|
||||
* @version 0.1
|
||||
* @author Philip Weir
|
||||
*
|
||||
* Copyright (C) Philip Weir
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class rcube_zxcvbn_password
|
||||
{
|
||||
function strength_rules()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$rules = [
|
||||
$rcmail->gettext('password.passwordnoseq'),
|
||||
$rcmail->gettext('password.passwordnocommon'),
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Password strength check
|
||||
*
|
||||
* @param string $passwd Password
|
||||
*
|
||||
* @return array Score (1 to 5) and Reason
|
||||
*/
|
||||
function check_strength($passwd)
|
||||
{
|
||||
if (!class_exists('ZxcvbnPhp\Zxcvbn')) {
|
||||
rcube::raise_error([
|
||||
'code' => 600,
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "Password plugin: Zxcvbn library not found."
|
||||
], true, false
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$zxcvbn = new ZxcvbnPhp\Zxcvbn();
|
||||
$strength = $zxcvbn->passwordStrength($passwd);
|
||||
|
||||
return [$strength['score'] + 1, $strength['feedback']['warning']];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user