From 4cd86ede0b93c2a4dd55dea60ddd22be0038cf11 Mon Sep 17 00:00:00 2001 From: Michael Barnathan Date: Thu, 17 Aug 2017 18:11:14 -0400 Subject: [PATCH 1/2] MailSo changes for TLS certs --- rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php | 6 ++++-- rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php | 5 +++-- rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php | 8 +++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php index 9e01e2c12d..86c281bf69 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php @@ -137,6 +137,7 @@ public function GetLogginedUser() * @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT * @param bool $bVerifySsl = false * @param bool $bAllowSelfSigned = true + * @param string $sClientCert = NULL * * @return \MailSo\Imap\ImapClient * @@ -146,11 +147,12 @@ public function GetLogginedUser() */ public function Connect($sServerName, $iPort = 143, $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT, - $bVerifySsl = false, $bAllowSelfSigned = true) + $bVerifySsl = false, $bAllowSelfSigned = true, + $sClientCert = '') { $this->aTagTimeouts['*'] = \microtime(true); - parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl, $bAllowSelfSigned); + parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl, $bAllowSelfSigned, $sClientCert); $this->parseResponseWithValidation('*', true); diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php index 3d387515e9..3f083ea845 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php @@ -59,6 +59,7 @@ public function ImapClient() * @param int $iPort = 143 * @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT * @param bool $bVerifySsl = false + * @param string $sClientCert = "" * * @return \MailSo\Mail\MailClient * @@ -67,9 +68,9 @@ public function ImapClient() * @throws \MailSo\Imap\Exceptions\Exception */ public function Connect($sServerName, $iPort = 143, - $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT, $bVerifySsl = false) + $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT, $bVerifySsl = false, $bAllowSelfSigned = false, $sClientCert = '') { - $this->oImapClient->Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl); + $this->oImapClient->Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl, $bAllowSelfSigned, $sClientCert); return $this; } diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php index 5fffbbf92b..35cad72ab5 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Net/NetClient.php @@ -196,6 +196,7 @@ public function capturePhpErrorWithException($iErrNo, $sErrStr, $sErrFile, $iErr * @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT * @param bool $bVerifySsl = false * @param bool $bAllowSelfSigned = true + * @param string $sClientCert = NULL * * @return void * @@ -205,7 +206,8 @@ public function capturePhpErrorWithException($iErrNo, $sErrStr, $sErrFile, $iErr */ public function Connect($sServerName, $iPort, $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT, - $bVerifySsl = false, $bAllowSelfSigned = true) + $bVerifySsl = false, $bAllowSelfSigned = true, + $sClientCert = '') { if (!\MailSo\Base\Validator::NotEmptyString($sServerName, true) || !\MailSo\Base\Validator::PortInt($iPort)) { @@ -254,13 +256,13 @@ public function Connect($sServerName, $iPort, $bVerifySsl = !!$bVerifySsl; $bAllowSelfSigned = $bVerifySsl ? !!$bAllowSelfSigned : true; - $aStreamContextSettings = array( 'ssl' => array( 'verify_host' => $bVerifySsl, 'verify_peer' => $bVerifySsl, 'verify_peer_name' => $bVerifySsl, - 'allow_self_signed' => $bAllowSelfSigned + 'allow_self_signed' => $bAllowSelfSigned, + 'local_cert' => $sClientCert ) ); From 02561e8acf023ee9ed9c36d54736a80996c167cd Mon Sep 17 00:00:00 2001 From: Michael Barnathan Date: Thu, 17 Aug 2017 18:13:01 -0400 Subject: [PATCH 2/2] TLS client certs in RainLoop. --- .../0.0.0/app/libraries/RainLoop/Actions.php | 14 +++++---- .../libraries/RainLoop/Config/Application.php | 1 + .../app/libraries/RainLoop/Model/Account.php | 30 +++++++++++++++---- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index 6a40a0a28f..57fe303be5 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -1261,11 +1261,12 @@ public function SetMailtoRequest($sTo) * @param string $sLogin * @param string $sPassword * @param string $sSignMeToken = '' + * @param string $sClientCert = '' * @param bool $bThrowProvideException = false * * @return \RainLoop\Model\Account|null */ - public function LoginProvide($sEmail, $sLogin, $sPassword, $sSignMeToken = '', $bThrowProvideException = false) + public function LoginProvide($sEmail, $sLogin, $sPassword, $sSignMeToken = '', $sClientCert = '', $bThrowProvideException = false) { $oAccount = null; if (0 < \strlen($sEmail) && 0 < \strlen($sLogin) && 0 < \strlen($sPassword)) @@ -1275,7 +1276,7 @@ public function LoginProvide($sEmail, $sLogin, $sPassword, $sSignMeToken = '', $ { if ($oDomain->ValidateWhiteList($sEmail, $sLogin)) { - $oAccount = \RainLoop\Model\Account::NewInstance($sEmail, $sLogin, $sPassword, $oDomain, $sSignMeToken); + $oAccount = \RainLoop\Model\Account::NewInstance($sEmail, $sLogin, $sPassword, $oDomain, $sSignMeToken, '', '', $sClientCert); $this->Plugins()->RunHook('filter.acount', array(&$oAccount)); if ($bThrowProvideException && !($oAccount instanceof \RainLoop\Model\Account)) @@ -1320,7 +1321,7 @@ public function GetAccountFromCustomToken($sToken, $bThrowExceptionOnFalse = tru ) { $oAccount = $this->LoginProvide($aAccountHash[1], $aAccountHash[2], $aAccountHash[3], - empty($aAccountHash[5]) ? '' : $aAccountHash[5], $bThrowExceptionOnFalse); + empty($aAccountHash[5]) ? '' : $aAccountHash[5], empty($aAccountHash[11]) ? '' : $aAccountHash[11], $bThrowExceptionOnFalse); if ($oAccount instanceof \RainLoop\Model\Account) { @@ -2241,10 +2242,10 @@ public function LoginProcess(&$sEmail, &$sPassword, $sSignMeToken = '', $this->Plugins()->RunHook('event.login-pre-login-provide', array()); $oAccount = null; - + $sClientCert = \trim($this->Config()->Get('ssl', 'client_cert', '')); try { - $oAccount = $this->LoginProvide($sEmail, $sLogin, $sPassword, $sSignMeToken, true); + $oAccount = $this->LoginProvide($sEmail, $sLogin, $sPassword, $sSignMeToken, $sClientCert, true); if (!($oAccount instanceof \RainLoop\Model\Account)) { @@ -4137,7 +4138,8 @@ public function DoAdminDomainTest() $iTime = \microtime(true); $oImapClient->Connect($oDomain->IncHost(), $oDomain->IncPort(), $oDomain->IncSecure(), !!$this->Config()->Get('ssl', 'verify_certificate', false), - !!$this->Config()->Get('ssl', 'allow_self_signed', true) + !!$this->Config()->Get('ssl', 'allow_self_signed', true), + $this->Config()->Get('ssl', 'client_cert', '') ); $iImapTime = \microtime(true) - $iTime; diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php index 873e9a0d6b..2bb35d2252 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php @@ -217,6 +217,7 @@ protected function defaultValues() 'allow_self_signed' => array(true, 'Allow self-signed certificates. Requires verify_certificate.'), 'cafile' => array('', 'Location of Certificate Authority file on local filesystem (/etc/ssl/certs/ca-certificates.crt)'), 'capath' => array('', 'capath must be a correctly hashed certificate directory. (/etc/ssl/certs/)'), + 'client_cert' => array('', 'Location of client certificate file (pem format with private key) on local filesystem'), ), 'capa' => array( diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php index 7c30a4724a..2e3f58c209 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php @@ -29,6 +29,11 @@ class Account extends \RainLoop\Account // for backward compatibility */ private $sProxyAuthPassword; + /** + * @var string + */ + private $sClientCert; + /** * @var string */ @@ -56,7 +61,7 @@ class Account extends \RainLoop\Account // for backward compatibility * @return void */ protected function __construct($sEmail, $sLogin, $sPassword, \RainLoop\Model\Domain $oDomain, - $sSignMeToken = '', $sProxyAuthUser = '', $sProxyAuthPassword = '') + $sSignMeToken = '', $sProxyAuthUser = '', $sProxyAuthPassword = '', $sClientCert = '') { $this->sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true); $this->sLogin = \MailSo\Base\Utils::IdnToAscii($sLogin); @@ -65,6 +70,7 @@ protected function __construct($sEmail, $sLogin, $sPassword, \RainLoop\Model\Dom $this->sSignMeToken = $sSignMeToken; $this->sProxyAuthUser = $sProxyAuthUser; $this->sProxyAuthPassword = $sProxyAuthPassword; + $this->sClientCert = $sClientCert; $this->sParentEmail = ''; } @@ -80,9 +86,9 @@ protected function __construct($sEmail, $sLogin, $sPassword, \RainLoop\Model\Dom * @return \RainLoop\Model\Account */ public static function NewInstance($sEmail, $sLogin, $sPassword, \RainLoop\Model\Domain $oDomain, - $sSignMeToken = '', $sProxyAuthUser = '', $sProxyAuthPassword = '') + $sSignMeToken = '', $sProxyAuthUser = '', $sProxyAuthPassword = '', $sClientCert = '') { - return new self($sEmail, $sLogin, $sPassword, $oDomain, $sSignMeToken, $sProxyAuthUser, $sProxyAuthPassword); + return new self($sEmail, $sLogin, $sPassword, $oDomain, $sSignMeToken, $sProxyAuthUser, $sProxyAuthPassword, $sClientCert); } /** @@ -185,6 +191,14 @@ public function Password() return $this->IncPassword(); } + /** + * @return string + */ + public function ClientCert() + { + return $this->sClientCert; + } + /** * @return bool */ @@ -362,7 +376,8 @@ public function GetAuthToken() \RainLoop\Utils::GetShortToken(), // 7 $this->sProxyAuthUser, // 8 $this->sProxyAuthPassword, // 9 - 0 // 10 // timelife + 0, // 10 // timelife + $this->sClientCert // 11 )); } @@ -382,7 +397,8 @@ public function GetAuthTokenQ() \RainLoop\Utils::GetShortToken(), // 7 $this->sProxyAuthUser, // 8 $this->sProxyAuthPassword, // 9 - 0 // 10 // timelife + 0, // 10 // timelife + $this->sClientCert // 11 )); } @@ -408,6 +424,7 @@ public function IncConnectAndLoginHelper($oPlugins, $oMailClient, $oConfig) 'ProxyAuthUser' => $this->ProxyAuthUser(), 'ProxyAuthPassword' => $this->ProxyAuthPassword(), 'VerifySsl' => !!$oConfig->Get('ssl', 'verify_certificate', false), + 'ClientCert' => $this->ClientCert(), 'AllowSelfSigned' => !!$oConfig->Get('ssl', 'allow_self_signed', true), 'UseAuthPlainIfSupported' => !!$oConfig->Get('labs', 'imap_use_auth_plain', true), 'UseAuthCramMd5IfSupported' => !!$oConfig->Get('labs', 'imap_use_auth_cram_md5', true) @@ -421,7 +438,8 @@ public function IncConnectAndLoginHelper($oPlugins, $oMailClient, $oConfig) { $oMailClient ->Connect($aImapCredentials['Host'], $aImapCredentials['Port'], - $aImapCredentials['Secure'], $aImapCredentials['VerifySsl'], $aImapCredentials['AllowSelfSigned']); + $aImapCredentials['Secure'], $aImapCredentials['VerifySsl'], + $aImapCredentials['AllowSelfSigned'], $aImapCredentials['ClientCert']); }