]> git.ipfire.org Git - thirdparty/squid.git/blame - src/security/ErrorDetail.h
Detail client closures of CONNECT tunnels during TLS handshake (#691)
[thirdparty/squid.git] / src / security / ErrorDetail.h
CommitLineData
83b053a0
CT
1/*
2 * Copyright (C) 1996-2020 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
22namespace 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)
35class ErrorDetail: public ::ErrorDetail
36{
37 MEMPROXY_CLASS(Security::ErrorDetail);
38
39public:
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 = NULL);
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 /// \returns whether we (rather than `them`) should detail ErrorState
59 bool takesPriorityOver(const ErrorDetail &them) const {
60 // to reduce pointless updates, return false if us is them
61 return this->generation < them.generation;
62 }
63
64 /* ErrorDetail API */
65 virtual SBuf brief() const;
66 virtual SBuf verbose(const HttpRequestPointer &) const;
67
68 /// \returns error category; \see ErrorCode
69 ErrorCode errorNo() const { return error_no; }
70
71 /// \returns the previously saved errno(3) or zero
72 int sysError() const { return sysErrorNo; }
73
74 /* Certificate manipulation API. TODO: Add GnuTLS implementations, users. */
75
76 /// the peer certificate (or nil)
77 Certificate *peerCert() { return peer_cert.get(); }
78
79 /// peer or intermediate certificate that failed validation (or nil)
80 Certificate *brokenCert() {return broken_cert.get(); }
81
82 /// remember the SSL certificate of our peer; requires nil peerCert()
83 /// unlike the cert-setting constructor, does not assume the cert is bad
84 void setPeerCertificate(const CertPointer &);
85
86private:
87 ErrorDetail(ErrorCode err, int aSysErrorNo);
88
89 /* methods for formatting error details using admin-configurable %codes */
90 const char *subject() const;
91 const char *ca_name() const;
92 const char *cn() const;
93 const char *notbefore() const;
94 const char *notafter() const;
95 const char *err_code() const;
96 const char *err_descr() const;
97 const char *err_lib_error() const;
98 size_t convert(const char *code, const char **value) const;
99
100 static uint64_t Generations; ///< the total number of ErrorDetails ever made
101 uint64_t generation; ///< the number of ErrorDetails made before us plus one
102
103 CertPointer peer_cert; ///< A pointer to the peer certificate
104 CertPointer broken_cert; ///< A pointer to the broken certificate (peer or intermediate)
105
106 /// Squid-discovered error, validation error, or zero; \see ErrorCode
107 ErrorCode error_no = 0;
108
109 /// TLS library-reported non-validation error or zero; \see LibErrorCode
110 LibErrorCode lib_error_no = 0;
111
112 /// errno(3); system call failure code or zero
113 int sysErrorNo = 0;
114
115#if USE_OPENSSL
116 /// OpenSSL-specific (first-level or intermediate) TLS I/O operation result
117 /// reported by SSL_get_error(3SSL) (e.g., SSL_ERROR_SYSCALL) or zero.
118 /// Unlike lib_error_no, this error is mostly meant for I/O control and has
119 /// no OpenSSL-provided human-friendly text representation.
120 int ioErrorNo = 0;
121
122 using ErrorDetailEntry = Ssl::ErrorDetailEntry;
123 mutable ErrorDetailEntry detailEntry;
124#else
125 // other TLS libraries do not use custom ErrorDetail members
126#endif
127
128 String errReason; ///< a custom reason for the error
129};
130
131/// \returns ErrorCode with a given name (or zero)
132ErrorCode ErrorCodeFromName(const char *name);
133
134/// \returns string representation of ErrorCode, including raw X.509 error codes
135/// \param prefixRawCode whether to prefix raw codes with "SSL_ERR="
136const char *ErrorNameFromCode(ErrorCode err, bool prefixRawCode = false);
137
138}
139
140#endif
141