Commit 6ddb325d authored by Thomas Bella's avatar Thomas Bella

Add basic logging of actions

parent afb8fe7d
......@@ -12,6 +12,7 @@ header("Content-Type: text/plain");
$SQL = new SQL(null, null, null, [ "file" => "monitor.sqlite", "driver" => "sqlite" ]);
vlog('Starting cronjob ...');
if (EMAIL && !empty(EMAIL_TARGET)) {
if (EMAIL_TARGET !== false) {
// Multiple emails
......@@ -23,37 +24,45 @@ if (EMAIL && !empty(EMAIL_TARGET)) {
} else {
$globalEmailList = [];
}
vlog('Got ' . count($globalEmailList) . ' global EMails');
}
$ressources = $SQL->query("SELECT domain.*, log.* FROM domain LEFT JOIN log ON domain.id = log.domain_id ORDER BY log.last_check ASC");
foreach ($ressources as $row) {
vlog('Checking \'' . $row["domain"] . '\'');
// Check if log exists and create a new one if not existant
if (empty($row["domain_id"])) {
$SQL->query("INSERT OR IGNORE INTO log (domain_id) VALUES (:id)", [ "id" => $row["id"] ]);
vlog('Adding entry in log table');
}
//// Check if certificate should be checked
// Certificates which will expire in under 30 days are checked every 15 minutes
if ($row["expire"] <= 31 && $row["last_check"] >= time()-60*15) {
vlog('Skip certificate check [<31|15m]', 1);
continue;
} else if ($row["last_check"] >= time()-60*60*6) {
vlog('Skip certificate check [>31|6h]', 1);
continue;
}
// Check if domain has DNS records or an IP was given
if (!checkdnsrr($row["domain"], "A") && !checkdnsrr($row["domain"], "AAAA") && !checkdnsrr($row["domain"], "CNAME") && filter_var($row["domain"], FILTER_VALIDATE_IP) === false) {
$SQL->query("UPDATE domain SET error = :error WHERE id = :id", [ "error" => "DNS cannot be resolved", "id" => $row["id"] ]);
vlog('DNS cannot be resolved. Skipping', 1);
continue;
}
// When certificate is obtained after an plaintext upgrade (STARTTLS), normal fetch cannot be used
if (isset($ports[$row["port"]]) && isset($ports[$row["port"]]["starttls"]) && $ports[$row["port"]]["starttls"] == true) { // STARTTLS
vlog('Using STARTTLS to fetch certificate', 1);
// Fetch certificates
$certificates = shell_exec("timeout 10 openssl s_client -showcerts -connect " . escapeshellarg($row["domain"]) . ":" . escapeshellarg($row["port"]) . " -starttls " . escapeshellarg($ports[$row["port"]]["protocol"]) . " < /dev/null");
if ($certificates == null) {
$SQL->query("UPDATE domain SET error = :error WHERE id = :id", [ "error" => "Can't fetch certificate from domain", "id" => $row["id"] ]);
vlog('Can\'t fetch certificate from domain', 2);
continue;
}
......@@ -99,6 +108,7 @@ foreach ($ressources as $row) {
}
} else { // STARTTLS END | SSL
vlog('Fetching certificate directly from target', 1);
// Fetch certificate from source
$certs = CertificateReader::fetchRawChain(trim($row["domain"]), (int)$row["port"]);
......@@ -106,6 +116,7 @@ foreach ($ressources as $row) {
// Check if certificate was fetched correctly
if ($certs === false) {
$SQL->query("UPDATE domain SET error = :error WHERE id = :id", [ "error" => "Can't fetch certificate from domain", "id" => $row["id"] ]);
vlog('Can\'t fetch certificate from domain', 1);
continue;
}
......@@ -120,6 +131,7 @@ foreach ($ressources as $row) {
// If no non-CA certificate can be found, save it as error
if ($cert === null) {
$SQL->query("UPDATE domain SET error = :error WHERE id = :id", [ "error" => "Can't fetch and parse correct certificate from domain", "id" => $row["id"] ]);
vlog('Can\'t fetch and parse correct certificate from domain', 1);
continue;
}
......@@ -161,15 +173,19 @@ foreach ($ressources as $row) {
if (!$wildcard && !in_array($row["domain"], CertificateReader::getDomains($cert))) {
$untrustedReason = "Domain name mismatch";
vlog('Domain name mismatch', 1);
} else if (CertificateReader::expiryDate($cert) < time()) {
$untrustedReason = "Certificate is expired";
vlog('Certificate is expired', 1);
} else if (customCertificateAuthority($SQL, $certs)) {
vlog('Certificate found within custom CA storage', 1);
$trusted = true;
}
}
} // SSL END
vlog('Writing updated information to database', 1);
// Write information into log table
$SQL->query("UPDATE log SET expire = :expire, domains = :domains, issuer = :issuer, trusted = :trusted, last_check = :lastcheck WHERE domain_id = :domain_id", [
"expire" => CertificateReader::expiryDate($cert),
......@@ -187,6 +203,7 @@ foreach ($ressources as $row) {
$SQL->query("UPDATE domain SET error = :error WHERE id = :id", [ "error" => $untrustedReason, "id" => $row["id"] ]);
}
vlog('Checking EMail notification', 1);
// Process email only if email addresses are given
if (EMAIL == true && (count($globalEmailList) != 0 || strlen($row['email']) != 0)) {
// Check if multiple emails are given
......@@ -197,28 +214,37 @@ foreach ($ressources as $row) {
} else {
$emailList = $globalEmailList;
}
vlog('Found ' . count($emailList) . ' EMail adresses to notify', 2);
// Determine days until certificate expires
$expiryDate = CertificateReader::expiryDate($cert);
$daysUntilExpire = floor(($expiryDate - time()) / (60 * 60 * 24));
vlog($daysUntilExpire . ' days until expiration', 2);
// Detect notification state
if ($daysUntilExpire < 0 && $row['notification_step'] < 4) {
vlog('Certificate is expired', 2);
$days = -1;
$index = 4;
} else if ($daysUntilExpire <= 3 && $row['notification_step'] < 3) {
vlog('3 days until expiration', 2);
$days = 3;
$index = 3;
} else if ($daysUntilExpire <= 7 && $row['notification_step'] < 2) {
vlog('7 days until expiration', 2);
$days = 7;
$index = 2;
} else if ($daysUntilExpire <= 29 && $row['notification_step'] < 1) {
vlog('29 days until expiration', 2);
$days = 29;
$index = 1;
} else {
// Reset expiry to 0 to reenable notifications
if ($daysUntilExpire > 29) {
vlog('Resetting expiration counter', 2);
$SQL->query("UPDATE log SET notification_step = :notstep WHERE domain_id = :id", [ "notstep" => 0, "id" => $row["id"] ]);
} else {
vlog('Notification already sent', 2);
}
$days = false;
}
......@@ -228,6 +254,7 @@ foreach ($ressources as $row) {
$SQL->query("UPDATE log SET notification_step = :notstep WHERE domain_id = :id", [ "notstep" => $index, "id" => $row["id"] ]);
foreach ($emailList as $singleEmail) {
vlog('Sending expiration EMail to ' . $singleEmail, 2);
$mail = new PHPMailer;
if (EMAIL_SMTP) {
......@@ -249,6 +276,9 @@ foreach ($ressources as $row) {
$mail->Body = 'Your certificate for ' . $row['domain'] . ':' . $row['port'] . ' will expire in about ' . $days . ' days (' . date("d.m.Y H:i", $expiryDate) . ').' . "\n" .
'Please renew your certificate.' . "\n\n" . 'Certificate Monitor on ' . BASEURL;
if (!$mail->send()) {
vlog($mail->ErrorInfo, 2);
}
}
} // $days not false
} // EMAIL enabled
......@@ -258,6 +288,7 @@ foreach ($ressources as $row) {
// Garbage Collection - Every 4 days
if ($SQL->single("SELECT value FROM meta WHERE key = 'garbagecollection'") <= time()-60*60*24*4) {
vlog('Starting garbage collector');
$SQL->query("INSERT OR REPLACE INTO meta (key, value) VALUES ('garbagecollection', :time)", ["time" => time()]);
// Delete unreferenced records
......@@ -324,3 +355,7 @@ function customCertificateAuthority($SQL, $certs) {
return $trusted;
}
function vlog($msg, $repeat = 0) {
echo date('M d H:i:s') . str_repeat("\t", $repeat) . ' ' . trim($msg) . "\n";
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment