These are most of the minor shuffling prerequisite for the proposal to allow generate-host-certificates to set a CA filename. These are required in libsecurity in order to prevent circular dependencies between libsecurity, libssl and libanyp.
Also contains some improvements to how configuration errors are displayed for these affected settings and some bugs fixed where the configured values were handled incorrectly.
vport(0),
disable_pmtu_discovery(0),
listenConn()
-#if USE_OPENSSL
- ,
- sslContextSessionId(NULL),
- generateHostCertificates(true),
- dynamicCertMemCacheSize(4*1024*1024), // 4 MB
- signingCert(),
- signPkey(),
- certsToChain(),
- untrustedSigningCert(),
- untrustedSignPkey()
-#endif
{
memset(&tcp_keepalive, 0, sizeof(tcp_keepalive));
}
safe_free(name);
safe_free(defaultsite);
-
-#if USE_OPENSSL
- safe_free(sslContextSessionId);
-#endif
}
AnyP::PortCfgPointer
b->tcp_keepalive = tcp_keepalive;
b->secure = secure;
-#if USE_OPENSSL
- if (sslContextSessionId)
- b->sslContextSessionId = xstrdup(sslContextSessionId);
-
-#if 0
- // TODO: AYJ: 2015-01-15: for now SSL does not clone the context object.
- // cloning should only be done before the PortCfg is post-configure initialized and opened
- Security::ContextPointer sslContext;
-#endif
-
-#endif /*0*/
-
return b;
}
-#if USE_OPENSSL
-void
-AnyP::PortCfg::configureSslServerContext()
-{
- if (!secure.certs.empty()) {
- Security::KeyData &keys = secure.certs.front();
- Ssl::readCertChainAndPrivateKeyFromFiles(signingCert, signPkey, certsToChain, keys.certFile.c_str(), keys.privateKeyFile.c_str());
- }
-
- if (!signingCert) {
- char buf[128];
- fatalf("No valid signing SSL certificate configured for %s_port %s", AnyP::ProtocolType_str[transport.protocol], s.toUrl(buf, sizeof(buf)));
- }
-
- if (!signPkey)
- debugs(3, DBG_IMPORTANT, "No SSL private key configured for " << AnyP::ProtocolType_str[transport.protocol] << "_port " << s);
-
- Ssl::generateUntrustedCert(untrustedSigningCert, untrustedSignPkey,
- signingCert, signPkey);
-
- if (!untrustedSigningCert) {
- 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 (!secure.createStaticServerContext(*this)) {
- char buf[128];
- fatalf("%s_port %s initialization error", AnyP::ProtocolType_str[transport.protocol], s.toUrl(buf, sizeof(buf)));
- }
-}
-#endif
-
#include "sbuf/SBuf.h"
#include "security/ServerOptions.h"
-#if USE_OPENSSL
-#include "ssl/gadgets.h"
-#endif
-
namespace AnyP
{
PortCfg();
~PortCfg();
AnyP::PortCfgPointer clone() const;
-#if USE_OPENSSL
- /// creates, configures, and validates SSL context and related port options
- void configureSslServerContext();
-#endif
PortCfgPointer next;
/// TLS configuration options for this listening port
Security::ServerOptions secure;
-
-#if USE_OPENSSL
- char *sslContextSessionId; ///< "session id context" for secure.staticSslContext
- bool generateHostCertificates; ///< dynamically make host cert for sslBump
- size_t dynamicCertMemCacheSize; ///< max size of generated certificates memory cache
-
- Security::CertPointer signingCert; ///< x509 certificate for signing generated certificates
- Ssl::EVP_PKEY_Pointer signPkey; ///< private key for sighing generated certificates
- Ssl::X509_STACK_Pointer certsToChain; ///< x509 certificates to send with the generated cert
- Security::CertPointer untrustedSigningCert; ///< x509 certificate for signing untrusted generated certificates
- Ssl::EVP_PKEY_Pointer untrustedSignPkey; ///< private key for signing untrusted generated certificates
-#endif
};
} // namespace AnyP
static int parse_line(char *);
static void parse_obsolete(const char *);
static void parseBytesLine(size_t * bptr, const char *units);
-#if USE_OPENSSL
-static void parseBytesOptionValue(size_t * bptr, const char *units, char const * value);
-#endif
static void parseBytesLineSigned(ssize_t * bptr, const char *units);
static size_t parseBytesUnits(const char *unit);
static void free_all(void);
}
}
-#if USE_OPENSSL
for (AnyP::PortCfgPointer s = HttpPortList; s != NULL; s = s->next) {
if (!s->secure.encryptTransport)
continue;
debugs(3, DBG_IMPORTANT, "Initializing " << AnyP::UriScheme(s->transport.protocol) << "_port " << s->s << " TLS context");
- s->configureSslServerContext();
+ s->secure.createSigningContexts(*s);
}
-#endif
// prevent infinite fetch loops in the request parser
// due to buffer full but not enough data recived to finish parse
* Similar to the parseBytesLine function but parses the string value instead of
* the current token value.
*/
-static void parseBytesOptionValue(size_t * bptr, const char *units, char const * value)
+void
+parseBytesOptionValue(size_t * bptr, const char *units, char const * value)
{
int u;
if ((u = parseBytesUnits(units)) == 0) {
// NP: deprecation warnings output by secure.parse() when relevant
s->secure.parse(token+3);
} else if (strncmp(token, "sslcontext=", 11) == 0) {
- safe_free(s->sslContextSessionId);
- s->sslContextSessionId = xstrdup(token + 11);
- } else if (strcmp(token, "generate-host-certificates") == 0) {
- s->generateHostCertificates = true;
- } else if (strcmp(token, "generate-host-certificates=on") == 0) {
- s->generateHostCertificates = true;
- } else if (strcmp(token, "generate-host-certificates=off") == 0) {
- s->generateHostCertificates = false;
- } else if (strncmp(token, "dynamic_cert_mem_cache_size=", 28) == 0) {
- parseBytesOptionValue(&s->dynamicCertMemCacheSize, B_BYTES_STR, token + 28);
+ // NP: deprecation warnings output by secure.parse() when relevant
+ s->secure.parse(token+3);
+ } else if (strncmp(token, "generate-host-certificates", 26) == 0) {
+ s->secure.parse(token);
#endif
+ } else if (strncmp(token, "dynamic_cert_mem_cache_size=", 28) == 0) {
+ s->secure.parse(token);
} else if (strncmp(token, "tls-", 4) == 0) {
s->secure.parse(token+4);
} else if (strcmp(token, "ftp-track-dirs") == 0) {
#endif
s->secure.dumpCfg(e, "tls-");
-
-#if USE_OPENSSL
- if (s->sslContextSessionId)
- storeAppendPrintf(e, " sslcontext=%s", s->sslContextSessionId);
-
- if (!s->generateHostCertificates)
- storeAppendPrintf(e, " generate-host-certificates=off");
-
- if (s->dynamicCertMemCacheSize != 4*1024*1024) // 4MB default
- storeAppendPrintf(e, "dynamic_cert_mem_cache_size=%" PRIuSIZE "%s\n", s->dynamicCertMemCacheSize, B_BYTES_STR);
-#endif
}
static void
void parse_wordlist(wordlist ** list);
void requirePathnameExists(const char *name, const char *path);
void parse_time_t(time_t * var);
+/// Parse bytes number from a string
+void parseBytesOptionValue(size_t * bptr, const char *units, char const * value);
#endif /* SQUID_CACHE_CF_H_ */
Security::ContextPointer ctx(Security::GetFrom(fd_table[clientConnection->fd].ssl));
Ssl::configureUnconfiguredSslContext(ctx, signAlgorithm, *port);
} else {
- Security::ContextPointer ctx(Ssl::GenerateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str(), *port, (signAlgorithm == Ssl::algSignTrusted)));
+ Security::ContextPointer ctx(Ssl::GenerateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str(), port->secure, (signAlgorithm == Ssl::algSignTrusted)));
if (ctx && !sslBumpCertKey.isEmpty())
storeTlsContextToCache(sslBumpCertKey, ctx);
getSslContextDone(ctx);
assert(certProperties.signAlgorithm != Ssl::algSignEnd);
if (certProperties.signAlgorithm == Ssl::algSignUntrusted) {
- assert(port->untrustedSigningCert.get());
- certProperties.signWithX509.resetAndLock(port->untrustedSigningCert.get());
- certProperties.signWithPkey.resetAndLock(port->untrustedSignPkey.get());
+ assert(port->secure.untrustedSigningCert);
+ certProperties.signWithX509.resetAndLock(port->secure.untrustedSigningCert.get());
+ certProperties.signWithPkey.resetAndLock(port->secure.untrustedSignPkey.get());
} else {
- assert(port->signingCert.get());
- certProperties.signWithX509.resetAndLock(port->signingCert.get());
+ assert(port->secure.signingCert.get());
+ certProperties.signWithX509.resetAndLock(port->secure.signingCert.get());
- if (port->signPkey.get())
- certProperties.signWithPkey.resetAndLock(port->signPkey.get());
+ if (port->secure.signPkey)
+ certProperties.signWithPkey.resetAndLock(port->secure.signPkey.get());
}
signAlgorithm = certProperties.signAlgorithm;
}
/* careful: finished() above frees request, host, etc. */
- if (port->generateHostCertificates) {
+ if (port->secure.generateHostCertificates) {
Ssl::CertificateProperties certProperties;
buildSslCertGenerationParams(certProperties);
Security::ContextPointer ctx(Security::GetFrom(fd_table[clientConnection->fd].ssl));
Ssl::configureUnconfiguredSslContext(ctx, certProperties.signAlgorithm, *port);
} else {
- Security::ContextPointer dynCtx(Ssl::GenerateSslContext(certProperties, *port, (signAlgorithm == Ssl::algSignTrusted)));
+ Security::ContextPointer dynCtx(Ssl::GenerateSslContext(certProperties, port->secure, (signAlgorithm == Ssl::algSignTrusted)));
if (dynCtx && !sslBumpCertKey.isEmpty())
storeTlsContextToCache(sslBumpCertKey, dynCtx);
getSslContextDone(dynCtx);
void
ConnStateData::getSslContextDone(Security::ContextPointer &ctx)
{
- if (port->generateHostCertificates && !ctx) {
+ if (port->secure.generateHostCertificates && !ctx) {
debugs(33, 2, "Failed to generate TLS cotnext for " << sslConnectHostOrIp);
}
}
// will call httpsPeeked() with certificate and connection, eventually
- Security::ContextPointer unConfiguredCTX(Ssl::createSSLContext(port->signingCert, port->signPkey, *port));
+ Security::ContextPointer unConfiguredCTX(Ssl::createSSLContext(port->secure.signingCert, port->secure.signPkey, port->secure));
fd_table[clientConnection->fd].dynamicTlsContext = unConfiguredCTX;
if (!httpsCreate(clientConnection, unConfiguredCTX))
debugs(33, DBG_IMPORTANT, "WARNING: No ssl_bump configured. Disabling ssl-bump on " << scheme << "_port " << s->s);
s->flags.tunnelSslBumping = false;
}
- if (!s->secure.staticContext && !s->generateHostCertificates) {
+ if (!s->secure.staticContext && !s->secure.generateHostCertificates) {
debugs(1, DBG_IMPORTANT, "Will not bump SSL at " << scheme << "_port " << s->s << " due to TLS initialization failure.");
s->flags.tunnelSslBumping = false;
if (s->transport.protocol == AnyP::PROTO_HTTP)
}
if (s->flags.tunnelSslBumping) {
// Create ssl_ctx cache for this port.
- auto sz = s->dynamicCertMemCacheSize == std::numeric_limits<size_t>::max() ? 4194304 : s->dynamicCertMemCacheSize;
- Ssl::TheGlobalContextStorage.addLocalStorage(s->s, sz);
+ Ssl::TheGlobalContextStorage.addLocalStorage(s->s, s->secure.dynamicCertMemCacheSize);
}
}
Security::ContextPointer t(createBlankContext());
if (t) {
+ if (setOptions)
+ updateContextOptions(t);
#if USE_OPENSSL
- // NP: GnuTLS uses 'priorities' which are set per-session instead.
- SSL_CTX_set_options(t.get(), (setOptions ? parsedOptions : 0));
-
// XXX: temporary performance regression. c_str() data copies and prevents this being a const method
Ssl::InitClientContext(t, *this, parsedFlags);
#endif
#endif
}
+void
+Security::PeerOptions::updateContextOptions(Security::ContextPointer &ctx) const
+{
+#if USE_OPENSSL
+ SSL_CTX_set_options(ctx.get(), parsedOptions);
+#elif USE_GNUTLS
+ // NP: GnuTLS uses 'priorities' which are set per-session instead.
+#endif
+}
+
#if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg)
// Dummy next_proto_neg callback
static int
/// sync the context options with tls-min-version=N configuration
void updateTlsVersionLimits();
+ /// Setup the library specific 'options=' parameters for the given context.
+ void updateContextOptions(Security::ContextPointer &) const;
+
/// setup the NPN extension details for the given context
void updateContextNpn(Security::ContextPointer &);
*/
#include "squid.h"
+#include "anyp/PortCfg.h"
#include "base/Packable.h"
+#include "cache_cf.h"
+#include "fatal.h"
#include "globals.h"
#include "security/ServerOptions.h"
+#include "security/Session.h"
+#include "SquidConfig.h"
#if USE_OPENSSL
#include "ssl/support.h"
#endif
#if USE_OPENSSL
if (auto *stk = SSL_dup_CA_list(old.clientCaStack.get()))
clientCaStack = Security::ServerOptions::X509_NAME_STACK_Pointer(stk);
-#else
- clientCaStack = nullptr;
+ else
#endif
+ clientCaStack = nullptr;
+
+ staticContextSessionId = old.staticContextSessionId;
+ generateHostCertificates = old.generateHostCertificates;
+ signingCert = old.signingCert;
+ signPkey = old.signPkey;
+ certsToChain = old.certsToChain;
+ untrustedSigningCert = old.untrustedSigningCert;
+ untrustedSignPkey = old.untrustedSignPkey;
+ dynamicCertMemCacheSize = old.dynamicCertMemCacheSize;
}
return *this;
}
loadDhParams();
+ } else if (strncmp(token, "dynamic_cert_mem_cache_size=", 28) == 0) {
+ parseBytesOptionValue(&dynamicCertMemCacheSize, "bytes", token + 28);
+ // XXX: parseBytesOptionValue() self_destruct()s on invalid values,
+ // probably making this comparison and misleading ERROR unnecessary.
+ if (dynamicCertMemCacheSize == std::numeric_limits<size_t>::max()) {
+ debugs(3, DBG_CRITICAL, "ERROR: Cannot allocate memory for '" << token << "'. Using default of 4MB instead.");
+ dynamicCertMemCacheSize = 4*1024*1024; // 4 MB
+ }
+
+ } else if (strcmp(token, "generate-host-certificates") == 0) {
+ generateHostCertificates = true;
+ } else if (strcmp(token, "generate-host-certificates=on") == 0) {
+ generateHostCertificates = true;
+ } else if (strcmp(token, "generate-host-certificates=off") == 0) {
+ generateHostCertificates = false;
+
+ } else if (strncmp(token, "context=", 8) == 0) {
+#if USE_OPENSSL
+ staticContextSessionId = SBuf(token+8);
+ // to hide its arguably sensitive value, do not print token in these debugs
+ if (staticContextSessionId.length() > SSL_MAX_SSL_SESSION_ID_LENGTH) {
+ debugs(83, DBG_CRITICAL, "FATAL: Option 'context=' value is too long. Maximum " << SSL_MAX_SSL_SESSION_ID_LENGTH << " characters.");
+ self_destruct();
+ }
+#else
+ debugs(83, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: Option 'context=' requires --with-openssl. Ignoring.");
+#endif
+
} else {
// parse generic TLS options
Security::PeerOptions::parse(token);
// dump the server-only options
if (!dh.isEmpty())
p->appendf(" %sdh=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(dh));
+
+ if (!generateHostCertificates)
+ p->appendf(" %sgenerate-host-certificates=off", pfx);
+
+ if (dynamicCertMemCacheSize != 4*1024*1024) // 4MB default, no 'tls-' prefix
+ p->appendf(" dynamic_cert_mem_cache_size=%" PRIuSIZE "bytes", dynamicCertMemCacheSize);
+
+ if (!staticContextSessionId.isEmpty())
+ p->appendf(" %scontext=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(staticContextSessionId));
}
Security::ContextPointer
return bool(staticContext);
}
+void
+Security::ServerOptions::createSigningContexts(AnyP::PortCfg &port)
+{
+ const char *portType = AnyP::ProtocolType_str[port.transport.protocol];
+ if (!certs.empty()) {
+#if USE_OPENSSL
+ Security::KeyData &keys = certs.front();
+ Ssl::readCertChainAndPrivateKeyFromFiles(signingCert, signPkey, certsToChain, keys.certFile.c_str(), keys.privateKeyFile.c_str());
+#else
+ char buf[128];
+ fatalf("Directive '%s_port %s' requires --with-openssl.", portType, port.s.toUrl(buf, sizeof(buf)));
+#endif
+ }
+
+ if (!signingCert) {
+ char buf[128];
+ fatalf("No valid signing SSL certificate configured for %s_port %s", portType, port.s.toUrl(buf, sizeof(buf)));
+ }
+
+ if (!signPkey)
+ debugs(3, DBG_IMPORTANT, "No SSL private key configured for " << portType << "_port " << port.s);
+
+#if USE_OPENSSL
+ Ssl::generateUntrustedCert(untrustedSigningCert, untrustedSignPkey, signingCert, signPkey);
+#endif
+
+ if (!untrustedSigningCert) {
+ char buf[128];
+ fatalf("Unable to generate signing SSL certificate for untrusted sites for %s_port %s", portType, port.s.toUrl(buf, sizeof(buf)));
+ }
+
+ if (!createStaticServerContext(port)) {
+ char buf[128];
+ fatalf("%s_port %s initialization error", portType, port.s.toUrl(buf, sizeof(buf)));
+ }
+}
+
void
Security::ServerOptions::syncCaFiles()
{
#endif
}
+bool
+Security::ServerOptions::updateContextConfig(Security::ContextPointer &ctx)
+{
+ updateContextOptions(ctx);
+ updateContextSessionId(ctx);
+
+#if USE_OPENSSL
+ if (parsedFlags & SSL_FLAG_NO_SESSION_REUSE) {
+ SSL_CTX_set_session_cache_mode(ctx.get(), SSL_SESS_CACHE_OFF);
+ }
+
+ if (Config.SSL.unclean_shutdown) {
+ debugs(83, 5, "Enabling quiet SSL shutdowns (RFC violation).");
+ SSL_CTX_set_quiet_shutdown(ctx.get(), 1);
+ }
+
+ if (!sslCipher.isEmpty()) {
+ debugs(83, 5, "Using cipher suite " << sslCipher << ".");
+ if (!SSL_CTX_set_cipher_list(ctx.get(), sslCipher.c_str())) {
+ auto ssl_error = ERR_get_error();
+ debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << sslCipher << "': " << Security::ErrorString(ssl_error));
+ return false;
+ }
+ }
+
+ Ssl::MaybeSetupRsaCallback(ctx);
+#endif
+
+ updateContextEecdh(ctx);
+ updateContextCa(ctx);
+ updateContextClientCa(ctx);
+
+#if USE_OPENSSL
+ if (parsedFlags & SSL_FLAG_DONT_VERIFY_DOMAIN)
+ SSL_CTX_set_ex_data(ctx.get(), ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
+
+ Security::SetSessionCacheCallbacks(ctx);
+#endif
+ return true;
+}
+
void
Security::ServerOptions::updateContextClientCa(Security::ContextPointer &ctx)
{
#endif
}
+void
+Security::ServerOptions::updateContextSessionId(Security::ContextPointer &ctx)
+{
+#if USE_OPENSSL
+ if (!staticContextSessionId.isEmpty())
+ SSL_CTX_set_session_id_context(ctx.get(), reinterpret_cast<const unsigned char*>(staticContextSessionId.rawContent()), staticContextSessionId.length());
+#endif
+}
+
/// \returns true if a context could be created
bool createStaticServerContext(AnyP::PortCfg &);
+ /// initialize contexts for signing dynamic TLS certificates (if needed)
+ /// the resulting context is stored in signingCert, signPKey, untrustedSigningCert, untrustedSignPKey
+ void createSigningContexts(AnyP::PortCfg &);
+
+ /// update the given TLS security context using squid.conf settings
+ bool updateContextConfig(Security::ContextPointer &);
+
/// update the context with DH, EDH, EECDH settings
void updateContextEecdh(Security::ContextPointer &);
/// update the context with CA details used to verify client certificates
void updateContextClientCa(Security::ContextPointer &);
+ /// update the context with a configured session ID (if any)
+ void updateContextSessionId(Security::ContextPointer &);
+
/// sync the various sources of CA files to be loaded
void syncCaFiles();
public:
/// TLS context to use for HTTPS accelerator or static SSL-Bump
Security::ContextPointer staticContext;
+ SBuf staticContextSessionId; ///< "session id context" for staticContext
+
+ bool generateHostCertificates = true; ///< dynamically make host cert
+
+ Security::CertPointer signingCert; ///< x509 certificate for signing generated certificates
+ Security::PrivateKeyPointer signPkey; ///< private key for signing generated certificates
+ Security::CertList certsToChain; ///< x509 certificates to send with the generated cert
+ Security::CertPointer untrustedSigningCert; ///< x509 certificate for signing untrusted generated certificates
+ Security::PrivateKeyPointer untrustedSignPkey; ///< private key for signing untrusted generated certificates
+
+ /// max size of generated certificates memory cache (4 MB default)
+ size_t dynamicCertMemCacheSize = 4*1024*1024;
private:
bool loadClientCaFile();
void SetSessionResumeData(const Security::SessionPointer &, const Security::SessionStatePointer &);
#if USE_OPENSSL
-// TODO: remove from public API. It is only public because of configureSslContext() in ssl/support.cc
+// TODO: remove from public API. It is only public because of Security::ServerOptions::updateContextConfig
/// Setup the given TLS context with callbacks used to manage the session cache
void SetSessionCacheCallbacks(Security::ContextPointer &);
}
bool
-Ssl::CertificateDb::find(std::string const &key, const Security::CertPointer &expectedOrig, Security::CertPointer & cert, Ssl::EVP_PKEY_Pointer & pkey)
+Ssl::CertificateDb::find(std::string const &key, const Security::CertPointer &expectedOrig, Security::CertPointer &cert, Security::PrivateKeyPointer &pkey)
{
const Locker locker(dbLock, Here);
load();
}
bool
-Ssl::CertificateDb::addCertAndPrivateKey(std::string const & useKey, const Security::CertPointer & cert, const Ssl::EVP_PKEY_Pointer & pkey, const Security::CertPointer &orig) {
+Ssl::CertificateDb::addCertAndPrivateKey(std::string const &useKey, const Security::CertPointer &cert, const Security::PrivateKeyPointer &pkey, const Security::CertPointer &orig)
+{
const Locker locker(dbLock, Here);
load();
if (!db || !cert || !pkey)
}
bool
-Ssl::CertificateDb::pure_find(std::string const &key, const Security::CertPointer &expectedOrig, Security::CertPointer & cert, Ssl::EVP_PKEY_Pointer & pkey)
+Ssl::CertificateDb::pure_find(std::string const &key, const Security::CertPointer &expectedOrig, Security::CertPointer &cert, Security::PrivateKeyPointer &pkey)
{
if (!db)
return false;
}
bool
-Ssl::CertificateDb::WriteEntry(const std::string &filename, const Security::CertPointer & cert, const Ssl::EVP_PKEY_Pointer & pkey, const Security::CertPointer &orig)
+Ssl::CertificateDb::WriteEntry(const std::string &filename, const Security::CertPointer &cert, const Security::PrivateKeyPointer &pkey, const Security::CertPointer &orig)
{
Ssl::BIO_Pointer bio;
if (!Ssl::OpenCertsFileForWriting(bio, filename.c_str()))
}
bool
-Ssl::CertificateDb::ReadEntry(std::string filename, Security::CertPointer & cert, Ssl::EVP_PKEY_Pointer & pkey, Security::CertPointer &orig)
+Ssl::CertificateDb::ReadEntry(std::string filename, Security::CertPointer &cert, Security::PrivateKeyPointer &pkey, Security::CertPointer &orig)
{
Ssl::BIO_Pointer bio;
if (!Ssl::OpenCertsFileForReading(bio, filename.c_str()))
CertificateDb(std::string const & db_path, size_t aMax_db_size, size_t aFs_block_size);
/// finds matching generated certificate and its private key
- bool find(std::string const & key, const Security::CertPointer &expectedOrig, Security::CertPointer & cert, Ssl::EVP_PKEY_Pointer & pkey);
+ bool find(std::string const & key, const Security::CertPointer &expectedOrig, Security::CertPointer & cert, Security::PrivateKeyPointer & pkey);
/// Delete a certificate from database
bool purgeCert(std::string const & key);
/// Save certificate to disk.
- bool addCertAndPrivateKey(std::string const & useKey, const Security::CertPointer & cert, const Ssl::EVP_PKEY_Pointer & pkey, const Security::CertPointer &orig);
+ bool addCertAndPrivateKey(std::string const & useKey, const Security::CertPointer & cert, const Security::PrivateKeyPointer & pkey, const Security::CertPointer &orig);
bool IsEnabledDiskStore() const; ///< Check enabled of dist store.
size_t getFileSize(std::string const & filename); ///< get file size on disk.
size_t rebuildSize(); ///< Rebuild size_file
/// Only find certificate in current db and return it.
- bool pure_find(std::string const & key, const Security::CertPointer & expectedOrig, Security::CertPointer & cert, Ssl::EVP_PKEY_Pointer & pkey);
+ bool pure_find(std::string const & key, const Security::CertPointer & expectedOrig, Security::CertPointer & cert, Security::PrivateKeyPointer & pkey);
void deleteRow(const char **row, int rowIndex); ///< Delete a row from TXT_DB
bool deleteInvalidCertificate(); ///< Delete invalid certificate.
bool hasRows() const; ///< Whether the TXT_DB has stored items.
/// stores the db entry into a file
- static bool WriteEntry(const std::string &filename, const Security::CertPointer & cert, const Ssl::EVP_PKEY_Pointer & pkey, const Security::CertPointer &orig);
+ static bool WriteEntry(const std::string &filename, const Security::CertPointer & cert, const Security::PrivateKeyPointer & pkey, const Security::CertPointer &orig);
/// loads a db entry from the file
- static bool ReadEntry(std::string filename, Security::CertPointer & cert, Ssl::EVP_PKEY_Pointer & pkey, Security::CertPointer &orig);
+ static bool ReadEntry(std::string filename, Security::CertPointer & cert, Security::PrivateKeyPointer & pkey, Security::CertPointer &orig);
/// Removes the first matching row from TXT_DB. Ignores failures.
static void sq_TXT_DB_delete(TXT_DB *db, const char **row);
Ssl::CertificateDb db(db_path, max_db_size, fs_block_size);
Security::CertPointer cert;
- Ssl::EVP_PKEY_Pointer pkey;
+ Security::PrivateKeyPointer pkey;
Security::CertPointer orig;
std::string &certKey = Ssl::OnDiskCertificateDbKey(certProperties);
#endif /* OpenSSL 1.0 CRYPTO_LOCK_X509_CRL */
#endif /* OpenSSL 1.1 DH_up_ref */
+#if !HAVE_LIBCRYPTO_EVP_PKEY_UP_REF
+#if defined(CRYPTO_LOCK_EVP_PKEY) // OpenSSL 1.0
+inline int EVP_PKEY_up_ref(EVP_PKEY *t) {if (t) CRYPTO_add(&t->references, 1, CRYPTO_LOCK_EVP_PKEY); return 0;}
+#endif
+#else
+#error missing both OpenSSL API features EVP_PKEY_up_ref (v1.1) and CRYPTO_LOCK_EVP_PKEY (v1.0)
+#endif
+
#endif /* USE_OPENSSL */
/* flags a SSL connection can be configured with */
class PeerConnector;
class PeerOptions;
+
+#if USE_OPENSSL
+CtoCpp1(EVP_PKEY_free, EVP_PKEY *)
+typedef Security::LockingPointer<EVP_PKEY, EVP_PKEY_free_cpp, HardFun<int, EVP_PKEY *, EVP_PKEY_up_ref> > PrivateKeyPointer;
+#else
+// XXX: incompatible with the other PrivateKeyPointer declaration (lacks self-initialization)
+typedef void *PrivateKeyPointer;
+#endif
+
class ServerOptions;
} // namespace Security
EVP_PKEY * Ssl::createSslPrivateKey()
{
- Ssl::EVP_PKEY_Pointer pkey(EVP_PKEY_new());
+ Security::PrivateKeyPointer pkey(EVP_PKEY_new());
if (!pkey)
return NULL;
return true;
}
-bool Ssl::writeCertAndPrivateKeyToMemory(Security::CertPointer const & cert, Ssl::EVP_PKEY_Pointer const & pkey, std::string & bufferToWrite)
+bool Ssl::writeCertAndPrivateKeyToMemory(Security::CertPointer const & cert, Security::PrivateKeyPointer const & pkey, std::string & bufferToWrite)
{
bufferToWrite.clear();
if (!pkey || !cert)
return true;
}
-bool Ssl::readCertAndPrivateKeyFromMemory(Security::CertPointer & cert, Ssl::EVP_PKEY_Pointer & pkey, char const * bufferToRead)
+bool Ssl::readCertAndPrivateKeyFromMemory(Security::CertPointer & cert, Security::PrivateKeyPointer & pkey, char const * bufferToRead)
{
Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
BIO_puts(bio.get(), bufferToRead);
return true;
}
-static bool generateFakeSslCertificate(Security::CertPointer & certToStore, Ssl::EVP_PKEY_Pointer & pkeyToStore, Ssl::CertificateProperties const &properties, Ssl::BIGNUM_Pointer const &serial)
+static bool generateFakeSslCertificate(Security::CertPointer & certToStore, Security::PrivateKeyPointer & pkeyToStore, Ssl::CertificateProperties const &properties, Ssl::BIGNUM_Pointer const &serial)
{
- Ssl::EVP_PKEY_Pointer pkey;
+ Security::PrivateKeyPointer pkey;
// Use signing certificates private key as generated certificate private key
if (properties.signWithPkey.get())
pkey.resetAndLock(properties.signWithPkey.get());
/// for a new generated certificate
static bool createSerial(Ssl::BIGNUM_Pointer &serial, Ssl::CertificateProperties const &properties)
{
- Ssl::EVP_PKEY_Pointer fakePkey;
+ Security::PrivateKeyPointer fakePkey;
Security::CertPointer fakeCert;
serial.reset(x509Pubkeydigest(properties.signWithX509));
return true;
}
-bool Ssl::generateSslCertificate(Security::CertPointer & certToStore, Ssl::EVP_PKEY_Pointer & pkeyToStore, Ssl::CertificateProperties const &properties)
+bool Ssl::generateSslCertificate(Security::CertPointer & certToStore, Security::PrivateKeyPointer & pkeyToStore, Ssl::CertificateProperties const &properties)
{
Ssl::BIGNUM_Pointer serial;
}
bool
-Ssl::ReadPrivateKey(Ssl::BIO_Pointer &bio, Ssl::EVP_PKEY_Pointer &pkey, pem_password_cb *passwd_callback)
+Ssl::ReadPrivateKey(Ssl::BIO_Pointer &bio, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback)
{
assert(bio);
if (EVP_PKEY *akey = PEM_read_bio_PrivateKey(bio.get(), NULL, passwd_callback, NULL)) {
}
void
-Ssl::ReadPrivateKeyFromFile(char const * keyFilename, Ssl::EVP_PKEY_Pointer &pkey, pem_password_cb *passwd_callback)
+Ssl::ReadPrivateKeyFromFile(char const * keyFilename, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback)
{
if (!keyFilename)
return;
}
bool
-Ssl::WritePrivateKey(Ssl::BIO_Pointer &bio, const Ssl::EVP_PKEY_Pointer &pkey)
+Ssl::WritePrivateKey(Ssl::BIO_Pointer &bio, const Security::PrivateKeyPointer &pkey)
{
if (!pkey || !bio)
return false;
sk_dtor_wrapper(sk_X509, STACK_OF(X509) *, X509_free);
typedef std::unique_ptr<STACK_OF(X509), sk_X509_free_wrapper> X509_STACK_Pointer;
-CtoCpp1(EVP_PKEY_free, EVP_PKEY *)
-#if defined(CRYPTO_LOCK_EVP_PKEY) // OpenSSL 1.0
-inline int EVP_PKEY_up_ref(EVP_PKEY *t) {if (t) CRYPTO_add(&t->references, 1, CRYPTO_LOCK_EVP_PKEY); return 0;}
-#endif
-typedef Security::LockingPointer<EVP_PKEY, EVP_PKEY_free_cpp, HardFun<int, EVP_PKEY *, EVP_PKEY_up_ref> > EVP_PKEY_Pointer;
-
typedef std::unique_ptr<BIGNUM, HardFun<void, BIGNUM*, &BN_free>> BIGNUM_Pointer;
typedef std::unique_ptr<BIO, HardFun<void, BIO*, &BIO_vfree>> BIO_Pointer;
\ingroup SslCrtdSslAPI
* Write private key and SSL certificate to memory.
*/
-bool writeCertAndPrivateKeyToMemory(Security::CertPointer const & cert, EVP_PKEY_Pointer const & pkey, std::string & bufferToWrite);
+bool writeCertAndPrivateKeyToMemory(Security::CertPointer const & cert, Security::PrivateKeyPointer const & pkey, std::string & bufferToWrite);
/**
\ingroup SslCrtdSslAPI
\ingroup SslCrtdSslAPI
* Write private key and SSL certificate to memory.
*/
-bool readCertAndPrivateKeyFromMemory(Security::CertPointer & cert, EVP_PKEY_Pointer & pkey, char const * bufferToRead);
+bool readCertAndPrivateKeyFromMemory(Security::CertPointer & cert, Security::PrivateKeyPointer & pkey, char const * bufferToRead);
/**
\ingroup SslCrtdSslAPI
\ingroup SslCrtdSslAPI
* Read private key from file.
*/
-void ReadPrivateKeyFromFile(char const * keyFilename, EVP_PKEY_Pointer &pkey, pem_password_cb *passwd_callback);
+void ReadPrivateKeyFromFile(char const * keyFilename, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback);
/**
\ingroup SslCrtdSslAPI
\ingroup SslCrtdSslAPI
* Read a private key from bio
*/
-bool ReadPrivateKey(BIO_Pointer &bio, EVP_PKEY_Pointer &pkey, pem_password_cb *passwd_callback);
+bool ReadPrivateKey(BIO_Pointer &bio, Security::PrivateKeyPointer &pkey, pem_password_cb *passwd_callback);
/**
\ingroup SslCrtdSslAPI
\ingroup SslCrtdSslAPI
* Write private key to BIO.
*/
-bool WritePrivateKey(BIO_Pointer &bio, const EVP_PKEY_Pointer &pkey);
+bool WritePrivateKey(BIO_Pointer &bio, const Security::PrivateKeyPointer &pkey);
/**
\ingroup SslCrtdSslAPI
CertificateProperties();
Security::CertPointer mimicCert; ///< Certificate to mimic
Security::CertPointer signWithX509; ///< Certificate to sign the generated request
- EVP_PKEY_Pointer signWithPkey; ///< The key of the signing certificate
+ Security::PrivateKeyPointer signWithPkey; ///< The key of the signing certificate
bool setValidAfter; ///< Do not mimic "Not Valid After" field
bool setValidBefore; ///< Do not mimic "Not Valid Before" field
bool setCommonName; ///< Replace the CN field of the mimicing subject with the given
* Return generated certificate and private key in resultX509 and resultPkey
* variables.
*/
-bool generateSslCertificate(Security::CertPointer & cert, EVP_PKEY_Pointer & pkey, CertificateProperties const &properties);
+bool generateSslCertificate(Security::CertPointer & cert, Security::PrivateKeyPointer & pkey, CertificateProperties const &properties);
/**
\ingroup SslCrtdSslAPI
// TODO: generate host certificates for SNI enabled accel ports
bool found = false;
for (AnyP::PortCfgPointer s = HttpPortList; !found && s != NULL; s = s->next)
- found = s->flags.tunnelSslBumping && s->generateHostCertificates;
+ found = s->flags.tunnelSslBumping && s->secure.generateHostCertificates;
if (!found)
return;
void Ssl::CrtdMessage::composeBody(BodyParams const & map, std::string const & other_part) STUB
#include "ssl/gadgets.h"
-X509_REQ * Ssl::createNewX509Request(EVP_PKEY_Pointer const &, const char *) STUB_RETVAL(NULL)
-bool Ssl::writeCertAndPrivateKeyToMemory(Security::CertPointer const &, EVP_PKEY_Pointer const &, std::string &) STUB_RETVAL(false)
-bool Ssl::writeCertAndPrivateKeyToFile(Security::CertPointer const &, EVP_PKEY_Pointer const &, char const *) STUB_RETVAL(false)
-bool Ssl::readCertAndPrivateKeyFromMemory(Security::CertPointer &, EVP_PKEY_Pointer &, char const *) STUB_RETVAL(false)
-X509 * Ssl::signRequest(X509_REQ_Pointer const &, Security::CertPointer const &, EVP_PKEY_Pointer const &, ASN1_TIME *, BIGNUM const *) STUB_RETVAL(NULL)
-bool Ssl::generateSslCertificateAndPrivateKey(char const *, Security::CertPointer const &, EVP_PKEY_Pointer const &, Security::CertPointer &, EVP_PKEY_Pointer &, BIGNUM const *) STUB_RETVAL(false)
-void Ssl::readCertAndPrivateKeyFromFiles(Security::CertPointer &, EVP_PKEY_Pointer &, char const *, char const *) STUB
+X509_REQ * Ssl::createNewX509Request(Security::PrivateKeyPointer const &, const char *) STUB_RETVAL(nullptr)
+bool Ssl::writeCertAndPrivateKeyToMemory(Security::CertPointer const &, Security::PrivateKeyPointer const &, std::string &) STUB_RETVAL(false)
+bool Ssl::writeCertAndPrivateKeyToFile(Security::CertPointer const &, Security::PrivateKeyPointer const &, char const *) STUB_RETVAL(false)
+bool Ssl::readCertAndPrivateKeyFromMemory(Security::CertPointer &, Security::PrivateKeyPointer &, char const *) STUB_RETVAL(false)
+X509 * Ssl::signRequest(X509_REQ_Pointer const &, Security::CertPointer const &, Security::PrivateKeyPointer const &, ASN1_TIME *, BIGNUM const *) STUB_RETVAL(nullptr)
+bool Ssl::generateSslCertificateAndPrivateKey(char const *, Security::CertPointer const &, Security::PrivateKeyPointer const &, Security::CertPointer &, Security::PrivateKeyPointer &, BIGNUM const *) STUB_RETVAL(false)
+void Ssl::readCertAndPrivateKeyFromFiles(Security::CertPointer &, Security::PrivateKeyPointer &, char const *, char const *) STUB
bool Ssl::sslDateIsInTheFuture(char const *) STUB_RETVAL(false)
#include "ssl/helper.h"
}
#endif
-static void
-maybeSetupRsaCallback(Security::ContextPointer &ctx)
+void
+Ssl::MaybeSetupRsaCallback(Security::ContextPointer &ctx)
{
#if HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK
debugs(83, 9, "Setting RSA key generation callback.");
ssl_ex_index_ssl_untrusted_chain = SSL_get_ex_new_index(0, (void *) "ssl_untrusted_chain", NULL, NULL, &ssl_free_CertChain);
}
-static bool
-configureSslContext(Security::ContextPointer &ctx, AnyP::PortCfg &port)
-{
- int ssl_error;
- SSL_CTX_set_options(ctx.get(), port.secure.parsedOptions);
-
- if (port.sslContextSessionId)
- SSL_CTX_set_session_id_context(ctx.get(), (const unsigned char *)port.sslContextSessionId, strlen(port.sslContextSessionId));
-
- if (port.secure.parsedFlags & SSL_FLAG_NO_SESSION_REUSE) {
- SSL_CTX_set_session_cache_mode(ctx.get(), SSL_SESS_CACHE_OFF);
- }
-
- if (Config.SSL.unclean_shutdown) {
- debugs(83, 5, "Enabling quiet SSL shutdowns (RFC violation).");
-
- SSL_CTX_set_quiet_shutdown(ctx.get(), 1);
- }
-
- if (!port.secure.sslCipher.isEmpty()) {
- debugs(83, 5, "Using chiper suite " << port.secure.sslCipher << ".");
-
- if (!SSL_CTX_set_cipher_list(ctx.get(), port.secure.sslCipher.c_str())) {
- ssl_error = ERR_get_error();
- debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.secure.sslCipher << "': " << Security::ErrorString(ssl_error));
- return false;
- }
- }
-
- maybeSetupRsaCallback(ctx);
-
- port.secure.updateContextEecdh(ctx);
- port.secure.updateContextCa(ctx);
- port.secure.updateContextClientCa(ctx);
-
- if (port.secure.parsedFlags & SSL_FLAG_DONT_VERIFY_DOMAIN)
- SSL_CTX_set_ex_data(ctx.get(), ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
-
- Security::SetSessionCacheCallbacks(ctx);
-
- return true;
-}
-
bool
Ssl::InitServerContext(Security::ContextPointer &ctx, AnyP::PortCfg &port)
{
if (!ctx)
return false;
- if (!SSL_CTX_use_certificate(ctx.get(), port.signingCert.get())) {
+ if (!SSL_CTX_use_certificate(ctx.get(), port.secure.signingCert.get())) {
const int ssl_error = ERR_get_error();
const auto &keys = port.secure.certs.front();
debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire TLS certificate '" << keys.certFile << "': " << Security::ErrorString(ssl_error));
return false;
}
- if (!SSL_CTX_use_PrivateKey(ctx.get(), port.signPkey.get())) {
+ if (!SSL_CTX_use_PrivateKey(ctx.get(), port.secure.signPkey.get())) {
const int ssl_error = ERR_get_error();
const auto &keys = port.secure.certs.front();
debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire TLS private key '" << keys.privateKeyFile << "': " << Security::ErrorString(ssl_error));
return false;
}
- Ssl::addChainToSslContext(ctx, port.certsToChain.get());
-
- /* Alternate code;
- debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile);
-
- if (!SSL_CTX_use_certificate_chain_file(ctx.get(), certfile)) {
- ssl_error = ERR_get_error();
- debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << Security::ErrorString(ssl_error));
- return false;
- }
-
- debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile);
- ssl_ask_password(ctx.get(), keyfile);
-
- if (!SSL_CTX_use_PrivateKey_file(ctx.get(), keyfile, SSL_FILETYPE_PEM)) {
- ssl_error = ERR_get_error();
- debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << Security::ErrorString(ssl_error));
- return false;
- }
-
- debugs(83, 5, "Comparing private and public SSL keys.");
-
- if (!SSL_CTX_check_private_key(ctx.get())) {
- ssl_error = ERR_get_error();
- debugs(83, DBG_CRITICAL, "ERROR: SSL private key '" << certfile << "' does not match public key '" <<
- keyfile << "': " << Security::ErrorString(ssl_error));
- return false;
- }
- */
+ Ssl::addChainToSslContext(ctx, port.secure.certsToChain);
- if (!configureSslContext(ctx, port)) {
+ if (!port.secure.updateContextConfig(ctx)) {
debugs(83, DBG_CRITICAL, "ERROR: Configuring static SSL context");
return false;
}
}
}
- maybeSetupRsaCallback(ctx);
+ MaybeSetupRsaCallback(ctx);
if (fl & SSL_FLAG_DONT_VERIFY_PEER) {
debugs(83, 2, "SECURITY WARNING: Peer certificates are not verified for validity!");
/// Create SSL context and apply ssl certificate and private key to it.
Security::ContextPointer
-Ssl::createSSLContext(Security::CertPointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port)
+Ssl::createSSLContext(Security::CertPointer & x509, Security::PrivateKeyPointer & pkey, Security::ServerOptions &options)
{
- Security::ContextPointer ctx(port.secure.createBlankContext());
+ Security::ContextPointer ctx(options.createBlankContext());
if (!SSL_CTX_use_certificate(ctx.get(), x509.get()))
return Security::ContextPointer();
if (!SSL_CTX_use_PrivateKey(ctx.get(), pkey.get()))
return Security::ContextPointer();
- if (!configureSslContext(ctx, port))
+ if (!options.updateContextConfig(ctx))
return Security::ContextPointer();
return ctx;
}
Security::ContextPointer
-Ssl::GenerateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port, bool trusted)
+Ssl::GenerateSslContextUsingPkeyAndCertFromMemory(const char * data, Security::ServerOptions &options, bool trusted)
{
Security::CertPointer cert;
- Ssl::EVP_PKEY_Pointer pkey;
+ Security::PrivateKeyPointer pkey;
if (!readCertAndPrivateKeyFromMemory(cert, pkey, data) || !cert || !pkey)
return Security::ContextPointer();
- Security::ContextPointer ctx(createSSLContext(cert, pkey, port));
+ Security::ContextPointer ctx(createSSLContext(cert, pkey, options));
if (ctx && trusted)
- Ssl::chainCertificatesToSSLContext(ctx, port);
+ Ssl::chainCertificatesToSSLContext(ctx, options);
return ctx;
}
Security::ContextPointer
-Ssl::GenerateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port, bool trusted)
+Ssl::GenerateSslContext(CertificateProperties const &properties, Security::ServerOptions &options, bool trusted)
{
Security::CertPointer cert;
- Ssl::EVP_PKEY_Pointer pkey;
+ Security::PrivateKeyPointer pkey;
if (!generateSslCertificate(cert, pkey, properties) || !cert || !pkey)
return Security::ContextPointer();
- Security::ContextPointer ctx(createSSLContext(cert, pkey, port));
+ Security::ContextPointer ctx(createSSLContext(cert, pkey, options));
if (ctx && trusted)
- Ssl::chainCertificatesToSSLContext(ctx, port);
+ Ssl::chainCertificatesToSSLContext(ctx, options);
return ctx;
}
void
-Ssl::chainCertificatesToSSLContext(Security::ContextPointer &ctx, AnyP::PortCfg &port)
+Ssl::chainCertificatesToSSLContext(Security::ContextPointer &ctx, Security::ServerOptions &options)
{
assert(ctx);
// Add signing certificate to the certificates chain
- X509 *signingCert = port.signingCert.get();
+ X509 *signingCert = options.signingCert.get();
if (SSL_CTX_add_extra_chain_cert(ctx.get(), signingCert)) {
// increase the certificate lock
X509_up_ref(signingCert);
const int ssl_error = ERR_get_error();
debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain: " << Security::ErrorString(ssl_error));
}
- Ssl::addChainToSslContext(ctx, port.certsToChain.get());
+ Ssl::addChainToSslContext(ctx, options.certsToChain);
}
void
Ssl::configureUnconfiguredSslContext(Security::ContextPointer &ctx, Ssl::CertSignAlgorithm signAlgorithm,AnyP::PortCfg &port)
{
if (ctx && signAlgorithm == Ssl::algSignTrusted)
- Ssl::chainCertificatesToSSLContext(ctx, port);
+ Ssl::chainCertificatesToSSLContext(ctx, port.secure);
}
bool
Ssl::configureSSL(SSL *ssl, CertificateProperties const &properties, AnyP::PortCfg &port)
{
Security::CertPointer cert;
- Ssl::EVP_PKEY_Pointer pkey;
+ Security::PrivateKeyPointer pkey;
if (!generateSslCertificate(cert, pkey, properties))
return false;
Ssl::configureSSLUsingPkeyAndCertFromMemory(SSL *ssl, const char *data, AnyP::PortCfg &port)
{
Security::CertPointer cert;
- Ssl::EVP_PKEY_Pointer pkey;
+ Security::PrivateKeyPointer pkey;
if (!readCertAndPrivateKeyFromMemory(cert, pkey, data))
return false;
}
void
-Ssl::addChainToSslContext(Security::ContextPointer &ctx, STACK_OF(X509) *chain)
+Ssl::addChainToSslContext(Security::ContextPointer &ctx, Security::CertList &chain)
{
- if (!chain)
+ if (chain.empty())
return;
- for (int i = 0; i < sk_X509_num(chain); ++i) {
- X509 *cert = sk_X509_value(chain, i);
- if (SSL_CTX_add_extra_chain_cert(ctx.get(), cert)) {
+ for (auto cert : chain) {
+ if (SSL_CTX_add_extra_chain_cert(ctx.get(), cert.get())) {
// increase the certificate lock
- X509_up_ref(cert);
+ X509_up_ref(cert.get());
} else {
const int ssl_error = ERR_get_error();
debugs(83, DBG_IMPORTANT, "WARNING: can not add certificate to SSL context chain: " << Security::ErrorString(ssl_error));
* Read certificate from file.
* See also: static readSslX509Certificate function, gadgets.cc file
*/
-static X509 * readSslX509CertificatesChain(char const * certFilename, STACK_OF(X509)* chain)
+static X509 * readSslX509CertificatesChain(char const * certFilename, Security::CertList &chain)
{
if (!certFilename)
return NULL;
return NULL;
X509 *certificate = PEM_read_bio_X509(bio.get(), NULL, NULL, NULL);
- if (certificate && chain) {
+ if (certificate) {
if (X509_check_issued(certificate, certificate) == X509_V_OK)
debugs(83, 5, "Certificate is self-signed, will not be chained");
else {
// and add to the chain any other certificate exist in the file
- while (X509 *ca = PEM_read_bio_X509(bio.get(), NULL, NULL, NULL)) {
- if (!sk_X509_push(chain, ca))
- debugs(83, DBG_IMPORTANT, "WARNING: unable to add CA certificate to cert chain");
- }
+ while (X509 *ca = PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr))
+ chain.emplace_front(Security::CertPointer(ca));
}
}
return certificate;
}
-void Ssl::readCertChainAndPrivateKeyFromFiles(Security::CertPointer & cert, EVP_PKEY_Pointer & pkey, X509_STACK_Pointer & chain, char const * certFilename, char const * keyFilename)
+void
+Ssl::readCertChainAndPrivateKeyFromFiles(Security::CertPointer & cert, Security::PrivateKeyPointer & pkey, Security::CertList &chain, char const * certFilename, char const * keyFilename)
{
if (keyFilename == NULL)
keyFilename = certFilename;
debugs(83, DBG_IMPORTANT, "Using certificate in " << certFilename);
- if (!chain)
- chain.reset(sk_X509_new_null());
- if (!chain)
- debugs(83, DBG_IMPORTANT, "WARNING: unable to allocate memory for cert chain");
// XXX: ssl_ask_password_cb needs SSL_CTX_set_default_passwd_cb_userdata()
// so this may not fully work iff Config.Program.ssl_password is set.
pem_password_cb *cb = ::Config.Program.ssl_password ? &ssl_ask_password_cb : NULL;
Ssl::ReadPrivateKeyFromFile(keyFilename, pkey, cb);
- cert.resetWithoutLocking(readSslX509CertificatesChain(certFilename, chain.get()));
+ cert.resetWithoutLocking(readSslX509CertificatesChain(certFilename, chain));
if (!cert) {
debugs(83, DBG_IMPORTANT, "WARNING: missing cert in '" << certFilename << "'");
} else if (!pkey) {
cert.reset();
}
-bool Ssl::generateUntrustedCert(Security::CertPointer &untrustedCert, EVP_PKEY_Pointer &untrustedPkey, Security::CertPointer const &cert, EVP_PKEY_Pointer const & pkey)
+bool Ssl::generateUntrustedCert(Security::CertPointer &untrustedCert, Security::PrivateKeyPointer &untrustedPkey, Security::CertPointer const &cert, Security::PrivateKeyPointer const & pkey)
{
// Generate the self-signed certificate, using a hard-coded subject prefix
Ssl::CertificateProperties certProperties;
/// set the certificate verify callback for a context
void SetupVerifyCallback(Security::ContextPointer &);
+/// if required, setup callback for generating ephemeral RSA keys
+void MaybeSetupRsaCallback(Security::ContextPointer &);
+
} //namespace Ssl
/// \ingroup ServerProtocolSSLAPI
\ingroup ServerProtocolSSLAPI
* Generate a certificate to be used as untrusted signing certificate, based on a trusted CA
*/
-bool generateUntrustedCert(Security::CertPointer & untrustedCert, EVP_PKEY_Pointer & untrustedPkey, Security::CertPointer const & cert, EVP_PKEY_Pointer const & pkey);
+bool generateUntrustedCert(Security::CertPointer & untrustedCert, Security::PrivateKeyPointer & untrustedPkey, Security::CertPointer const & cert, Security::PrivateKeyPointer const & pkey);
/// certificates indexed by issuer name
typedef std::multimap<SBuf, X509 *> CertsIndexedList;
\ingroup ServerProtocolSSLAPI
* Decide on the kind of certificate and generate a CA- or self-signed one
*/
-Security::ContextPointer GenerateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port, bool trusted);
+Security::ContextPointer GenerateSslContext(CertificateProperties const &, Security::ServerOptions &, bool trusted);
/**
\ingroup ServerProtocolSSLAPI
* Read private key and certificate from memory and generate SSL context
* using their.
*/
-Security::ContextPointer GenerateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port, bool trusted);
+Security::ContextPointer GenerateSslContextUsingPkeyAndCertFromMemory(const char * data, Security::ServerOptions &, bool trusted);
/**
\ingroup ServerProtocolSSLAPI
* Create an SSL context using the provided certificate and key
*/
-Security::ContextPointer createSSLContext(Security::CertPointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port);
+Security::ContextPointer createSSLContext(Security::CertPointer & x509, Security::PrivateKeyPointer & pkey, Security::ServerOptions &);
/**
\ingroup ServerProtocolSSLAPI
* Chain signing certificate and chained certificates to an SSL Context
*/
-void chainCertificatesToSSLContext(Security::ContextPointer &, AnyP::PortCfg &);
+void chainCertificatesToSSLContext(Security::ContextPointer &, Security::ServerOptions &);
/**
\ingroup ServerProtocolSSLAPI
\ingroup ServerProtocolSSLAPI
* Adds the certificates in certList to the certificate chain of the SSL context
*/
-void addChainToSslContext(Security::ContextPointer &, STACK_OF(X509) *certList);
+void addChainToSslContext(Security::ContextPointer &, Security::CertList &);
/**
\ingroup ServerProtocolSSLAPI
* \param certFilename name of file with certificate and certificates which must be chainned.
* \param keyFilename name of file with private key.
*/
-void readCertChainAndPrivateKeyFromFiles(Security::CertPointer & cert, EVP_PKEY_Pointer & pkey, X509_STACK_Pointer & chain, char const * certFilename, char const * keyFilename);
+void readCertChainAndPrivateKeyFromFiles(Security::CertPointer & cert, Security::PrivateKeyPointer & pkey, Security::CertList &chain, char const * certFilename, char const * keyFilename);
/**
\ingroup ServerProtocolSSLAPI
void Security::ServerOptions::dumpCfg(Packable *, const char *) const STUB
Security::ContextPointer Security::ServerOptions::createBlankContext() const STUB_RETVAL(Security::ContextPointer())
bool Security::ServerOptions::createStaticServerContext(AnyP::PortCfg &) STUB_RETVAL(false)
+void Security::ServerOptions::createSigningContexts(AnyP::PortCfg &) STUB
+bool Security::ServerOptions::updateContextConfig(Security::ContextPointer &) STUB_RETVAL(false)
void Security::ServerOptions::updateContextEecdh(Security::ContextPointer &) STUB
void Security::ServerOptions::updateContextClientCa(Security::ContextPointer &) STUB
void Security::ServerOptions::syncCaFiles() STUB
+void Security::ServerOptions::updateContextSessionId(Security::ContextPointer &) STUB
#include "security/Session.h"
namespace Security {
{
bool InitServerContext(Security::ContextPointer &, AnyP::PortCfg &) STUB_RETVAL(false)
bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, const char *) STUB_RETVAL(false)
+void SetupVerifyCallback(Security::ContextPointer &) STUB
+void MaybeSetupRsaCallback(Security::ContextPointer &) STUB
} // namespace Ssl
const char *sslGetUserEmail(SSL *ssl) STUB_RETVAL(NULL)
const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name) STUB_RETVAL(NULL)
//GETX509ATTRIBUTE GetX509CAAttribute;
//GETX509ATTRIBUTE GetX509Fingerprint;
std::vector<const char *> BumpModeStr = {""};
-bool generateUntrustedCert(Security::CertPointer & untrustedCert, EVP_PKEY_Pointer & untrustedPkey, Security::CertPointer const & cert, EVP_PKEY_Pointer const & pkey) STUB_RETVAL(false)
-Security::ContextPointer GenerateSslContext(CertificateProperties const &, AnyP::PortCfg &, bool) STUB_RETVAL(Security::ContextPointer())
+bool generateUntrustedCert(Security::CertPointer &, Security::PrivateKeyPointer &, Security::CertPointer const &, Security::PrivateKeyPointer const &) STUB_RETVAL(false)
+Security::ContextPointer GenerateSslContext(CertificateProperties const &, Security::ServerOptions &, bool) STUB_RETVAL(Security::ContextPointer())
bool verifySslCertificate(Security::ContextPointer &, CertificateProperties const &) STUB_RETVAL(false)
-Security::ContextPointer GenerateSslContextUsingPkeyAndCertFromMemory(const char *, AnyP::PortCfg &, bool) STUB_RETVAL(Security::ContextPointer())
+Security::ContextPointer GenerateSslContextUsingPkeyAndCertFromMemory(const char *, Security::ServerOptions &, bool) STUB_RETVAL(Security::ContextPointer())
void addChainToSslContext(Security::ContextPointer &, STACK_OF(X509) *) STUB
-void readCertChainAndPrivateKeyFromFiles(Security::CertPointer & cert, EVP_PKEY_Pointer & pkey, X509_STACK_Pointer & chain, char const * certFilename, char const * keyFilename) STUB
+void readCertChainAndPrivateKeyFromFiles(Security::CertPointer &, Security::PrivateKeyPointer &, Security::CertList &, char const *, char const *) STUB
int matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data)) STUB_RETVAL(0)
bool checkX509ServerValidity(X509 *cert, const char *server) STUB_RETVAL(false)
int asn1timeToString(ASN1_TIME *tm, char *buf, int len) STUB_RETVAL(0)