mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-07 00:17:03 +03:00
Add better Docker development and prod support
This commit is contained in:
parent
e0462af9da
commit
fcf2c2468d
27 changed files with 1453 additions and 66 deletions
359
.docker/release/files/usr/local/include/application.ini
Normal file
359
.docker/release/files/usr/local/include/application.ini
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
; SnappyMail Webmail configuration file
|
||||
; Please don't add custom parameters here, those will be overwritten
|
||||
|
||||
[webmail]
|
||||
; Text displayed as page title
|
||||
title = "SnappyMail Webmail"
|
||||
|
||||
; Text displayed on startup
|
||||
loading_description = "SnappyMail"
|
||||
favicon_url = ""
|
||||
|
||||
; Theme used by default
|
||||
theme = "Default"
|
||||
|
||||
; Allow theme selection on settings screen
|
||||
allow_themes = On
|
||||
allow_user_background = Off
|
||||
|
||||
; Language used by default
|
||||
language = "en"
|
||||
|
||||
; Admin Panel interface language
|
||||
language_admin = "en"
|
||||
|
||||
; Allow language selection on settings screen
|
||||
allow_languages_on_settings = On
|
||||
allow_additional_accounts = On
|
||||
allow_additional_identities = On
|
||||
|
||||
; Number of messages displayed on page by default
|
||||
messages_per_page = 20
|
||||
|
||||
; File size limit (MB) for file upload on compose screen
|
||||
; 0 for unlimited.
|
||||
attachment_size_limit = 25
|
||||
|
||||
[interface]
|
||||
show_attachment_thumbnail = On
|
||||
use_native_scrollbars = Off
|
||||
new_move_to_folder_button = On
|
||||
|
||||
[branding]
|
||||
login_logo = ""
|
||||
login_background = ""
|
||||
login_desc = ""
|
||||
login_css = ""
|
||||
user_css = ""
|
||||
user_logo = ""
|
||||
user_logo_title = ""
|
||||
user_logo_message = ""
|
||||
user_iframe_message = ""
|
||||
welcome_page_url = ""
|
||||
welcome_page_display = "none"
|
||||
|
||||
[contacts]
|
||||
; Enable contacts
|
||||
enable = Off
|
||||
allow_sync = On
|
||||
sync_interval = 20
|
||||
type = "sqlite"
|
||||
pdo_dsn = "mysql:host=127.0.0.1;port=3306;dbname=snappymail"
|
||||
pdo_user = "root"
|
||||
pdo_password = ""
|
||||
suggestions_limit = 30
|
||||
|
||||
[security]
|
||||
; Enable CSRF protection (http://en.wikipedia.org/wiki/Cross-site_request_forgery)
|
||||
csrf_protection = On
|
||||
custom_server_signature = "SnappyMail"
|
||||
x_frame_options_header = ""
|
||||
x_xss_protection_header = "1; mode=block"
|
||||
openpgp = Off
|
||||
|
||||
; Login and password for web admin panel
|
||||
admin_login = "admin"
|
||||
admin_password = "12345"
|
||||
|
||||
; Access settings
|
||||
allow_admin_panel = On
|
||||
allow_two_factor_auth = Off
|
||||
force_two_factor_auth = Off
|
||||
hide_x_mailer_header = Off
|
||||
admin_panel_host = ""
|
||||
admin_panel_key = "admin"
|
||||
content_security_policy = ""
|
||||
core_install_access_domain = ""
|
||||
|
||||
[ssl]
|
||||
; Require verification of SSL certificate used.
|
||||
verify_certificate = Off
|
||||
|
||||
; Allow self-signed certificates. Requires verify_certificate.
|
||||
allow_self_signed = On
|
||||
|
||||
; Location of Certificate Authority file on local filesystem (/etc/ssl/certs/ca-certificates.crt)
|
||||
cafile = ""
|
||||
|
||||
; capath must be a correctly hashed certificate directory. (/etc/ssl/certs/)
|
||||
capath = ""
|
||||
|
||||
; Location of client certificate file (pem format with private key) on local filesystem
|
||||
client_cert = ""
|
||||
|
||||
[capa]
|
||||
folders = On
|
||||
composer = On
|
||||
contacts = On
|
||||
settings = On
|
||||
quota = On
|
||||
help = On
|
||||
reload = On
|
||||
search = On
|
||||
search_adv = On
|
||||
filters = On
|
||||
x-templates = Off
|
||||
dangerous_actions = On
|
||||
message_actions = On
|
||||
messagelist_actions = On
|
||||
attachments_actions = On
|
||||
|
||||
[login]
|
||||
default_domain = ""
|
||||
|
||||
; Allow language selection on webmail login screen
|
||||
allow_languages_on_login = On
|
||||
determine_user_language = On
|
||||
determine_user_domain = Off
|
||||
welcome_page = Off
|
||||
hide_submit_button = On
|
||||
forgot_password_link_url = ""
|
||||
registration_link_url = ""
|
||||
login_lowercase = On
|
||||
|
||||
; This option allows webmail to remember the logged in user
|
||||
; once they closed the browser window.
|
||||
;
|
||||
; Values:
|
||||
; "DefaultOff" - can be used, disabled by default;
|
||||
; "DefaultOn" - can be used, enabled by default;
|
||||
; "Unused" - cannot be used
|
||||
sign_me_auto = "DefaultOff"
|
||||
|
||||
[plugins]
|
||||
; Enable plugin support
|
||||
enable = Off
|
||||
|
||||
; List of enabled plugins
|
||||
enabled_list = ""
|
||||
|
||||
[defaults]
|
||||
; Editor mode used by default (Plain, Html, HtmlForced or PlainForced)
|
||||
view_editor_type = "Html"
|
||||
|
||||
; layout: 0 - no preview, 1 - side preview, 2 - bottom preview
|
||||
view_layout = 1
|
||||
view_use_checkboxes = On
|
||||
autologout = 30
|
||||
show_images = Off
|
||||
contacts_autosave = On
|
||||
mail_use_threads = Off
|
||||
allow_draft_autosave = On
|
||||
mail_reply_same_folder = Off
|
||||
|
||||
[logs]
|
||||
; Enable logging
|
||||
enable = Off
|
||||
|
||||
; Logs entire request only if error occured (php requred)
|
||||
write_on_error_only = Off
|
||||
|
||||
; Logs entire request only if php error occured
|
||||
write_on_php_error_only = Off
|
||||
|
||||
; Logs entire request only if request timeout (in seconds) occured.
|
||||
write_on_timeout_only = 0
|
||||
|
||||
; Required for development purposes only.
|
||||
; Disabling this option is not recommended.
|
||||
hide_passwords = On
|
||||
time_offset = "0"
|
||||
session_filter = ""
|
||||
sentry_dsn = ""
|
||||
|
||||
; Log filename.
|
||||
; For security reasons, some characters are removed from filename.
|
||||
; Allows for pattern-based folder creation (see examples below).
|
||||
;
|
||||
; Patterns:
|
||||
; {date:Y-m-d} - Replaced by pattern-based date
|
||||
; Detailed info: http://www.php.net/manual/en/function.date.php
|
||||
; {user:email} - Replaced by user's email address
|
||||
; If user is not logged in, value is set to "unknown"
|
||||
; {user:login} - Replaced by user's login (the user part of an email)
|
||||
; If user is not logged in, value is set to "unknown"
|
||||
; {user:domain} - Replaced by user's domain name (the domain part of an email)
|
||||
; If user is not logged in, value is set to "unknown"
|
||||
; {user:uid} - Replaced by user's UID regardless of account currently used
|
||||
;
|
||||
; {user:ip}
|
||||
; {request:ip} - Replaced by user's IP address
|
||||
;
|
||||
; Others:
|
||||
; {imap:login} {imap:host} {imap:port}
|
||||
; {smtp:login} {smtp:host} {smtp:port}
|
||||
;
|
||||
; Examples:
|
||||
; filename = "log-{date:Y-m-d}.txt"
|
||||
; filename = "{date:Y-m-d}/{user:domain}/{user:email}_{user:uid}.log"
|
||||
; filename = "{user:email}-{date:Y-m-d}.txt"
|
||||
filename = "log-{date:Y-m-d}.txt"
|
||||
|
||||
; Enable auth logging in a separate file (for fail2ban)
|
||||
auth_logging = Off
|
||||
auth_logging_filename = "fail2ban/auth-{date:Y-m-d}.txt"
|
||||
auth_logging_format = "[{date:Y-m-d H:i:s}] Auth failed: ip={request:ip} user={imap:login} host={imap:host} port={imap:port}"
|
||||
|
||||
[debug]
|
||||
; Special option required for development purposes
|
||||
enable = Off
|
||||
|
||||
[social]
|
||||
; Google
|
||||
google_enable = Off
|
||||
google_enable_auth = Off
|
||||
google_enable_auth_gmail = Off
|
||||
google_enable_drive = Off
|
||||
google_enable_preview = Off
|
||||
google_client_id = ""
|
||||
google_client_secret = ""
|
||||
google_api_key = ""
|
||||
|
||||
; Facebook
|
||||
fb_enable = Off
|
||||
fb_app_id = ""
|
||||
fb_app_secret = ""
|
||||
|
||||
; Twitter
|
||||
twitter_enable = Off
|
||||
twitter_consumer_key = ""
|
||||
twitter_consumer_secret = ""
|
||||
|
||||
; Dropbox
|
||||
dropbox_enable = Off
|
||||
dropbox_api_key = ""
|
||||
|
||||
[cache]
|
||||
; The section controls caching of the entire application.
|
||||
;
|
||||
; Enables caching in the system
|
||||
enable = On
|
||||
|
||||
; Additional caching key. If changed, cache is purged
|
||||
index = "v1"
|
||||
|
||||
; Can be: files, APC, memcache, redis (beta)
|
||||
fast_cache_driver = "files"
|
||||
|
||||
; Additional caching key. If changed, fast cache is purged
|
||||
fast_cache_index = "v1"
|
||||
|
||||
; Browser-level cache. If enabled, caching is maintainted without using files
|
||||
http = On
|
||||
|
||||
; Browser-level cache time (seconds, Expires header)
|
||||
http_expires = 3600
|
||||
|
||||
; Caching message UIDs when searching and sorting (threading)
|
||||
server_uids = On
|
||||
|
||||
[labs]
|
||||
; Experimental settings. Handle with care.
|
||||
;
|
||||
allow_mobile_version = On
|
||||
ignore_folders_subscription = Off
|
||||
check_new_password_strength = On
|
||||
update_channel = "stable"
|
||||
allow_gravatar = On
|
||||
allow_prefetch = On
|
||||
allow_smart_html_links = On
|
||||
cache_system_data = On
|
||||
date_from_headers = On
|
||||
autocreate_system_folders = On
|
||||
allow_message_append = Off
|
||||
disable_iconv_if_mbstring_supported = Off
|
||||
login_fault_delay = 1
|
||||
log_ajax_response_write_limit = 300
|
||||
allow_html_editor_source_button = Off
|
||||
allow_html_editor_biti_buttons = Off
|
||||
allow_ctrl_enter_on_compose = On
|
||||
try_to_detect_hidden_images = Off
|
||||
hide_dangerous_actions = Off
|
||||
use_app_debug_js = Off
|
||||
use_mobile_version_for_tablets = Off
|
||||
use_app_debug_css = Off
|
||||
use_imap_sort = On
|
||||
use_imap_force_selection = Off
|
||||
use_imap_list_subscribe = On
|
||||
use_imap_thread = On
|
||||
use_imap_move = Off
|
||||
use_imap_expunge_all_on_delete = Off
|
||||
imap_forwarded_flag = "$Forwarded"
|
||||
imap_read_receipt_flag = "$ReadReceipt"
|
||||
imap_body_text_limit = 555000
|
||||
imap_message_list_fast_simple_search = On
|
||||
imap_message_list_count_limit_trigger = 0
|
||||
imap_message_list_date_filter = 0
|
||||
imap_message_list_permanent_filter = ""
|
||||
imap_message_all_headers = Off
|
||||
imap_large_thread_limit = 50
|
||||
imap_folder_list_limit = 200
|
||||
imap_show_login_alert = On
|
||||
imap_use_auth_plain = On
|
||||
imap_use_auth_cram_md5 = Off
|
||||
smtp_show_server_errors = Off
|
||||
smtp_use_auth_plain = On
|
||||
smtp_use_auth_cram_md5 = Off
|
||||
sieve_allow_raw_script = Off
|
||||
sieve_utf8_folder_name = On
|
||||
sieve_auth_plain_initial = On
|
||||
sieve_allow_fileinto_inbox = Off
|
||||
imap_timeout = 300
|
||||
smtp_timeout = 60
|
||||
sieve_timeout = 10
|
||||
domain_list_limit = 99
|
||||
mail_func_clear_headers = On
|
||||
mail_func_additional_parameters = Off
|
||||
favicon_status = On
|
||||
folders_spec_limit = 50
|
||||
owncloud_save_folder = "Attachments"
|
||||
owncloud_suggestions = On
|
||||
curl_proxy = ""
|
||||
curl_proxy_auth = ""
|
||||
in_iframe = Off
|
||||
force_https = Off
|
||||
custom_login_link = ""
|
||||
custom_logout_link = ""
|
||||
allow_external_login = Off
|
||||
allow_external_sso = Off
|
||||
external_sso_key = ""
|
||||
http_client_ip_check_proxy = Off
|
||||
fast_cache_memcache_host = "127.0.0.1"
|
||||
fast_cache_memcache_port = 11211
|
||||
fast_cache_redis_host = "127.0.0.1"
|
||||
fast_cache_redis_port = 6379
|
||||
use_local_proxy_for_external_images = Off
|
||||
detect_image_exif_orientation = On
|
||||
cookie_default_path = ""
|
||||
cookie_default_secure = Off
|
||||
check_new_messages = On
|
||||
replace_env_in_configuration = ""
|
||||
startup_url = ""
|
||||
strict_html_parser = Off
|
||||
allow_cmd = Off
|
||||
dev_email = ""
|
||||
dev_password = ""
|
||||
|
||||
[version]
|
||||
current = "1.14.0"
|
||||
saved = "Wed, 08 Apr 2020 16:37:27 +0000"
|
||||
|
|
@ -0,0 +1,342 @@
|
|||
<?php
|
||||
|
||||
class ChangePasswordPostfixAdminDriver implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sEngine = 'MySQL';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sHost = '127.0.0.1';
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $iPort = 3306;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDatabase = 'postfixadmin';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sTable = 'mailbox';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sUsercol = 'username';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sPasscol = 'password';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sUser = 'postfixadmin';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sPassword = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sEncrypt = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sAllowedEmails = '';
|
||||
|
||||
/**
|
||||
* @var \MailSo\Log\Logger
|
||||
*/
|
||||
private $oLogger = null;
|
||||
|
||||
/**
|
||||
* @param string $sEngine
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetEngine($sEngine)
|
||||
{
|
||||
$this->sEngine = $sEngine;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHost
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetHost($sHost)
|
||||
{
|
||||
$this->sHost = $sHost;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iPort
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetPort($iPort)
|
||||
{
|
||||
$this->iPort = (int) $iPort;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDatabase
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetDatabase($sDatabase)
|
||||
{
|
||||
$this->sDatabase = $sDatabase;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTable
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetTable($sTable)
|
||||
{
|
||||
$this->sTable = $sTable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sUsercol
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetUserColumn($sUsercol)
|
||||
{
|
||||
$this->sUsercol = $sUsercol;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPasscol
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetPasswordColumn($sPasscol)
|
||||
{
|
||||
$this->sPasscol = $sPasscol;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sUser
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetUser($sUser)
|
||||
{
|
||||
$this->sUser = $sUser;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPassword
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetPassword($sPassword)
|
||||
{
|
||||
$this->sPassword = $sPassword;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEncrypt
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetEncrypt($sEncrypt)
|
||||
{
|
||||
$this->sEncrypt = $sEncrypt;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sAllowedEmails
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetAllowedEmails($sAllowedEmails)
|
||||
{
|
||||
$this->sAllowedEmails = $sAllowedEmails;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Log\Logger $oLogger
|
||||
*
|
||||
* @return \ChangePasswordPostfixAdminDriver
|
||||
*/
|
||||
public function SetLogger($oLogger)
|
||||
{
|
||||
if ($oLogger instanceof \MailSo\Log\Logger)
|
||||
{
|
||||
$this->oLogger = $oLogger;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function PasswordChangePossibility($oAccount)
|
||||
{
|
||||
return $oAccount && $oAccount->Email() &&
|
||||
\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->sAllowedEmails);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sPrevPassword
|
||||
* @param string $sNewPassword
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Postfix: Try to change password for '.$oAccount->Email());
|
||||
}
|
||||
|
||||
unset($sPrevPassword);
|
||||
|
||||
$bResult = false;
|
||||
|
||||
if (0 < \strlen($sNewPassword))
|
||||
{
|
||||
try
|
||||
{
|
||||
$sDsn = '';
|
||||
switch($this->sEngine){
|
||||
case 'MySQL':
|
||||
$sDsn = 'mysql:host='.$this->sHost.';port='.$this->iPort.';dbname='.$this->sDatabase;
|
||||
break;
|
||||
case 'PostgreSQL':
|
||||
$sDsn = 'pgsql:host='.$this->sHost.';port='.$this->iPort.';dbname='.$this->sDatabase;
|
||||
break;
|
||||
default:
|
||||
$sDsn = 'mysql:host='.$this->sHost.';port='.$this->iPort.';dbname='.$this->sDatabase;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$oPdo = new \PDO($sDsn, $this->sUser, $this->sPassword);
|
||||
$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
$sUpdatePassword = $this->cryptPassword($sNewPassword, $oPdo);
|
||||
if (0 < \strlen($sUpdatePassword))
|
||||
{
|
||||
$oStmt = $oPdo->prepare("UPDATE {$this->sTable} SET {$this->sPasscol} = ? WHERE {$this->sUsercol} = ?");
|
||||
$bResult = (bool) $oStmt->execute(array($sUpdatePassword, $oAccount->Email()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Postfix: Encrypted password is empty',
|
||||
\MailSo\Log\Enumerations\Type::ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
$oPdo = null;
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->WriteException($oException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPassword
|
||||
* @param \PDO $oPdo
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function cryptPassword($sPassword, $oPdo)
|
||||
{
|
||||
$sResult = '';
|
||||
if (function_exists('random_bytes')) {
|
||||
$sSalt = substr(base64_encode(random_bytes(32)), 0, 16);
|
||||
} else {
|
||||
$sSalt = substr(str_shuffle('./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'), 0, 16);
|
||||
}
|
||||
switch (strtolower($this->sEncrypt))
|
||||
{
|
||||
default:
|
||||
case 'plain':
|
||||
case 'cleartext':
|
||||
$sResult = '{PLAIN}' . $sPassword;
|
||||
break;
|
||||
|
||||
case 'md5crypt':
|
||||
include_once __DIR__.'/md5crypt.php';
|
||||
$sResult = '{MD5-CRYPT}' . md5crypt($sPassword);
|
||||
break;
|
||||
|
||||
case 'md5':
|
||||
$sResult = '{PLAIN-MD5}' . md5($sPassword);
|
||||
break;
|
||||
|
||||
case 'system':
|
||||
$sResult = '{CRYPT}' . crypt($sPassword);
|
||||
break;
|
||||
|
||||
case 'sha256-crypt':
|
||||
$sResult = '{SHA256-CRYPT}' . crypt($sPassword,'$5$'.$sSalt);
|
||||
break;
|
||||
|
||||
case 'sha512-crypt':
|
||||
$sResult = '{SHA512-CRYPT}' . crypt($sPassword,'$6$'.$sSalt);
|
||||
break;
|
||||
|
||||
case 'mysql_encrypt':
|
||||
if($this->sEngine == 'MySQL'){
|
||||
$oStmt = $oPdo->prepare('SELECT ENCRYPT(?) AS encpass');
|
||||
if ($oStmt->execute(array($sPassword)))
|
||||
{
|
||||
$aFetchResult = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
if (\is_array($aFetchResult) && isset($aFetchResult[0]['encpass']))
|
||||
{
|
||||
$sResult = $aFetchResult[0]['encpass'];
|
||||
}
|
||||
}
|
||||
}else{
|
||||
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CouldNotSaveNewPassword);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 RainLoop Team, @zaffkea
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1 @@
|
|||
Plugin that adds functionality to change the email account password (PostfixAdmin).
|
||||
|
|
@ -0,0 +1 @@
|
|||
1.3
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
class PostfixadminChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||
{
|
||||
public function Init()
|
||||
{
|
||||
$this->addHook('main.fabrica', 'MainFabrica');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Supported()
|
||||
{
|
||||
if (!extension_loaded('pdo') || !class_exists('PDO'))
|
||||
{
|
||||
return 'The PHP extension PDO must be installed to use this plugin';
|
||||
}
|
||||
|
||||
$aDrivers = \PDO::getAvailableDrivers();
|
||||
if (!is_array($aDrivers) || (!in_array('mysql', $aDrivers) && !in_array('pgsql', $aDrivers)))
|
||||
{
|
||||
return 'The PHP extension PDO (mysql or pgsql) must be installed to use this plugin';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param mixed $oProvider
|
||||
*/
|
||||
public function MainFabrica($sName, &$oProvider)
|
||||
{
|
||||
switch ($sName)
|
||||
{
|
||||
case 'change-password':
|
||||
|
||||
include_once __DIR__.'/ChangePasswordPostfixAdminDriver.php';
|
||||
|
||||
$oProvider = new ChangePasswordPostfixAdminDriver();
|
||||
|
||||
$oProvider
|
||||
->SetEngine($this->Config()->Get('plugin', 'engine',''))
|
||||
->SetHost($this->Config()->Get('plugin', 'host', ''))
|
||||
->SetPort((int) $this->Config()->Get('plugin', 'port', 3306))
|
||||
->SetDatabase($this->Config()->Get('plugin', 'database', ''))
|
||||
->SetTable($this->Config()->Get('plugin', 'table', ''))
|
||||
->SetUserColumn($this->Config()->Get('plugin', 'usercol', ''))
|
||||
->SetPasswordColumn($this->Config()->Get('plugin', 'passcol', ''))
|
||||
->SetUser($this->Config()->Get('plugin', 'user', ''))
|
||||
->SetPassword($this->Config()->Get('plugin', 'password', ''))
|
||||
->SetEncrypt($this->Config()->Get('plugin', 'encrypt', ''))
|
||||
->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', ''))))
|
||||
->SetLogger($this->Manager()->Actions()->Logger())
|
||||
;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function configMapping()
|
||||
{
|
||||
return array(
|
||||
\RainLoop\Plugins\Property::NewInstance('engine')->SetLabel('Engine')
|
||||
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
|
||||
->SetDefaultValue(array('MySQL', 'PostgreSQL'))
|
||||
->SetDescription('Database Engine'),
|
||||
\RainLoop\Plugins\Property::NewInstance('host')->SetLabel('Host')
|
||||
->SetDefaultValue('127.0.0.1'),
|
||||
\RainLoop\Plugins\Property::NewInstance('port')->SetLabel('Port')
|
||||
->SetType(\RainLoop\Enumerations\PluginPropertyType::INT)
|
||||
->SetDefaultValue(3306),
|
||||
\RainLoop\Plugins\Property::NewInstance('database')->SetLabel('Database')
|
||||
->SetDefaultValue('postfixadmin'),
|
||||
\RainLoop\Plugins\Property::NewInstance('table')->SetLabel('table')
|
||||
->SetDefaultValue('mailbox'),
|
||||
\RainLoop\Plugins\Property::NewInstance('usercol')->SetLabel('username column')
|
||||
->SetDefaultValue('username'),
|
||||
\RainLoop\Plugins\Property::NewInstance('passcol')->SetLabel('password column')
|
||||
->SetDefaultValue('password'),
|
||||
\RainLoop\Plugins\Property::NewInstance('user')->SetLabel('User')
|
||||
->SetDefaultValue('postfixadmin'),
|
||||
\RainLoop\Plugins\Property::NewInstance('password')->SetLabel('Password')
|
||||
->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD)
|
||||
->SetDefaultValue(''),
|
||||
\RainLoop\Plugins\Property::NewInstance('encrypt')->SetLabel('Encrypt')
|
||||
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
|
||||
->SetDefaultValue(array('md5crypt', 'md5', 'system', 'cleartext', 'mysql_encrypt', 'SHA256-CRYPT', 'SHA512-CRYPT'))
|
||||
->SetDescription('In what way do you want the passwords to be crypted ?'),
|
||||
\RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails')
|
||||
->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT)
|
||||
->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net')
|
||||
->SetDefaultValue('*')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
// md5crypt
|
||||
// Action: Creates MD5 encrypted password
|
||||
// Call: md5crypt (string cleartextpassword)
|
||||
|
||||
function md5crypt($pw, $salt = "", $magic = "")
|
||||
{
|
||||
$MAGIC = "$1$";
|
||||
|
||||
if ($magic == "")
|
||||
{
|
||||
$magic = $MAGIC;
|
||||
}
|
||||
|
||||
if ($salt == "")
|
||||
{
|
||||
$salt = create_salt();
|
||||
}
|
||||
|
||||
$slist = explode("$", $salt);
|
||||
if (isset($slist[0]) && $slist[0] == "1")
|
||||
{
|
||||
$salt = $slist[1];
|
||||
}
|
||||
|
||||
$salt = substr($salt, 0, 8);
|
||||
$ctx = $pw.$magic.$salt;
|
||||
$final = hex2bin(md5($pw.$salt.$pw));
|
||||
|
||||
for ($i = strlen($pw); $i > 0; $i -= 16)
|
||||
{
|
||||
if ($i > 16)
|
||||
{
|
||||
$ctx .= substr($final,0,16);
|
||||
}
|
||||
else
|
||||
{
|
||||
$ctx .= substr($final,0,$i);
|
||||
}
|
||||
}
|
||||
|
||||
$i = strlen($pw);
|
||||
|
||||
while ($i > 0)
|
||||
{
|
||||
if ($i & 1)
|
||||
{
|
||||
$ctx .= chr(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
$ctx .= $pw[0];
|
||||
}
|
||||
|
||||
$i = $i >> 1;
|
||||
}
|
||||
|
||||
$final = hex2bin(md5($ctx));
|
||||
|
||||
for ($i=0; $i<1000; $i++)
|
||||
{
|
||||
$ctx1 = "";
|
||||
if ($i & 1)
|
||||
{
|
||||
$ctx1 .= $pw;
|
||||
}
|
||||
else
|
||||
{
|
||||
$ctx1 .= substr($final,0,16);
|
||||
}
|
||||
if ($i % 3)
|
||||
{
|
||||
$ctx1 .= $salt;
|
||||
}
|
||||
if ($i % 7)
|
||||
{
|
||||
$ctx1 .= $pw;
|
||||
}
|
||||
if ($i & 1)
|
||||
{
|
||||
$ctx1 .= substr($final, 0, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
$ctx1 .= $pw;
|
||||
}
|
||||
|
||||
$final = hex2bin(md5($ctx1));
|
||||
}
|
||||
|
||||
$passwd = "";
|
||||
$passwd .= to64(((ord($final[0]) << 16) | (ord($final[6]) << 8) | (ord($final[12]))), 4);
|
||||
$passwd .= to64(((ord($final[1]) << 16) | (ord($final[7]) << 8) | (ord($final[13]))), 4);
|
||||
$passwd .= to64(((ord($final[2]) << 16) | (ord($final[8]) << 8) | (ord($final[14]))), 4);
|
||||
$passwd .= to64(((ord($final[3]) << 16) | (ord($final[9]) << 8) | (ord($final[15]))), 4);
|
||||
$passwd .= to64(((ord($final[4]) << 16) | (ord($final[10]) << 8) | (ord($final[5]))), 4);
|
||||
$passwd .= to64(ord($final[11]), 2);
|
||||
|
||||
return $magic.$salt.'$'.$passwd;
|
||||
}
|
||||
|
||||
function create_salt()
|
||||
{
|
||||
srand((double) microtime() * 1000000);
|
||||
return substr(md5(rand(0,9999999)), 0, 8);
|
||||
}
|
||||
|
||||
// PHP around 5.3.8 includes hex2bin as native function - http://php.net/hex2bin
|
||||
if (!function_exists('hex2bin'))
|
||||
{
|
||||
function hex2bin($str)
|
||||
{
|
||||
$len = strlen($str);
|
||||
$nstr = "";
|
||||
for ($i = 0; $i < $len; $i += 2)
|
||||
{
|
||||
$num = sscanf(substr($str, $i, 2), "%x");
|
||||
$nstr .= chr($num[0]);
|
||||
}
|
||||
|
||||
return $nstr;
|
||||
}
|
||||
}
|
||||
|
||||
function to64($v, $n)
|
||||
{
|
||||
$ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
$ret = "";
|
||||
|
||||
while (($n - 1) >= 0)
|
||||
{
|
||||
$n--;
|
||||
$ret .= $ITOA64[$v & 0x3f];
|
||||
$v = $v >> 6;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue