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