]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/support.h
Polishing fixes from squid-dev review
[thirdparty/squid.git] / src / ssl / support.h
1 /*
2 * Copyright (C) 1996-2016 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 "sbuf/SBuf.h"
18 #include "security/forward.h"
19 #include "ssl/gadgets.h"
20
21 #if HAVE_OPENSSL_X509V3_H
22 #include <openssl/x509v3.h>
23 #endif
24 #if HAVE_OPENSSL_ERR_H
25 #include <openssl/err.h>
26 #endif
27 #if HAVE_OPENSSL_ENGINE_H
28 #include <openssl/engine.h>
29 #endif
30 #include <queue>
31 #include <map>
32
33 /**
34 \defgroup ServerProtocolSSLAPI Server-Side SSL API
35 \ingroup ServerProtocol
36 */
37
38 // Custom SSL errors; assumes all official errors are positive
39 #define SQUID_X509_V_ERR_INFINITE_VALIDATION -4
40 #define SQUID_X509_V_ERR_CERT_CHANGE -3
41 #define SQUID_ERR_SSL_HANDSHAKE -2
42 #define SQUID_X509_V_ERR_DOMAIN_MISMATCH -1
43 // All SSL errors range: from smallest (negative) custom to largest SSL error
44 #define SQUID_SSL_ERROR_MIN SQUID_X509_V_ERR_CERT_CHANGE
45 #define SQUID_SSL_ERROR_MAX INT_MAX
46
47 // Maximum certificate validation callbacks. OpenSSL versions exceeding this
48 // limit are deemed stuck in an infinite validation loop (OpenSSL bug #3090)
49 // and will trigger the SQUID_X509_V_ERR_INFINITE_VALIDATION error.
50 // Can be set to a number up to UINT32_MAX
51 #ifndef SQUID_CERT_VALIDATION_ITERATION_MAX
52 #define SQUID_CERT_VALIDATION_ITERATION_MAX 16384
53 #endif
54
55 namespace AnyP
56 {
57 class PortCfg;
58 };
59
60 namespace Ipc
61 {
62 class MemMap;
63 }
64
65 namespace Ssl
66 {
67 /// initialize the SSL library global state.
68 /// call before generating any SSL context
69 void Initialize();
70
71 /// Squid defined error code (<0), an error code returned by SSL X509 api, or SSL_ERROR_NONE
72 typedef int ssl_error_t;
73
74 typedef CbDataList<Ssl::ssl_error_t> Errors;
75
76 class ErrorDetail;
77 class CertValidationResponse;
78 typedef RefCount<CertValidationResponse> CertValidationResponsePointer;
79
80 /// Creates SSL Client connection structure and initializes SSL I/O (Comm and BIO).
81 /// On errors, emits DBG_IMPORTANT with details and returns NULL.
82 SSL *CreateClient(Security::ContextPtr sslContext, const int fd, const char *squidCtx);
83
84 /// Creates SSL Server connection structure and initializes SSL I/O (Comm and BIO).
85 /// On errors, emits DBG_IMPORTANT with details and returns NULL.
86 SSL *CreateServer(Security::ContextPtr sslContext, const int fd, const char *squidCtx);
87
88 /// An SSL certificate-related error.
89 /// Pairs an error code with the certificate experiencing the error.
90 class CertError
91 {
92 public:
93 ssl_error_t code; ///< certificate error code
94 Security::CertPointer cert; ///< certificate with the above error code
95 /**
96 * Absolute cert position in the final certificate chain that may include
97 * intermediate certificates. Chain positions start with zero and increase
98 * towards the root certificate. Negative if unknown.
99 */
100 int depth;
101 CertError(ssl_error_t anErr, X509 *aCert, int depth = -1);
102 CertError(CertError const &err);
103 CertError & operator = (const CertError &old);
104 bool operator == (const CertError &ce) const;
105 bool operator != (const CertError &ce) const;
106 };
107
108 /// Holds a list of certificate SSL errors
109 typedef CbDataList<Ssl::CertError> CertErrors;
110
111 void SetSessionCallbacks(Security::ContextPtr);
112 extern Ipc::MemMap *SessionCache;
113 extern const char *SessionCacheName;
114
115 /// initialize a TLS server context with OpenSSL specific settings
116 bool InitServerContext(const Security::ContextPointer &, AnyP::PortCfg &);
117
118 /// initialize a TLS client context with OpenSSL specific settings
119 bool InitClientContext(Security::ContextPtr &, Security::PeerOptions &, long options, long flags);
120
121 } //namespace Ssl
122
123 /// \ingroup ServerProtocolSSLAPI
124 int ssl_read_method(int, char *, int);
125
126 /// \ingroup ServerProtocolSSLAPI
127 int ssl_write_method(int, const char *, int);
128
129 /// \ingroup ServerProtocolSSLAPI
130 void ssl_shutdown_method(SSL *ssl);
131
132 /// \ingroup ServerProtocolSSLAPI
133 const char *sslGetUserEmail(SSL *ssl);
134
135 /// \ingroup ServerProtocolSSLAPI
136 const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name);
137
138 /// \ingroup ServerProtocolSSLAPI
139 const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name);
140
141 /// \ingroup ServerProtocolSSLAPI
142 const char *sslGetUserCertificatePEM(SSL *ssl);
143
144 /// \ingroup ServerProtocolSSLAPI
145 const char *sslGetUserCertificateChainPEM(SSL *ssl);
146
147 namespace Ssl
148 {
149 /// \ingroup ServerProtocolSSLAPI
150 typedef char const *GETX509ATTRIBUTE(X509 *, const char *);
151
152 /// \ingroup ServerProtocolSSLAPI
153 GETX509ATTRIBUTE GetX509UserAttribute;
154
155 /// \ingroup ServerProtocolSSLAPI
156 GETX509ATTRIBUTE GetX509CAAttribute;
157
158 /// \ingroup ServerProtocolSSLAPI
159 GETX509ATTRIBUTE GetX509Fingerprint;
160
161 extern const EVP_MD *DefaultSignHash;
162
163 /**
164 \ingroup ServerProtocolSSLAPI
165 * Supported ssl-bump modes
166 */
167 enum BumpMode {bumpNone = 0, bumpClientFirst, bumpServerFirst, bumpPeek, bumpStare, bumpBump, bumpSplice, bumpTerminate, /*bumpErr,*/ bumpEnd};
168
169 enum BumpStep {bumpStep1, bumpStep2, bumpStep3};
170
171 /**
172 \ingroup ServerProtocolSSLAPI
173 * Short names for ssl-bump modes
174 */
175 extern const char *BumpModeStr[];
176
177 /**
178 \ingroup ServerProtocolSSLAPI
179 * Return the short name of the ssl-bump mode "bm"
180 */
181 inline const char *bumpMode(int bm)
182 {
183 return (0 <= bm && bm < Ssl::bumpEnd) ? Ssl::BumpModeStr[bm] : NULL;
184 }
185
186 /// certificates indexed by issuer name
187 typedef std::multimap<SBuf, X509 *> CertsIndexedList;
188
189 /**
190 * Load PEM-encoded certificates from the given file.
191 */
192 bool loadCerts(const char *certsFile, Ssl::CertsIndexedList &list);
193
194 /**
195 * Load PEM-encoded certificates to the squid untrusteds certificates
196 * internal DB from the given file.
197 */
198 bool loadSquidUntrusted(const char *path);
199
200 /**
201 * Removes all certificates from squid untrusteds certificates
202 * internal DB and frees all memory
203 */
204 void unloadSquidUntrusted();
205
206 /**
207 * Add the certificate cert to ssl object untrusted certificates.
208 * Squid uses an attached to SSL object list of untrusted certificates,
209 * with certificates which can be used to complete incomplete chains sent
210 * by the SSL server.
211 */
212 void SSL_add_untrusted_cert(SSL *ssl, X509 *cert);
213
214 /**
215 * Searches in serverCertificates list for the cert issuer and if not found
216 * and Authority Info Access of cert provides a URI return it.
217 */
218 const char *uriOfIssuerIfMissing(X509 *cert, Security::CertList const &serverCertificates);
219
220 /**
221 * Fill URIs queue with the uris of missing certificates from serverCertificate chain
222 * if this information provided by Authority Info Access.
223 */
224 void missingChainCertificatesUrls(std::queue<SBuf> &URIs, Security::CertList const &serverCertificates);
225
226 /**
227 \ingroup ServerProtocolSSLAPI
228 * Generate a certificate to be used as untrusted signing certificate, based on a trusted CA
229 */
230 bool generateUntrustedCert(Security::CertPointer & untrustedCert, EVP_PKEY_Pointer & untrustedPkey, Security::CertPointer const & cert, EVP_PKEY_Pointer const & pkey);
231
232 /// certificates indexed by issuer name
233 typedef std::multimap<SBuf, X509 *> CertsIndexedList;
234
235 /**
236 \ingroup ServerProtocolSSLAPI
237 * Load PEM-encoded certificates from the given file.
238 */
239 bool loadCerts(const char *certsFile, Ssl::CertsIndexedList &list);
240
241 /**
242 \ingroup ServerProtocolSSLAPI
243 * Load PEM-encoded certificates to the squid untrusteds certificates
244 * internal DB from the given file.
245 */
246 bool loadSquidUntrusted(const char *path);
247
248 /**
249 \ingroup ServerProtocolSSLAPI
250 * Removes all certificates from squid untrusteds certificates
251 * internal DB and frees all memory
252 */
253 void unloadSquidUntrusted();
254
255 /**
256 \ingroup ServerProtocolSSLAPI
257 * Decide on the kind of certificate and generate a CA- or self-signed one
258 */
259 Security::ContextPtr generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port);
260
261 /**
262 \ingroup ServerProtocolSSLAPI
263 * Check if the certificate of the given context is still valid
264 \param sslContext The context to check
265 \param properties Check if the context certificate matches the given properties
266 \return true if the contexts certificate is valid, false otherwise
267 */
268 bool verifySslCertificate(Security::ContextPtr sslContext, CertificateProperties const &properties);
269
270 /**
271 \ingroup ServerProtocolSSLAPI
272 * Read private key and certificate from memory and generate SSL context
273 * using their.
274 */
275 Security::ContextPtr generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port);
276
277 /**
278 \ingroup ServerProtocolSSLAPI
279 * Create an SSL context using the provided certificate and key
280 */
281 Security::ContextPtr createSSLContext(Security::CertPointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port);
282
283 /**
284 \ingroup ServerProtocolSSLAPI
285 * Chain signing certificate and chained certificates to an SSL Context
286 */
287 void chainCertificatesToSSLContext(SSL_CTX *sslContext, AnyP::PortCfg &port);
288
289 /**
290 \ingroup ServerProtocolSSLAPI
291 * Configure a previously unconfigured SSL context object.
292 */
293 void configureUnconfiguredSslContext(SSL_CTX *sslContext, Ssl::CertSignAlgorithm signAlgorithm,AnyP::PortCfg &port);
294
295 /**
296 \ingroup ServerProtocolSSLAPI
297 * Generates a certificate and a private key using provided properies and set it
298 * to SSL object.
299 */
300 bool configureSSL(SSL *ssl, CertificateProperties const &properties, AnyP::PortCfg &port);
301
302 /**
303 \ingroup ServerProtocolSSLAPI
304 * Read private key and certificate from memory and set it to SSL object
305 * using their.
306 */
307 bool configureSSLUsingPkeyAndCertFromMemory(SSL *ssl, const char *data, AnyP::PortCfg &port);
308
309 /**
310 \ingroup ServerProtocolSSLAPI
311 * Adds the certificates in certList to the certificate chain of the SSL context
312 */
313 void addChainToSslContext(Security::ContextPtr sslContext, STACK_OF(X509) *certList);
314
315 /**
316 \ingroup ServerProtocolSSLAPI
317 * Configures sslContext to use squid untrusted certificates internal list
318 * to complete certificate chains when verifies SSL servers certificates.
319 */
320 void useSquidUntrusted(SSL_CTX *sslContext);
321
322 /**
323 \ingroup ServerProtocolSSLAPI
324 * Read certificate, private key and any certificates which must be chained from files.
325 * See also: Ssl::readCertAndPrivateKeyFromFiles function, defined in gadgets.h
326 * \param certFilename name of file with certificate and certificates which must be chainned.
327 * \param keyFilename name of file with private key.
328 */
329 void readCertChainAndPrivateKeyFromFiles(Security::CertPointer & cert, EVP_PKEY_Pointer & pkey, X509_STACK_Pointer & chain, char const * certFilename, char const * keyFilename);
330
331 /**
332 \ingroup ServerProtocolSSLAPI
333 * Iterates over the X509 common and alternate names and to see if matches with given data
334 * using the check_func.
335 \param peer_cert The X509 cert to check
336 \param check_data The data with which the X509 CNs compared
337 \param check_func The function used to match X509 CNs. The CN data passed as ASN1_STRING data
338 \return 1 if any of the certificate CN matches, 0 if none matches.
339 */
340 int matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data));
341
342 /**
343 \ingroup ServerProtocolSSLAPI
344 * Check if the certificate is valid for a server
345 \param cert The X509 cert to check.
346 \param server The server name.
347 \return true if the certificate is valid for the server or false otherwise.
348 */
349 bool checkX509ServerValidity(X509 *cert, const char *server);
350
351 /**
352 \ingroup ServerProtocolSSLAPI
353 * Convert a given ASN1_TIME to a string form.
354 \param tm the time in ASN1_TIME form
355 \param buf the buffer to write the output
356 \param len write at most len bytes
357 \return The number of bytes written
358 */
359 int asn1timeToString(ASN1_TIME *tm, char *buf, int len);
360
361 /**
362 \ingroup ServerProtocolSSLAPI
363 * Sets the hostname for the Server Name Indication (SNI) TLS extension
364 * if supported by the used openssl toolkit.
365 \return true if SNI set false otherwise
366 */
367 bool setClientSNI(SSL *ssl, const char *fqdn);
368
369 } //namespace Ssl
370
371 #if _SQUID_WINDOWS_
372
373 #if defined(__cplusplus)
374
375 /** \cond AUTODOCS-IGNORE */
376 namespace Squid
377 {
378 /** \endcond */
379
380 /// \ingroup ServerProtocolSSLAPI
381 inline
382 int SSL_set_fd(SSL *ssl, int fd)
383 {
384 return ::SSL_set_fd(ssl, _get_osfhandle(fd));
385 }
386
387 /// \ingroup ServerProtocolSSLAPI
388 #define SSL_set_fd(ssl,fd) Squid::SSL_set_fd(ssl,fd)
389
390 } /* namespace Squid */
391
392 #else
393
394 /// \ingroup ServerProtocolSSLAPI
395 #define SSL_set_fd(s,f) (SSL_set_fd(s, _get_osfhandle(f)))
396
397 #endif /* __cplusplus */
398
399 #endif /* _SQUID_WINDOWS_ */
400
401 #endif /* USE_OPENSSL */
402 #endif /* SQUID_SSL_SUPPORT_H */
403