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