Compare commits
3 Commits
ecaf54e2fb
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e12a26a04 | |||
| 9ea739650a | |||
| 573421700d |
31
check_content.php
Normal file
31
check_content.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$jsonFile = __DIR__ . '/web_check.json';
|
||||||
|
|
||||||
|
if (!file_exists($jsonFile)) {
|
||||||
|
echo "CRITICAL - JSON file not found\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode(file_get_contents($jsonFile), true);
|
||||||
|
if (!$data) {
|
||||||
|
echo "CRITICAL - Invalid JSON\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$problems = [];
|
||||||
|
|
||||||
|
foreach ($data as $site) {
|
||||||
|
if ($site['wordcheck_ok'] != 1) {
|
||||||
|
$problems[] = $site['domain'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($problems)) {
|
||||||
|
echo "CRITICAL - Content problems on: " . implode(', ', $problems) . "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "OK - All content checks passed\n";
|
||||||
|
exit(0);
|
||||||
49
check_expiry.php
Normal file
49
check_expiry.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/config/init.php';
|
||||||
|
|
||||||
|
|
||||||
|
$jsonFile = __DIR__ . '/web_check.json';
|
||||||
|
|
||||||
|
|
||||||
|
if (!file_exists($jsonFile)) {
|
||||||
|
echo "CRITICAL - JSON file not found\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode(file_get_contents($jsonFile), true);
|
||||||
|
if (!$data) {
|
||||||
|
echo "CRITICAL - Invalid JSON\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$critical = [];
|
||||||
|
$warning = [];
|
||||||
|
|
||||||
|
foreach ($data as $site) {
|
||||||
|
|
||||||
|
$days = ssl_days_left($site['ssl-expiry']);
|
||||||
|
|
||||||
|
if ($days === null) continue;
|
||||||
|
|
||||||
|
if ($days <= SSL_CRITICAL_DAYS) {
|
||||||
|
$critical[] = $site['domain'] . " ($days days)";
|
||||||
|
}
|
||||||
|
elseif ($days <= SSL_WARNING_DAYS) {
|
||||||
|
$warning[] = $site['domain'] . " ($days days)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($critical)) {
|
||||||
|
echo "CRITICAL - SSL expiring soon: " . implode(', ', $critical) . "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($warning)) {
|
||||||
|
echo "WARNING - SSL expiring: " . implode(', ', $warning) . "\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "OK - No SSL expiring soon\n";
|
||||||
|
exit(0);
|
||||||
33
check_ssl.php
Normal file
33
check_ssl.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/config/init.php';
|
||||||
|
|
||||||
|
$jsonFile = __DIR__ . '/web_check.json';
|
||||||
|
|
||||||
|
if (!file_exists($jsonFile)) {
|
||||||
|
echo "CRITICAL - JSON file not found\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode(file_get_contents($jsonFile), true);
|
||||||
|
if (!$data) {
|
||||||
|
echo "CRITICAL - Invalid JSON\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$problems = [];
|
||||||
|
|
||||||
|
foreach ($data as $site) {
|
||||||
|
if ($site['sslcheck_ok'] != 1) {
|
||||||
|
$problems[] = $site['domain'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($problems)) {
|
||||||
|
echo "CRITICAL - SSL problems on: " . implode(', ', $problems) . "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "OK - All SSL certificates valid\n";
|
||||||
|
exit(0);
|
||||||
@@ -20,68 +20,27 @@ use function PHPSTORM_META\type;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function status_class_bg($ssl, $word, $expiry, $retcol=null, $showday="null"){
|
function get_status_class($ssl, $word, $expiry){
|
||||||
|
|
||||||
// CSS CLASS
|
|
||||||
$red = "alert_red";
|
|
||||||
$orange = "alert_orange";
|
|
||||||
$yellow = "alert_yellow";
|
|
||||||
$green = "alert_green";
|
|
||||||
|
|
||||||
// CSS COLOR
|
|
||||||
$col_red = "#ff4747";
|
|
||||||
$col_orange = "#ff830f";
|
|
||||||
$col_yellow = "#ffd70f";
|
|
||||||
$col_green = "#42c500";
|
|
||||||
$style="style='font-weight:bold; color:";
|
|
||||||
|
|
||||||
|
if ($ssl != 1 || $word != 1) {
|
||||||
|
return "alert_red";
|
||||||
|
}
|
||||||
|
|
||||||
$days = ssl_days_left($expiry);
|
$days = ssl_days_left($expiry);
|
||||||
|
|
||||||
if ($showday == "on"){
|
|
||||||
return $days;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ssl != 1 || $word != 1) {
|
|
||||||
echo $red;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ($days !== null) {
|
if ($days !== null) {
|
||||||
|
if ($days < 0) {
|
||||||
if ($days <= SSL_CRITICAL_DAYS) {
|
return "alert_red";
|
||||||
|
|
||||||
if ($retcol){ // CRITICAL
|
|
||||||
echo $style . $col_orange . ";'";
|
|
||||||
}else{
|
|
||||||
echo $orange;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}elseif ($days <= SSL_WARNING_DAYS) {
|
elseif ($days <= SSL_CRITICAL_DAYS) {
|
||||||
|
return "alert_orange";
|
||||||
if ($retcol){
|
|
||||||
echo $style . $col_yellow . ";'";
|
|
||||||
|
|
||||||
}else{
|
|
||||||
echo $yellow;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
elseif ($days <= SSL_WARNING_DAYS) {
|
||||||
|
return "alert_yellow";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return "alert_green";
|
||||||
if ($retcol){
|
|
||||||
echo $style . $col_green . ";'";
|
|
||||||
return ;
|
|
||||||
}else{
|
|
||||||
echo $green;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -100,17 +59,27 @@ function status_class_bg($ssl, $word, $expiry, $retcol=null, $showday="null"){
|
|||||||
// Ordina: problemi prima
|
// Ordina: problemi prima
|
||||||
usort($webcheck_json, function($a, $b) {
|
usort($webcheck_json, function($a, $b) {
|
||||||
|
|
||||||
$a_problem = ($a['sslcheck_ok'] != 1 || $a['wordcheck_ok'] != 1);
|
// 1️⃣ Problemi contenuto o SSL
|
||||||
$b_problem = ($b['sslcheck_ok'] != 1 || $b['wordcheck_ok'] != 1);
|
$a_problem = ($a['sslcheck_ok'] != 1 || $a['wordcheck_ok'] != 1);
|
||||||
|
$b_problem = ($b['sslcheck_ok'] != 1 || $b['wordcheck_ok'] != 1);
|
||||||
|
|
||||||
// Se A ha problema e B no → A prima
|
if ($a_problem && !$b_problem) return -1;
|
||||||
if ($a_problem && !$b_problem) return -1;
|
if (!$a_problem && $b_problem) return 1;
|
||||||
|
|
||||||
// Se B ha problema e A no → B prima
|
// 2️⃣ Giorni alla scadenza
|
||||||
if (!$a_problem && $b_problem) return 1;
|
$a_days = ssl_days_left($a['ssl-expiry']);
|
||||||
|
$b_days = ssl_days_left($b['ssl-expiry']);
|
||||||
|
|
||||||
// Se entrambi uguali → mantieni ordine
|
// Se uno non ha data → mettilo in fondo
|
||||||
return 0;
|
if ($a_days === null && $b_days !== null) return 1;
|
||||||
|
if ($b_days === null && $a_days !== null) return -1;
|
||||||
|
|
||||||
|
// 3️⃣ SSL già scaduti prima
|
||||||
|
if ($a_days < 0 && $b_days >= 0) return -1;
|
||||||
|
if ($b_days < 0 && $a_days >= 0) return 1;
|
||||||
|
|
||||||
|
// 4️⃣ Ordina per giorni crescenti (meno giorni prima)
|
||||||
|
return $a_days <=> $b_days;
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach($webcheck_json as $check_element){
|
foreach($webcheck_json as $check_element){
|
||||||
@@ -124,9 +93,14 @@ function status_class_bg($ssl, $word, $expiry, $retcol=null, $showday="null"){
|
|||||||
$wordtocheck=$check_element['wordtocheck'];
|
$wordtocheck=$check_element['wordtocheck'];
|
||||||
$ssl_released=$check_element['ssl-released'];
|
$ssl_released=$check_element['ssl-released'];
|
||||||
$ssl_expiry=$check_element['ssl-expiry'];
|
$ssl_expiry=$check_element['ssl-expiry'];
|
||||||
$ssl_company=$check_element['ssl-company'];
|
$ssl_cn=$check_element['ssl-cn'];
|
||||||
|
$ssl_org=$check_element['ssl-org'];
|
||||||
$http_error=$check_element['content_http_code'];
|
$http_error=$check_element['content_http_code'];
|
||||||
$expirying_days=status_class_bg($sslcheck_ok, $checkword_ok, $ssl_expiry, false, 'on');
|
$content_error=$check_element['content_error'];
|
||||||
|
$ssl_error=$check_element['ssl_error'];
|
||||||
|
$expirying_days = ssl_days_left($ssl_expiry);
|
||||||
|
$expiry_col = get_expiry_style($expirying_days);
|
||||||
|
$status_class = get_status_class($sslcheck_ok, $checkword_ok, $ssl_expiry);
|
||||||
$col_red = "#ff4747";
|
$col_red = "#ff4747";
|
||||||
$col_orange = "#ff830f";
|
$col_orange = "#ff830f";
|
||||||
$col_yellow = "#ffd70f";
|
$col_yellow = "#ffd70f";
|
||||||
@@ -147,7 +121,7 @@ function status_class_bg($ssl, $word, $expiry, $retcol=null, $showday="null"){
|
|||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<div class="alert-container <?php status_class_bg($sslcheck_ok, $checkword_ok, $ssl_expiry)?>">
|
<div class="alert-container <?= $status_class ?>">
|
||||||
<div class="alert-info">
|
<div class="alert-info">
|
||||||
<div><b>HOST: </b><span><?= $host ?></span></div>
|
<div><b>HOST: </b><span><?= $host ?></span></div>
|
||||||
<div><b>DOMAIN: </b><span><?= $domain ?></span></div>
|
<div><b>DOMAIN: </b><span><?= $domain ?></span></div>
|
||||||
@@ -155,13 +129,23 @@ function status_class_bg($ssl, $word, $expiry, $retcol=null, $showday="null"){
|
|||||||
<div <?php word_col_status($sslcheck_ok) ?>><b>SSL: </b><span><?= checktoword($sslcheck_ok) ?></span></div>
|
<div <?php word_col_status($sslcheck_ok) ?>><b>SSL: </b><span><?= checktoword($sslcheck_ok) ?></span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="alert-details">
|
<div class="alert-details">
|
||||||
|
<?php
|
||||||
|
if (!$content_error || !$ssl_error){
|
||||||
|
?>
|
||||||
<div><b>WORD TO CHECK: </b> <span><?= $wordtocheck ?></span></div>
|
<div><b>WORD TO CHECK: </b> <span><?= $wordtocheck ?></span></div>
|
||||||
<div><b>SSL RELEASED: </b> <span><?= $ssl_released ?></span></div>
|
<div><b>SSL RELEASED: </b> <span><?= $ssl_released ?></span></div>
|
||||||
<div><b>SSL EXPIRY: </b> <span <?= $expiry_col ?>> <?= $ssl_expiry ?></span></div>
|
<div><b>SSL EXPIRY: </b> <span <?= $expiry_col ?>><?= $ssl_expiry ?></span></div>
|
||||||
<div><b>SSL DAYS LEFT: </b> <span <?= $expiry_col ?>><?= $expirying_days ?></span></div>
|
<div><b>SSL DAYS LEFT: </b> <span <?= $expiry_col ?>><?= $expirying_days ?></span></span></div>
|
||||||
<div><b>SSL COMPANY: </b> <span> <?= $ssl_company ?></span></div>
|
<div><b>SSL COMMON NAME(CN): </b> <span> <?= $ssl_cn ?></span></div>
|
||||||
|
<div><b>SSL ORGANISATION(O): </b> <span> <?= $ssl_org ?></span></div>
|
||||||
<div><b>PATH: </b> <span><?= $path ?></span></div>
|
<div><b>PATH: </b> <span><?= $path ?></span></div>
|
||||||
<div><b>ERROR CODE: </b> <span><?= $http_error ?></span></div>
|
<div><b>ERROR CODE: </b> <span><?= $http_error ?></span></div>
|
||||||
|
<?php }else{?>
|
||||||
|
<div style="color:red;"><b>ERROR CODE: </b> <span><?= $http_error ?></span></div>
|
||||||
|
<div style="color:red;"><b>CONTENT ERROR: </b> <span><?= $content_error ?></span></div>
|
||||||
|
<div style="color:red;"><b>SSL ERROR: </b> <span><?= $ssl_error ?></span></div>
|
||||||
|
|
||||||
|
<?php }?>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -236,5 +220,27 @@ function status_class_bg($ssl, $word, $expiry, $retcol=null, $showday="null"){
|
|||||||
return $days;
|
return $days;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_expiry_style($days){
|
||||||
|
|
||||||
|
$col_red = "#ff4747";
|
||||||
|
$col_orange = "#ff830f";
|
||||||
|
$col_yellow = "#ffd70f";
|
||||||
|
$col_green = "#42c500";
|
||||||
|
|
||||||
|
if ($days === null) return "";
|
||||||
|
|
||||||
|
if ($days < 0) {
|
||||||
|
return "style='font-weight:bold;color:$col_red;'";
|
||||||
|
}
|
||||||
|
elseif ($days <= SSL_CRITICAL_DAYS) {
|
||||||
|
return "style='font-weight:bold;color:$col_orange;'";
|
||||||
|
}
|
||||||
|
elseif ($days <= SSL_WARNING_DAYS) {
|
||||||
|
return "style='font-weight:bold;color:$col_yellow;'";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "style='font-weight:bold;color:$col_green;'";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
@@ -1,97 +1,75 @@
|
|||||||
|
#!/usr/bin/php
|
||||||
<?php
|
<?php
|
||||||
// check_domains.php
|
// generate-report.php
|
||||||
|
// Legge web_list.json, controlla SSL + contenuto, salva web_check.json
|
||||||
|
// Aggiunge campi ssl-cn e ssl-org (Common Name e Organisation dall'issuer)
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
set_time_limit(0);
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
// --- Configurazione ---
|
// --- Configurazione ---
|
||||||
$inputFile = __DIR__ . '/web_list.json'; // modifica se necessario
|
$inputFile = __DIR__ . '/web_list.json';
|
||||||
$outputFile = __DIR__ . '/web_check.json';
|
$outputFile = __DIR__ . '/web_check.json';
|
||||||
$timeout = 10; // timeout secondi per connessioni
|
$timeout = 10; // timeout secondi per connessioni
|
||||||
|
$opensslTimeoutBin = (is_executable('/usr/bin/timeout') ? '/usr/bin/timeout' :
|
||||||
|
(is_executable('/bin/timeout') ? '/bin/timeout' : ''));
|
||||||
|
|
||||||
// --- Helpers ---
|
// --- Helpers ---
|
||||||
// Estrae hostname da domain (rimuove eventuali schema/port/path)
|
|
||||||
|
|
||||||
function ssl_days_left($expiry_date) {
|
function ssl_days_left($expiry_date) {
|
||||||
|
|
||||||
if (empty($expiry_date)) return null;
|
if (empty($expiry_date)) return null;
|
||||||
|
|
||||||
$expiry = DateTime::createFromFormat('d/m/Y', $expiry_date);
|
$expiry = DateTime::createFromFormat('d/m/Y', $expiry_date);
|
||||||
if (!$expiry) return null;
|
if (!$expiry) return null;
|
||||||
|
|
||||||
$now = new DateTime();
|
$now = new DateTime();
|
||||||
|
|
||||||
$interval = $now->diff($expiry);
|
$interval = $now->diff($expiry);
|
||||||
$days = (int)$interval->format('%r%a'); // giorni con segno
|
return (int)$interval->format('%r%a'); // giorni con segno
|
||||||
|
|
||||||
return $days;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeDomainHost(string $domain): string {
|
function normalizeDomainHost(string $domain): string {
|
||||||
// rimuovi schema se presente
|
|
||||||
if (preg_match('#^https?://#i', $domain)) {
|
if (preg_match('#^https?://#i', $domain)) {
|
||||||
$p = parse_url($domain);
|
$p = parse_url($domain);
|
||||||
return $p['host'] ?? rtrim($domain, '/');
|
return $p['host'] ?? rtrim($domain, '/');
|
||||||
}
|
}
|
||||||
// rimuovi eventuale slash e porta
|
|
||||||
$d = preg_replace('#/.*$#', '', $domain);
|
$d = preg_replace('#/.*$#', '', $domain);
|
||||||
$d = preg_replace('/:\d+$/', '', $d);
|
$d = preg_replace('/:\d+$/', '', $d);
|
||||||
return $d;
|
return $d;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Estrae nome "company" dall'issuer del certificato (controlla più chiavi possibili)
|
// Estrazione CN / O dall'issuer ottenuto via openssl_x509_parse
|
||||||
function extractIssuerName(array $cert_info): ?string {
|
function extractIssuerFieldsFromParsed(array $cert_info): array {
|
||||||
if (empty($cert_info['issuer']) || !is_array($cert_info['issuer'])) return null;
|
$cn = null;
|
||||||
$issuer = $cert_info['issuer'];
|
$org = null;
|
||||||
|
if (!empty($cert_info['issuer']) && is_array($cert_info['issuer'])) {
|
||||||
// controlla le chiavi comunemente usate
|
$issuer = $cert_info['issuer'];
|
||||||
$keys = ['O', 'commonName', 'o', 'OU', 'CN', 'organizationName'];
|
// chiavi possibili: CN, commonName, O, organizationName
|
||||||
foreach ($keys as $k) {
|
$cnKeys = ['CN', 'commonName', 'cn'];
|
||||||
if (isset($issuer[$k]) && !empty($issuer[$k])) {
|
$orgKeys = ['O', 'organizationName', 'o'];
|
||||||
return $issuer[$k];
|
foreach ($cnKeys as $k) {
|
||||||
|
if (isset($issuer[$k]) && $issuer[$k] !== '') { $cn = $issuer[$k]; break; }
|
||||||
|
}
|
||||||
|
foreach ($orgKeys as $k) {
|
||||||
|
if (isset($issuer[$k]) && $issuer[$k] !== '') { $org = $issuer[$k]; break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ['cn' => $cn, 'org' => $org];
|
||||||
// fallback: unisci i valori dell'issuer in una stringa
|
|
||||||
$vals = [];
|
|
||||||
foreach ($issuer as $k => $v) {
|
|
||||||
if (!is_numeric($k)) $vals[] = "$k=$v";
|
|
||||||
else $vals[] = $v;
|
|
||||||
}
|
|
||||||
return $vals ? implode(', ', $vals) : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractIssuerCN(array $cert_info): ?string {
|
// Ottieni informazioni certificato via stream_socket_client (SNI), fallback a openssl s_client
|
||||||
if (empty($cert_info['issuer']) || !is_array($cert_info['issuer'])) return null;
|
|
||||||
$issuer = $cert_info['issuer'];
|
|
||||||
|
|
||||||
// prima prova CN (Common Name)
|
|
||||||
$keys = ['CN', 'commonName', 'O', 'o', 'OU', 'organizationName'];
|
|
||||||
foreach ($keys as $k) {
|
|
||||||
if (isset($issuer[$k]) && !empty($issuer[$k])) {
|
|
||||||
return $issuer[$k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallback: unisci tutti
|
|
||||||
$vals = [];
|
|
||||||
foreach ($issuer as $k => $v) {
|
|
||||||
if (!is_numeric($k)) $vals[] = "$k=$v";
|
|
||||||
else $vals[] = $v;
|
|
||||||
}
|
|
||||||
return $vals ? implode(', ', $vals) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ottieni informazioni certificato via stream_socket_client (SNI)
|
|
||||||
function getCertInfo(string $host, int $port = 443, int $timeout = 10): array {
|
function getCertInfo(string $host, int $port = 443, int $timeout = 10): array {
|
||||||
$result = [
|
$result = [
|
||||||
'status' => 0,
|
'status' => 0,
|
||||||
'issued' => null,
|
'issued' => null,
|
||||||
'expiry' => null,
|
'expiry' => null,
|
||||||
'company' => null,
|
'cn' => null,
|
||||||
|
'org' => null,
|
||||||
'error' => null
|
'error' => null
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// stream context con SNI
|
||||||
$ctx = stream_context_create([
|
$ctx = stream_context_create([
|
||||||
'ssl' => [
|
'ssl' => [
|
||||||
'capture_peer_cert' => true,
|
'capture_peer_cert' => true,
|
||||||
'verify_peer' => false, // non forziamo la verifica CA per garantire il fetch del cert
|
'verify_peer' => false,
|
||||||
'verify_peer_name' => false,
|
'verify_peer_name' => false,
|
||||||
'peer_name' => $host,
|
'peer_name' => $host,
|
||||||
'SNI_enabled' => true,
|
'SNI_enabled' => true,
|
||||||
@@ -109,16 +87,17 @@ function getCertInfo(string $host, int $port = 443, int $timeout = 10): array {
|
|||||||
if ($cert_info !== false) {
|
if ($cert_info !== false) {
|
||||||
$issued = isset($cert_info['validFrom_time_t']) ? date('d/m/Y', $cert_info['validFrom_time_t']) : null;
|
$issued = isset($cert_info['validFrom_time_t']) ? date('d/m/Y', $cert_info['validFrom_time_t']) : null;
|
||||||
$expiry = isset($cert_info['validTo_time_t']) ? date('d/m/Y', $cert_info['validTo_time_t']) : null;
|
$expiry = isset($cert_info['validTo_time_t']) ? date('d/m/Y', $cert_info['validTo_time_t']) : null;
|
||||||
$company = extractIssuerCN($cert_info) ?? null;
|
// preferiamo CN come "company" visibile, ma manteniamo CN e ORG separati
|
||||||
|
$fields = extractIssuerFieldsFromParsed($cert_info);
|
||||||
|
$company = $fields['cn'] ?? ($fields['org'] ?? null);
|
||||||
$isValid = (isset($cert_info['validTo_time_t']) && time() < $cert_info['validTo_time_t']) ? 1 : 0;
|
$isValid = (isset($cert_info['validTo_time_t']) && time() < $cert_info['validTo_time_t']) ? 1 : 0;
|
||||||
|
|
||||||
$result = [
|
$result['status'] = $isValid;
|
||||||
'status' => $isValid,
|
$result['issued'] = $issued;
|
||||||
'issued' => $issued,
|
$result['expiry'] = $expiry;
|
||||||
'expiry' => $expiry,
|
$result['company'] = $company;
|
||||||
'company' => $company,
|
$result['cn'] = $fields['cn'];
|
||||||
'error' => null
|
$result['org'] = $fields['org'];
|
||||||
];
|
|
||||||
return $result;
|
return $result;
|
||||||
} else {
|
} else {
|
||||||
$result['error'] = 'openssl_x509_parse failed';
|
$result['error'] = 'openssl_x509_parse failed';
|
||||||
@@ -130,46 +109,49 @@ function getCertInfo(string $host, int $port = 443, int $timeout = 10): array {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback: prova con openssl s_client se disponibile (solo se exec abilitato)
|
// fallback: openssl s_client (se exec è permesso)
|
||||||
$escHost = escapeshellarg($host);
|
$escHost = escapeshellarg($host);
|
||||||
$cmd = sprintf("timeout %d openssl s_client -connect %s:443 -servername %s -showcerts </dev/null 2>/dev/null | openssl x509 -noout -dates -issuer", $timeout, $escHost, $escHost);
|
$cmd = sprintf("openssl s_client -connect %s:443 -servername %s -showcerts </dev/null 2>/dev/null | openssl x509 -noout -dates -issuer", $escHost, $escHost);
|
||||||
|
if (!empty($GLOBALS['opensslTimeoutBin'])) {
|
||||||
|
$cmd = $GLOBALS['opensslTimeoutBin'] . " {$timeout} " . $cmd;
|
||||||
|
}
|
||||||
@exec($cmd, $out, $ret);
|
@exec($cmd, $out, $ret);
|
||||||
if ($ret === 0 && !empty($out)) {
|
if ($ret === 0 && !empty($out)) {
|
||||||
$joined = implode("\n", $out);
|
$joined = implode("\n", $out);
|
||||||
// notBefore / notAfter
|
$issued = null; $expiry = null; $company = null; $cn = null; $org = null;
|
||||||
if (preg_match('/notBefore=(.+)/i', $joined, $m1)) {
|
if (preg_match('/notBefore=(.+)/i', $joined, $m1)) {
|
||||||
$issuedRaw = trim($m1[1]);
|
$issuedRaw = trim($m1[1]);
|
||||||
$issuedTs = strtotime($issuedRaw);
|
$issuedTs = strtotime($issuedRaw);
|
||||||
$issued = $issuedTs ? date('d/m/Y', $issuedTs) : $issuedRaw;
|
$issued = $issuedTs ? date('d/m/Y', $issuedTs) : $issuedRaw;
|
||||||
} else {
|
|
||||||
$issued = null;
|
|
||||||
}
|
}
|
||||||
if (preg_match('/notAfter=(.+)/i', $joined, $m2)) {
|
if (preg_match('/notAfter=(.+)/i', $joined, $m2)) {
|
||||||
$expiryRaw = trim($m2[1]);
|
$expiryRaw = trim($m2[1]);
|
||||||
$expiryTs = strtotime($expiryRaw);
|
$expiryTs = strtotime($expiryRaw);
|
||||||
$expiry = $expiryTs ? date('d/m/Y', $expiryTs) : $expiryRaw;
|
$expiry = $expiryTs ? date('d/m/Y', $expiryTs) : $expiryRaw;
|
||||||
} else {
|
|
||||||
$expiry = null;
|
|
||||||
}
|
}
|
||||||
if (preg_match('/issuer=.*O=([^,\/]+)/i', $joined, $m3)) {
|
// extract CN and O from issuer string
|
||||||
$company = trim($m3[1]);
|
if (preg_match('/issuer=.*CN=([^,\/]+)/i', $joined, $mCN)) {
|
||||||
} elseif (preg_match('/issuer=.*CN=([^,\/]+)/i', $joined, $m4)) {
|
$cn = trim($mCN[1]);
|
||||||
$company = trim($m4[1]);
|
|
||||||
} else {
|
|
||||||
$company = null;
|
|
||||||
}
|
}
|
||||||
|
if (preg_match('/issuer=.*O=([^,\/]+)/i', $joined, $mO)) {
|
||||||
|
$org = trim($mO[1]);
|
||||||
|
}
|
||||||
|
// company fallback: prefer CN then org
|
||||||
|
$company = $cn ?? $org ?? null;
|
||||||
|
|
||||||
$isValid = 0;
|
$isValid = 0;
|
||||||
if ($expiry) {
|
if ($expiry) {
|
||||||
$dt = DateTime::createFromFormat('d/m/Y', $expiry);
|
$dt = DateTime::createFromFormat('d/m/Y', $expiry);
|
||||||
if ($dt) $isValid = (time() < $dt->getTimestamp()) ? 1 : 0;
|
if ($dt) $isValid = (time() < $dt->getTimestamp()) ? 1 : 0;
|
||||||
}
|
}
|
||||||
return [
|
|
||||||
'status' => $isValid,
|
$result['status'] = $isValid;
|
||||||
'issued' => $issued,
|
$result['issued'] = $issued;
|
||||||
'expiry' => $expiry,
|
$result['expiry'] = $expiry;
|
||||||
'company' => $company,
|
$result['company'] = $company;
|
||||||
'error' => null
|
$result['cn'] = $cn;
|
||||||
];
|
$result['org'] = $org;
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result['error'] = "stream_socket_client failed: $errstr ($errno)";
|
$result['error'] = "stream_socket_client failed: $errstr ($errno)";
|
||||||
@@ -187,10 +169,14 @@ function fetchWithCurl(string $url, ?string $user, ?string $pass, int $timeout =
|
|||||||
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
||||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
|
||||||
|
|
||||||
// se vuoi abilitare la verifica CA, metti true e assicurati che PHP abbia CA bundle
|
// non forziamo verifica CA per evitare falsi negativi in ambienti senza CA bundle
|
||||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||||
|
|
||||||
|
// browser-like headers per evitare 403 anti-bot
|
||||||
|
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117 Safari/537.36');
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8']);
|
||||||
|
|
||||||
if ($user !== null && $pass !== null) {
|
if ($user !== null && $pass !== null) {
|
||||||
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
||||||
curl_setopt($ch, CURLOPT_USERPWD, $user . ':' . $pass);
|
curl_setopt($ch, CURLOPT_USERPWD, $user . ':' . $pass);
|
||||||
@@ -217,13 +203,13 @@ function checkContentMatch(string $url, string $match, ?string $user, ?string $p
|
|||||||
|
|
||||||
// --- Leggi input JSON ---
|
// --- Leggi input JSON ---
|
||||||
if (!file_exists($inputFile)) {
|
if (!file_exists($inputFile)) {
|
||||||
echo "File $inputFile non trovato\n";
|
fwrite(STDERR, "File $inputFile non trovato\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
$raw = file_get_contents($inputFile);
|
$raw = file_get_contents($inputFile);
|
||||||
$domains = json_decode($raw, true);
|
$domains = json_decode($raw, true);
|
||||||
if ($domains === null) {
|
if ($domains === null) {
|
||||||
echo "Errore parsing JSON di input\n";
|
fwrite(STDERR, "Errore parsing JSON di input\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,12 +219,12 @@ $totalContentOk = 0;
|
|||||||
|
|
||||||
foreach ($domains as $entry) {
|
foreach ($domains as $entry) {
|
||||||
$host = $entry['host'] ?? null;
|
$host = $entry['host'] ?? null;
|
||||||
$domain = $entry['domain'] ?? null; // es. wiki.sld-server.org
|
$domain = $entry['domain'] ?? null;
|
||||||
$path = $entry['path'] ?? ''; // es. /doku.php?id=start oppure ""
|
$path = $entry['path'] ?? '';
|
||||||
$word = $entry['word-to-check'] ?? '';
|
$word = $entry['word-to-check'] ?? '';
|
||||||
$basicAuth = $entry['basic_auth'] ?? false;
|
$basicAuth = $entry['basic_auth'] ?? false;
|
||||||
|
|
||||||
// supporta sia basic_auth_password che basic_auth_pass (tolleranza nomi)
|
// supporta diversi nomi per password in input
|
||||||
$user = ($basicAuth && !empty($entry['basic_auth_name'])) ? $entry['basic_auth_name'] : null;
|
$user = ($basicAuth && !empty($entry['basic_auth_name'])) ? $entry['basic_auth_name'] : null;
|
||||||
$pass = null;
|
$pass = null;
|
||||||
if ($basicAuth) {
|
if ($basicAuth) {
|
||||||
@@ -248,12 +234,12 @@ foreach ($domains as $entry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// costruisci URL (https://domain + path). se path vuoto -> '/'
|
// costruisci URL (https://domain + path). se path vuoto -> '/'
|
||||||
$domainClean = preg_replace('#^https?://#i', '', rtrim($domain, '/'));
|
$domainClean = preg_replace('#^https?://#i', '', rtrim($domain ?? '', '/'));
|
||||||
$pathClean = $path === '' ? '/' : (strpos($path, '/') === 0 ? $path : '/' . $path);
|
$pathClean = $path === '' ? '/' : (strpos($path, '/') === 0 ? $path : '/' . $path);
|
||||||
$url = 'https://' . $domainClean . $pathClean;
|
$url = 'https://' . $domainClean . $pathClean;
|
||||||
|
|
||||||
// estrai host per SSL (rimuove eventuale port/path)
|
// estrai host per SSL (rimuove eventuale port/path)
|
||||||
$sslHost = normalizeDomainHost($domain);
|
$sslHost = normalizeDomainHost($domain ?? '');
|
||||||
|
|
||||||
// --- SSL info ---
|
// --- SSL info ---
|
||||||
$sslInfo = getCertInfo($sslHost, 443, $timeout);
|
$sslInfo = getCertInfo($sslHost, 443, $timeout);
|
||||||
@@ -277,7 +263,8 @@ foreach ($domains as $entry) {
|
|||||||
'sslcheck_ok' => $sslInfo['status'],
|
'sslcheck_ok' => $sslInfo['status'],
|
||||||
'ssl-released' => $sslInfo['issued'],
|
'ssl-released' => $sslInfo['issued'],
|
||||||
'ssl-expiry' => $sslInfo['expiry'],
|
'ssl-expiry' => $sslInfo['expiry'],
|
||||||
'ssl-company' => $sslInfo['company'],
|
'ssl-cn' => $sslInfo['cn'] ?? null,
|
||||||
|
'ssl-org' => $sslInfo['org'] ?? null,
|
||||||
// campi di debug utili per capire perché auth/content falliscono
|
// campi di debug utili per capire perché auth/content falliscono
|
||||||
'content_http_code' => $http_code,
|
'content_http_code' => $http_code,
|
||||||
'content_error' => $content_error,
|
'content_error' => $content_error,
|
||||||
@@ -291,4 +278,3 @@ file_put_contents($outputFile, json_encode($results, JSON_PRETTY_PRINT | JSON_UN
|
|||||||
// stampa sommario
|
// stampa sommario
|
||||||
echo "Check completato. Risultati salvati in $outputFile\n";
|
echo "Check completato. Risultati salvati in $outputFile\n";
|
||||||
echo "Totali: SSL ok = $totalSSLok, Content ok = $totalContentOk\n";
|
echo "Totali: SSL ok = $totalSSLok, Content ok = $totalContentOk\n";
|
||||||
?>
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"host": "hostname",
|
||||||
|
"domain": "domain",
|
||||||
|
"path": "/path(leave empty if is the webroot)",
|
||||||
|
"wordtocheck": "word to check",
|
||||||
|
"wordcheck_ok": 0,
|
||||||
|
"sslcheck_ok": 0,
|
||||||
|
"ssl-released": null,
|
||||||
|
"ssl-expiry": null,
|
||||||
|
"ssl-cn": null,
|
||||||
|
"ssl-org": null,
|
||||||
|
"content_http_code": 0,
|
||||||
|
"content_error": "URL rejected: Malformed input to a URL function",
|
||||||
|
"ssl_error": "stream_socket_client failed: php_network_getaddresses: getaddrinfo for domain failed: Name or service not known (0)"
|
||||||
|
}
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user