2 * Copyright (C) 1996-2017 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.
10 #include "base/Packable.h"
12 #include "security/ServerOptions.h"
14 #include "ssl/support.h"
17 #if HAVE_OPENSSL_ERR_H
18 #include <openssl/err.h>
20 #if HAVE_OPENSSL_X509_H
21 #include <openssl/x509.h>
25 Security::ServerOptions::parse(const char *token
)
28 // config says just "ssl" or "tls" (or "tls-")
29 encryptTransport
= true;
33 // parse the server-only options
34 if (strncmp(token
, "dh=", 3) == 0) {
35 // clear any previous Diffi-Helman configuration
43 auto pos
= dh
.find(':');
44 if (pos
!= SBuf::npos
) { // tls-dh=eecdhCurve:dhParamsFile
45 eecdhCurve
= dh
.substr(0,pos
);
46 dhParamsFile
= dh
.substr(pos
+1);
47 } else { // tls-dh=dhParamsFile
49 // empty eecdhCurve means "do not use EECDH"
55 } else if (strncmp(token
, "dhparams=", 9) == 0) {
56 if (!eecdhCurve
.isEmpty()) {
57 debugs(83, DBG_PARSE_NOTE(1), "UPGRADE WARNING: EECDH settings in tls-dh= override dhparams=");
61 // backward compatibility for dhparams= configuration
69 // parse generic TLS options
70 Security::PeerOptions::parse(token
);
75 Security::ServerOptions::dumpCfg(Packable
*p
, const char *pfx
) const
77 // dump out the generic TLS options
78 Security::PeerOptions::dumpCfg(p
, pfx
);
80 if (!encryptTransport
)
81 return; // no other settings are relevant
83 // dump the server-only options
85 p
->appendf(" %sdh=" SQUIDSBUFPH
, pfx
, SQUIDSBUFPRINT(dh
));
88 Security::ContextPointer
89 Security::ServerOptions::createBlankContext() const
91 Security::ContextPointer ctx
;
95 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
96 SSL_CTX
*t
= SSL_CTX_new(TLS_server_method());
98 SSL_CTX
*t
= SSL_CTX_new(SSLv23_server_method());
101 const auto x
= ERR_get_error();
102 debugs(83, DBG_CRITICAL
, "ERROR: Failed to allocate TLS server context: " << Security::ErrorString(x
));
104 ctx
.resetWithoutLocking(t
);
107 // Initialize for X.509 certificate exchange
108 gnutls_certificate_credentials_t t
;
109 if (const int x
= gnutls_certificate_allocate_credentials(&t
)) {
110 debugs(83, DBG_CRITICAL
, "ERROR: Failed to allocate TLS server context: " << Security::ErrorString(x
));
112 ctx
.resetWithoutLocking(t
);
115 debugs(83, DBG_CRITICAL
, "ERROR: Failed to allocate TLS server context: No TLS library");
123 Security::ServerOptions::createStaticServerContext(AnyP::PortCfg
&port
)
125 updateTlsVersionLimits();
127 Security::ContextPointer
t(createBlankContext());
130 if (!Ssl::InitServerContext(t
, port
))
135 staticContext
= std::move(t
);
136 return bool(staticContext
);
140 Security::ServerOptions::loadDhParams()
142 if (dhParamsFile
.isEmpty())
147 if (FILE *in
= fopen(dhParamsFile
.c_str(), "r")) {
148 dhp
= PEM_read_DHparams(in
, NULL
, NULL
, NULL
);
153 debugs(83, DBG_IMPORTANT
, "WARNING: Failed to read DH parameters '" << dhParamsFile
<< "'");
158 if (DH_check(dhp
, &codes
) == 0) {
160 debugs(83, DBG_IMPORTANT
, "WARNING: Failed to verify DH parameters '" << dhParamsFile
<< "' (" << std::hex
<< codes
<< ")");
166 parsedDhParams
.resetWithoutLocking(dhp
);
171 Security::ServerOptions::updateContextEecdh(Security::ContextPointer
&ctx
)
173 // set Elliptic Curve details into the server context
174 if (!eecdhCurve
.isEmpty()) {
175 debugs(83, 9, "Setting Ephemeral ECDH curve to " << eecdhCurve
<< ".");
177 #if USE_OPENSSL && OPENSSL_VERSION_NUMBER >= 0x0090800fL && !defined(OPENSSL_NO_ECDH)
178 int nid
= OBJ_sn2nid(eecdhCurve
.c_str());
180 debugs(83, DBG_CRITICAL
, "ERROR: Unknown EECDH curve '" << eecdhCurve
<< "'");
184 auto ecdh
= EC_KEY_new_by_curve_name(nid
);
186 const auto x
= ERR_get_error();
187 debugs(83, DBG_CRITICAL
, "ERROR: Unable to configure Ephemeral ECDH: " << Security::ErrorString(x
));
191 if (!SSL_CTX_set_tmp_ecdh(ctx
.get(), ecdh
)) {
192 const auto x
= ERR_get_error();
193 debugs(83, DBG_CRITICAL
, "ERROR: Unable to set Ephemeral ECDH: " << Security::ErrorString(x
));
198 debugs(83, DBG_CRITICAL
, "ERROR: EECDH is not available in this build." <<
199 " Please link against OpenSSL>=0.9.8 and ensure OPENSSL_NO_ECDH is not set.");
203 // set DH parameters into the server context
205 if (parsedDhParams
) {
206 SSL_CTX_set_tmp_dh(ctx
.get(), parsedDhParams
.get());