24#if HAVE_GNUTLS_GNUTLS_H
25#include <gnutls/gnutls.h>
36 "SQUID_TLS_ERR_ACCEPT"
39 "SQUID_TLS_ERR_CONNECT"
42 "SQUID_X509_V_ERR_INFINITE_VALIDATION"
45 "SQUID_X509_V_ERR_CERT_CHANGE"
48 "SQUID_X509_V_ERR_DOMAIN_MISMATCH"
51 { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT,
52 "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT"
54 { X509_V_ERR_UNABLE_TO_GET_CRL,
55 "X509_V_ERR_UNABLE_TO_GET_CRL"
57 { X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
58 "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE"
60 { X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
61 "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE"
63 { X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
64 "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY"
66 { X509_V_ERR_CERT_SIGNATURE_FAILURE,
67 "X509_V_ERR_CERT_SIGNATURE_FAILURE"
69 { X509_V_ERR_CRL_SIGNATURE_FAILURE,
70 "X509_V_ERR_CRL_SIGNATURE_FAILURE"
72 { X509_V_ERR_CERT_NOT_YET_VALID,
73 "X509_V_ERR_CERT_NOT_YET_VALID"
75 { X509_V_ERR_CERT_HAS_EXPIRED,
76 "X509_V_ERR_CERT_HAS_EXPIRED"
78 { X509_V_ERR_CRL_NOT_YET_VALID,
79 "X509_V_ERR_CRL_NOT_YET_VALID"
81 { X509_V_ERR_CRL_HAS_EXPIRED,
82 "X509_V_ERR_CRL_HAS_EXPIRED"
84 { X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD,
85 "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD"
87 { X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD,
88 "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD"
90 { X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD,
91 "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD"
93 { X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD,
94 "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD"
96 { X509_V_ERR_OUT_OF_MEM,
97 "X509_V_ERR_OUT_OF_MEM"
99 { X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,
100 "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT"
102 { X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN,
103 "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN"
105 { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
106 "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY"
108 { X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE,
109 "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE"
111 { X509_V_ERR_CERT_CHAIN_TOO_LONG,
112 "X509_V_ERR_CERT_CHAIN_TOO_LONG"
114 { X509_V_ERR_CERT_REVOKED,
115 "X509_V_ERR_CERT_REVOKED"
117 { X509_V_ERR_INVALID_CA,
118 "X509_V_ERR_INVALID_CA"
120 { X509_V_ERR_PATH_LENGTH_EXCEEDED,
121 "X509_V_ERR_PATH_LENGTH_EXCEEDED"
123 { X509_V_ERR_INVALID_PURPOSE,
124 "X509_V_ERR_INVALID_PURPOSE"
126 { X509_V_ERR_CERT_UNTRUSTED,
127 "X509_V_ERR_CERT_UNTRUSTED"
129 { X509_V_ERR_CERT_REJECTED,
130 "X509_V_ERR_CERT_REJECTED"
132 { X509_V_ERR_SUBJECT_ISSUER_MISMATCH,
133 "X509_V_ERR_SUBJECT_ISSUER_MISMATCH"
135 { X509_V_ERR_AKID_SKID_MISMATCH,
136 "X509_V_ERR_AKID_SKID_MISMATCH"
138 { X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH,
139 "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH"
141 { X509_V_ERR_KEYUSAGE_NO_CERTSIGN,
142 "X509_V_ERR_KEYUSAGE_NO_CERTSIGN"
144#if defined(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER)
146 X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER,
147 "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER"
150#if defined(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)
152 X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION,
153 "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION"
156#if defined(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN)
158 X509_V_ERR_KEYUSAGE_NO_CRL_SIGN,
159 "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN"
162#if defined(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION)
164 X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION,
165 "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION"
168#if defined(X509_V_ERR_INVALID_NON_CA)
170 X509_V_ERR_INVALID_NON_CA,
171 "X509_V_ERR_INVALID_NON_CA"
174#if defined(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED)
176 X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED,
177 "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED"
180#if defined(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE)
182 X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE,
183 "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE"
186#if defined(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED)
188 X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED,
189 "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED"
192#if defined(X509_V_ERR_INVALID_EXTENSION)
194 X509_V_ERR_INVALID_EXTENSION,
195 "X509_V_ERR_INVALID_EXTENSION"
198#if defined(X509_V_ERR_INVALID_POLICY_EXTENSION)
200 X509_V_ERR_INVALID_POLICY_EXTENSION,
201 "X509_V_ERR_INVALID_POLICY_EXTENSION"
204#if defined(X509_V_ERR_NO_EXPLICIT_POLICY)
206 X509_V_ERR_NO_EXPLICIT_POLICY,
207 "X509_V_ERR_NO_EXPLICIT_POLICY"
210#if defined(X509_V_ERR_DIFFERENT_CRL_SCOPE)
212 X509_V_ERR_DIFFERENT_CRL_SCOPE,
213 "X509_V_ERR_DIFFERENT_CRL_SCOPE"
216#if defined(X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE)
218 X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE,
219 "X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE"
222#if defined(X509_V_ERR_UNNESTED_RESOURCE)
224 X509_V_ERR_UNNESTED_RESOURCE,
225 "X509_V_ERR_UNNESTED_RESOURCE"
228#if defined(X509_V_ERR_PERMITTED_VIOLATION)
230 X509_V_ERR_PERMITTED_VIOLATION,
231 "X509_V_ERR_PERMITTED_VIOLATION"
234#if defined(X509_V_ERR_EXCLUDED_VIOLATION)
236 X509_V_ERR_EXCLUDED_VIOLATION,
237 "X509_V_ERR_EXCLUDED_VIOLATION"
240#if defined(X509_V_ERR_SUBTREE_MINMAX)
242 X509_V_ERR_SUBTREE_MINMAX,
243 "X509_V_ERR_SUBTREE_MINMAX"
246 { X509_V_ERR_APPLICATION_VERIFICATION,
247 "X509_V_ERR_APPLICATION_VERIFICATION"
249#if defined(X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE)
251 X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE,
252 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE"
255#if defined(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX)
257 X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX,
258 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX"
261#if defined(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX)
263 X509_V_ERR_UNSUPPORTED_NAME_SYNTAX,
264 "X509_V_ERR_UNSUPPORTED_NAME_SYNTAX"
267#if defined(X509_V_ERR_CRL_PATH_VALIDATION_ERROR)
269 X509_V_ERR_CRL_PATH_VALIDATION_ERROR,
270 "X509_V_ERR_CRL_PATH_VALIDATION_ERROR"
273#if defined(X509_V_ERR_PATH_LOOP)
275 X509_V_ERR_PATH_LOOP,
276 "X509_V_ERR_PATH_LOOP"
279#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION)
281 X509_V_ERR_SUITE_B_INVALID_VERSION,
282 "X509_V_ERR_SUITE_B_INVALID_VERSION"
285#if defined(X509_V_ERR_SUITE_B_INVALID_ALGORITHM)
287 X509_V_ERR_SUITE_B_INVALID_ALGORITHM,
288 "X509_V_ERR_SUITE_B_INVALID_ALGORITHM"
291#if defined(X509_V_ERR_SUITE_B_INVALID_CURVE)
293 X509_V_ERR_SUITE_B_INVALID_CURVE,
294 "X509_V_ERR_SUITE_B_INVALID_CURVE"
297#if defined(X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM)
299 X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM,
300 "X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM"
303#if defined(X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED)
305 X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED,
306 "X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED"
309#if defined(X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256)
311 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"
315#if defined(X509_V_ERR_HOSTNAME_MISMATCH)
317 X509_V_ERR_HOSTNAME_MISMATCH,
318 "X509_V_ERR_HOSTNAME_MISMATCH"
321#if defined(X509_V_ERR_EMAIL_MISMATCH)
323 X509_V_ERR_EMAIL_MISMATCH,
324 "X509_V_ERR_EMAIL_MISMATCH"
327#if defined(X509_V_ERR_IP_ADDRESS_MISMATCH)
329 X509_V_ERR_IP_ADDRESS_MISMATCH,
330 "X509_V_ERR_IP_ADDRESS_MISMATCH"
333#if defined(X509_V_ERR_DANE_NO_MATCH)
335 X509_V_ERR_DANE_NO_MATCH,
336 "X509_V_ERR_DANE_NO_MATCH"
339#if defined(X509_V_ERR_EE_KEY_TOO_SMALL)
341 X509_V_ERR_EE_KEY_TOO_SMALL,
342 "X509_V_ERR_EE_KEY_TOO_SMALL"
345#if defined(X509_V_ERR_CA_KEY_TOO_SMALL)
347 X509_V_ERR_CA_KEY_TOO_SMALL,
348 "X509_V_ERR_CA_KEY_TOO_SMALL"
351#if defined(X509_V_ERR_CA_MD_TOO_WEAK)
353 X509_V_ERR_CA_MD_TOO_WEAK,
354 "X509_V_ERR_CA_MD_TOO_WEAK"
357#if defined(X509_V_ERR_INVALID_CALL)
359 X509_V_ERR_INVALID_CALL,
360 "X509_V_ERR_INVALID_CALL"
363#if defined(X509_V_ERR_STORE_LOOKUP)
365 X509_V_ERR_STORE_LOOKUP,
366 "X509_V_ERR_STORE_LOOKUP"
369#if defined(X509_V_ERR_NO_VALID_SCTS)
371 X509_V_ERR_NO_VALID_SCTS,
372 "X509_V_ERR_NO_VALID_SCTS"
375#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION)
377 X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION,
378 "X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION"
381#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED)
383 X509_V_ERR_OCSP_VERIFY_NEEDED,
384 "X509_V_ERR_OCSP_VERIFY_NEEDED"
387#if defined(X509_V_ERR_OCSP_VERIFY_FAILED)
389 X509_V_ERR_OCSP_VERIFY_FAILED,
390 "X509_V_ERR_OCSP_VERIFY_FAILED"
393#if defined(X509_V_ERR_OCSP_CERT_UNKNOWN)
395 X509_V_ERR_OCSP_CERT_UNKNOWN,
396 "X509_V_ERR_OCSP_CERT_UNKNOWN"
411 static auto TheCmp = [](
const char *a,
const char *b) {
return strcmp(a, b) < 0;};
412 static std::map<
const char *,
ErrorCode,
decltype(TheCmp)> TheErrorCodeByNameIndx(TheCmp);
413 if (TheErrorCodeByNameIndx.empty()) {
415 TheErrorCodeByNameIndx.insert(std::make_pair(i.second, i.first));
421 const auto it = TheErrorCodeByNameIndx.find(name);
422 if (it != TheErrorCodeByNameIndx.end())
435 static char tmpBuffer[128];
436 snprintf(tmpBuffer,
sizeof(tmpBuffer),
"%s%d",
437 (prefixRawCode ?
"SSL_ERR=" :
""),
static_cast<int>(err));
450 sysErrorNo(aSysErrorNo)
501 SBuf buf(err_code());
507 buf.
append(
ToSBuf(
"+TLS_LIB_ERR=", std::hex, std::uppercase, lib_error_no));
509 buf.
append(
ToSBuf(
"+", gnutls_strerror_name(lib_error_no)));
526 buf.
append(
"+broken_cert");
534 char const *format =
nullptr;
537 format = detailEntry.detail.termedBuf();
542 format =
"SSL handshake error (%err_name)";
546 auto remainder = format;
547 while (
auto p = strchr(remainder,
'%')) {
548 errDetailStr.
append(remainder, p - remainder);
549 char const *converted =
nullptr;
550 const auto formattingCodeLen = convert(++p, &converted);
551 if (formattingCodeLen)
552 errDetailStr.
append(converted);
555 remainder = p + formattingCodeLen;
557 errDetailStr.
append(remainder, strlen(remainder));
567 if (!buf.isEmpty()) {
573 return "[Not available]";
579copy_cn(
void *check_data, ASN1_STRING *cn_data)
581 const auto str =
static_cast<String*
>(check_data);
584 if (cn_data && cn_data->length) {
587 str->append(
reinterpret_cast<const char *
>(cn_data->data), cn_data->length);
598 if (broken_cert.get()) {
609 return "[Not available]";
618 if (!buf.isEmpty()) {
624 return "[Not available]";
632 if (broken_cert.get()) {
634 static char tmpBuffer[256];
640 return "[Not available]";
648 if (broken_cert.get()) {
650 static char tmpBuffer[256];
656 return "[Not available]";
665 if (
const char *err = detailEntry.name.termedBuf())
679 if (
const char *err = detailEntry.descr.termedBuf())
682 return "[Not available]";
689 if (errReason.size() > 0)
690 return errReason.termedBuf();
691 else if (lib_error_no)
695 return "[Not available]";
719 typedef const char *(
ErrorDetail::*PartDescriber)()
const;
720 static const std::map<const char*, PartDescriber> PartDescriberByCode = {
731 for (
const auto &pair: PartDescriberByCode) {
732 const auto len = strlen(pair.first);
733 if (strncmp(
code, pair.first, len) == 0) {
734 const auto method = pair.second;
735 *value = (this->*method)();
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
SBuf & append(const SBuf &S)
size_t convert(const char *code, const char **value) const
SBuf verbose(const HttpRequestPointer &) const override
const char * err_code() const
textual representation of error_no
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)
const char * err_descr() const
short description of error_no
const char * subject() const
textual representation of the subject of the broken certificate
const char * err_lib_error() const
textual representation of lib_error_no
String errReason
a custom reason for the error
void setPeerCertificate(const CertPointer &)
SBuf brief() const override
const char * notafter() const
textual representation of the "not after" field of the broken certificate
const char * cn() const
a list of the broken certificates CN and alternate names
const char * ca_name() const
the issuer of the broken certificate
CertPointer peer_cert
A pointer to the peer certificate.
const char * notbefore() const
textual representation of the "not before" field of the broken certificate
static ErrorDetailsManager & GetInstance()
Instance class.
char const * termedBuf() const
void append(char const *buf, int len)
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 *)
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
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
static int copy_cn(void *check_data, ASN1_STRING *cn_data)
helper function to collect CNs using Ssl::matchX509CommonNames()
@ 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