24#if HAVE_GNUTLS_GNUTLS_H
25#include <gnutls/gnutls.h>
37 "SQUID_TLS_ERR_ACCEPT"
40 "SQUID_TLS_ERR_CONNECT"
43 "SQUID_X509_V_ERR_INFINITE_VALIDATION"
46 "SQUID_X509_V_ERR_CERT_CHANGE"
49 "SQUID_X509_V_ERR_DOMAIN_MISMATCH"
52 { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT,
53 "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT"
55 { X509_V_ERR_UNABLE_TO_GET_CRL,
56 "X509_V_ERR_UNABLE_TO_GET_CRL"
58 { X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
59 "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE"
61 { X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
62 "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE"
64 { X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
65 "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY"
67 { X509_V_ERR_CERT_SIGNATURE_FAILURE,
68 "X509_V_ERR_CERT_SIGNATURE_FAILURE"
70 { X509_V_ERR_CRL_SIGNATURE_FAILURE,
71 "X509_V_ERR_CRL_SIGNATURE_FAILURE"
73 { X509_V_ERR_CERT_NOT_YET_VALID,
74 "X509_V_ERR_CERT_NOT_YET_VALID"
76 { X509_V_ERR_CERT_HAS_EXPIRED,
77 "X509_V_ERR_CERT_HAS_EXPIRED"
79 { X509_V_ERR_CRL_NOT_YET_VALID,
80 "X509_V_ERR_CRL_NOT_YET_VALID"
82 { X509_V_ERR_CRL_HAS_EXPIRED,
83 "X509_V_ERR_CRL_HAS_EXPIRED"
85 { X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD,
86 "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD"
88 { X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD,
89 "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD"
91 { X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD,
92 "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD"
94 { X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD,
95 "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD"
97 { X509_V_ERR_OUT_OF_MEM,
98 "X509_V_ERR_OUT_OF_MEM"
100 { X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,
101 "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT"
103 { X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN,
104 "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN"
106 { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
107 "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY"
109 { X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE,
110 "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE"
112 { X509_V_ERR_CERT_CHAIN_TOO_LONG,
113 "X509_V_ERR_CERT_CHAIN_TOO_LONG"
115 { X509_V_ERR_CERT_REVOKED,
116 "X509_V_ERR_CERT_REVOKED"
118 { X509_V_ERR_INVALID_CA,
119 "X509_V_ERR_INVALID_CA"
121 { X509_V_ERR_PATH_LENGTH_EXCEEDED,
122 "X509_V_ERR_PATH_LENGTH_EXCEEDED"
124 { X509_V_ERR_INVALID_PURPOSE,
125 "X509_V_ERR_INVALID_PURPOSE"
127 { X509_V_ERR_CERT_UNTRUSTED,
128 "X509_V_ERR_CERT_UNTRUSTED"
130 { X509_V_ERR_CERT_REJECTED,
131 "X509_V_ERR_CERT_REJECTED"
133 { X509_V_ERR_SUBJECT_ISSUER_MISMATCH,
134 "X509_V_ERR_SUBJECT_ISSUER_MISMATCH"
136 { X509_V_ERR_AKID_SKID_MISMATCH,
137 "X509_V_ERR_AKID_SKID_MISMATCH"
139 { X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH,
140 "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH"
142 { X509_V_ERR_KEYUSAGE_NO_CERTSIGN,
143 "X509_V_ERR_KEYUSAGE_NO_CERTSIGN"
145#if defined(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER)
147 X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER,
148 "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER"
151#if defined(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)
153 X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION,
154 "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION"
157#if defined(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN)
159 X509_V_ERR_KEYUSAGE_NO_CRL_SIGN,
160 "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN"
163#if defined(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION)
165 X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION,
166 "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION"
169#if defined(X509_V_ERR_INVALID_NON_CA)
171 X509_V_ERR_INVALID_NON_CA,
172 "X509_V_ERR_INVALID_NON_CA"
175#if defined(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED)
177 X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED,
178 "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED"
181#if defined(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE)
183 X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE,
184 "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE"
187#if defined(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED)
189 X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED,
190 "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED"
193#if defined(X509_V_ERR_INVALID_EXTENSION)
195 X509_V_ERR_INVALID_EXTENSION,
196 "X509_V_ERR_INVALID_EXTENSION"
199#if defined(X509_V_ERR_INVALID_POLICY_EXTENSION)
201 X509_V_ERR_INVALID_POLICY_EXTENSION,
202 "X509_V_ERR_INVALID_POLICY_EXTENSION"
205#if defined(X509_V_ERR_NO_EXPLICIT_POLICY)
207 X509_V_ERR_NO_EXPLICIT_POLICY,
208 "X509_V_ERR_NO_EXPLICIT_POLICY"
211#if defined(X509_V_ERR_DIFFERENT_CRL_SCOPE)
213 X509_V_ERR_DIFFERENT_CRL_SCOPE,
214 "X509_V_ERR_DIFFERENT_CRL_SCOPE"
217#if defined(X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE)
219 X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE,
220 "X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE"
223#if defined(X509_V_ERR_UNNESTED_RESOURCE)
225 X509_V_ERR_UNNESTED_RESOURCE,
226 "X509_V_ERR_UNNESTED_RESOURCE"
229#if defined(X509_V_ERR_PERMITTED_VIOLATION)
231 X509_V_ERR_PERMITTED_VIOLATION,
232 "X509_V_ERR_PERMITTED_VIOLATION"
235#if defined(X509_V_ERR_EXCLUDED_VIOLATION)
237 X509_V_ERR_EXCLUDED_VIOLATION,
238 "X509_V_ERR_EXCLUDED_VIOLATION"
241#if defined(X509_V_ERR_SUBTREE_MINMAX)
243 X509_V_ERR_SUBTREE_MINMAX,
244 "X509_V_ERR_SUBTREE_MINMAX"
247 { X509_V_ERR_APPLICATION_VERIFICATION,
248 "X509_V_ERR_APPLICATION_VERIFICATION"
250#if defined(X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE)
252 X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE,
253 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE"
256#if defined(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX)
258 X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX,
259 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX"
262#if defined(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX)
264 X509_V_ERR_UNSUPPORTED_NAME_SYNTAX,
265 "X509_V_ERR_UNSUPPORTED_NAME_SYNTAX"
268#if defined(X509_V_ERR_CRL_PATH_VALIDATION_ERROR)
270 X509_V_ERR_CRL_PATH_VALIDATION_ERROR,
271 "X509_V_ERR_CRL_PATH_VALIDATION_ERROR"
274#if defined(X509_V_ERR_PATH_LOOP)
276 X509_V_ERR_PATH_LOOP,
277 "X509_V_ERR_PATH_LOOP"
280#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION)
282 X509_V_ERR_SUITE_B_INVALID_VERSION,
283 "X509_V_ERR_SUITE_B_INVALID_VERSION"
286#if defined(X509_V_ERR_SUITE_B_INVALID_ALGORITHM)
288 X509_V_ERR_SUITE_B_INVALID_ALGORITHM,
289 "X509_V_ERR_SUITE_B_INVALID_ALGORITHM"
292#if defined(X509_V_ERR_SUITE_B_INVALID_CURVE)
294 X509_V_ERR_SUITE_B_INVALID_CURVE,
295 "X509_V_ERR_SUITE_B_INVALID_CURVE"
298#if defined(X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM)
300 X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM,
301 "X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM"
304#if defined(X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED)
306 X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED,
307 "X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED"
310#if defined(X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256)
312 X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256,
313 "X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256"
316#if defined(X509_V_ERR_HOSTNAME_MISMATCH)
318 X509_V_ERR_HOSTNAME_MISMATCH,
319 "X509_V_ERR_HOSTNAME_MISMATCH"
322#if defined(X509_V_ERR_EMAIL_MISMATCH)
324 X509_V_ERR_EMAIL_MISMATCH,
325 "X509_V_ERR_EMAIL_MISMATCH"
328#if defined(X509_V_ERR_IP_ADDRESS_MISMATCH)
330 X509_V_ERR_IP_ADDRESS_MISMATCH,
331 "X509_V_ERR_IP_ADDRESS_MISMATCH"
334#if defined(X509_V_ERR_DANE_NO_MATCH)
336 X509_V_ERR_DANE_NO_MATCH,
337 "X509_V_ERR_DANE_NO_MATCH"
340#if defined(X509_V_ERR_EE_KEY_TOO_SMALL)
342 X509_V_ERR_EE_KEY_TOO_SMALL,
343 "X509_V_ERR_EE_KEY_TOO_SMALL"
346#if defined(X509_V_ERR_CA_KEY_TOO_SMALL)
348 X509_V_ERR_CA_KEY_TOO_SMALL,
349 "X509_V_ERR_CA_KEY_TOO_SMALL"
352#if defined(X509_V_ERR_CA_MD_TOO_WEAK)
354 X509_V_ERR_CA_MD_TOO_WEAK,
355 "X509_V_ERR_CA_MD_TOO_WEAK"
358#if defined(X509_V_ERR_INVALID_CALL)
360 X509_V_ERR_INVALID_CALL,
361 "X509_V_ERR_INVALID_CALL"
364#if defined(X509_V_ERR_STORE_LOOKUP)
366 X509_V_ERR_STORE_LOOKUP,
367 "X509_V_ERR_STORE_LOOKUP"
370#if defined(X509_V_ERR_NO_VALID_SCTS)
372 X509_V_ERR_NO_VALID_SCTS,
373 "X509_V_ERR_NO_VALID_SCTS"
376#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION)
378 X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION,
379 "X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION"
382#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED)
384 X509_V_ERR_OCSP_VERIFY_NEEDED,
385 "X509_V_ERR_OCSP_VERIFY_NEEDED"
388#if defined(X509_V_ERR_OCSP_VERIFY_FAILED)
390 X509_V_ERR_OCSP_VERIFY_FAILED,
391 "X509_V_ERR_OCSP_VERIFY_FAILED"
394#if defined(X509_V_ERR_OCSP_CERT_UNKNOWN)
396 X509_V_ERR_OCSP_CERT_UNKNOWN,
397 "X509_V_ERR_OCSP_CERT_UNKNOWN"
412 static auto TheCmp = [](
const char *a,
const char *b) {
return strcmp(a, b) < 0;};
413 static std::map<
const char *,
ErrorCode,
decltype(TheCmp)> TheErrorCodeByNameIndx(TheCmp);
414 if (TheErrorCodeByNameIndx.empty()) {
416 TheErrorCodeByNameIndx.insert(std::make_pair(i.second, i.first));
422 const auto it = TheErrorCodeByNameIndx.find(name);
423 if (it != TheErrorCodeByNameIndx.end())
436 static char tmpBuffer[128];
437 snprintf(tmpBuffer,
sizeof(tmpBuffer),
"%s%d",
438 (prefixRawCode ?
"SSL_ERR=" :
""),
static_cast<int>(err));
451 sysErrorNo(aSysErrorNo)
510 os <<
"+TLS_LIB_ERR=" << std::hex << std::uppercase << lib_error_no << std::nouppercase << std::dec;
512 os <<
'+' << gnutls_strerror_name(lib_error_no);
520 os <<
"+TLS_IO_ERR=" << ioErrorNo;
528 os <<
"+broken_cert";
536 std::optional<SBuf> customFormat;
539 customFormat = errorDetail->detail;
543 auto format = customFormat ? customFormat->c_str() :
"SSL handshake error (%err_name)";
547 auto remainder = format;
548 while (
auto p = strchr(remainder,
'%')) {
549 os.write(remainder, p - remainder);
550 const auto formattingCodeLen = convertErrorCodeToDescription(++p, os);
551 if (!formattingCodeLen)
553 remainder = p + formattingCodeLen;
565 if (!buf.isEmpty()) {
573 os <<
"[Not available]";
584 static int PrintName(
void *, ASN1_STRING *);
587 bool printed =
false;
590 void printName(
const ASN1_STRING *);
608 if (name && name->length) {
613 SBuf buf(
reinterpret_cast<const char *
>(name->data), name->length);
626 if (broken_cert.get()) {
633 os <<
"[Not available]";
642 if (!buf.isEmpty()) {
649 os <<
"[Not available]";
657 if (broken_cert.get()) {
660 static char tmpBuffer[256];
667 os <<
"[Not available]";
675 if (broken_cert.get()) {
678 static char tmpBuffer[256];
685 os <<
"[Not available]";
695 os << detailEntry->name;
713 os << detailEntry->descr;
718 os <<
"[Not available]";
725 if (errReason.size() > 0)
727 else if (lib_error_no)
754 using PartDescriber = void (
ErrorDetail::*)(std::ostream &os)
const;
755 static const std::map<const char*, PartDescriber> PartDescriberByCode = {
768 for (
const auto &pair: PartDescriberByCode) {
769 const auto len = strlen(pair.first);
770 if (strncmp(
code, pair.first, len) == 0) {
771 const auto method = pair.second;
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
a helper class to print CNs extracted using Ssl::matchX509CommonNames()
CommonNamesPrinter(std::ostream &os)
void printName(const ASN1_STRING *)
static int PrintName(void *, ASN1_STRING *)
Ssl::matchX509CommonNames() visitor that reports the given name (if any)
bool printed
whether any names have been printed so far
std::ostream & os_
destination for printed names
SBuf buf()
bytes written so far
void printErrorCode(std::ostream &os) const
textual representation of error_no
SBuf verbose(const HttpRequestPointer &) const override
void printCommonName(std::ostream &os) const
a list of the broken certificates CN and alternate names
LibErrorCode lib_error_no
TLS library-reported non-validation error or zero;.
ErrorDetail(ErrorCode err_no, const CertPointer &peer, const CertPointer &broken, const char *aReason=nullptr)
CertPointer broken_cert
A pointer to the broken certificate (peer or intermediate)
void printSubject(std::ostream &os) const
textual representation of the subject of the broken certificate
size_t convertErrorCodeToDescription(const char *code, std::ostream &os) const
void printErrorLibError(std::ostream &os) const
textual representation of lib_error_no
void printErrorDescription(std::ostream &os) const
short description of error_no
String errReason
a custom reason for the error
void setPeerCertificate(const CertPointer &)
SBuf brief() const override
void printNotBefore(std::ostream &os) const
textual representation of the "not before" field of the broken certificate
void printCaName(std::ostream &os) const
the issuer of the broken certificate
void printNotAfter(std::ostream &os) const
textual representation of the "not after" field of the broken certificate
CertPointer peer_cert
A pointer to the peer certificate.
static ErrorDetailsManager & GetInstance()
Instance class.
static SBuf Brief(int errorNo)
#define debugs(SECTION, LEVEL, CONTENT)
int asn1timeToString(ASN1_TIME *tm, char *buf, int len)
int matchX509CommonNames(X509 *peer_cert, void *check_data, int(*check_func)(void *check_data, ASN1_STRING *cn_data))
char * html_quote(const char *string)
Network/connection security abstraction layer.
SBuf IssuerName(Certificate &)
The Issuer field of the given certificate (if found) or an empty SBuf.
std::map< ErrorCode, const char * > ErrorCodeNames
int ErrorCode
Squid-defined error code (<0), an error code returned by X.509 API, or zero.
const char * ErrorNameFromCode(ErrorCode err, bool prefixRawCode=false)
unsigned long LibErrorCode
TLS library-reported non-validation error.
ErrorCode ErrorCodeFromName(const char *name)
SBuf SubjectName(Certificate &)
The SubjectName field of the given certificate (if found) or an empty SBuf.
const char * ErrorString(const LibErrorCode code)
converts numeric LibErrorCode into a human-friendlier string
static const ErrorCodeNames TheErrorCodeNames
void ForgetErrors()
clear any errors that a TLS library has accumulated in its global storage
#define X509_getm_notAfter
#define X509_getm_notBefore
@ SQUID_X509_V_ERR_INFINITE_VALIDATION
@ SQUID_X509_V_ERR_DOMAIN_MISMATCH
@ SQUID_TLS_ERR_CONNECT
failure to establish a connection with a TLS server
@ SQUID_TLS_ERR_ACCEPT
failure to accept a connection from a TLS client
@ SQUID_X509_V_ERR_CERT_CHANGE