]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/ErrorDetail.cc
Detail client closures of CONNECT tunnels during TLS handshake (#691)
[thirdparty/squid.git] / src / ssl / ErrorDetail.cc
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 #include "squid.h"
10 #include "errorpage.h"
11 #include "fatal.h"
12 #include "ssl/ErrorDetail.h"
13 #include "ssl/ErrorDetailManager.h"
14
15 #include <map>
16
17 static const char *OptionalSslErrors[] = {
18 "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER",
19 "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION",
20 "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN",
21 "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION",
22 "X509_V_ERR_INVALID_NON_CA",
23 "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED",
24 "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE",
25 "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED",
26 "X509_V_ERR_INVALID_EXTENSION",
27 "X509_V_ERR_INVALID_POLICY_EXTENSION",
28 "X509_V_ERR_NO_EXPLICIT_POLICY",
29 "X509_V_ERR_DIFFERENT_CRL_SCOPE",
30 "X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE",
31 "X509_V_ERR_UNNESTED_RESOURCE",
32 "X509_V_ERR_PERMITTED_VIOLATION",
33 "X509_V_ERR_EXCLUDED_VIOLATION",
34 "X509_V_ERR_SUBTREE_MINMAX",
35 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE",
36 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX",
37 "X509_V_ERR_UNSUPPORTED_NAME_SYNTAX",
38 "X509_V_ERR_CRL_PATH_VALIDATION_ERROR",
39 "X509_V_ERR_PATH_LOOP",
40 "X509_V_ERR_SUITE_B_INVALID_VERSION",
41 "X509_V_ERR_SUITE_B_INVALID_ALGORITHM",
42 "X509_V_ERR_SUITE_B_INVALID_CURVE",
43 "X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM",
44 "X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED",
45 "X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256",
46 "X509_V_ERR_HOSTNAME_MISMATCH",
47 "X509_V_ERR_EMAIL_MISMATCH",
48 "X509_V_ERR_IP_ADDRESS_MISMATCH",
49 "X509_V_ERR_DANE_NO_MATCH",
50 "X509_V_ERR_EE_KEY_TOO_SMALL",
51 "X509_V_ERR_CA_KEY_TOO_SMALL",
52 "X509_V_ERR_CA_MD_TOO_WEAK",
53 "X509_V_ERR_INVALID_CALL",
54 "X509_V_ERR_STORE_LOOKUP",
55 "X509_V_ERR_NO_VALID_SCTS",
56 "X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION",
57 "X509_V_ERR_OCSP_VERIFY_NEEDED",
58 "X509_V_ERR_OCSP_VERIFY_FAILED",
59 "X509_V_ERR_OCSP_CERT_UNKNOWN",
60 NULL
61 };
62
63 struct SslErrorAlias {
64 const char *name;
65 const Security::ErrorCode *errors;
66 };
67
68 static const Security::ErrorCode hasExpired[] = {X509_V_ERR_CERT_HAS_EXPIRED, SSL_ERROR_NONE};
69 static const Security::ErrorCode notYetValid[] = {X509_V_ERR_CERT_NOT_YET_VALID, SSL_ERROR_NONE};
70 static const Security::ErrorCode domainMismatch[] = {SQUID_X509_V_ERR_DOMAIN_MISMATCH, SSL_ERROR_NONE};
71 static const Security::ErrorCode certUntrusted[] = {X509_V_ERR_INVALID_CA,
72 X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN,
73 X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE,
74 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT,
75 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
76 X509_V_ERR_CERT_UNTRUSTED, SSL_ERROR_NONE
77 };
78 static const Security::ErrorCode certSelfSigned[] = {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, SSL_ERROR_NONE};
79
80 // The list of error name shortcuts for use with ssl_error acls.
81 // The keys without the "ssl::" scope prefix allow shorter error
82 // names within the SSL options scope. This is easier than
83 // carefully stripping the scope prefix in Ssl::ParseErrorString().
84 static SslErrorAlias TheSslErrorShortcutsArray[] = {
85 {"ssl::certHasExpired", hasExpired},
86 {"certHasExpired", hasExpired},
87 {"ssl::certNotYetValid", notYetValid},
88 {"certNotYetValid", notYetValid},
89 {"ssl::certDomainMismatch", domainMismatch},
90 {"certDomainMismatch", domainMismatch},
91 {"ssl::certUntrusted", certUntrusted},
92 {"certUntrusted", certUntrusted},
93 {"ssl::certSelfSigned", certSelfSigned},
94 {"certSelfSigned", certSelfSigned},
95 {NULL, NULL}
96 };
97
98 // Use std::map to optimize search.
99 typedef std::map<std::string, const Security::ErrorCode *> SslErrorShortcuts;
100 SslErrorShortcuts TheSslErrorShortcuts;
101
102 static void loadSslErrorShortcutsMap()
103 {
104 assert(TheSslErrorShortcuts.empty());
105 for (int i = 0; TheSslErrorShortcutsArray[i].name; ++i)
106 TheSslErrorShortcuts[TheSslErrorShortcutsArray[i].name] = TheSslErrorShortcutsArray[i].errors;
107 }
108
109 bool
110 Ssl::ParseErrorString(const char *name, Security::Errors &errors)
111 {
112 assert(name);
113
114 const Security::ErrorCode ssl_error = GetErrorCode(name);
115 if (ssl_error != SSL_ERROR_NONE) {
116 errors.emplace(ssl_error);
117 return true;
118 }
119
120 if (xisdigit(*name)) {
121 const long int value = strtol(name, NULL, 0);
122 if ((SQUID_TLS_ERR_OFFSET < value && value < SQUID_TLS_ERR_END) || // custom
123 (value >= 0)) { // an official error, including SSL_ERROR_NONE
124 errors.emplace(value);
125 return true;
126 }
127 fatalf("Too small or too big TLS error code '%s'", name);
128 }
129
130 if (TheSslErrorShortcuts.empty())
131 loadSslErrorShortcutsMap();
132
133 const SslErrorShortcuts::const_iterator it = TheSslErrorShortcuts.find(name);
134 if (it != TheSslErrorShortcuts.end()) {
135 // Should not be empty...
136 assert(it->second[0] != SSL_ERROR_NONE);
137 for (int i = 0; it->second[i] != SSL_ERROR_NONE; ++i) {
138 errors.emplace(it->second[i]);
139 }
140 return true;
141 }
142
143 fatalf("Unknown TLS error name '%s'", name);
144 return false; // not reached
145 }
146
147 bool
148 Ssl::ErrorIsOptional(const char *name)
149 {
150 for (int i = 0; OptionalSslErrors[i] != NULL; ++i) {
151 if (strcmp(name, OptionalSslErrors[i]) == 0)
152 return true;
153 }
154 return false;
155 }
156
157 const char *
158 Ssl::GetErrorDescr(Security::ErrorCode value)
159 {
160 return ErrorDetailsManager::GetInstance().getDefaultErrorDescr(value);
161 }
162