]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/support.h
Maintenance: Removed most NULLs using modernize-use-nullptr (#1075)
[thirdparty/squid.git] / src / ssl / support.h
1 /*
2 * Copyright (C) 1996-2022 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 /* DEBUG: section 83 SSL accelerator support */
10
11 #ifndef SQUID_SSL_SUPPORT_H
12 #define SQUID_SSL_SUPPORT_H
13
14 #if USE_OPENSSL
15
16 #include "base/CbDataList.h"
17 #include "comm/forward.h"
18 #include "compat/openssl.h"
19 #include "sbuf/SBuf.h"
20 #include "security/forward.h"
21 #include "ssl/gadgets.h"
22
23 #if HAVE_OPENSSL_X509V3_H
24 #include <openssl/x509v3.h>
25 #endif
26 #if HAVE_OPENSSL_ERR_H
27 #include <openssl/err.h>
28 #endif
29 #if HAVE_OPENSSL_ENGINE_H
30 #include <openssl/engine.h>
31 #endif
32 #include <queue>
33 #include <map>
34
35 /**
36 \defgroup ServerProtocolSSLAPI Server-Side SSL API
37 \ingroup ServerProtocol
38 */
39
40 // Maximum certificate validation callbacks. OpenSSL versions exceeding this
41 // limit are deemed stuck in an infinite validation loop (OpenSSL bug #3090)
42 // and will trigger the SQUID_X509_V_ERR_INFINITE_VALIDATION error.
43 // Can be set to a number up to UINT32_MAX
44 #ifndef SQUID_CERT_VALIDATION_ITERATION_MAX
45 #define SQUID_CERT_VALIDATION_ITERATION_MAX 16384
46 #endif
47
48 namespace AnyP
49 {
50 class PortCfg;
51 };
52
53 namespace Ipc
54 {
55 class MemMap;
56 }
57
58 namespace Ssl
59 {
60
61 /// callback for receiving password to access password secured PEM files
62 /// XXX: Requires SSL_CTX_set_default_passwd_cb_userdata()!
63 int AskPasswordCb(char *buf, int size, int rwflag, void *userdata);
64
65 /// initialize the SSL library global state.
66 /// call before generating any SSL context
67 void Initialize();
68
69 class CertValidationResponse;
70 typedef RefCount<CertValidationResponse> CertValidationResponsePointer;
71
72 /// initialize a TLS server context with OpenSSL specific settings
73 bool InitServerContext(Security::ContextPointer &, AnyP::PortCfg &);
74
75 /// initialize a TLS client context with OpenSSL specific settings
76 bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, Security::ParsedPortFlags);
77
78 /// set the certificate verify callback for a context
79 void ConfigurePeerVerification(Security::ContextPointer &, const Security::ParsedPortFlags);
80 void DisablePeerVerification(Security::ContextPointer &);
81
82 /// if required, setup callback for generating ephemeral RSA keys
83 void MaybeSetupRsaCallback(Security::ContextPointer &);
84
85 } //namespace Ssl
86
87 /// \ingroup ServerProtocolSSLAPI
88 const char *sslGetUserEmail(SSL *ssl);
89
90 /// \ingroup ServerProtocolSSLAPI
91 const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name);
92
93 /// \ingroup ServerProtocolSSLAPI
94 const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name);
95
96 /// \ingroup ServerProtocolSSLAPI
97 SBuf sslGetUserCertificatePEM(SSL *ssl);
98
99 /// \ingroup ServerProtocolSSLAPI
100 SBuf sslGetUserCertificateChainPEM(SSL *ssl);
101
102 namespace Ssl
103 {
104 /// \ingroup ServerProtocolSSLAPI
105 typedef char const *GETX509ATTRIBUTE(X509 *, const char *);
106 typedef SBuf GETX509PEM(X509 *);
107
108 /// \ingroup ServerProtocolSSLAPI
109 GETX509ATTRIBUTE GetX509UserAttribute;
110
111 /// \ingroup ServerProtocolSSLAPI
112 GETX509ATTRIBUTE GetX509CAAttribute;
113
114 /// \ingroup ServerProtocolSSLAPI
115 GETX509PEM GetX509PEM;
116
117 /// \ingroup ServerProtocolSSLAPI
118 GETX509ATTRIBUTE GetX509Fingerprint;
119
120 extern const EVP_MD *DefaultSignHash;
121
122 /**
123 \ingroup ServerProtocolSSLAPI
124 * Supported ssl-bump modes
125 */
126 enum BumpMode {bumpNone = 0, bumpClientFirst, bumpServerFirst, bumpPeek, bumpStare, bumpBump, bumpSplice, bumpTerminate, /*bumpErr,*/ bumpEnd};
127
128 /**
129 \ingroup ServerProtocolSSLAPI
130 * Short names for ssl-bump modes
131 */
132 extern std::vector<const char *>BumpModeStr;
133
134 /**
135 \ingroup ServerProtocolSSLAPI
136 * Return the short name of the ssl-bump mode "bm"
137 */
138 inline const char *bumpMode(int bm)
139 {
140 return (0 <= bm && bm < Ssl::bumpEnd) ? Ssl::BumpModeStr.at(bm) : nullptr;
141 }
142
143 /// certificates indexed by issuer name
144 typedef std::multimap<SBuf, X509 *> CertsIndexedList;
145
146 /**
147 * Load PEM-encoded certificates from the given file.
148 */
149 bool loadCerts(const char *certsFile, Ssl::CertsIndexedList &list);
150
151 /**
152 * Load PEM-encoded certificates to the squid untrusteds certificates
153 * internal DB from the given file.
154 */
155 bool loadSquidUntrusted(const char *path);
156
157 /**
158 * Removes all certificates from squid untrusteds certificates
159 * internal DB and frees all memory
160 */
161 void unloadSquidUntrusted();
162
163 /**
164 * Add the certificate cert to ssl object untrusted certificates.
165 * Squid uses an attached to SSL object list of untrusted certificates,
166 * with certificates which can be used to complete incomplete chains sent
167 * by the SSL server.
168 */
169 void SSL_add_untrusted_cert(SSL *ssl, X509 *cert);
170
171 /// finds certificate issuer URI in the Authority Info Access extension
172 const char *findIssuerUri(X509 *cert);
173
174 /// Searches serverCertificates and local databases for the cert issuer.
175 /// \param context where to retrieve the configured CA's db; may be nil
176 /// \returns the found issuer certificate or nil
177 Security::CertPointer findIssuerCertificate(X509 *cert, const STACK_OF(X509) *serverCertificates, const Security::ContextPointer &context);
178
179 /**
180 * Fill URIs queue with the uris of missing certificates from serverCertificate chain
181 * if this information provided by Authority Info Access.
182 \return whether at least one URI is known, including previously known ones
183 */
184 bool missingChainCertificatesUrls(std::queue<SBuf> &URIs, const STACK_OF(X509) &serverCertificates, const Security::ContextPointer &context);
185
186 /**
187 \ingroup ServerProtocolSSLAPI
188 * Generate a certificate to be used as untrusted signing certificate, based on a trusted CA
189 */
190 bool generateUntrustedCert(Security::CertPointer & untrustedCert, Security::PrivateKeyPointer & untrustedPkey, Security::CertPointer const & cert, Security::PrivateKeyPointer const & pkey);
191
192 /// certificates indexed by issuer name
193 typedef std::multimap<SBuf, X509 *> CertsIndexedList;
194
195 /**
196 \ingroup ServerProtocolSSLAPI
197 * Load PEM-encoded certificates from the given file.
198 */
199 bool loadCerts(const char *certsFile, Ssl::CertsIndexedList &list);
200
201 /**
202 \ingroup ServerProtocolSSLAPI
203 * Load PEM-encoded certificates to the squid untrusteds certificates
204 * internal DB from the given file.
205 */
206 bool loadSquidUntrusted(const char *path);
207
208 /**
209 \ingroup ServerProtocolSSLAPI
210 * Removes all certificates from squid untrusteds certificates
211 * internal DB and frees all memory
212 */
213 void unloadSquidUntrusted();
214
215 /**
216 \ingroup ServerProtocolSSLAPI
217 * Decide on the kind of certificate and generate a CA- or self-signed one
218 */
219 Security::ContextPointer GenerateSslContext(CertificateProperties const &, Security::ServerOptions &, bool trusted);
220
221 /**
222 \ingroup ServerProtocolSSLAPI
223 * Check if the certificate of the given context is still valid
224 \param sslContext The context to check
225 \param properties Check if the context certificate matches the given properties
226 \return true if the contexts certificate is valid, false otherwise
227 */
228 bool verifySslCertificate(const Security::ContextPointer &, CertificateProperties const &);
229
230 /**
231 \ingroup ServerProtocolSSLAPI
232 * Read private key and certificate from memory and generate SSL context
233 * using their.
234 */
235 Security::ContextPointer GenerateSslContextUsingPkeyAndCertFromMemory(const char * data, Security::ServerOptions &, bool trusted);
236
237 /**
238 \ingroup ServerProtocolSSLAPI
239 * Create an SSL context using the provided certificate and key
240 */
241 Security::ContextPointer createSSLContext(Security::CertPointer & x509, Security::PrivateKeyPointer & pkey, Security::ServerOptions &);
242
243 /**
244 \ingroup ServerProtocolSSLAPI
245 * Chain signing certificate and chained certificates to an SSL Context
246 */
247 void chainCertificatesToSSLContext(Security::ContextPointer &, Security::ServerOptions &);
248
249 /**
250 \ingroup ServerProtocolSSLAPI
251 * Configure a previously unconfigured SSL context object.
252 */
253 void configureUnconfiguredSslContext(Security::ContextPointer &, Ssl::CertSignAlgorithm signAlgorithm, AnyP::PortCfg &);
254
255 /**
256 \ingroup ServerProtocolSSLAPI
257 * Generates a certificate and a private key using provided properties and set it
258 * to SSL object.
259 */
260 bool configureSSL(SSL *ssl, CertificateProperties const &properties, AnyP::PortCfg &port);
261
262 /**
263 \ingroup ServerProtocolSSLAPI
264 * Read private key and certificate from memory and set it to SSL object
265 * using their.
266 */
267 bool configureSSLUsingPkeyAndCertFromMemory(SSL *ssl, const char *data, AnyP::PortCfg &port);
268
269 /**
270 \ingroup ServerProtocolSSLAPI
271 * Configures sslContext to use squid untrusted certificates internal list
272 * to complete certificate chains when verifies SSL servers certificates.
273 */
274 void useSquidUntrusted(SSL_CTX *sslContext);
275
276 /**
277 \ingroup ServerProtocolSSLAPI
278 * Iterates over the X509 common and alternate names and to see if matches with given data
279 * using the check_func.
280 \param peer_cert The X509 cert to check
281 \param check_data The data with which the X509 CNs compared
282 \param check_func The function used to match X509 CNs. The CN data passed as ASN1_STRING data
283 \return 1 if any of the certificate CN matches, 0 if none matches.
284 */
285 int matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data));
286
287 /**
288 \ingroup ServerProtocolSSLAPI
289 * Check if the certificate is valid for a server
290 \param cert The X509 cert to check.
291 \param server The server name.
292 \return true if the certificate is valid for the server or false otherwise.
293 */
294 bool checkX509ServerValidity(X509 *cert, const char *server);
295
296 /**
297 \ingroup ServerProtocolSSLAPI
298 * Convert a given ASN1_TIME to a string form.
299 \param tm the time in ASN1_TIME form
300 \param buf the buffer to write the output
301 \param len write at most len bytes
302 \return The number of bytes written
303 */
304 int asn1timeToString(ASN1_TIME *tm, char *buf, int len);
305
306 /**
307 \ingroup ServerProtocolSSLAPI
308 * Sets the hostname for the Server Name Indication (SNI) TLS extension
309 * if supported by the used openssl toolkit.
310 */
311 void setClientSNI(SSL *ssl, const char *fqdn);
312
313 /**
314 \ingroup ServerProtocolSSLAPI
315 * Generates a unique key based on CertificateProperties object and store it to key
316 */
317 void InRamCertificateDbKey(const Ssl::CertificateProperties &certProperties, SBuf &key);
318
319 /**
320 \ingroup ServerProtocolSSLAPI
321 Creates and returns an OpenSSL BIO object for writing to `buf` (or throws).
322 TODO: Add support for reading from `buf`.
323 */
324 BIO *BIO_new_SBuf(SBuf *buf);
325
326 /// Validates the given TLS connection server certificate chain in conjunction
327 /// with a (possibly empty) set of "extra" intermediate certs. Also consults
328 /// sslproxy_foreign_intermediate_certs. This is a C++/Squid-friendly wrapper of
329 /// OpenSSL "verification callback function" (\ref OpenSSL_vcb_disambiguation).
330 /// OpenSSL has a similar wrapper, ssl_verify_cert_chain(), but that wrapper is
331 /// not a part of the public OpenSSL API.
332 bool VerifyConnCertificates(Security::Connection &, const Ssl::X509_STACK_Pointer &extraCerts);
333
334 // TODO: Move other ssl_ex_index_* validation-related information here.
335 /// OpenSSL "verify_callback function" input/output parameters. This information
336 /// cannot be passed through the verification API directly, so it is aggregated
337 /// in this class and exchanged via ssl_ex_index_verify_callback_parameters. For
338 /// OpenSSL validation callback details, see \ref OpenSSL_vcb_disambiguation.
339 class VerifyCallbackParameters {
340 public:
341 /// creates a VerifyCallbackParameters object and adds it to the given TLS connection
342 /// \returns the successfully created and added object
343 static VerifyCallbackParameters *New(Security::Connection &);
344
345 /// \returns the VerifyCallbackParameters object previously attached via New()
346 static VerifyCallbackParameters &At(Security::Connection &);
347
348 /// \returns the VerifyCallbackParameters object previously attached via New() or nil
349 static VerifyCallbackParameters *Find(Security::Connection &);
350
351 /* input parameters */
352
353 /// whether X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY should be cleared
354 /// (after setting hidMissingIssuer) because the validation initiator wants
355 /// to get the missing certificates and redo the validation with them
356 bool callerHandlesMissingCertificates = false;
357
358 /* output parameters */
359
360 /// whether certificate validation has failed due to missing certificate(s)
361 /// (i.e. X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY), but the failure was
362 /// cleared/hidden due to true callerHandlesMissingCertificates setting; the
363 /// certificate chain has to be deemed untrusted until revalidation (if any)
364 bool hidMissingIssuer = false;
365 };
366
367 } //namespace Ssl
368
369 #if _SQUID_WINDOWS_
370
371 #if defined(__cplusplus)
372
373 /** \cond AUTODOCS-IGNORE */
374 namespace Squid
375 {
376 /** \endcond */
377
378 /// \ingroup ServerProtocolSSLAPI
379 inline
380 int SSL_set_fd(SSL *ssl, int fd)
381 {
382 return ::SSL_set_fd(ssl, _get_osfhandle(fd));
383 }
384
385 /// \ingroup ServerProtocolSSLAPI
386 #define SSL_set_fd(ssl,fd) Squid::SSL_set_fd(ssl,fd)
387
388 } /* namespace Squid */
389
390 #else
391
392 /// \ingroup ServerProtocolSSLAPI
393 #define SSL_set_fd(s,f) (SSL_set_fd(s, _get_osfhandle(f)))
394
395 #endif /* __cplusplus */
396
397 #endif /* _SQUID_WINDOWS_ */
398
399 #endif /* USE_OPENSSL */
400 #endif /* SQUID_SSL_SUPPORT_H */
401