Fixed Generate Script
This commit is contained in:
278
generate-report.php
Normal file
278
generate-report.php
Normal file
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
// check_domains.php
|
||||
// --- Configurazione ---
|
||||
$inputFile = __DIR__ . '/web_list.json'; // modifica se necessario
|
||||
$outputFile = __DIR__ . '/web_check.json';
|
||||
$timeout = 10; // timeout secondi per connessioni
|
||||
|
||||
// --- Helpers ---
|
||||
// Estrae hostname da domain (rimuove eventuali schema/port/path)
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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 {
|
||||
$result = [
|
||||
'status' => 0,
|
||||
'issued' => null,
|
||||
'expiry' => null,
|
||||
'company' => null,
|
||||
'error' => null
|
||||
];
|
||||
|
||||
$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_name' => false,
|
||||
'peer_name' => $host,
|
||||
'SNI_enabled' => true,
|
||||
]
|
||||
]);
|
||||
|
||||
$address = "ssl://{$host}:{$port}";
|
||||
$client = @stream_socket_client($address, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $ctx);
|
||||
if ($client !== false) {
|
||||
$params = stream_context_get_params($client);
|
||||
@fclose($client);
|
||||
if (!empty($params['options']['ssl']['peer_certificate'])) {
|
||||
$cert = $params['options']['ssl']['peer_certificate'];
|
||||
$cert_info = @openssl_x509_parse($cert);
|
||||
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;
|
||||
$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
|
||||
];
|
||||
return $result;
|
||||
} else {
|
||||
$result['error'] = 'openssl_x509_parse failed';
|
||||
return $result;
|
||||
}
|
||||
} else {
|
||||
$result['error'] = 'no peer_certificate found';
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback: prova con openssl s_client se disponibile (solo se exec abilitato)
|
||||
$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);
|
||||
@exec($cmd, $out, $ret);
|
||||
if ($ret === 0 && !empty($out)) {
|
||||
$joined = implode("\n", $out);
|
||||
// notBefore / notAfter
|
||||
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;
|
||||
}
|
||||
$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['error'] = "stream_socket_client failed: $errstr ($errno)";
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Fetch content con cURL (supporta basic auth), ritorna array con body, http_code, error
|
||||
function fetchWithCurl(string $url, ?string $user, ?string $pass, int $timeout = 10) {
|
||||
if (!function_exists('curl_init')) return ['ok' => false, 'error' => 'curl missing'];
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
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
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
|
||||
if ($user !== null && $pass !== null) {
|
||||
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
||||
curl_setopt($ch, CURLOPT_USERPWD, $user . ':' . $pass);
|
||||
}
|
||||
|
||||
$body = curl_exec($ch);
|
||||
$err = curl_error($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($body === false) return ['ok' => false, 'error' => $err, 'http_code' => $code];
|
||||
return ['ok' => true, 'body' => $body, 'http_code' => $code];
|
||||
}
|
||||
|
||||
// Controlla presenza stringa (1/0) e ritorna anche eventuale debug
|
||||
function checkContentMatch(string $url, string $match, ?string $user, ?string $pass, int $timeout = 10): array {
|
||||
$resp = fetchWithCurl($url, $user, $pass, $timeout);
|
||||
if (!$resp['ok']) {
|
||||
return ['ok' => 0, 'http_code' => $resp['http_code'] ?? null, 'error' => $resp['error'] ?? 'fetch failed'];
|
||||
}
|
||||
$found = (strpos($resp['body'], $match) !== false) ? 1 : 0;
|
||||
return ['ok' => $found, 'http_code' => $resp['http_code'] ?? null, 'error' => null];
|
||||
}
|
||||
|
||||
// --- Leggi input JSON ---
|
||||
if (!file_exists($inputFile)) {
|
||||
echo "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";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$results = [];
|
||||
$totalSSLok = 0;
|
||||
$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 ""
|
||||
$word = $entry['word-to-check'] ?? '';
|
||||
$basicAuth = $entry['basic_auth'] ?? false;
|
||||
|
||||
// supporta sia basic_auth_password che basic_auth_pass (tolleranza nomi)
|
||||
$user = ($basicAuth && !empty($entry['basic_auth_name'])) ? $entry['basic_auth_name'] : null;
|
||||
$pass = null;
|
||||
if ($basicAuth) {
|
||||
if (!empty($entry['basic_auth_password'])) $pass = $entry['basic_auth_password'];
|
||||
elseif (!empty($entry['basic_auth_pass'])) $pass = $entry['basic_auth_pass'];
|
||||
elseif (!empty($entry['basic_auth_passwd'])) $pass = $entry['basic_auth_passwd'];
|
||||
}
|
||||
|
||||
// costruisci URL (https://domain + path). se path vuoto -> '/'
|
||||
$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);
|
||||
|
||||
// --- SSL info ---
|
||||
$sslInfo = getCertInfo($sslHost, 443, $timeout);
|
||||
|
||||
// --- content check ---
|
||||
$contentCheck = checkContentMatch($url, $word, $user, $pass, $timeout);
|
||||
|
||||
$word_ok = $contentCheck['ok'];
|
||||
$http_code = $contentCheck['http_code'] ?? null;
|
||||
$content_error = $contentCheck['error'] ?? null;
|
||||
|
||||
if ($sslInfo['status'] === 1) $totalSSLok++;
|
||||
if ($word_ok === 1) $totalContentOk++;
|
||||
|
||||
$results[] = [
|
||||
'host' => $host,
|
||||
'domain' => $domain,
|
||||
'path' => $path,
|
||||
'wordtocheck' => $word,
|
||||
'wordcheck_ok' => $word_ok,
|
||||
'sslcheck_ok' => $sslInfo['status'],
|
||||
'ssl-released' => $sslInfo['issued'],
|
||||
'ssl-expiry' => $sslInfo['expiry'],
|
||||
'ssl-company' => $sslInfo['company'],
|
||||
// campi di debug utili per capire perché auth/content falliscono
|
||||
'content_http_code' => $http_code,
|
||||
'content_error' => $content_error,
|
||||
'ssl_error' => $sslInfo['error'] ?? null
|
||||
];
|
||||
}
|
||||
|
||||
// salva output (unescaped slashes)
|
||||
file_put_contents($outputFile, json_encode($results, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
|
||||
// stampa sommario
|
||||
echo "Check completato. Risultati salvati in $outputFile\n";
|
||||
echo "Totali: SSL ok = $totalSSLok, Content ok = $totalContentOk\n";
|
||||
?>
|
||||
Reference in New Issue
Block a user