760 lines
23 KiB
PHP
760 lines
23 KiB
PHP
<?php
|
|
/**
|
|
* Copyright seit 2024 Webshop System
|
|
*
|
|
* Security Controller für das Admin-Bereich
|
|
*
|
|
* @author Webshop System
|
|
* @license GPL v3
|
|
*/
|
|
|
|
namespace App\Controllers\Admin;
|
|
|
|
use App\Core\Security;
|
|
use App\Core\Backup;
|
|
use App\Core\SessionHandler;
|
|
use App\Core\Configuration;
|
|
|
|
class SecurityController extends AdminController
|
|
{
|
|
private $security;
|
|
private $backup;
|
|
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
$this->security = new Security();
|
|
$this->backup = new Backup();
|
|
}
|
|
|
|
/**
|
|
* Security Dashboard
|
|
*/
|
|
public function dashboard()
|
|
{
|
|
if (!$this->checkAdminSession()) {
|
|
$this->redirect('/admin/login');
|
|
}
|
|
|
|
$securityStatus = $this->getSecurityStatus();
|
|
$backupStatus = $this->backup->checkBackupStatus();
|
|
$recentEvents = $this->getRecentSecurityEvents();
|
|
$rateLimitStats = $this->getRateLimitStatistics();
|
|
|
|
$this->render('admin/security/dashboard.html.twig', [
|
|
'title' => 'Sicherheits-Dashboard',
|
|
'security_status' => $securityStatus,
|
|
'backup_status' => $backupStatus,
|
|
'recent_events' => $recentEvents,
|
|
'rate_limit_stats' => $rateLimitStats
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Security Settings
|
|
*/
|
|
public function settings()
|
|
{
|
|
if (!$this->checkAdminSession()) {
|
|
$this->redirect('/admin/login');
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$this->updateSecuritySettings();
|
|
}
|
|
|
|
$settings = $this->getSecuritySettings();
|
|
|
|
$this->render('admin/security/settings.html.twig', [
|
|
'title' => 'Sicherheitseinstellungen',
|
|
'settings' => $settings
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Backup Management
|
|
*/
|
|
public function backup()
|
|
{
|
|
if (!$this->checkAdminSession()) {
|
|
$this->redirect('/admin/login');
|
|
}
|
|
|
|
$action = $_GET['action'] ?? '';
|
|
|
|
switch ($action) {
|
|
case 'create':
|
|
$this->createBackup();
|
|
break;
|
|
|
|
case 'restore':
|
|
$this->restoreBackup();
|
|
break;
|
|
|
|
case 'download':
|
|
$this->downloadBackup();
|
|
break;
|
|
|
|
case 'delete':
|
|
$this->deleteBackup();
|
|
break;
|
|
|
|
default:
|
|
$this->showBackupList();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Security Logs
|
|
*/
|
|
public function logs()
|
|
{
|
|
if (!$this->checkAdminSession()) {
|
|
$this->redirect('/admin/login');
|
|
}
|
|
|
|
$page = max(1, intval($_GET['page'] ?? 1));
|
|
$limit = 50;
|
|
$offset = ($page - 1) * $limit;
|
|
|
|
$filters = [
|
|
'level' => $_GET['level'] ?? '',
|
|
'event' => $_GET['event'] ?? '',
|
|
'date_from' => $_GET['date_from'] ?? '',
|
|
'date_to' => $_GET['date_to'] ?? ''
|
|
];
|
|
|
|
$logs = $this->getSecurityLogs($filters, $limit, $offset);
|
|
$totalLogs = $this->getSecurityLogsCount($filters);
|
|
|
|
$this->render('admin/security/logs.html.twig', [
|
|
'title' => 'Sicherheits-Logs',
|
|
'logs' => $logs,
|
|
'filters' => $filters,
|
|
'pagination' => [
|
|
'page' => $page,
|
|
'limit' => $limit,
|
|
'total' => $totalLogs,
|
|
'pages' => ceil($totalLogs / $limit)
|
|
]
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Rate Limiting Management
|
|
*/
|
|
public function rateLimiting()
|
|
{
|
|
if (!$this->checkAdminSession()) {
|
|
$this->redirect('/admin/login');
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$this->updateRateLimiting();
|
|
}
|
|
|
|
$rateLimits = $this->getRateLimitingConfig();
|
|
$statistics = $this->getRateLimitStatistics();
|
|
|
|
$this->render('admin/security/rate_limiting.html.twig', [
|
|
'title' => 'Rate Limiting',
|
|
'rate_limits' => $rateLimits,
|
|
'statistics' => $statistics
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* SSL/TLS Configuration
|
|
*/
|
|
public function ssl()
|
|
{
|
|
if (!$this->checkAdminSession()) {
|
|
$this->redirect('/admin/login');
|
|
}
|
|
|
|
$sslStatus = $this->getSSLStatus();
|
|
$sslConfig = $this->getSSLConfiguration();
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$this->updateSSLConfiguration();
|
|
}
|
|
|
|
$this->render('admin/security/ssl.html.twig', [
|
|
'title' => 'SSL/TLS Konfiguration',
|
|
'ssl_status' => $sslStatus,
|
|
'ssl_config' => $sslConfig
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Security Status abrufen
|
|
*/
|
|
private function getSecurityStatus()
|
|
{
|
|
$status = [
|
|
'ssl_enabled' => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on',
|
|
'security_headers' => $this->checkSecurityHeaders(),
|
|
'session_security' => $this->checkSessionSecurity(),
|
|
'file_permissions' => $this->checkFilePermissions(),
|
|
'database_security' => $this->checkDatabaseSecurity(),
|
|
'backup_status' => $this->backup->checkBackupStatus()
|
|
];
|
|
|
|
$status['overall_score'] = $this->calculateSecurityScore($status);
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Security Headers prüfen
|
|
*/
|
|
private function checkSecurityHeaders()
|
|
{
|
|
$headers = [
|
|
'Strict-Transport-Security' => false,
|
|
'X-Content-Type-Options' => false,
|
|
'X-Frame-Options' => false,
|
|
'X-XSS-Protection' => false,
|
|
'Referrer-Policy' => false,
|
|
'Content-Security-Policy' => false
|
|
];
|
|
|
|
$responseHeaders = headers_list();
|
|
|
|
foreach ($responseHeaders as $header) {
|
|
$parts = explode(':', $header, 2);
|
|
if (count($parts) === 2) {
|
|
$name = trim($parts[0]);
|
|
if (isset($headers[$name])) {
|
|
$headers[$name] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $headers;
|
|
}
|
|
|
|
/**
|
|
* Session Security prüfen
|
|
*/
|
|
private function checkSessionSecurity()
|
|
{
|
|
return [
|
|
'httponly' => ini_get('session.cookie_httponly') == '1',
|
|
'secure' => ini_get('session.cookie_secure') == '1',
|
|
'samesite' => ini_get('session.cookie_samesite') === 'Strict',
|
|
'strict_mode' => ini_get('session.use_strict_mode') == '1'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* File Permissions prüfen
|
|
*/
|
|
private function checkFilePermissions()
|
|
{
|
|
$criticalFiles = [
|
|
__DIR__ . '/../../../config/database.php' => '0400',
|
|
__DIR__ . '/../../../.env' => '0400',
|
|
__DIR__ . '/../../../backups' => '0755'
|
|
];
|
|
|
|
$permissions = [];
|
|
|
|
foreach ($criticalFiles as $file => $expected) {
|
|
if (file_exists($file)) {
|
|
$actual = substr(sprintf('%o', fileperms($file)), -4);
|
|
$permissions[$file] = [
|
|
'expected' => $expected,
|
|
'actual' => $actual,
|
|
'secure' => $actual <= $expected
|
|
];
|
|
}
|
|
}
|
|
|
|
return $permissions;
|
|
}
|
|
|
|
/**
|
|
* Database Security prüfen
|
|
*/
|
|
private function checkDatabaseSecurity()
|
|
{
|
|
try {
|
|
$stmt = $this->conn->prepare('
|
|
SELECT COUNT(*) as user_count
|
|
FROM ws_user
|
|
WHERE role = "admin"
|
|
');
|
|
$stmt->execute();
|
|
$adminCount = $stmt->fetchAssociative()['user_count'];
|
|
|
|
$stmt = $this->conn->prepare('
|
|
SELECT COUNT(*) as failed_logins
|
|
FROM ws_security_log
|
|
WHERE event = "login_failed"
|
|
AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)
|
|
');
|
|
$stmt->execute();
|
|
$failedLogins = $stmt->fetchAssociative()['failed_logins'];
|
|
|
|
return [
|
|
'admin_users' => $adminCount,
|
|
'recent_failed_logins' => $failedLogins,
|
|
'secure' => $adminCount > 0 && $failedLogins < 100
|
|
];
|
|
|
|
} catch (Exception $e) {
|
|
return [
|
|
'admin_users' => 0,
|
|
'recent_failed_logins' => 0,
|
|
'secure' => false,
|
|
'error' => $e->getMessage()
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Security Score berechnen
|
|
*/
|
|
private function calculateSecurityScore($status)
|
|
{
|
|
$score = 0;
|
|
$total = 0;
|
|
|
|
// SSL Score
|
|
$total++;
|
|
if ($status['ssl_enabled']) {
|
|
$score++;
|
|
}
|
|
|
|
// Security Headers Score
|
|
$headerScore = 0;
|
|
$headerTotal = count($status['security_headers']);
|
|
foreach ($status['security_headers'] as $enabled) {
|
|
if ($enabled) $headerScore++;
|
|
}
|
|
$score += ($headerScore / $headerTotal);
|
|
$total++;
|
|
|
|
// Session Security Score
|
|
$sessionScore = 0;
|
|
$sessionTotal = count($status['session_security']);
|
|
foreach ($status['session_security'] as $enabled) {
|
|
if ($enabled) $sessionScore++;
|
|
}
|
|
$score += ($sessionScore / $sessionTotal);
|
|
$total++;
|
|
|
|
// File Permissions Score
|
|
$fileScore = 0;
|
|
$fileTotal = count($status['file_permissions']);
|
|
foreach ($status['file_permissions'] as $file) {
|
|
if ($file['secure']) $fileScore++;
|
|
}
|
|
$score += ($fileScore / $fileTotal);
|
|
$total++;
|
|
|
|
// Database Security Score
|
|
$total++;
|
|
if ($status['database_security']['secure']) {
|
|
$score++;
|
|
}
|
|
|
|
return round(($score / $total) * 100, 1);
|
|
}
|
|
|
|
/**
|
|
* Recent Security Events
|
|
*/
|
|
private function getRecentSecurityEvents()
|
|
{
|
|
try {
|
|
$stmt = $this->conn->prepare('
|
|
SELECT event, level, ip_address, user_agent, created_at
|
|
FROM ws_security_log
|
|
ORDER BY created_at DESC
|
|
LIMIT 10
|
|
');
|
|
$stmt->execute();
|
|
|
|
return $stmt->fetchAllAssociative();
|
|
|
|
} catch (Exception $e) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Rate Limit Statistics
|
|
*/
|
|
private function getRateLimitStatistics()
|
|
{
|
|
try {
|
|
$stmt = $this->conn->prepare('
|
|
SELECT action, COUNT(*) as attempts,
|
|
COUNT(CASE WHEN created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR) THEN 1 END) as recent_attempts
|
|
FROM ws_rate_limit
|
|
WHERE created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)
|
|
GROUP BY action
|
|
');
|
|
$stmt->execute();
|
|
|
|
return $stmt->fetchAllAssociative();
|
|
|
|
} catch (Exception $e) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Security Settings abrufen
|
|
*/
|
|
private function getSecuritySettings()
|
|
{
|
|
return [
|
|
'csrf_protection' => $this->config->get('CSRF_PROTECTION', true),
|
|
'rate_limiting' => $this->config->get('RATE_LIMITING', true),
|
|
'session_timeout' => $this->config->get('SESSION_TIMEOUT', 3600),
|
|
'max_login_attempts' => $this->config->get('MAX_LOGIN_ATTEMPTS', 5),
|
|
'password_min_length' => $this->config->get('PASSWORD_MIN_LENGTH', 8),
|
|
'require_strong_password' => $this->config->get('REQUIRE_STRONG_PASSWORD', true),
|
|
'two_factor_auth' => $this->config->get('TWO_FACTOR_AUTH', false),
|
|
'ssl_required' => $this->config->get('SSL_REQUIRED', true),
|
|
'security_headers' => $this->config->get('SECURITY_HEADERS', true),
|
|
'file_upload_security' => $this->config->get('FILE_UPLOAD_SECURITY', true)
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Security Settings aktualisieren
|
|
*/
|
|
private function updateSecuritySettings()
|
|
{
|
|
$settings = [
|
|
'CSRF_PROTECTION' => isset($_POST['csrf_protection']),
|
|
'RATE_LIMITING' => isset($_POST['rate_limiting']),
|
|
'SESSION_TIMEOUT' => intval($_POST['session_timeout'] ?? 3600),
|
|
'MAX_LOGIN_ATTEMPTS' => intval($_POST['max_login_attempts'] ?? 5),
|
|
'PASSWORD_MIN_LENGTH' => intval($_POST['password_min_length'] ?? 8),
|
|
'REQUIRE_STRONG_PASSWORD' => isset($_POST['require_strong_password']),
|
|
'TWO_FACTOR_AUTH' => isset($_POST['two_factor_auth']),
|
|
'SSL_REQUIRED' => isset($_POST['ssl_required']),
|
|
'SECURITY_HEADERS' => isset($_POST['security_headers']),
|
|
'FILE_UPLOAD_SECURITY' => isset($_POST['file_upload_security'])
|
|
];
|
|
|
|
foreach ($settings as $key => $value) {
|
|
$this->config->set($key, $value);
|
|
}
|
|
|
|
$this->addFlashMessage('Sicherheitseinstellungen wurden aktualisiert', 'success');
|
|
$this->redirect('/admin/security/settings');
|
|
}
|
|
|
|
/**
|
|
* Backup erstellen
|
|
*/
|
|
private function createBackup()
|
|
{
|
|
$description = $_POST['description'] ?? 'Manuelles Backup';
|
|
|
|
$result = $this->backup->createFullBackup($description);
|
|
|
|
if ($result['success']) {
|
|
$this->addFlashMessage('Backup erfolgreich erstellt: ' . $result['backup_name'], 'success');
|
|
} else {
|
|
$this->addFlashMessage('Backup fehlgeschlagen: ' . $result['error'], 'error');
|
|
}
|
|
|
|
$this->redirect('/admin/security/backup');
|
|
}
|
|
|
|
/**
|
|
* Backup wiederherstellen
|
|
*/
|
|
private function restoreBackup()
|
|
{
|
|
$backupFile = $_POST['backup_file'] ?? '';
|
|
|
|
if (!$backupFile || !file_exists($backupFile)) {
|
|
$this->addFlashMessage('Backup-Datei nicht gefunden', 'error');
|
|
$this->redirect('/admin/security/backup');
|
|
}
|
|
|
|
$options = [
|
|
'restore_database' => isset($_POST['restore_database']),
|
|
'restore_files' => isset($_POST['restore_files']),
|
|
'restore_config' => isset($_POST['restore_config'])
|
|
];
|
|
|
|
$result = $this->backup->restoreBackup($backupFile, $options);
|
|
|
|
if ($result['success']) {
|
|
$this->addFlashMessage('Backup erfolgreich wiederhergestellt', 'success');
|
|
} else {
|
|
$this->addFlashMessage('Backup-Wiederherstellung fehlgeschlagen: ' . $result['error'], 'error');
|
|
}
|
|
|
|
$this->redirect('/admin/security/backup');
|
|
}
|
|
|
|
/**
|
|
* Backup herunterladen
|
|
*/
|
|
private function downloadBackup()
|
|
{
|
|
$backupFile = $_GET['file'] ?? '';
|
|
|
|
if (!$backupFile || !file_exists($backupFile)) {
|
|
$this->addFlashMessage('Backup-Datei nicht gefunden', 'error');
|
|
$this->redirect('/admin/security/backup');
|
|
}
|
|
|
|
header('Content-Type: application/octet-stream');
|
|
header('Content-Disposition: attachment; filename="' . basename($backupFile) . '"');
|
|
header('Content-Length: ' . filesize($backupFile));
|
|
|
|
readfile($backupFile);
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Backup löschen
|
|
*/
|
|
private function deleteBackup()
|
|
{
|
|
$backupFile = $_POST['backup_file'] ?? '';
|
|
|
|
if (!$backupFile || !file_exists($backupFile)) {
|
|
$this->addFlashMessage('Backup-Datei nicht gefunden', 'error');
|
|
$this->redirect('/admin/security/backup');
|
|
}
|
|
|
|
if (unlink($backupFile)) {
|
|
$this->addFlashMessage('Backup erfolgreich gelöscht', 'success');
|
|
} else {
|
|
$this->addFlashMessage('Fehler beim Löschen des Backups', 'error');
|
|
}
|
|
|
|
$this->redirect('/admin/security/backup');
|
|
}
|
|
|
|
/**
|
|
* Backup-Liste anzeigen
|
|
*/
|
|
private function showBackupList()
|
|
{
|
|
$backups = $this->backup->getBackupList();
|
|
$backupStatus = $this->backup->checkBackupStatus();
|
|
|
|
$this->render('admin/security/backup.html.twig', [
|
|
'title' => 'Backup-Verwaltung',
|
|
'backups' => $backups,
|
|
'backup_status' => $backupStatus
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Security Logs abrufen
|
|
*/
|
|
private function getSecurityLogs($filters, $limit, $offset)
|
|
{
|
|
try {
|
|
$whereConditions = [];
|
|
$params = [];
|
|
|
|
if (!empty($filters['level'])) {
|
|
$whereConditions[] = 'level = ?';
|
|
$params[] = $filters['level'];
|
|
}
|
|
|
|
if (!empty($filters['event'])) {
|
|
$whereConditions[] = 'event LIKE ?';
|
|
$params[] = '%' . $filters['event'] . '%';
|
|
}
|
|
|
|
if (!empty($filters['date_from'])) {
|
|
$whereConditions[] = 'created_at >= ?';
|
|
$params[] = $filters['date_from'] . ' 00:00:00';
|
|
}
|
|
|
|
if (!empty($filters['date_to'])) {
|
|
$whereConditions[] = 'created_at <= ?';
|
|
$params[] = $filters['date_to'] . ' 23:59:59';
|
|
}
|
|
|
|
$whereClause = !empty($whereConditions) ? 'WHERE ' . implode(' AND ', $whereConditions) : '';
|
|
|
|
$sql = "
|
|
SELECT id, event, level, ip_address, user_agent, created_at
|
|
FROM ws_security_log
|
|
$whereClause
|
|
ORDER BY created_at DESC
|
|
LIMIT $limit OFFSET $offset
|
|
";
|
|
|
|
$stmt = $this->conn->prepare($sql);
|
|
$stmt->execute($params);
|
|
|
|
return $stmt->fetchAllAssociative();
|
|
|
|
} catch (Exception $e) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Security Logs Count
|
|
*/
|
|
private function getSecurityLogsCount($filters)
|
|
{
|
|
try {
|
|
$whereConditions = [];
|
|
$params = [];
|
|
|
|
if (!empty($filters['level'])) {
|
|
$whereConditions[] = 'level = ?';
|
|
$params[] = $filters['level'];
|
|
}
|
|
|
|
if (!empty($filters['event'])) {
|
|
$whereConditions[] = 'event LIKE ?';
|
|
$params[] = '%' . $filters['event'] . '%';
|
|
}
|
|
|
|
if (!empty($filters['date_from'])) {
|
|
$whereConditions[] = 'created_at >= ?';
|
|
$params[] = $filters['date_from'] . ' 00:00:00';
|
|
}
|
|
|
|
if (!empty($filters['date_to'])) {
|
|
$whereConditions[] = 'created_at <= ?';
|
|
$params[] = $filters['date_to'] . ' 23:59:59';
|
|
}
|
|
|
|
$whereClause = !empty($whereConditions) ? 'WHERE ' . implode(' AND ', $whereConditions) : '';
|
|
|
|
$sql = "SELECT COUNT(*) as total FROM ws_security_log $whereClause";
|
|
|
|
$stmt = $this->conn->prepare($sql);
|
|
$stmt->execute($params);
|
|
|
|
return $stmt->fetchAssociative()['total'];
|
|
|
|
} catch (Exception $e) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Rate Limiting Config abrufen
|
|
*/
|
|
private function getRateLimitingConfig()
|
|
{
|
|
return [
|
|
'login' => ['max_attempts' => 5, 'window' => 300],
|
|
'api' => ['max_attempts' => 100, 'window' => 3600],
|
|
'register' => ['max_attempts' => 3, 'window' => 1800],
|
|
'password_reset' => ['max_attempts' => 3, 'window' => 3600],
|
|
'review' => ['max_attempts' => 10, 'window' => 3600],
|
|
'contact' => ['max_attempts' => 5, 'window' => 1800]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Rate Limiting aktualisieren
|
|
*/
|
|
private function updateRateLimiting()
|
|
{
|
|
$actions = ['login', 'api', 'register', 'password_reset', 'review', 'contact'];
|
|
|
|
foreach ($actions as $action) {
|
|
$maxAttempts = intval($_POST[$action . '_max_attempts'] ?? 5);
|
|
$window = intval($_POST[$action . '_window'] ?? 300);
|
|
|
|
// In Konfiguration speichern
|
|
$this->config->set('RATE_LIMIT_' . strtoupper($action) . '_MAX', $maxAttempts);
|
|
$this->config->set('RATE_LIMIT_' . strtoupper($action) . '_WINDOW', $window);
|
|
}
|
|
|
|
$this->addFlashMessage('Rate Limiting-Einstellungen aktualisiert', 'success');
|
|
$this->redirect('/admin/security/rate_limiting');
|
|
}
|
|
|
|
/**
|
|
* SSL Status abrufen
|
|
*/
|
|
private function getSSLStatus()
|
|
{
|
|
return [
|
|
'enabled' => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on',
|
|
'certificate' => $this->getSSLCertificateInfo(),
|
|
'headers' => $this->checkSecurityHeaders()
|
|
];
|
|
}
|
|
|
|
/**
|
|
* SSL Certificate Info
|
|
*/
|
|
private function getSSLCertificateInfo()
|
|
{
|
|
if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
|
|
return null;
|
|
}
|
|
|
|
$host = $_SERVER['HTTP_HOST'];
|
|
$context = stream_context_create(['ssl' => ['capture_peer_cert' => true]]);
|
|
$socket = stream_socket_client("ssl://$host:443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
|
|
|
|
if ($socket) {
|
|
$cert = stream_context_get_params($socket);
|
|
fclose($socket);
|
|
|
|
if (isset($cert['options']['ssl']['peer_certificate'])) {
|
|
$certInfo = openssl_x509_parse($cert['options']['ssl']['peer_certificate']);
|
|
return [
|
|
'subject' => $certInfo['subject']['CN'] ?? '',
|
|
'issuer' => $certInfo['issuer']['CN'] ?? '',
|
|
'valid_from' => date('Y-m-d H:i:s', $certInfo['validFrom_time_t']),
|
|
'valid_to' => date('Y-m-d H:i:s', $certInfo['validTo_time_t']),
|
|
'days_remaining' => ceil(($certInfo['validTo_time_t'] - time()) / 86400)
|
|
];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* SSL Configuration abrufen
|
|
*/
|
|
private function getSSLConfiguration()
|
|
{
|
|
return [
|
|
'force_https' => $this->config->get('FORCE_HTTPS', true),
|
|
'hsts_enabled' => $this->config->get('HSTS_ENABLED', true),
|
|
'hsts_max_age' => $this->config->get('HSTS_MAX_AGE', 31536000),
|
|
'secure_cookies' => $this->config->get('SECURE_COOKIES', true)
|
|
];
|
|
}
|
|
|
|
/**
|
|
* SSL Configuration aktualisieren
|
|
*/
|
|
private function updateSSLConfiguration()
|
|
{
|
|
$settings = [
|
|
'FORCE_HTTPS' => isset($_POST['force_https']),
|
|
'HSTS_ENABLED' => isset($_POST['hsts_enabled']),
|
|
'HSTS_MAX_AGE' => intval($_POST['hsts_max_age'] ?? 31536000),
|
|
'SECURE_COOKIES' => isset($_POST['secure_cookies'])
|
|
];
|
|
|
|
foreach ($settings as $key => $value) {
|
|
$this->config->set($key, $value);
|
|
}
|
|
|
|
$this->addFlashMessage('SSL/TLS-Konfiguration aktualisiert', 'success');
|
|
$this->redirect('/admin/security/ssl');
|
|
}
|
|
}
|