ErrorDetail.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#include "squid.h"
10#include "base/IoManip.h"
12#include "html_quote.h"
13#include "sbuf/SBuf.h"
14#include "sbuf/Stream.h"
17#include "security/forward.h"
18#include "security/Io.h"
19#include "util.h"
20
21#if USE_OPENSSL
23#elif USE_GNUTLS
24#if HAVE_GNUTLS_GNUTLS_H
25#include <gnutls/gnutls.h>
26#endif
27#endif
28#include <map>
29
30namespace Security {
31
32// we use std::map to optimize search; TODO: Use std::unordered_map instead?
33typedef std::map<ErrorCode, const char *> ErrorCodeNames;
36 "SQUID_TLS_ERR_ACCEPT"
37 },
39 "SQUID_TLS_ERR_CONNECT"
40 },
42 "SQUID_X509_V_ERR_INFINITE_VALIDATION"
43 },
45 "SQUID_X509_V_ERR_CERT_CHANGE"
46 },
48 "SQUID_X509_V_ERR_DOMAIN_MISMATCH"
49 },
50#if USE_OPENSSL
51 { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT,
52 "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT"
53 },
54 { X509_V_ERR_UNABLE_TO_GET_CRL,
55 "X509_V_ERR_UNABLE_TO_GET_CRL"
56 },
57 { X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
58 "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE"
59 },
60 { X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
61 "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE"
62 },
63 { X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
64 "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY"
65 },
66 { X509_V_ERR_CERT_SIGNATURE_FAILURE,
67 "X509_V_ERR_CERT_SIGNATURE_FAILURE"
68 },
69 { X509_V_ERR_CRL_SIGNATURE_FAILURE,
70 "X509_V_ERR_CRL_SIGNATURE_FAILURE"
71 },
72 { X509_V_ERR_CERT_NOT_YET_VALID,
73 "X509_V_ERR_CERT_NOT_YET_VALID"
74 },
75 { X509_V_ERR_CERT_HAS_EXPIRED,
76 "X509_V_ERR_CERT_HAS_EXPIRED"
77 },
78 { X509_V_ERR_CRL_NOT_YET_VALID,
79 "X509_V_ERR_CRL_NOT_YET_VALID"
80 },
81 { X509_V_ERR_CRL_HAS_EXPIRED,
82 "X509_V_ERR_CRL_HAS_EXPIRED"
83 },
84 { X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD,
85 "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD"
86 },
87 { X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD,
88 "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD"
89 },
90 { X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD,
91 "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD"
92 },
93 { X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD,
94 "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD"
95 },
96 { X509_V_ERR_OUT_OF_MEM,
97 "X509_V_ERR_OUT_OF_MEM"
98 },
99 { X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,
100 "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT"
101 },
102 { X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN,
103 "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN"
104 },
105 { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
106 "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY"
107 },
108 { X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE,
109 "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE"
110 },
111 { X509_V_ERR_CERT_CHAIN_TOO_LONG,
112 "X509_V_ERR_CERT_CHAIN_TOO_LONG"
113 },
114 { X509_V_ERR_CERT_REVOKED,
115 "X509_V_ERR_CERT_REVOKED"
116 },
117 { X509_V_ERR_INVALID_CA,
118 "X509_V_ERR_INVALID_CA"
119 },
120 { X509_V_ERR_PATH_LENGTH_EXCEEDED,
121 "X509_V_ERR_PATH_LENGTH_EXCEEDED"
122 },
123 { X509_V_ERR_INVALID_PURPOSE,
124 "X509_V_ERR_INVALID_PURPOSE"
125 },
126 { X509_V_ERR_CERT_UNTRUSTED,
127 "X509_V_ERR_CERT_UNTRUSTED"
128 },
129 { X509_V_ERR_CERT_REJECTED,
130 "X509_V_ERR_CERT_REJECTED"
131 },
132 { X509_V_ERR_SUBJECT_ISSUER_MISMATCH,
133 "X509_V_ERR_SUBJECT_ISSUER_MISMATCH"
134 },
135 { X509_V_ERR_AKID_SKID_MISMATCH,
136 "X509_V_ERR_AKID_SKID_MISMATCH"
137 },
138 { X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH,
139 "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH"
140 },
141 { X509_V_ERR_KEYUSAGE_NO_CERTSIGN,
142 "X509_V_ERR_KEYUSAGE_NO_CERTSIGN"
143 },
144#if defined(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER)
145 {
146 X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, // 33
147 "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER"
148 },
149#endif
150#if defined(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)
151 {
152 X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION, // 34
153 "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION"
154 },
155#endif
156#if defined(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN)
157 {
158 X509_V_ERR_KEYUSAGE_NO_CRL_SIGN, // 35
159 "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN"
160 },
161#endif
162#if defined(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION)
163 {
164 X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION, // 36
165 "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION"
166 },
167#endif
168#if defined(X509_V_ERR_INVALID_NON_CA)
169 {
170 X509_V_ERR_INVALID_NON_CA, // 37
171 "X509_V_ERR_INVALID_NON_CA"
172 },
173#endif
174#if defined(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED)
175 {
176 X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED, // 38
177 "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED"
178 },
179#endif
180#if defined(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE)
181 {
182 X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE, // 39
183 "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE"
184 },
185#endif
186#if defined(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED)
187 {
188 X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED, // 40
189 "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED"
190 },
191#endif
192#if defined(X509_V_ERR_INVALID_EXTENSION)
193 {
194 X509_V_ERR_INVALID_EXTENSION, // 41
195 "X509_V_ERR_INVALID_EXTENSION"
196 },
197#endif
198#if defined(X509_V_ERR_INVALID_POLICY_EXTENSION)
199 {
200 X509_V_ERR_INVALID_POLICY_EXTENSION, // 42
201 "X509_V_ERR_INVALID_POLICY_EXTENSION"
202 },
203#endif
204#if defined(X509_V_ERR_NO_EXPLICIT_POLICY)
205 {
206 X509_V_ERR_NO_EXPLICIT_POLICY, // 43
207 "X509_V_ERR_NO_EXPLICIT_POLICY"
208 },
209#endif
210#if defined(X509_V_ERR_DIFFERENT_CRL_SCOPE)
211 {
212 X509_V_ERR_DIFFERENT_CRL_SCOPE, // 44
213 "X509_V_ERR_DIFFERENT_CRL_SCOPE"
214 },
215#endif
216#if defined(X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE)
217 {
218 X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE, // 45
219 "X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE"
220 },
221#endif
222#if defined(X509_V_ERR_UNNESTED_RESOURCE)
223 {
224 X509_V_ERR_UNNESTED_RESOURCE, // 46
225 "X509_V_ERR_UNNESTED_RESOURCE"
226 },
227#endif
228#if defined(X509_V_ERR_PERMITTED_VIOLATION)
229 {
230 X509_V_ERR_PERMITTED_VIOLATION, // 47
231 "X509_V_ERR_PERMITTED_VIOLATION"
232 },
233#endif
234#if defined(X509_V_ERR_EXCLUDED_VIOLATION)
235 {
236 X509_V_ERR_EXCLUDED_VIOLATION, // 48
237 "X509_V_ERR_EXCLUDED_VIOLATION"
238 },
239#endif
240#if defined(X509_V_ERR_SUBTREE_MINMAX)
241 {
242 X509_V_ERR_SUBTREE_MINMAX, // 49
243 "X509_V_ERR_SUBTREE_MINMAX"
244 },
245#endif
246 { X509_V_ERR_APPLICATION_VERIFICATION, // 50
247 "X509_V_ERR_APPLICATION_VERIFICATION"
248 },
249#if defined(X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE)
250 {
251 X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE, // 51
252 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE"
253 },
254#endif
255#if defined(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX)
256 {
257 X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX, // 52
258 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX"
259 },
260#endif
261#if defined(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX)
262 {
263 X509_V_ERR_UNSUPPORTED_NAME_SYNTAX, // 53
264 "X509_V_ERR_UNSUPPORTED_NAME_SYNTAX"
265 },
266#endif
267#if defined(X509_V_ERR_CRL_PATH_VALIDATION_ERROR)
268 {
269 X509_V_ERR_CRL_PATH_VALIDATION_ERROR, // 54
270 "X509_V_ERR_CRL_PATH_VALIDATION_ERROR"
271 },
272#endif
273#if defined(X509_V_ERR_PATH_LOOP)
274 {
275 X509_V_ERR_PATH_LOOP, // 55
276 "X509_V_ERR_PATH_LOOP"
277 },
278#endif
279#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION)
280 {
281 X509_V_ERR_SUITE_B_INVALID_VERSION, // 56
282 "X509_V_ERR_SUITE_B_INVALID_VERSION"
283 },
284#endif
285#if defined(X509_V_ERR_SUITE_B_INVALID_ALGORITHM)
286 {
287 X509_V_ERR_SUITE_B_INVALID_ALGORITHM, // 57
288 "X509_V_ERR_SUITE_B_INVALID_ALGORITHM"
289 },
290#endif
291#if defined(X509_V_ERR_SUITE_B_INVALID_CURVE)
292 {
293 X509_V_ERR_SUITE_B_INVALID_CURVE, // 58
294 "X509_V_ERR_SUITE_B_INVALID_CURVE"
295 },
296#endif
297#if defined(X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM)
298 {
299 X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM, // 59
300 "X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM"
301 },
302#endif
303#if defined(X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED)
304 {
305 X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED, // 60
306 "X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED"
307 },
308#endif
309#if defined(X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256)
310 {
311 X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256, // 61
312 "X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256"
313 },
314#endif
315#if defined(X509_V_ERR_HOSTNAME_MISMATCH)
316 {
317 X509_V_ERR_HOSTNAME_MISMATCH, // 62
318 "X509_V_ERR_HOSTNAME_MISMATCH"
319 },
320#endif
321#if defined(X509_V_ERR_EMAIL_MISMATCH)
322 {
323 X509_V_ERR_EMAIL_MISMATCH, // 63
324 "X509_V_ERR_EMAIL_MISMATCH"
325 },
326#endif
327#if defined(X509_V_ERR_IP_ADDRESS_MISMATCH)
328 {
329 X509_V_ERR_IP_ADDRESS_MISMATCH, // 64
330 "X509_V_ERR_IP_ADDRESS_MISMATCH"
331 },
332#endif
333#if defined(X509_V_ERR_DANE_NO_MATCH)
334 {
335 X509_V_ERR_DANE_NO_MATCH, // 65
336 "X509_V_ERR_DANE_NO_MATCH"
337 },
338#endif
339#if defined(X509_V_ERR_EE_KEY_TOO_SMALL)
340 {
341 X509_V_ERR_EE_KEY_TOO_SMALL, // 66
342 "X509_V_ERR_EE_KEY_TOO_SMALL"
343 },
344#endif
345#if defined(X509_V_ERR_CA_KEY_TOO_SMALL)
346 {
347 X509_V_ERR_CA_KEY_TOO_SMALL, // 67
348 "X509_V_ERR_CA_KEY_TOO_SMALL"
349 },
350#endif
351#if defined(X509_V_ERR_CA_MD_TOO_WEAK)
352 {
353 X509_V_ERR_CA_MD_TOO_WEAK, // 68
354 "X509_V_ERR_CA_MD_TOO_WEAK"
355 },
356#endif
357#if defined(X509_V_ERR_INVALID_CALL)
358 {
359 X509_V_ERR_INVALID_CALL, // 69
360 "X509_V_ERR_INVALID_CALL"
361 },
362#endif
363#if defined(X509_V_ERR_STORE_LOOKUP)
364 {
365 X509_V_ERR_STORE_LOOKUP, // 70
366 "X509_V_ERR_STORE_LOOKUP"
367 },
368#endif
369#if defined(X509_V_ERR_NO_VALID_SCTS)
370 {
371 X509_V_ERR_NO_VALID_SCTS, // 71
372 "X509_V_ERR_NO_VALID_SCTS"
373 },
374#endif
375#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION)
376 {
377 X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION, // 72
378 "X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION"
379 },
380#endif
381#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED)
382 {
383 X509_V_ERR_OCSP_VERIFY_NEEDED, // 73
384 "X509_V_ERR_OCSP_VERIFY_NEEDED"
385 },
386#endif
387#if defined(X509_V_ERR_OCSP_VERIFY_FAILED)
388 {
389 X509_V_ERR_OCSP_VERIFY_FAILED, // 74
390 "X509_V_ERR_OCSP_VERIFY_FAILED"
391 },
392#endif
393#if defined(X509_V_ERR_OCSP_CERT_UNKNOWN)
394 {
395 X509_V_ERR_OCSP_CERT_UNKNOWN, // 75
396 "X509_V_ERR_OCSP_CERT_UNKNOWN"
397 },
398#endif
399 {
400 SSL_ERROR_NONE,
401 "SSL_ERROR_NONE"
402 },
403#endif // USE_OPENSSL
404};
405
406} // namespace Security
407
410{
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()) {
414 for (const auto &i: TheErrorCodeNames)
415 TheErrorCodeByNameIndx.insert(std::make_pair(i.second, i.first));
416
417 // redirector to support legacy error translations
418 TheErrorCodeByNameIndx.insert(std::make_pair("SQUID_ERR_SSL_HANDSHAKE", SQUID_TLS_ERR_CONNECT));
419 }
420
421 const auto it = TheErrorCodeByNameIndx.find(name);
422 if (it != TheErrorCodeByNameIndx.end())
423 return it->second;
424
425 return 0;
426}
427
428const char *
429Security::ErrorNameFromCode(const ErrorCode err, const bool prefixRawCode)
430{
431 const auto it = TheErrorCodeNames.find(err);
432 if (it != TheErrorCodeNames.end())
433 return it->second;
434
435 static char tmpBuffer[128];
436 snprintf(tmpBuffer, sizeof(tmpBuffer), "%s%d",
437 (prefixRawCode ? "SSL_ERR=" : ""), static_cast<int>(err));
438 return tmpBuffer;
439}
440
441/* Security::ErrorDetail */
442
444Security::ErrorDetail::ErrorDetail(const ErrorCode err, const int aSysErrorNo):
445 error_no(err),
446 // We could restrict errno(3) collection to cases where the TLS library
447 // explicitly talks about the errno being set, but correctly detecting those
448 // cases is difficult. We simplify in hope that all other cases will either
449 // have a useful errno or a zero errno.
450 sysErrorNo(aSysErrorNo)
451{
452#if USE_OPENSSL
454 if ((lib_error_no = ERR_get_error())) {
455 debugs(83, 7, "got " << asHex(lib_error_no));
456 // more errors may be stacked
457 // TODO: Save/detail all stacked errors by always flushing stale ones.
458 ForgetErrors();
459 }
460#else
461 // other libraries return errors explicitly instead of auto-storing them
462#endif
463}
464
465Security::ErrorDetail::ErrorDetail(const ErrorCode anErrorCode, const CertPointer &cert, const CertPointer &broken, const char *aReason):
466 ErrorDetail(anErrorCode, 0)
467{
468 errReason = aReason;
469 peer_cert = cert;
470 broken_cert = broken ? broken : cert;
471}
472
473#if USE_OPENSSL
474Security::ErrorDetail::ErrorDetail(const ErrorCode anErrorCode, const int anIoErrorNo, const int aSysErrorNo):
475 ErrorDetail(anErrorCode, aSysErrorNo)
476{
477 ioErrorNo = anIoErrorNo;
478}
479
480#elif USE_GNUTLS
481Security::ErrorDetail::ErrorDetail(const ErrorCode anErrorCode, const LibErrorCode aLibErrorNo, const int aSysErrorNo):
482 ErrorDetail(anErrorCode, aSysErrorNo)
483{
484 lib_error_no = aLibErrorNo;
485}
486#endif
487
488void
490{
491 assert(cert);
492 assert(!peer_cert);
493 assert(!broken_cert);
494 peer_cert = cert;
495 // unlike the constructor, the supplied certificate is not a broken_cert
496}
497
498SBuf
500{
501 SBuf buf(err_code()); // TODO: Upgrade err_code()/etc. to return SBuf.
502
503 if (lib_error_no) {
504#if USE_OPENSSL
505 // TODO: Log ERR_error_string_n() instead, despite length, whitespace?
506 // Example: `error:1408F09C:SSL routines:ssl3_get_record:http request`.
507 buf.append(ToSBuf("+TLS_LIB_ERR=", std::hex, std::uppercase, lib_error_no));
508#elif USE_GNUTLS
509 buf.append(ToSBuf("+", gnutls_strerror_name(lib_error_no)));
510#endif
511 }
512
513#if USE_OPENSSL
514 // TODO: Consider logging long but human-friendly names (e.g.,
515 // SSL_ERROR_SYSCALL).
516 if (ioErrorNo)
517 buf.append(ToSBuf("+TLS_IO_ERR=", ioErrorNo));
518#endif
519
520 if (sysErrorNo) {
521 buf.append('+');
522 buf.append(SysErrorDetail::Brief(sysErrorNo));
523 }
524
525 if (broken_cert)
526 buf.append("+broken_cert");
527
528 return buf;
529}
530
531SBuf
533{
534 char const *format = nullptr;
535#if USE_OPENSSL
536 if (Ssl::ErrorDetailsManager::GetInstance().getErrorDetail(error_no, request, detailEntry))
537 format = detailEntry.detail.termedBuf();
538#else
539 (void)request;
540#endif
541 if (!format)
542 format = "SSL handshake error (%err_name)";
543
544 SBuf errDetailStr;
545 assert(format);
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);
553 else
554 errDetailStr.append("%");
555 remainder = p + formattingCodeLen;
556 }
557 errDetailStr.append(remainder, strlen(remainder));
558 return errDetailStr;
559}
560
562const char *
564{
565 if (broken_cert) {
566 auto buf = SubjectName(*broken_cert);
567 if (!buf.isEmpty()) {
568 // quote to avoid possible html code injection through
569 // certificate subject
570 return html_quote(buf.c_str());
571 }
572 }
573 return "[Not available]";
574}
575
576#if USE_OPENSSL
578static int
579copy_cn(void *check_data, ASN1_STRING *cn_data)
580{
581 const auto str = static_cast<String*>(check_data);
582 if (!str) // no data? abort
583 return 0;
584 if (cn_data && cn_data->length) {
585 if (str->size() > 0)
586 str->append(", ");
587 str->append(reinterpret_cast<const char *>(cn_data->data), cn_data->length);
588 }
589 return 1;
590}
591#endif // USE_OPENSSL
592
594const char *
596{
597#if USE_OPENSSL
598 if (broken_cert.get()) {
599 static String tmpStr;
600 tmpStr.clean();
601 Ssl::matchX509CommonNames(broken_cert.get(), &tmpStr, copy_cn);
602 if (tmpStr.size()) {
603 // quote to avoid possible HTML code injection through
604 // certificate subject
605 return html_quote(tmpStr.termedBuf());
606 }
607 }
608#endif // USE_OPENSSL
609 return "[Not available]";
610}
611
613const char *
615{
616 if (broken_cert) {
617 auto buf = IssuerName(*broken_cert);
618 if (!buf.isEmpty()) {
619 // quote to avoid possible html code injection through
620 // certificate issuer subject
621 return html_quote(buf.c_str());
622 }
623 }
624 return "[Not available]";
625}
626
628const char *
630{
631#if USE_OPENSSL
632 if (broken_cert.get()) {
633 if (const auto tm = X509_getm_notBefore(broken_cert.get())) {
634 static char tmpBuffer[256]; // A temporary buffer
635 Ssl::asn1timeToString(tm, tmpBuffer, sizeof(tmpBuffer));
636 return tmpBuffer;
637 }
638 }
639#endif // USE_OPENSSL
640 return "[Not available]";
641}
642
644const char *
646{
647#if USE_OPENSSL
648 if (broken_cert.get()) {
649 if (const auto tm = X509_getm_notAfter(broken_cert.get())) {
650 static char tmpBuffer[256]; // A temporary buffer
651 Ssl::asn1timeToString(tm, tmpBuffer, sizeof(tmpBuffer));
652 return tmpBuffer;
653 }
654 }
655#endif // USE_OPENSSL
656 return "[Not available]";
657}
658
660const char *
662{
663#if USE_OPENSSL
664 // try detailEntry first because it is faster
665 if (const char *err = detailEntry.name.termedBuf())
666 return err;
667#endif
668
669 return ErrorNameFromCode(error_no);
670}
671
673const char *
675{
676 if (!error_no)
677 return "[No Error]";
678#if USE_OPENSSL
679 if (const char *err = detailEntry.descr.termedBuf())
680 return err;
681#endif
682 return "[Not available]";
683}
684
686const char *
688{
689 if (errReason.size() > 0)
690 return errReason.termedBuf();
691 else if (lib_error_no)
692 return ErrorString(lib_error_no);
693 else
694 return "[No Error]";
695 return "[Not available]";
696}
697
716size_t
717Security::ErrorDetail::convert(const char *code, const char **value) const
718{
719 typedef const char *(ErrorDetail::*PartDescriber)() const;
720 static const std::map<const char*, PartDescriber> PartDescriberByCode = {
721 {"ssl_subject", &ErrorDetail::subject},
722 {"ssl_ca_name", &ErrorDetail::ca_name},
723 {"ssl_cn", &ErrorDetail::cn},
724 {"ssl_notbefore", &ErrorDetail::notbefore},
725 {"ssl_notafter", &ErrorDetail::notafter},
726 {"err_name", &ErrorDetail::err_code},
727 {"ssl_error_descr", &ErrorDetail::err_descr},
728 {"ssl_lib_error", &ErrorDetail::err_lib_error}
729 };
730
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)();
736 return len;
737 }
738 }
739
740 // TODO: Support logformat %codes.
741 *value = ""; // unused with zero return
742 return 0;
743}
744
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
Definition: IoManip.h:100
#define assert(EX)
Definition: assert.h:17
Definition: SBuf.h:94
SBuf & append(const SBuf &S)
Definition: SBuf.cc:185
size_t convert(const char *code, const char **value) const
Definition: ErrorDetail.cc:717
SBuf verbose(const HttpRequestPointer &) const override
Definition: ErrorDetail.cc:532
const char * err_code() const
textual representation of error_no
Definition: ErrorDetail.cc:661
LibErrorCode lib_error_no
TLS library-reported non-validation error or zero;.
Definition: ErrorDetail.h:101
ErrorDetail(ErrorCode err_no, const CertPointer &peer, const CertPointer &broken, const char *aReason=nullptr)
Definition: ErrorDetail.cc:465
CertPointer broken_cert
A pointer to the broken certificate (peer or intermediate)
Definition: ErrorDetail.h:95
const char * err_descr() const
short description of error_no
Definition: ErrorDetail.cc:674
const char * subject() const
textual representation of the subject of the broken certificate
Definition: ErrorDetail.cc:563
const char * err_lib_error() const
textual representation of lib_error_no
Definition: ErrorDetail.cc:687
String errReason
a custom reason for the error
Definition: ErrorDetail.h:119
void setPeerCertificate(const CertPointer &)
Definition: ErrorDetail.cc:489
SBuf brief() const override
Definition: ErrorDetail.cc:499
const char * notafter() const
textual representation of the "not after" field of the broken certificate
Definition: ErrorDetail.cc:645
const char * cn() const
a list of the broken certificates CN and alternate names
Definition: ErrorDetail.cc:595
const char * ca_name() const
the issuer of the broken certificate
Definition: ErrorDetail.cc:614
CertPointer peer_cert
A pointer to the peer certificate.
Definition: ErrorDetail.h:94
const char * notbefore() const
textual representation of the "not before" field of the broken certificate
Definition: ErrorDetail.cc:629
static ErrorDetailsManager & GetInstance()
Instance class.
void clean()
Definition: String.cc:103
char const * termedBuf() const
Definition: SquidString.h:92
void append(char const *buf, int len)
Definition: String.cc:130
size_type size() const
Definition: SquidString.h:73
static SBuf Brief(int errorNo)
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
int asn1timeToString(ASN1_TIME *tm, char *buf, int len)
Definition: support.cc:181
int matchX509CommonNames(X509 *peer_cert, void *check_data, int(*check_func)(void *check_data, ASN1_STRING *cn_data))
Definition: support.cc:195
unsigned char code
Definition: html_quote.c:20
char * html_quote(const char *)
Definition: html_quote.c:53
SBuf ErrorDetail
Definition: Esi.h:29
Network/connection security abstraction layer.
Definition: Connection.h:34
SBuf IssuerName(Certificate &)
The Issuer field of the given certificate (if found) or an empty SBuf.
Definition: Certificate.cc:28
std::map< ErrorCode, const char * > ErrorCodeNames
Definition: ErrorDetail.cc:33
int ErrorCode
Squid-defined error code (<0), an error code returned by X.509 API, or zero.
Definition: forward.h:128
const char * ErrorNameFromCode(ErrorCode err, bool prefixRawCode=false)
Definition: ErrorDetail.cc:429
unsigned long LibErrorCode
TLS library-reported non-validation error.
Definition: forward.h:135
ErrorCode ErrorCodeFromName(const char *name)
Definition: ErrorDetail.cc:409
SBuf SubjectName(Certificate &)
The SubjectName field of the given certificate (if found) or an empty SBuf.
Definition: Certificate.cc:68
const char * ErrorString(const LibErrorCode code)
converts numeric LibErrorCode into a human-friendlier string
Definition: forward.h:146
static const ErrorCodeNames TheErrorCodeNames
Definition: ErrorDetail.cc:34
void ForgetErrors()
clear any errors that a TLS library has accumulated in its global storage
Definition: Io.cc:57
#define X509_getm_notAfter
Definition: openssl.h:247
#define X509_getm_notBefore
Definition: openssl.h:248
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:63
static int copy_cn(void *check_data, ASN1_STRING *cn_data)
helper function to collect CNs using Ssl::matchX509CommonNames()
Definition: ErrorDetail.cc:579
@ SQUID_X509_V_ERR_INFINITE_VALIDATION
Definition: forward.h:231
@ SQUID_X509_V_ERR_DOMAIN_MISMATCH
Definition: forward.h:230
@ SQUID_TLS_ERR_CONNECT
failure to establish a connection with a TLS server
Definition: forward.h:226
@ SQUID_TLS_ERR_ACCEPT
failure to accept a connection from a TLS client
Definition: forward.h:225
@ SQUID_X509_V_ERR_CERT_CHANGE
Definition: forward.h:229

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors