getParsedTlsHost($host); if ($parsedHost === null) { // Unable to parse the specified host $this->logger->debug('Ignoring certificate check of non-tls host ' . $host); return null; } // We need to disable verification here to also get an expired certificate $streamContext = stream_context_create([ 'ssl' => [ 'capture_peer_cert' => true, 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true, ], ]); // In case no port was specified, use port 443 for the check if (!str_contains($parsedHost, ':')) { $parsedHost .= ':443'; } $this->logger->debug('Checking certificate of ' . $parsedHost); $streamClient = stream_socket_client('ssl://' . $parsedHost, $errorNumber, $errorString, 30, STREAM_CLIENT_CONNECT, $streamContext); if ($streamClient === false || $errorNumber !== 0) { // Unable to connect or invalid server address $this->logger->debug('Unable to check certificate of ' . $parsedHost); return null; } $streamCertificate = stream_context_get_params($streamClient); $certificateInfo = openssl_x509_parse($streamCertificate['options']['ssl']['peer_certificate']); $certificateValidTo = new \DateTime('@' . $certificateInfo['validTo_time_t']); $now = new \DateTime(); $diff = $now->diff($certificateValidTo); $days = $diff->days; if ($days === false) { return null; } // $days will always be positive -> invert it, when the end date of the certificate is in the past if ($diff->invert) { $days *= -1; } return $days; } }