]> git.ipfire.org Git - thirdparty/squid.git/blob - src/security/ErrorDetail.h
Maintenance: automate header guards 2/3 (#1655)
[thirdparty/squid.git] / src / security / ErrorDetail.h
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 #ifndef SQUID_SRC_SECURITY_ERRORDETAIL_H
10 #define SQUID_SRC_SECURITY_ERRORDETAIL_H
11
12 #include "base/RefCount.h"
13 #include "error/Detail.h"
14 #include "http/forward.h"
15 #include "security/forward.h"
16 #include "SquidString.h"
17
18 #if USE_OPENSSL
19 #include "ssl/ErrorDetailManager.h"
20 #endif
21
22 #if USE_OPENSSL
23 #include <optional>
24 #endif
25
26 namespace Security {
27
28 /// Details a TLS-related error. Two kinds of errors can be detailed:
29 /// * certificate validation errors (including built-in and helper-driven) and
30 /// * TLS logic and I/O errors (detected by Squid or the TLS library).
31 ///
32 /// The following details may be available (only the first one is required):
33 /// * for all errors: problem classification (\see ErrorCode)
34 /// * for all errors: peer certificate
35 /// * for certificate validation errors: the broken certificate
36 /// * for certificate validation errors: validation failure reason
37 /// * for non-validation errors: TLS library-reported error(s)
38 /// * for non-validation errors: system call errno(3)
39 class ErrorDetail: public ::ErrorDetail
40 {
41 MEMPROXY_CLASS(Security::ErrorDetail);
42
43 public:
44 typedef ErrorDetailPointer Pointer;
45
46 /// Details a server-side certificate verification failure.
47 /// If `broken` is nil, then the broken certificate is the peer certificate.
48 ErrorDetail(ErrorCode err_no, const CertPointer &peer, const CertPointer &broken, const char *aReason = nullptr);
49
50 #if USE_OPENSSL
51 /// Details (or starts detailing) a non-validation failure.
52 /// \param anIoErrorNo TLS I/O function outcome; \see ErrorDetail::ioErrorNo
53 /// \param aSysErrorNo saved errno(3); \see ErrorDetail::sysErrorNo
54 ErrorDetail(ErrorCode anErrorCode, int anIoErrorNo, int aSysErrorNo);
55 #elif USE_GNUTLS
56 /// Details (or starts detailing) a non-validation failure.
57 /// \param anLibErrorNo TLS function outcome; \see ErrorDetail::lib_error_no
58 /// \param aSysErrorNo saved errno(3); \see ErrorDetail::sysErrorNo
59 ErrorDetail(ErrorCode anErrorCode, LibErrorCode aLibErrorNo, int aSysErrorNo);
60 #endif
61
62 /* ErrorDetail API */
63 SBuf brief() const override;
64 SBuf verbose(const HttpRequestPointer &) const override;
65
66 /// \returns error category; \see ErrorCode
67 ErrorCode errorNo() const { return error_no; }
68
69 /// \returns the previously saved errno(3) or zero
70 int sysError() const { return sysErrorNo; }
71
72 /* Certificate manipulation API. TODO: Add GnuTLS implementations, users. */
73
74 /// the peer certificate (or nil)
75 Certificate *peerCert() { return peer_cert.get(); }
76
77 /// peer or intermediate certificate that failed validation (or nil)
78 Certificate *brokenCert() {return broken_cert.get(); }
79
80 /// remember the SSL certificate of our peer; requires nil peerCert()
81 /// unlike the cert-setting constructor, does not assume the cert is bad
82 void setPeerCertificate(const CertPointer &);
83
84 private:
85 ErrorDetail(ErrorCode err, int aSysErrorNo);
86
87 /* methods for formatting error details using admin-configurable %codes */
88 void printSubject(std::ostream &os) const;
89 void printCaName(std::ostream &os) const;
90 void printCommonName(std::ostream &os) const;
91 void printNotBefore(std::ostream &os) const;
92 void printNotAfter(std::ostream &os) const;
93 void printErrorCode(std::ostream &os) const;
94 void printErrorDescription(std::ostream &os) const;
95 void printErrorLibError(std::ostream &os) const;
96 size_t convertErrorCodeToDescription(const char *code, std::ostream &os) const;
97
98 CertPointer peer_cert; ///< A pointer to the peer certificate
99 CertPointer broken_cert; ///< A pointer to the broken certificate (peer or intermediate)
100
101 /// Squid-discovered error, validation error, or zero; \see ErrorCode
102 ErrorCode error_no = 0;
103
104 /// TLS library-reported non-validation error or zero; \see LibErrorCode
105 LibErrorCode lib_error_no = 0;
106
107 /// errno(3); system call failure code or zero
108 int sysErrorNo = 0;
109
110 #if USE_OPENSSL
111 /// OpenSSL-specific (first-level or intermediate) TLS I/O operation result
112 /// reported by SSL_get_error(3SSL) (e.g., SSL_ERROR_SYSCALL) or zero.
113 /// Unlike lib_error_no, this error is mostly meant for I/O control and has
114 /// no OpenSSL-provided human-friendly text representation.
115 int ioErrorNo = 0;
116
117 using ErrorDetailEntry = Ssl::ErrorDetailEntry;
118 mutable std::optional<ErrorDetailEntry> detailEntry;
119 #else
120 // other TLS libraries do not use custom ErrorDetail members
121 #endif
122
123 String errReason; ///< a custom reason for the error
124 };
125
126 /// \returns ErrorCode with a given name (or zero)
127 ErrorCode ErrorCodeFromName(const char *name);
128
129 /// \returns string representation of ErrorCode, including raw X.509 error codes
130 /// \param prefixRawCode whether to prefix raw codes with "SSL_ERR="
131 const char *ErrorNameFromCode(ErrorCode err, bool prefixRawCode = false);
132
133 /// Dump the given Security::ErrorDetail via a possibly nil pointer (for
134 /// debugging). Unfortunately, without this, compilers pick generic RefCount<T>
135 /// operator "<<" overload (with T=Security::ErrorDetail) instead of the
136 /// overload provided by the parent ErrorDetail class (that we call here).
137 inline std::ostream &
138 operator <<(std::ostream &os, const ErrorDetail::Pointer &p)
139 {
140 return operator <<(os, ::ErrorDetail::Pointer(p));
141 }
142
143 } // namespace Security
144
145 #endif /* SQUID_SRC_SECURITY_ERRORDETAIL_H */
146