SMTP password security fix
This commit is contained in:
@@ -34,30 +34,47 @@
|
||||
* Метод отображения настроек
|
||||
*
|
||||
*/
|
||||
function settingsShow()
|
||||
{
|
||||
global $AVE_Template;
|
||||
function settingsShow()
|
||||
{
|
||||
global $AVE_Template;
|
||||
|
||||
$date_formats = array(
|
||||
'%d.%m.%Y',
|
||||
'%d %B %Y',
|
||||
'%A, %d.%m.%Y',
|
||||
'%A, %d %B %Y'
|
||||
);
|
||||
$date_formats = array(
|
||||
'%d.%m.%Y',
|
||||
'%d %B %Y',
|
||||
'%A, %d.%m.%Y',
|
||||
'%A, %d %B %Y'
|
||||
);
|
||||
|
||||
$time_formats = array(
|
||||
'%d.%m.%Y, %H:%M',
|
||||
'%d %B %Y, %H:%M',
|
||||
'%A, %d.%m.%Y (%H:%M)',
|
||||
'%A, %d %B %Y (%H:%M)'
|
||||
);
|
||||
$time_formats = array(
|
||||
'%d.%m.%Y, %H:%M',
|
||||
'%d %B %Y, %H:%M',
|
||||
'%A, %d.%m.%Y (%H:%M)',
|
||||
'%A, %d %B %Y (%H:%M)'
|
||||
);
|
||||
|
||||
$AVE_Template->assign('date_formats', $date_formats);
|
||||
$AVE_Template->assign('time_formats', $time_formats);
|
||||
$AVE_Template->assign('row', get_settings());
|
||||
$AVE_Template->assign('available_countries', get_country_list(1));
|
||||
$AVE_Template->assign('content', $AVE_Template->fetch('settings/settings_main.tpl'));
|
||||
}
|
||||
// 1. Получаем настройки (ПАРОЛЬ УЖЕ ДЕШИФРОВАН в кэше get_settings())
|
||||
$settings_data_array = get_settings();
|
||||
|
||||
// 2. Извлекаем строку настроек (обычно это $settings[0])
|
||||
$row = (isset($settings_data_array[0]) && is_array($settings_data_array[0]))
|
||||
? $settings_data_array[0]
|
||||
: (is_array($settings_data_array) ? $settings_data_array : array());
|
||||
|
||||
// 3. КРИТИЧЕСКАЯ ЛОГИКА МАСКИРОВКИ: Заменяем дешифрованный пароль на '****' для отображения
|
||||
if (isset($row['mail_type']) && $row['mail_type'] === 'smtp' && !empty($row['mail_smtp_pass'])) {
|
||||
// Дешифрованный пароль заменяется на '****' для поля формы
|
||||
$row['mail_smtp_pass'] = '****';
|
||||
}
|
||||
|
||||
$AVE_Template->assign('date_formats', $date_formats);
|
||||
$AVE_Template->assign('time_formats', $time_formats);
|
||||
|
||||
// 4. Передаем модифицированный массив с '****' в шаблон
|
||||
$AVE_Template->assign('row', $row);
|
||||
|
||||
$AVE_Template->assign('available_countries', get_country_list(1));
|
||||
$AVE_Template->assign('content', $AVE_Template->fetch('settings/settings_main.tpl'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Записывает события переключения файлов в специальный лог.
|
||||
@@ -342,98 +359,162 @@ function settingsCase()
|
||||
* Метод записи настроек
|
||||
*
|
||||
*/
|
||||
function settingsSave()
|
||||
{
|
||||
global $AVE_DB, $AVE_Template;
|
||||
function settingsSave()
|
||||
{
|
||||
global $AVE_DB, $AVE_Template;
|
||||
|
||||
// ДОБАВЛЕНО: Принудительно загружаем ключ шифрования.
|
||||
get_smtp_encryption_key();
|
||||
|
||||
$muname = ($_REQUEST['mail_smtp_login']) ? "mail_smtp_login = '" . $_REQUEST['mail_smtp_login'] . "'," : '';
|
||||
$mpass = ($_REQUEST['mail_smtp_pass']) ? "mail_smtp_pass = '" . $_REQUEST['mail_smtp_pass'] . "'," : '';
|
||||
$msmp = ($_REQUEST['mail_sendmail_path']) ? "mail_sendmail_path = '" . $_REQUEST['mail_sendmail_path'] . "'," : '';
|
||||
$mn = ($_REQUEST['mail_from_name']) ? "mail_from_name = '" . $_REQUEST['mail_from_name'] . "'," : '';
|
||||
$ma = ($_REQUEST['mail_from']) ? "mail_from = '" . $_REQUEST['mail_from'] . "'," : '';
|
||||
$ep = ($_REQUEST['page_not_found_id']) ? "page_not_found_id = '" . $_REQUEST['page_not_found_id'] . "'," : '';
|
||||
$sn = ($_REQUEST['site_name']) ? "site_name = '" . $_REQUEST['site_name'] . "'," : '';
|
||||
$mp = ($_REQUEST['mail_port']) ? "mail_port = '" . $_REQUEST['mail_port'] . "'," : '';
|
||||
$mh = ($_REQUEST['mail_host']) ? "mail_host = '" . $_REQUEST['mail_host'] . "'," : '';
|
||||
// ----------------------------------------------------
|
||||
// 1. ЛОГИКА ГЕНЕРАЦИИ УНИКАЛЬНОГО КЛЮЧА
|
||||
// ----------------------------------------------------
|
||||
if (isset($_REQUEST['mail_type']) && $_REQUEST['mail_type'] === 'smtp' && !file_exists(BASE_DIR . '/inc/smtp_key.php')) {
|
||||
|
||||
$new_key = create_smtp_key_file();
|
||||
|
||||
if (empty($new_key)) {
|
||||
$message = 'Ошибка: Не удалось создать файл ключа для SMTP-пароля. Проверьте права записи в папке inc/.';
|
||||
$header = $AVE_Template->get_config_vars('SETTINGS_ERROR');
|
||||
$theme = 'error';
|
||||
|
||||
$sql = $AVE_DB->Query("
|
||||
UPDATE
|
||||
" . PREFIX . "_settings
|
||||
SET
|
||||
" . $muname . "
|
||||
" . $mpass . "
|
||||
mail_smtp_encrypt = '" . $_REQUEST['mail_smtp_encrypt'] . "',
|
||||
" . $msmp . "
|
||||
" . $ma . "
|
||||
" . $mn . "
|
||||
" . $ep . "
|
||||
" . $sn . "
|
||||
" . $mp . "
|
||||
" . $mh . "
|
||||
default_country = '" . $_REQUEST['default_country'] . "',
|
||||
mail_type = '" . $_REQUEST['mail_type'] . "',
|
||||
mail_content_type = '" . $_REQUEST['mail_content_type'] . "',
|
||||
mail_word_wrap = '" . (int)$_REQUEST['mail_word_wrap'] . "',
|
||||
mail_new_user = '" . $_REQUEST['mail_new_user'] . "',
|
||||
mail_signature = '" . $_REQUEST['mail_signature'] . "',
|
||||
message_forbidden = '" . $_REQUEST['message_forbidden'] . "',
|
||||
hidden_text = '" . $_REQUEST['hidden_text'] . "',
|
||||
navi_box = '" . $_REQUEST['navi_box'] . "',
|
||||
start_label = '" . $_REQUEST['start_label'] . "',
|
||||
end_label = '" . $_REQUEST['end_label'] . "',
|
||||
separator_label = '" . $_REQUEST['separator_label'] . "',
|
||||
next_label = '" . $_REQUEST['next_label'] . "',
|
||||
prev_label = '" . $_REQUEST['prev_label'] . "',
|
||||
total_label = '" . $_REQUEST['total_label'] . "',
|
||||
link_box = '" . $_REQUEST['link_box'] . "',
|
||||
total_box = '" . $_REQUEST['total_box'] . "',
|
||||
active_box = '" . $_REQUEST['active_box'] . "',
|
||||
separator_box = '" . $_REQUEST['separator_box'] . "',
|
||||
bread_box = '" . $_REQUEST['bread_box'] . "',
|
||||
bread_show_main = '" . ($_REQUEST['bread_show_main'] != 0 ? 1 : 0) . "',
|
||||
bread_show_host = '" . ($_REQUEST['bread_show_host'] != 0 ? 1 : 0) . "',
|
||||
bread_sepparator = '" . $_REQUEST['bread_sepparator'] . "',
|
||||
bread_sepparator_use = '" . ($_REQUEST['bread_sepparator_use'] != 0 ? 1 : 0) . "',
|
||||
bread_link_box = '" . $_REQUEST['bread_link_box'] . "',
|
||||
bread_link_template = '" . $_REQUEST['bread_link_template'] . "',
|
||||
bread_self_box = '" . $_REQUEST['bread_self_box'] . "',
|
||||
bread_link_box_last = '" . ($_REQUEST['bread_link_box_last'] != 0 ? 1 : 0) . "',
|
||||
date_format = '" . $_REQUEST['date_format'] . "',
|
||||
time_format = '" . $_REQUEST['time_format'] . "',
|
||||
use_doctime = '" . intval($_REQUEST['use_doctime']) . "'
|
||||
WHERE
|
||||
Id = 1
|
||||
");
|
||||
if (isset($_REQUEST['ajax']) && $_REQUEST['ajax'] == '1') {
|
||||
echo json_encode(array('message' => $message, 'header' => $header, 'theme' => $theme));
|
||||
} else {
|
||||
$AVE_Template->assign('message', $message);
|
||||
header('Location:index.php?do=settings&cp=' . SESSION);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
// 2. ОБРАБОТКА И ШИФРОВАНИЕ SMTP ПАРОЛЯ (С ИГНОРОМ ****)
|
||||
// ----------------------------------------------------
|
||||
$smtp_pass_encrypted = null; // Используем null, чтобы пропустить поле в SQL, если оно пустое или ****
|
||||
|
||||
if ($sql->_result === false)
|
||||
{
|
||||
$message = $AVE_Template->get_config_vars('SETTINGS_SAVED_ERR');
|
||||
$header = $AVE_Template->get_config_vars('SETTINGS_ERROR');
|
||||
$theme = 'error';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->clearSettingsCache();
|
||||
if (isset($_REQUEST['mail_smtp_pass'])) {
|
||||
|
||||
$new_smtp_pass_raw = trim($_REQUEST['mail_smtp_pass']);
|
||||
|
||||
$message = $AVE_Template->get_config_vars('SETTINGS_SAVED');
|
||||
$header = $AVE_Template->get_config_vars('SETTINGS_SUCCESS');
|
||||
$theme = 'accept';
|
||||
reportLog($AVE_Template->get_config_vars('SETTINGS_SAVE_MAIN'));
|
||||
}
|
||||
// ИСПРАВЛЕНО: Если пароль не пуст И не равен маске
|
||||
if (!empty($new_smtp_pass_raw) && $new_smtp_pass_raw !== '****') {
|
||||
|
||||
// ПАРОЛЬ БЫЛ ВВЕДЕН ИЛИ ИЗМЕНЕН: Шифруем новый пароль
|
||||
if (isset($_REQUEST['mail_type']) && $_REQUEST['mail_type'] === 'smtp') {
|
||||
$smtp_pass_encrypted = encrypt_smtp_pass($new_smtp_pass_raw);
|
||||
} else {
|
||||
$smtp_pass_encrypted = $new_smtp_pass_raw;
|
||||
}
|
||||
}
|
||||
// Если $new_smtp_pass_raw === '****' ИЛИ ПУСТОЙ, поле mail_smtp_pass не будет добавлено в SQL.
|
||||
}
|
||||
|
||||
if (isset($_REQUEST['ajax']) && $_REQUEST['ajax'] = '1')
|
||||
{
|
||||
echo json_encode(array('message' => $message, 'header' => $header, 'theme' => $theme));
|
||||
}
|
||||
else
|
||||
{
|
||||
$AVE_Template->assign('message', $message);
|
||||
header('Location:index.php?do=settings&cp=' . SESSION);
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
// ----------------------------------------------------
|
||||
// 3. ФОРМИРОВАНИЕ УСЛОВНЫХ И ОБЯЗАТЕЛЬНЫХ ПОЛЕЙ
|
||||
// ----------------------------------------------------
|
||||
|
||||
$mandatory_fields = array(
|
||||
"mail_smtp_login" => addslashes($_REQUEST['mail_smtp_login']),
|
||||
"mail_smtp_encrypt" => addslashes($_REQUEST['mail_smtp_encrypt']),
|
||||
"mail_sendmail_path" => addslashes($_REQUEST['mail_sendmail_path']),
|
||||
"mail_from_name" => addslashes($_REQUEST['mail_from_name']),
|
||||
"mail_from" => addslashes($_REQUEST['mail_from']),
|
||||
"page_not_found_id" => addslashes($_REQUEST['page_not_found_id']),
|
||||
"mail_port" => addslashes($_REQUEST['mail_port']),
|
||||
"mail_host" => addslashes($_REQUEST['mail_host']),
|
||||
"default_country" => addslashes($_REQUEST['default_country']),
|
||||
"mail_type" => addslashes($_REQUEST['mail_type']),
|
||||
"mail_content_type" => addslashes($_REQUEST['mail_content_type']),
|
||||
"mail_word_wrap" => (int)$_REQUEST['mail_word_wrap'],
|
||||
"mail_new_user" => addslashes($_REQUEST['mail_new_user']),
|
||||
"mail_signature" => addslashes($_REQUEST['mail_signature']),
|
||||
"message_forbidden" => addslashes($_REQUEST['message_forbidden']),
|
||||
"hidden_text" => addslashes($_REQUEST['hidden_text']),
|
||||
"date_format" => addslashes($_REQUEST['date_format']),
|
||||
"time_format" => addslashes($_REQUEST['time_format']),
|
||||
"use_doctime" => intval($_REQUEST['use_doctime'])
|
||||
);
|
||||
|
||||
// ДОБАВЛЯЕМ ПАРОЛЬ ТОЛЬКО ЕСЛИ ОН БЫЛ ВВЕДЕН ИЛИ ИЗМЕНЕН
|
||||
if ($smtp_pass_encrypted !== null) {
|
||||
$mandatory_fields["mail_smtp_pass"] = addslashes($smtp_pass_encrypted);
|
||||
}
|
||||
|
||||
|
||||
// Поля, которые обновляются ТОЛЬКО, если они были отправлены формой
|
||||
$conditional_keys = array(
|
||||
'site_name', 'navi_box', 'start_label', 'end_label', 'separator_label',
|
||||
'next_label', 'prev_label', 'total_label', 'link_box', 'total_box',
|
||||
'active_box', 'separator_box', 'bread_box', 'bread_show_main', 'bread_show_host',
|
||||
'bread_sepparator', 'bread_sepparator_use', 'bread_link_box', 'bread_link_template',
|
||||
'bread_self_box', 'bread_link_box_last'
|
||||
);
|
||||
|
||||
$set_clauses = array();
|
||||
|
||||
// 1. Формируем обязательные поля
|
||||
foreach ($mandatory_fields as $key => $value) {
|
||||
$set_clauses[] = "{$key} = '{$value}'";
|
||||
}
|
||||
|
||||
// 2. Формируем условные поля
|
||||
foreach ($conditional_keys as $key) {
|
||||
if (isset($_REQUEST[$key])) {
|
||||
$value = $_REQUEST[$key];
|
||||
|
||||
if (strpos($key, 'bread_') === 0 && (strpos($key, 'show') !== false || strpos($key, 'use') !== false || strpos($key, 'last') !== false)) {
|
||||
$set_clauses[] = "{$key} = '" . ($value != 0 ? 1 : 0) . "'";
|
||||
} else {
|
||||
$set_clauses[] = "{$key} = '" . addslashes($value) . "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Объединяем все части через запятую для SQL
|
||||
$set_string = implode(",\r\n", $set_clauses);
|
||||
|
||||
// ----------------------------------------------------
|
||||
// 4. ВЫПОЛНЕНИЕ SQL-ЗАПРОСА
|
||||
// ----------------------------------------------------
|
||||
$sql = $AVE_DB->Query("
|
||||
UPDATE
|
||||
" . PREFIX . "_settings
|
||||
SET
|
||||
" . $set_string . "
|
||||
WHERE
|
||||
Id = 1
|
||||
");
|
||||
|
||||
if ($sql->_result === false)
|
||||
{
|
||||
$message = $AVE_Template->get_config_vars('SETTINGS_SAVED_ERR');
|
||||
$header = $AVE_Template->get_config_vars('SETTINGS_ERROR');
|
||||
$theme = 'error';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->clearSettingsCache();
|
||||
|
||||
$message = $AVE_Template->get_config_vars('SETTINGS_SAVED');
|
||||
$header = $AVE_Template->get_config_vars('SETTINGS_SUCCESS');
|
||||
$theme = 'accept';
|
||||
reportLog($AVE_Template->get_config_vars('SETTINGS_SAVE_MAIN'));
|
||||
}
|
||||
|
||||
if (isset($_REQUEST['ajax']) && $_REQUEST['ajax'] == '1')
|
||||
{
|
||||
echo json_encode(array('message' => $message, 'header' => $header, 'theme' => $theme));
|
||||
}
|
||||
else
|
||||
{
|
||||
$AVE_Template->assign('message', $message);
|
||||
header('Location:index.php?do=settings&cp=' . SESSION);
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
/**
|
||||
* Метод отображения списка стран
|
||||
*
|
||||
|
@@ -265,6 +265,135 @@ function rrmdir($dir, &$result = 0)
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерирует новый 32-байтовый ключ шифрования.
|
||||
* @return string 64-символьная HEX-строка.
|
||||
*/
|
||||
function generate_encryption_key() {
|
||||
// 32 байта для AES-256
|
||||
$bytes = openssl_random_pseudo_bytes(32, $cstrong);
|
||||
|
||||
// Проверка на криптографическую надежность
|
||||
if ($cstrong === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return bin2hex($bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает файл ключа inc/smtp_key.php с уникальным ключом.
|
||||
* @return string Сгенерированный ключ, или пустая строка в случае ошибки.
|
||||
*/
|
||||
function create_smtp_key_file() {
|
||||
$key = generate_encryption_key();
|
||||
|
||||
if (empty($key)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$key_path = BASE_DIR . '/inc/smtp_key.php';
|
||||
$content = "<?php\n// Ключ шифрования. НЕ МЕНЯТЬ после первого использования!\n// Сгенерирован: " . date('Y-m-d H:i:s') . "\ndefine('SMTP_ENCRYPTION_KEY', '{$key}');";
|
||||
|
||||
// Пытаемся записать файл
|
||||
if (file_put_contents($key_path, $content) === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// @chmod($key_path, 0400); // Была причиной ошибок, оставляем закомментированной
|
||||
|
||||
// Определяем константу, чтобы не читать файл снова
|
||||
if (!defined('SMTP_ENCRYPTION_KEY')) {
|
||||
define('SMTP_ENCRYPTION_KEY', $key);
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает ключ шифрования SMTP, читая файл inc/smtp_key.php.
|
||||
* @return string Ключ шифрования (64 символа), или пустая строка, если ключ отсутствует.
|
||||
*/
|
||||
function get_smtp_encryption_key() {
|
||||
if (defined('SMTP_ENCRYPTION_KEY')) {
|
||||
return SMTP_ENCRYPTION_KEY;
|
||||
}
|
||||
|
||||
$key_path = BASE_DIR . '/inc/smtp_key.php';
|
||||
|
||||
if (!file_exists($key_path)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$content = @file_get_contents($key_path);
|
||||
|
||||
if (preg_match('/define\(\s*\'SMTP_ENCRYPTION_KEY\'\s*,\s*\'([a-fA-F0-9]{64})\'\s*\)/', $content, $matches)) {
|
||||
$key = $matches[1];
|
||||
define('SMTP_ENCRYPTION_KEY', $key);
|
||||
return $key;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Шифрует данные (SMTP-пароль).
|
||||
* @param string $data Нешифрованный пароль.
|
||||
* @return string Зашифрованная строка в Base64 (IV + Ciphertext), или исходные данные в случае ошибки.
|
||||
*/
|
||||
function encrypt_smtp_pass($data)
|
||||
{
|
||||
$key = get_smtp_encryption_key();
|
||||
|
||||
if (empty($data) || empty($key)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$cipher = 'aes-256-cbc';
|
||||
$ivlen = openssl_cipher_iv_length($cipher);
|
||||
$iv = openssl_random_pseudo_bytes($ivlen);
|
||||
|
||||
$ciphertext = openssl_encrypt($data, $cipher, $key, OPENSSL_RAW_DATA, $iv);
|
||||
|
||||
if ($ciphertext === false) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
return base64_encode($iv . $ciphertext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Дешифрует данные (SMTP-пароль).
|
||||
* @param string $data Зашифрованная строка в Base64.
|
||||
* @return string Дешифрованный пароль, или исходная строка в случае ошибки/отсутствия ключа.
|
||||
*/
|
||||
function decrypt_smtp_pass($data)
|
||||
{
|
||||
$key = get_smtp_encryption_key();
|
||||
|
||||
if (empty($data) || empty($key)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$decoded = base64_decode($data, true);
|
||||
if ($decoded === false) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$cipher = 'aes-256-cbc';
|
||||
$ivlen = openssl_cipher_iv_length($cipher);
|
||||
|
||||
if (strlen($decoded) < $ivlen) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$iv = substr($decoded, 0, $ivlen);
|
||||
$ciphertext_raw = substr($decoded, $ivlen);
|
||||
|
||||
$decrypted = openssl_decrypt($ciphertext_raw, $cipher, $key, OPENSSL_RAW_DATA, $iv);
|
||||
|
||||
return $decrypted !== false ? $decrypted : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение основных настроек
|
||||
@@ -272,28 +401,54 @@ function rrmdir($dir, &$result = 0)
|
||||
* @param string $field параметр настройки, если не указан - все параметры
|
||||
* @return mixed
|
||||
*/
|
||||
function get_settings($field = '')
|
||||
{
|
||||
global $AVE_DB;
|
||||
function get_settings($field = '')
|
||||
{
|
||||
global $AVE_DB;
|
||||
|
||||
static $settings = null;
|
||||
static $settings = null;
|
||||
|
||||
if ($settings === null)
|
||||
$settings = $AVE_DB->Query("
|
||||
SELECT
|
||||
# SETTINGS
|
||||
*
|
||||
FROM
|
||||
" . PREFIX . "_settings
|
||||
", -1, 'settings', true, '.settings')->FetchAssocArray();
|
||||
if ($settings === null)
|
||||
{
|
||||
get_smtp_encryption_key();
|
||||
|
||||
if ($field == '')
|
||||
return $settings;
|
||||
// Включаем параметры кэша (-1, 'settings', true, '.settings').
|
||||
$result = $AVE_DB->Query("
|
||||
SELECT * FROM " . PREFIX . "_settings
|
||||
", -1, 'settings', true, '.settings')->FetchAssocArray();
|
||||
|
||||
// 2. НОРМАЛИЗАЦИЯ: Преобразуем результат в одномерный массив $settings.
|
||||
// Если кэш вернул двумерный массив (Array([0] => Array(...))), берем индекс [0].
|
||||
if (isset($result[0]) && is_array($result[0])) {
|
||||
$settings = $result[0];
|
||||
} else {
|
||||
// Если вернулся одномерный массив (например, при первом чтении из БД без кэша), используем его напрямую.
|
||||
$settings = $result;
|
||||
}
|
||||
|
||||
// --- ЛОГИКА ДЕШИФРОВАНИЯ ---
|
||||
// Теперь $settings гарантированно одномерный массив.
|
||||
$row = $settings;
|
||||
|
||||
if (isset($row['mail_type']) && $row['mail_type'] === 'smtp' && !empty($row['mail_smtp_pass'])) {
|
||||
|
||||
$pass = trim($row['mail_smtp_pass']);
|
||||
|
||||
return isset($settings[$field])
|
||||
? $settings[$field]
|
||||
: null;
|
||||
}
|
||||
$decrypted_pass = decrypt_smtp_pass($pass);
|
||||
|
||||
// Если дешифровка сработала, обновляем значение
|
||||
if ($decrypted_pass !== $pass) {
|
||||
$settings['mail_smtp_pass'] = $decrypted_pass; // Обновляем в статическом кэше $settings
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($field == '')
|
||||
return $settings;
|
||||
|
||||
return isset($settings[$field])
|
||||
? $settings[$field]
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@@ -141,14 +141,18 @@ use Symfony\Component\Mime\Address;
|
||||
break;
|
||||
|
||||
case 'smtp':
|
||||
$host = stripslashes(get_settings('mail_host'));
|
||||
$port = (int)get_settings('mail_port');
|
||||
$user = stripslashes(get_settings('mail_smtp_login'));
|
||||
$pass = stripslashes(get_settings('mail_smtp_pass'));
|
||||
// --- ОПТИМИЗАЦИЯ: Получаем дешифрованные настройки одним вызовом ---
|
||||
// Пароль уже ДЕШИФРОВАН функцией get_settings()
|
||||
$settings = get_settings();
|
||||
|
||||
$host = stripslashes($settings['mail_host']);
|
||||
$port = (int)$settings['mail_port'];
|
||||
$user = stripslashes($settings['mail_smtp_login']);
|
||||
$pass = stripslashes($settings['mail_smtp_pass']);
|
||||
|
||||
// Получаем значение шифрования
|
||||
$encrypt_setting = strtolower(stripslashes($settings['mail_smtp_encrypt']));
|
||||
|
||||
// Получаем значение шифрования, которое теперь может быть 'tls_insecure' или 'ssl_insecure'
|
||||
$encrypt_setting = strtolower(stripslashes(get_settings('mail_smtp_encrypt')));
|
||||
|
||||
$scheme = 'smtp';
|
||||
$encryption = '';
|
||||
$extra_params = '';
|
||||
@@ -170,7 +174,7 @@ use Symfony\Component\Mime\Address;
|
||||
$transport_dsn = sprintf('%s://%s:%s@%s:%d?encryption=%s%s',
|
||||
$scheme,
|
||||
urlencode($user),
|
||||
urlencode($pass),
|
||||
urlencode($pass), // Здесь используется ДЕШИФРОВАННЫЙ пароль
|
||||
$host,
|
||||
$port,
|
||||
$encryption, // 'tls' или 'ssl'
|
||||
@@ -180,7 +184,7 @@ use Symfony\Component\Mime\Address;
|
||||
// Без шифрования (когда выбрано "Нет")
|
||||
$transport_dsn = sprintf('smtp://%s:%s@%s:%d',
|
||||
urlencode($user),
|
||||
urlencode($pass),
|
||||
urlencode($pass), // Здесь используется ДЕШИФРОВАННЫЙ пароль
|
||||
$host,
|
||||
$port ?: 25 // Порт 25 по умолчанию
|
||||
);
|
||||
|
5
inc/.htaccess
Normal file
5
inc/.htaccess
Normal file
@@ -0,0 +1,5 @@
|
||||
# Запретить прямой доступ к файлу, содержащему ключ шифрования
|
||||
<Files "smtp_key.php">
|
||||
Order Allow,Deny
|
||||
Deny from all
|
||||
</Files>
|
Reference in New Issue
Block a user