protected function fetchLatestCertData($until = false) { $ctx = $this->getStreamContext(); set_error_handler(function ($code, $message, $filename, $lineno, $context) { throw new \ErrorException(sprintf('%s: %s in %s line %d', $code, $message, $filename, $lineno), $code, 0, $filename, $lineno); }); try { $fp = stream_socket_client('ssl://mxr.mozilla.org:443', $errNo, $errStr, 30, STREAM_CLIENT_CONNECT, $ctx); } catch (\ErrorException $e) { restore_error_handler(); throw new \RuntimeException($errStr, $errNo, $e); } restore_error_handler(); $headers = "GET /mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1 HTTP/1.1\r\n"; $headers .= "Host: mxr.mozilla.org\r\n"; $headers .= "Connection: close\r\n"; $headers .= "Accept: */*\r\n"; fwrite($fp, "{$headers}\r\n"); // send request $response = ''; while (!feof($fp)) { $response .= fgets($fp); if ($until && strpos($response, $until) !== false) { break; } } fclose($fp); $params = stream_context_get_params($ctx); $cert = new X509Certificate($params['options']['ssl']['peer_certificate']); $pin = $cert->getPin(); if ($pin !== static::MOZILLA_MXR_SSL_PIN) { if (time() < static::MOZILLA_MXR_SSL_EXP) { throw new \RuntimeException(sprintf('ERROR: Certificate pin for mxr.mozilla.org did NOT match expected value! ' . 'Expected: %s Received: %s', static::MOZILLA_MXR_SSL_PIN, $pin)); } trigger_error('WARNING: mxr.mozilla.org certificate pin may be out of date. ' . 'If you continue to see this message after updating Sslurp, please ' . 'file an issue at https://github.com/EvanDotPro/Sslurp/issues'); } return $this->decodeChunkedString($this->getResponseBody($response)); }