This commit is contained in:
the-djmaze 2023-04-24 11:19:07 +02:00
parent 6e0372dcee
commit 80d64574a6
7 changed files with 149 additions and 48 deletions

View file

@ -24,6 +24,10 @@ export class AdminSettingsContacts extends AbstractViewSettings {
this.addSettings(['contactsEnable','contactsSync']);
this.addSetting('contactsMySQLSSLCA');
this.addSetting('contactsMySQLSSLVerify');
this.addSetting('contactsMySQLSSLCiphers');
addObservablesTo(this, {
testing: false,
testContactsSuccess: false,
@ -92,10 +96,13 @@ export class AdminSettingsContacts extends AbstractViewSettings {
this.testing(false);
}, {
contactsPdoType: this.contactsPdoType(),
contactsPdoDsn: this.contactsPdoDsn(),
contactsPdoUser: this.contactsPdoUser(),
contactsPdoPassword: this.contactsPdoPassword()
PdoType: this.contactsPdoType(),
PdoDsn: this.contactsPdoDsn(),
PdoUser: this.contactsPdoUser(),
PdoPassword: this.contactsPdoPassword(),
MySQLSSLCA: this.contactsMySQLSSLCA(),
MySQLSSLVerify: this.contactsMySQLSSLVerify(),
MySQLSSLCiphers: this.contactsMySQLSSLCiphers()
}
);
}

View file

@ -625,6 +625,7 @@ class Actions
$UserLanguageRaw = $this->detectUserLanguage($bAdmin);
if ($bAdmin) {
// $this->AdminAppData($aResult);
$aResult['Auth'] = $this->IsAdminLoggined(false);
if ($aResult['Auth']) {
$aResult['adminLogin'] = (string)$oConfig->Get('security', 'admin_login', '');
@ -639,11 +640,14 @@ class Actions
$aResult['contactsEnable'] = (bool)$oConfig->Get('contacts', 'enable', false);
$aResult['contactsSync'] = (bool)$oConfig->Get('contacts', 'allow_sync', false);
$aResult['contactsPdoType'] = Providers\AddressBook\PdoAddressBook::validPdoType($this->oConfig->Get('contacts', 'type', 'sqlite'));
$aResult['contactsPdoType'] = Providers\AddressBook\PdoAddressBook::validPdoType($oConfig->Get('contacts', 'type', 'sqlite'));
$aResult['contactsPdoDsn'] = (string)$oConfig->Get('contacts', 'pdo_dsn', '');
$aResult['contactsPdoType'] = (string)$oConfig->Get('contacts', 'type', '');
$aResult['contactsPdoUser'] = (string)$oConfig->Get('contacts', 'pdo_user', '');
$aResult['contactsPdoPassword'] = static::APP_DUMMY;
$aResult['contactsMySQLSSLCA'] = (string) $oConfig->Get('contacts', 'mysql_ssl_ca', '');
$aResult['contactsMySQLSSLVerify'] = !!$oConfig->Get('contacts', 'mysql_ssl_verify', true);
$aResult['contactsMySQLSSLCiphers'] = (string) $oConfig->Get('contacts', 'mysql_ssl_ciphers', '');
$aResult['contactsSuggestionsLimit'] = (int)$oConfig->Get('contacts', 'suggestions_limit', 20);
$aResult['faviconUrl'] = $oConfig->Get('webmail', 'favicon_url', '');

View file

@ -73,6 +73,9 @@ class ActionsAdmin extends Actions
$this->setConfigFromParams($oConfig, 'contactsPdoDsn', 'contacts', 'pdo_dsn', 'string');
$this->setConfigFromParams($oConfig, 'contactsPdoUser', 'contacts', 'pdo_user', 'string');
$this->setConfigFromParams($oConfig, 'contactsPdoPassword', 'contacts', 'pdo_password', 'dummy');
$this->setConfigFromParams($oConfig, 'contactsMySQLSSLCA', 'contacts', 'mysql_ssl_ca', 'string');
$this->setConfigFromParams($oConfig, 'contactsMySQLSSLVerify', 'contacts', 'mysql_ssl_verify', 'bool');
$this->setConfigFromParams($oConfig, 'contactsMySQLSSLCiphers', 'contacts', 'mysql_ssl_ciphers', 'string');
$this->setConfigFromParams($oConfig, 'contactsSuggestionsLimit', 'contacts', 'suggestions_limit', 'int');
$this->setConfigFromParams($oConfig, 'contactsPdoType', 'contacts', 'type', 'string', function ($sType) use ($self) {
return Providers\AddressBook\PdoAddressBook::validPdoType($sType);
@ -141,12 +144,15 @@ class ActionsAdmin extends Actions
$this->IsAdminLoggined();
$oConfig = $this->Config();
$this->setConfigFromParams($oConfig, 'contactsPdoDsn', 'contacts', 'pdo_dsn', 'string');
$this->setConfigFromParams($oConfig, 'contactsPdoUser', 'contacts', 'pdo_user', 'string');
$this->setConfigFromParams($oConfig, 'contactsPdoPassword', 'contacts', 'pdo_password', 'dummy');
$this->setConfigFromParams($oConfig, 'contactsPdoType', 'contacts', 'type', 'string', function ($sType) {
$this->setConfigFromParams($oConfig, 'PdoDsn', 'contacts', 'pdo_dsn', 'string');
$this->setConfigFromParams($oConfig, 'PdoUser', 'contacts', 'pdo_user', 'string');
$this->setConfigFromParams($oConfig, 'PdoPassword', 'contacts', 'pdo_password', 'dummy');
$this->setConfigFromParams($oConfig, 'PdoType', 'contacts', 'type', 'string', function ($sType) {
return Providers\AddressBook\PdoAddressBook::validPdoType($sType);
});
$this->setConfigFromParams($oConfig, 'MySQLSSLCA', 'contacts', 'mysql_ssl_ca', 'string');
$this->setConfigFromParams($oConfig, 'MySQLSSLVerify', 'contacts', 'mysql_ssl_verify', 'bool');
$this->setConfigFromParams($oConfig, 'MySQLSSLCiphers', 'contacts', 'mysql_ssl_ciphers', 'string');
$sTestMessage = '';
try {
@ -323,6 +329,55 @@ class ActionsAdmin extends Actions
return $this->DefaultResponse($QR->__toString());
}
/*
public function AdminAppData(array &$aResult): void
{
$oConfig = $this->oConfig;
$aResult['Auth'] = $this->IsAdminLoggined(false);
if ($aResult['Auth']) {
$aResult['adminLogin'] = (string)$oConfig->Get('security', 'admin_login', '');
$aResult['adminTOTP'] = (string)$oConfig->Get('security', 'admin_totp', '');
$aResult['pluginsEnable'] = (bool)$oConfig->Get('plugins', 'enable', false);
$aResult['loginDefaultDomain'] = $oConfig->Get('login', 'default_domain', '');
$aResult['determineUserLanguage'] = (bool)$oConfig->Get('login', 'determine_user_language', true);
$aResult['determineUserDomain'] = (bool)$oConfig->Get('login', 'determine_user_domain', false);
$aResult['supportedPdoDrivers'] = \RainLoop\Common\PdoAbstract::getAvailableDrivers();
$aResult['contactsEnable'] = (bool)$oConfig->Get('contacts', 'enable', false);
$aResult['contactsSync'] = (bool)$oConfig->Get('contacts', 'allow_sync', false);
$aResult['contactsPdoType'] = Providers\AddressBook\PdoAddressBook::validPdoType($oConfig->Get('contacts', 'type', 'sqlite'));
$aResult['contactsPdoDsn'] = (string)$oConfig->Get('contacts', 'pdo_dsn', '');
$aResult['contactsPdoType'] = (string)$oConfig->Get('contacts', 'type', '');
$aResult['contactsPdoUser'] = (string)$oConfig->Get('contacts', 'pdo_user', '');
$aResult['contactsPdoPassword'] = static::APP_DUMMY;
$aResult['contactsMySQLSSLCA'] = (string) $oConfig->Get('contacts', 'mysql_ssl_ca', '');
$aResult['contactsMySQLSSLVerify'] = !!$oConfig->Get('contacts', 'mysql_ssl_verify', true);
$aResult['contactsMySQLSSLCiphers'] = (string) $oConfig->Get('contacts', 'mysql_ssl_ciphers', '');
$aResult['contactsSuggestionsLimit'] = (int)$oConfig->Get('contacts', 'suggestions_limit', 20);
$aResult['faviconUrl'] = $oConfig->Get('webmail', 'favicon_url', '');
$aResult['weakPassword'] = \is_file(APP_PRIVATE_DATA.'admin_password.txt');
$aResult['System']['languagesAdmin'] = \SnappyMail\L10n::getLanguages(true);
$aResult['languageAdmin'] = $this->ValidateLanguage($oConfig->Get('webmail', 'language_admin', 'en'), '', true);
$aResult['languageUsers'] = $this->ValidateLanguage($this->detectUserLanguage(true), '', true, true);
} else {
$passfile = APP_PRIVATE_DATA.'admin_password.txt';
$sPassword = $oConfig->Get('security', 'admin_password', '');
if (!$sPassword) {
$sPassword = \substr(\base64_encode(\random_bytes(16)), 0, 12);
Utils::saveFile($passfile, $sPassword . "\n");
// \chmod($passfile, 0600);
$oConfig->SetPassword($sPassword);
$oConfig->Save();
}
}
}
*/
private function setAdminAuthToken() : string
{
$sRand = \MailSo\Base\Utils::Sha1Rand();

View file

@ -6,35 +6,20 @@ abstract class PdoAbstract
{
use \MailSo\Log\Inherit;
/**
* @var \PDO
*/
protected $oPDO = null;
protected ?\PDO $oPDO = null;
/**
* @var bool
*/
protected $bExplain = false;
protected bool $bExplain = false;
/**
* @var bool
*/
protected $bSqliteCollate = true;
protected bool $bSqliteCollate = true;
/**
* @var string
*/
protected $sDbType;
protected string $sDbType;
public function IsSupported() : bool
{
return !!\class_exists('PDO');
}
protected function getPdoAccessData() : array
{
return array('', '', '', '');
}
abstract protected function getPdoAccessData() : array;
public function sqliteNoCaseCollationHelper(string $sStr1, string $sStr2) : int
{
@ -64,7 +49,7 @@ abstract class PdoAbstract
}
$sType = $sDsn = $sDbLogin = $sDbPassword = '';
list($sType, $sDsn, $sDbLogin, $sDbPassword) = $this->getPdoAccessData();
list($sType, $sDsn, $sDbLogin, $sDbPassword, $sSslCa, $bSslVerify, $sSslCiphers) = $this->getPdoAccessData();
if (!\in_array($sType, static::getAvailableDrivers())) {
throw new \Exception('Unknown PDO SQL connection type');
@ -76,7 +61,24 @@ abstract class PdoAbstract
$this->sDbType = $sType;
$oPdo = new \PDO($sDsn, $sDbLogin, $sDbPassword);
$options = [];
if ('mysql' === $sType) {
if ($sSslCa) {
$options[\PDO::MYSQL_ATTR_SSL_CA] = $sSslCa;
}
$options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = !empty($bSslVerify);
if ($sSslCiphers) {
$options[\PDO::MYSQL_ATTR_SSL_CIPHER] = $sSslCiphers;
}
/*
$options[\PDO::MYSQL_ATTR_SSL_CAPATH] = '';
// mutual (two-way) authentication
$options[\PDO::MYSQL_ATTR_SSL_KEY] = '';
$options[\PDO::MYSQL_ATTR_SSL_CERT] = '';
*/
}
$oPdo = new \PDO($sDsn, $sDbLogin, $sDbPassword, $options);
$sPdoType = $oPdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

View file

@ -189,6 +189,9 @@ Warning: only enable when server does not do this, else double compression error
'pdo_dsn' => array('host=127.0.0.1;port=3306;dbname=snappymail'),
'pdo_user' => array('root'),
'pdo_password' => array(''),
'mysql_ssl_ca' => array('', 'PEM format certificate'),
'mysql_ssl_verify' => array(true),
'mysql_ssl_ciphers' => array('', 'HIGH'),
'suggestions_limit' => array(20)
),

View file

@ -16,25 +16,19 @@ class PdoAddressBook
private $iUserID = 0;
/**
* @var string
*/
private $sDsn;
private string $sDsn;
/**
* @var string
*/
private $sDsnType;
private string $sDsnType;
/**
* @var string
*/
private $sUser;
private string $sUser;
/**
* @var string
*/
private $sPassword;
private string $sPassword;
private string $sSslCa = '';
private bool $bSslVerify = true;
private string $sSslCiphers = '';
private static $aSearchInFields = [
PropertyType::EMAIl,
@ -69,6 +63,11 @@ class PdoAddressBook
$sUser = \trim($oConfig->Get('contacts', 'pdo_user', ''));
$sPassword = (string)$oConfig->Get('contacts', 'pdo_password', '');
$sDsn = $sDsnType . ':' . \preg_replace('/^[a-z]+:/', '', $sDsn);
if ('mysql' === $sDsnType) {
$this->sSslCa = \trim($oConfig->Get('contacts', 'mysql_ssl_ca', ''));
$this->bSslVerify = !!$oConfig->Get('contacts', 'mysql_ssl_verify', true);
$this->sSslCiphers = \trim($oConfig->Get('contacts', 'mysql_ssl_ciphers', ''));
}
}
$this->sDsn = $sDsn;
@ -1308,7 +1307,15 @@ SQLITEINITIAL;
protected function getPdoAccessData() : array
{
return array($this->sDsnType, $this->sDsn, $this->sUser, $this->sPassword);
$sSslCa = $this->sSslCa;
if ($sSslCa && !\is_file($sSslCa)) {
$sFile = \APP_PRIVATE_DATA . 'configs/contacts_mysql_ssl_ca.pem';
// $sSslCa = (\is_file($sFile) || \file_put_contents($sFile, $sSslCa)) ? $sFile : '';
$sSslCa = \file_put_contents($sFile, $sSslCa) ? $sFile : '';
}
return array($this->sDsnType, $this->sDsn, $this->sUser, $this->sPassword,
$sSslCa, $this->bSslVerify, $this->sSslCiphers
);
}
protected function getUserId(string $sEmail, bool $bSkipInsert = false, bool $bCache = true) : int

View file

@ -64,6 +64,29 @@
data-bind="value: contactsPdoPassword, saveTrigger: contactsPdoPasswordTrigger">
</div>
</div>
<div data-bind="visible: 'mysql' === contactsPdoType()">
<div class="control-group">
<label>SSL CA</label>
<div>
<textarea placeholder="PEM formatted" data-bind="value: contactsMySQLSSLCA, saveTrigger: contactsMySQLSSLCATrigger"></textarea>
</div>
</div>
<div class="control-group">
<label></label>
<div data-bind="component: {
name: 'Checkbox',
params: { value: contactsMySQLSSLVerify, label: 'VERIFY SERVER CERT' }
}"></div>
</div>
<div class="control-group">
<label>SSL CIPHER</label>
<div>
<input type="text" placeholder="HIGH" data-bind="value: contactsMySQLSSLCiphers, saveTrigger: contactsMySQLSSLCiphersTrigger">
</div>
</div>
</div>
<div class="control-group">
<label></label>
<a class="btn" data-bind="command: testContactsCommand, css: { 'btn-success': testContactsSuccess, 'btn-danger': testContactsError }">