2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
9 #ifndef SQUID_SRC_SECURITY_DETAIL_H
10 #define SQUID_SRC_SECURITY_DETAIL_H
12 #include "base/RefCount.h"
13 #include "error/Detail.h"
14 #include "http/forward.h"
15 #include "security/forward.h"
16 #include "SquidString.h"
19 #include "ssl/ErrorDetailManager.h"
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).
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
37 MEMPROXY_CLASS(Security::ErrorDetail
);
40 typedef ErrorDetailPointer Pointer
;
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);
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
);
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
);
59 SBuf
brief() const override
;
60 SBuf
verbose(const HttpRequestPointer
&) const override
;
62 /// \returns error category; \see ErrorCode
63 ErrorCode
errorNo() const { return error_no
; }
65 /// \returns the previously saved errno(3) or zero
66 int sysError() const { return sysErrorNo
; }
68 /* Certificate manipulation API. TODO: Add GnuTLS implementations, users. */
70 /// the peer certificate (or nil)
71 Certificate
*peerCert() { return peer_cert
.get(); }
73 /// peer or intermediate certificate that failed validation (or nil)
74 Certificate
*brokenCert() {return broken_cert
.get(); }
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
&);
81 ErrorDetail(ErrorCode err
, int aSysErrorNo
);
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;
94 CertPointer peer_cert
; ///< A pointer to the peer certificate
95 CertPointer broken_cert
; ///< A pointer to the broken certificate (peer or intermediate)
97 /// Squid-discovered error, validation error, or zero; \see ErrorCode
98 ErrorCode error_no
= 0;
100 /// TLS library-reported non-validation error or zero; \see LibErrorCode
101 LibErrorCode lib_error_no
= 0;
103 /// errno(3); system call failure code or zero
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.
113 using ErrorDetailEntry
= Ssl::ErrorDetailEntry
;
114 mutable ErrorDetailEntry detailEntry
;
116 // other TLS libraries do not use custom ErrorDetail members
119 String errReason
; ///< a custom reason for the error
122 /// \returns ErrorCode with a given name (or zero)
123 ErrorCode
ErrorCodeFromName(const char *name
);
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);
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
)
136 return operator <<(os
, ::ErrorDetail::Pointer(p
));
139 } // namespace Security