diff --git a/functions/main.php b/functions/main.php
index a4ecf5e..d640f74 100644
--- a/functions/main.php
+++ b/functions/main.php
@@ -93,7 +93,8 @@ function get_status_class($ssl, $word, $expiry){
$wordtocheck=$check_element['wordtocheck'];
$ssl_released=$check_element['ssl-released'];
$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'];
$content_error=$check_element['content_error'];
$ssl_error=$check_element['ssl_error'];
@@ -135,7 +136,8 @@ function get_status_class($ssl, $word, $expiry){
SSL RELEASED: = $ssl_released ?>
SSL EXPIRY: >= $ssl_expiry ?>
SSL DAYS LEFT: >= $expirying_days ?>
- SSL COMPANY: = $ssl_company ?>
+ SSL COMMON NAME(CN): = $ssl_cn ?>
+ SSL ORGANISATION(O): = $ssl_org ?>
PATH: = $path ?>
ERROR CODE: = $http_error ?>
diff --git a/generate-report.php b/generate-report.php
index 98140f2..55ea22e 100644
--- a/generate-report.php
+++ b/generate-report.php
@@ -1,97 +1,75 @@
+#!/usr/bin/php
diff($expiry);
- $days = (int)$interval->format('%r%a'); // giorni con segno
-
- return $days;
+ return (int)$interval->format('%r%a'); // giorni con segno
}
function normalizeDomainHost(string $domain): string {
- // rimuovi schema se presente
if (preg_match('#^https?://#i', $domain)) {
$p = parse_url($domain);
return $p['host'] ?? rtrim($domain, '/');
}
- // rimuovi eventuale slash e porta
$d = preg_replace('#/.*$#', '', $domain);
$d = preg_replace('/:\d+$/', '', $d);
return $d;
}
-// Estrae nome "company" dall'issuer del certificato (controlla più chiavi possibili)
-function extractIssuerName(array $cert_info): ?string {
- if (empty($cert_info['issuer']) || !is_array($cert_info['issuer'])) return null;
- $issuer = $cert_info['issuer'];
-
- // controlla le chiavi comunemente usate
- $keys = ['O', 'commonName', 'o', 'OU', 'CN', 'organizationName'];
- foreach ($keys as $k) {
- if (isset($issuer[$k]) && !empty($issuer[$k])) {
- return $issuer[$k];
+// Estrazione CN / O dall'issuer ottenuto via openssl_x509_parse
+function extractIssuerFieldsFromParsed(array $cert_info): array {
+ $cn = null;
+ $org = null;
+ if (!empty($cert_info['issuer']) && is_array($cert_info['issuer'])) {
+ $issuer = $cert_info['issuer'];
+ // chiavi possibili: CN, commonName, O, organizationName
+ $cnKeys = ['CN', 'commonName', 'cn'];
+ $orgKeys = ['O', 'organizationName', 'o'];
+ 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; }
}
}
-
- // 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;
+ return ['cn' => $cn, 'org' => $org];
}
-function extractIssuerCN(array $cert_info): ?string {
- 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)
+// Ottieni informazioni certificato via stream_socket_client (SNI), fallback a openssl s_client
function getCertInfo(string $host, int $port = 443, int $timeout = 10): array {
$result = [
'status' => 0,
'issued' => null,
'expiry' => null,
- 'company' => null,
+ 'cn' => null,
+ 'org' => null,
'error' => null
];
+ // stream context con SNI
$ctx = stream_context_create([
'ssl' => [
'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,
'peer_name' => $host,
'SNI_enabled' => true,
@@ -109,16 +87,17 @@ function getCertInfo(string $host, int $port = 443, int $timeout = 10): array {
if ($cert_info !== false) {
$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;
- $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;
- $result = [
- 'status' => $isValid,
- 'issued' => $issued,
- 'expiry' => $expiry,
- 'company' => $company,
- 'error' => null
- ];
+ $result['status'] = $isValid;
+ $result['issued'] = $issued;
+ $result['expiry'] = $expiry;
+ $result['company'] = $company;
+ $result['cn'] = $fields['cn'];
+ $result['org'] = $fields['org'];
return $result;
} else {
$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);
- $cmd = sprintf("timeout %d openssl s_client -connect %s:443 -servername %s -showcerts /dev/null | openssl x509 -noout -dates -issuer", $timeout, $escHost, $escHost);
+ $cmd = sprintf("openssl s_client -connect %s:443 -servername %s -showcerts /dev/null | openssl x509 -noout -dates -issuer", $escHost, $escHost);
+ if (!empty($GLOBALS['opensslTimeoutBin'])) {
+ $cmd = $GLOBALS['opensslTimeoutBin'] . " {$timeout} " . $cmd;
+ }
@exec($cmd, $out, $ret);
if ($ret === 0 && !empty($out)) {
$joined = implode("\n", $out);
- // notBefore / notAfter
+ $issued = null; $expiry = null; $company = null; $cn = null; $org = null;
if (preg_match('/notBefore=(.+)/i', $joined, $m1)) {
$issuedRaw = trim($m1[1]);
$issuedTs = strtotime($issuedRaw);
$issued = $issuedTs ? date('d/m/Y', $issuedTs) : $issuedRaw;
- } else {
- $issued = null;
}
if (preg_match('/notAfter=(.+)/i', $joined, $m2)) {
$expiryRaw = trim($m2[1]);
$expiryTs = strtotime($expiryRaw);
$expiry = $expiryTs ? date('d/m/Y', $expiryTs) : $expiryRaw;
- } else {
- $expiry = null;
}
- if (preg_match('/issuer=.*O=([^,\/]+)/i', $joined, $m3)) {
- $company = trim($m3[1]);
- } elseif (preg_match('/issuer=.*CN=([^,\/]+)/i', $joined, $m4)) {
- $company = trim($m4[1]);
- } else {
- $company = null;
+ // extract CN and O from issuer string
+ if (preg_match('/issuer=.*CN=([^,\/]+)/i', $joined, $mCN)) {
+ $cn = trim($mCN[1]);
}
+ if (preg_match('/issuer=.*O=([^,\/]+)/i', $joined, $mO)) {
+ $org = trim($mO[1]);
+ }
+ // company fallback: prefer CN then org
+ $company = $cn ?? $org ?? null;
+
$isValid = 0;
if ($expiry) {
$dt = DateTime::createFromFormat('d/m/Y', $expiry);
if ($dt) $isValid = (time() < $dt->getTimestamp()) ? 1 : 0;
}
- return [
- 'status' => $isValid,
- 'issued' => $issued,
- 'expiry' => $expiry,
- 'company' => $company,
- 'error' => null
- ];
+
+ $result['status'] = $isValid;
+ $result['issued'] = $issued;
+ $result['expiry'] = $expiry;
+ $result['company'] = $company;
+ $result['cn'] = $cn;
+ $result['org'] = $org;
+ return $result;
}
$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_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_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) {
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $user . ':' . $pass);
@@ -217,13 +203,13 @@ function checkContentMatch(string $url, string $match, ?string $user, ?string $p
// --- Leggi input JSON ---
if (!file_exists($inputFile)) {
- echo "File $inputFile non trovato\n";
+ fwrite(STDERR, "File $inputFile non trovato\n");
exit(1);
}
$raw = file_get_contents($inputFile);
$domains = json_decode($raw, true);
if ($domains === null) {
- echo "Errore parsing JSON di input\n";
+ fwrite(STDERR, "Errore parsing JSON di input\n");
exit(1);
}
@@ -233,12 +219,12 @@ $totalContentOk = 0;
foreach ($domains as $entry) {
$host = $entry['host'] ?? null;
- $domain = $entry['domain'] ?? null; // es. wiki.sld-server.org
- $path = $entry['path'] ?? ''; // es. /doku.php?id=start oppure ""
+ $domain = $entry['domain'] ?? null;
+ $path = $entry['path'] ?? '';
$word = $entry['word-to-check'] ?? '';
$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;
$pass = null;
if ($basicAuth) {
@@ -248,12 +234,12 @@ foreach ($domains as $entry) {
}
// 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);
$url = 'https://' . $domainClean . $pathClean;
// estrai host per SSL (rimuove eventuale port/path)
- $sslHost = normalizeDomainHost($domain);
+ $sslHost = normalizeDomainHost($domain ?? '');
// --- SSL info ---
$sslInfo = getCertInfo($sslHost, 443, $timeout);
@@ -277,7 +263,8 @@ foreach ($domains as $entry) {
'sslcheck_ok' => $sslInfo['status'],
'ssl-released' => $sslInfo['issued'],
'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
'content_http_code' => $http_code,
'content_error' => $content_error,
@@ -291,4 +278,3 @@ file_put_contents($outputFile, json_encode($results, JSON_PRETTY_PRINT | JSON_UN
// stampa sommario
echo "Check completato. Risultati salvati in $outputFile\n";
echo "Totali: SSL ok = $totalSSLok, Content ok = $totalContentOk\n";
-?>
diff --git a/web_check.json b/web_check.json
index b915f90..63a6704 100644
--- a/web_check.json
+++ b/web_check.json
@@ -8,7 +8,8 @@
"sslcheck_ok": 0,
"ssl-released": null,
"ssl-expiry": null,
- "ssl-company": 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)"