disable_pmtu_discovery(0),
listenConn()
#if USE_OPENSSL
- ,cert(NULL),
- key(NULL),
- version(0),
- cipher(NULL),
- options(NULL),
+ ,
clientca(NULL),
- cafile(NULL),
- capath(NULL),
- crlfile(NULL),
dhfile(NULL),
sslContextSessionId(NULL),
generateHostCertificates(false),
clientVerifyCrls(),
clientCA(),
dhParams(),
- contextMethod(),
- sslContextFlags(0),
- sslOptions(0)
+ contextMethod()
#endif
{
memset(&tcp_keepalive, 0, sizeof(tcp_keepalive));
safe_free(defaultsite);
#if USE_OPENSSL
- safe_free(cert);
- safe_free(key);
- safe_free(cipher);
- safe_free(options);
safe_free(clientca);
- safe_free(cafile);
- safe_free(capath);
- safe_free(crlfile);
safe_free(dhfile);
safe_free(sslContextSessionId);
#endif
b->ftp_track_dirs = ftp_track_dirs;
b->disable_pmtu_discovery = disable_pmtu_discovery;
b->tcp_keepalive = tcp_keepalive;
+ b->secure = secure;
#if USE_OPENSSL
- if (cert)
- b->cert = xstrdup(cert);
- if (key)
- b->key = xstrdup(key);
- b->version = version;
- if (cipher)
- b->cipher = xstrdup(cipher);
- if (options)
- b->options = xstrdup(options);
if (clientca)
b->clientca = xstrdup(clientca);
- if (cafile)
- b->cafile = xstrdup(cafile);
- if (capath)
- b->capath = xstrdup(capath);
- if (crlfile)
- b->crlfile = xstrdup(crlfile);
if (dhfile)
b->dhfile = xstrdup(dhfile);
- b->sslflags = sslflags;
- b->sslContextFlags = sslContextFlags;
if (sslContextSessionId)
b->sslContextSessionId = xstrdup(sslContextSessionId);
void
AnyP::PortCfg::configureSslServerContext()
{
- if (cert)
- Ssl::readCertChainAndPrivateKeyFromFiles(signingCert, signPkey, certsToChain, cert, key);
+ if (!secure.certFile.isEmpty())
+ Ssl::readCertChainAndPrivateKeyFromFiles(signingCert, signPkey, certsToChain, secure.certFile.c_str(), secure.privateKeyFile.c_str());
if (!signingCert) {
char buf[128];
fatalf("Unable to generate signing SSL certificate for untrusted sites for %s_port %s", AnyP::ProtocolType_str[transport.protocol], s.toUrl(buf, sizeof(buf)));
}
- if (crlfile)
- clientVerifyCrls.reset(Ssl::loadCrl(crlfile, sslContextFlags));
+ if (!secure.crlFile.isEmpty())
+ clientVerifyCrls.reset(Ssl::loadCrl(secure.crlFile.c_str(), secure.parsedFlags));
if (clientca) {
clientCA.reset(SSL_load_client_CA_file(clientca));
}
}
- contextMethod = Ssl::contextMethod(version);
+ contextMethod = Ssl::contextMethod(secure.sslVersion);
if (!contextMethod)
fatalf("Unable to compute context method to use");
if (dhfile)
dhParams.reset(Ssl::readDHParams(dhfile));
- sslContextFlags = Security::ParseFlags(sslflags);
- sslOptions = Security::ParseOptions(options);
-
staticSslContext.reset(sslCreateServerContext(*this));
if (!staticSslContext) {
#include "anyp/TrafficMode.h"
#include "comm/Connection.h"
#include "SBuf.h"
+#include "security/PeerOptions.h"
#if USE_OPENSSL
#include "ssl/gadgets.h"
*/
Comm::ConnectionPointer listenConn;
+ /// TLS configuration options for this listening port
+ Security::PeerOptions secure;
+
#if USE_OPENSSL
- char *cert;
- char *key;
- int version;
- char *cipher;
- char *options;
char *clientca;
- char *cafile;
- char *capath;
- char *crlfile;
char *dhfile;
- SBuf sslflags;
char *sslContextSessionId; ///< "session id context" for staticSslContext
bool generateHostCertificates; ///< dynamically make host cert for sslBump
size_t dynamicCertMemCacheSize; ///< max size of generated certificates memory cache
Ssl::X509_NAME_STACK_Pointer clientCA; ///< CA certificates to use when verifying client certificates
Ssl::DH_Pointer dhParams; ///< DH parameters for temporary/ephemeral DH key exchanges
Ssl::ContextMethod contextMethod; ///< The context method (SSL_METHOD) to use when creating certificates
- long sslContextFlags; ///< flags modifying the use of SSL
- long sslOptions; ///< SSL engine options
#endif
};
}
#if USE_OPENSSL
} else if (strcmp(token, "sslBump") == 0) {
- debugs(3, DBG_CRITICAL, "WARNING: '" << token << "' is deprecated " <<
+ debugs(3, DBG_PARSE_NOTE(1), "WARNING: '" << token << "' is deprecated " <<
"in " << cfg_directive << ". Use 'ssl-bump' instead.");
s->flags.tunnelSslBumping = true;
} else if (strcmp(token, "ssl-bump") == 0) {
s->flags.tunnelSslBumping = true;
} else if (strncmp(token, "cert=", 5) == 0) {
- safe_free(s->cert);
- s->cert = xstrdup(token + 5);
+ s->secure.parse(token);
} else if (strncmp(token, "key=", 4) == 0) {
- safe_free(s->key);
- s->key = xstrdup(token + 4);
+ s->secure.parse(token);
} else if (strncmp(token, "version=", 8) == 0) {
- s->version = xatoi(token + 8);
- if (s->version < 1 || s->version > 4)
+ s->secure.parse(token);
+ if (s->secure.sslVersion < 1 || s->secure.sslVersion > 4)
self_destruct();
} else if (strncmp(token, "options=", 8) == 0) {
- safe_free(s->options);
- s->options = xstrdup(token + 8);
+ s->secure.parse(token);
} else if (strncmp(token, "cipher=", 7) == 0) {
- safe_free(s->cipher);
- s->cipher = xstrdup(token + 7);
+ s->secure.parse(token);
} else if (strncmp(token, "clientca=", 9) == 0) {
safe_free(s->clientca);
s->clientca = xstrdup(token + 9);
} else if (strncmp(token, "cafile=", 7) == 0) {
- safe_free(s->cafile);
- s->cafile = xstrdup(token + 7);
+ s->secure.parse(token);
} else if (strncmp(token, "capath=", 7) == 0) {
- safe_free(s->capath);
- s->capath = xstrdup(token + 7);
+ s->secure.parse(token);
} else if (strncmp(token, "crlfile=", 8) == 0) {
- safe_free(s->crlfile);
- s->crlfile = xstrdup(token + 8);
+ s->secure.parse(token);
} else if (strncmp(token, "dhparams=", 9) == 0) {
safe_free(s->dhfile);
s->dhfile = xstrdup(token + 9);
} else if (strncmp(token, "sslflags=", 9) == 0) {
- s->sslflags = SBuf(token + 9);
+ s->secure.parse(token+3);
} else if (strncmp(token, "sslcontext=", 11) == 0) {
safe_free(s->sslContextSessionId);
s->sslContextSessionId = xstrdup(token + 11);
} else if (strncmp(token, "dynamic_cert_mem_cache_size=", 28) == 0) {
parseBytesOptionValue(&s->dynamicCertMemCacheSize, B_BYTES_STR, token + 28);
#endif
+ } else if (strncmp(token, "tls-", 4) == 0) {
+ s->secure.parse(token+4);
} else if (strcmp(token, "ftp-track-dirs") == 0) {
s->ftp_track_dirs = true;
} else {
#if USE_OPENSSL
if (s->flags.tunnelSslBumping)
storeAppendPrintf(e, " ssl-bump");
+#endif
- if (s->cert)
- storeAppendPrintf(e, " cert=%s", s->cert);
+ if (!s->secure.certFile.isEmpty())
+ storeAppendPrintf(e, " tls-cert=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.certFile));
- if (s->key)
- storeAppendPrintf(e, " key=%s", s->key);
+ if (!s->secure.privateKeyFile.isEmpty() && s->secure.privateKeyFile != s->secure.certFile)
+ storeAppendPrintf(e, " tls-key=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.privateKeyFile));
- if (s->version)
- storeAppendPrintf(e, " version=%d", s->version);
+ if (s->secure.sslVersion)
+ storeAppendPrintf(e, " tls-version=%d", s->secure.sslVersion);
- if (s->options)
- storeAppendPrintf(e, " options=%s", s->options);
+ if (!s->secure.sslOptions.isEmpty())
+ storeAppendPrintf(e, " tls-options=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.sslOptions));
- if (s->cipher)
- storeAppendPrintf(e, " cipher=%s", s->cipher);
+ if (!s->secure.sslCipher.isEmpty())
+ storeAppendPrintf(e, " tls-cipher=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.sslCipher));
- if (s->cafile)
- storeAppendPrintf(e, " cafile=%s", s->cafile);
+ if (!s->secure.caFile.isEmpty())
+ storeAppendPrintf(e, " tls-cafile=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.caFile));
- if (s->capath)
- storeAppendPrintf(e, " capath=%s", s->capath);
+ if (!s->secure.caDir.isEmpty())
+ storeAppendPrintf(e, " tls-capath=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.caDir));
- if (s->crlfile)
- storeAppendPrintf(e, " crlfile=%s", s->crlfile);
+ if (!s->secure.crlFile.isEmpty())
+ storeAppendPrintf(e, " tls-crlfile=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.crlFile));
+#if USE_OPENSSL
if (s->dhfile)
storeAppendPrintf(e, " dhparams=%s", s->dhfile);
- if (!s->sslflags.isEmpty())
- storeAppendPrintf(e, " sslflags=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->sslflags));
-
if (s->sslContextSessionId)
storeAppendPrintf(e, " sslcontext=%s", s->sslContextSessionId);
if (s->dynamicCertMemCacheSize != std::numeric_limits<size_t>::max())
storeAppendPrintf(e, "dynamic_cert_mem_cache_size=%lu%s\n", (unsigned long)s->dynamicCertMemCacheSize, B_BYTES_STR);
#endif
+
+ if (!s->secure.sslFlags.isEmpty())
+ storeAppendPrintf(e, " tls-flags=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.sslFlags));
}
static void
Security::PeerOptions Security::ProxyOutgoingConfig;
+Security::PeerOptions::PeerOptions(const Security::PeerOptions &p) :
+ certFile(p.certFile),
+ privateKeyFile(p.privateKeyFile),
+ sslOptions(p.sslOptions),
+ caFile(p.caFile),
+ caDir(p.caDir),
+ crlFile(p.crlFile),
+ sslCipher(p.sslCipher),
+ sslFlags(p.sslFlags),
+ sslDomain(p.sslDomain),
+ parsedOptions(p.parsedOptions),
+ parsedFlags(p.parsedFlags),
+ sslVersion(p.sslVersion),
+ encryptTransport(p.encryptTransport)
+{
+}
+
void
Security::PeerOptions::parse(const char *token)
{
} else if (strncmp(token, "key=", 4) == 0) {
privateKeyFile = SBuf(token + 4);
if (certFile.isEmpty()) {
- debugs(0, DBG_PARSE_NOTE(1), "WARNING: cert= option needs to be set before key= is used.");
+ debugs(3, DBG_PARSE_NOTE(1), "WARNING: cert= option needs to be set before key= is used.");
certFile = privateKeyFile;
}
} else if (strncmp(token, "version=", 8) == 0) {
crlFile = SBuf(token + 8);
} else if (strncmp(token, "flags=", 6) == 0) {
if (parsedFlags != 0) {
- debugs(0, DBG_PARSE_NOTE(1), "WARNING: Overwriting flags=" << sslFlags << " with " << SBuf(token + 6));
+ debugs(3, DBG_PARSE_NOTE(1), "WARNING: Overwriting flags=" << sslFlags << " with " << SBuf(token + 6));
}
sslFlags = SBuf(token + 6);
parsedFlags = Security::ParseFlags(sslFlags);
} else if (strncmp(token, "domain=", 7) == 0) {
sslDomain = SBuf(token + 7);
+ } else {
+ debugs(3, DBG_CRITICAL, "ERROR: Unknown TLS option '" << token << "'");
}
}
{
public:
PeerOptions() : parsedOptions(0), sslVersion(0), encryptTransport(false) {}
+ PeerOptions(const PeerOptions &);
/// parse a TLS squid.conf option
void parse(const char *);
configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
{
int ssl_error;
- SSL_CTX_set_options(sslContext, port.sslOptions);
+ SSL_CTX_set_options(sslContext, port.secure.parsedOptions);
if (port.sslContextSessionId)
SSL_CTX_set_session_id_context(sslContext, (const unsigned char *)port.sslContextSessionId, strlen(port.sslContextSessionId));
- if (port.sslContextFlags & SSL_FLAG_NO_SESSION_REUSE) {
+ if (port.secure.parsedFlags & SSL_FLAG_NO_SESSION_REUSE) {
SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
}
SSL_CTX_set_quiet_shutdown(sslContext, 1);
}
- if (port.cipher) {
- debugs(83, 5, "Using chiper suite " << port.cipher << ".");
+ if (!port.secure.sslCipher.isEmpty()) {
+ debugs(83, 5, "Using chiper suite " << port.secure.sslCipher << ".");
- if (!SSL_CTX_set_cipher_list(sslContext, port.cipher)) {
+ if (!SSL_CTX_set_cipher_list(sslContext, port.secure.sslCipher.c_str())) {
ssl_error = ERR_get_error();
- debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.cipher << "': " << ERR_error_string(ssl_error, NULL));
+ debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.secure.sslCipher << "': " << ERR_error_string(ssl_error, NULL));
return false;
}
}
debugs(83, 9, "Setting CA certificate locations.");
- const char *cafile = port.cafile ? port.cafile : port.clientca;
- if ((cafile || port.capath) && !SSL_CTX_load_verify_locations(sslContext, cafile, port.capath)) {
+ const char *cafile = port.secure.caFile.isEmpty() ? port.clientca : port.secure.caFile.c_str();
+ if ((cafile || !port.secure.caDir.isEmpty()) && !SSL_CTX_load_verify_locations(sslContext, cafile, port.secure.caDir.c_str())) {
ssl_error = ERR_get_error();
debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
}
- if (!(port.sslContextFlags & SSL_FLAG_NO_DEFAULT_CA) &&
+ if (!(port.secure.parsedFlags & SSL_FLAG_NO_DEFAULT_CA) &&
!SSL_CTX_set_default_verify_paths(sslContext)) {
ssl_error = ERR_get_error();
debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL));
ERR_clear_error();
SSL_CTX_set_client_CA_list(sslContext, port.clientCA.get());
- if (port.sslContextFlags & SSL_FLAG_DELAYED_AUTH) {
+ if (port.secure.parsedFlags & SSL_FLAG_DELAYED_AUTH) {
debugs(83, 9, "Not requesting client certificates until acl processing requires one");
SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
} else {
}
#if X509_V_FLAG_CRL_CHECK
- if (port.sslContextFlags & SSL_FLAG_VERIFY_CRL_ALL)
+ if (port.secure.parsedFlags & SSL_FLAG_VERIFY_CRL_ALL)
X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
- else if (port.sslContextFlags & SSL_FLAG_VERIFY_CRL)
+ else if (port.secure.parsedFlags & SSL_FLAG_VERIFY_CRL)
X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK);
#endif
SSL_CTX_set_tmp_dh(sslContext, port.dhParams.get());
}
- if (port.sslContextFlags & SSL_FLAG_DONT_VERIFY_DOMAIN)
+ if (port.secure.parsedFlags & SSL_FLAG_DONT_VERIFY_DOMAIN)
SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
setSessionCallbacks(sslContext);
SSL_CTX *
sslCreateServerContext(AnyP::PortCfg &port)
{
- int ssl_error;
- SSL_CTX *sslContext;
- const char *keyfile, *certfile;
- certfile = port.cert;
- keyfile = port.key;
-
ssl_initialize();
+ SSL_CTX *sslContext = SSL_CTX_new(port.contextMethod);
- if (!keyfile)
- keyfile = certfile;
-
- if (!certfile)
- certfile = keyfile;
-
- sslContext = SSL_CTX_new(port.contextMethod);
-
+ int ssl_error;
if (sslContext == NULL) {
ssl_error = ERR_get_error();
debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate SSL context: " << ERR_error_string(ssl_error, NULL));
if (!SSL_CTX_use_certificate(sslContext, port.signingCert.get())) {
ssl_error = ERR_get_error();
- debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL));
+ debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << port.secure.certFile << "': " << ERR_error_string(ssl_error, NULL));
SSL_CTX_free(sslContext);
return NULL;
}
if (!SSL_CTX_use_PrivateKey(sslContext, port.signPkey.get())) {
ssl_error = ERR_get_error();
- debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL));
+ debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << port.secure.privateKeyFile << "': " << ERR_error_string(ssl_error, NULL));
SSL_CTX_free(sslContext);
return NULL;
}