#include <openssl/ssl.h>
#include <openssl/err.h>
+#include <openssl/dh.h>
#ifdef _WIN32
# pragma comment(lib, "ssleay32.lib")
# pragma comment(lib, "libeay32.lib")
#endif
-#if ((OPENSSL_VERSION_NUMBER >= 0x10000000L) && (!(defined(OPENSSL_NO_ECDH))))
-// OpenSSL 0.9.8 includes some ECC support, but it's unfinished. Enable only for 1.0.0 and later.
-#define INSPIRCD_OPENSSL_ENABLE_ECDH
-#endif
-
-// BIO is opaque in OpenSSL 1.1 but the access API does not exist in 1.0 and older.
+// Compatibility layer to allow OpenSSL 1.0 to use the 1.1 API.
#if ((defined LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L))
+
+// BIO is opaque in OpenSSL 1.1 but the access API does not exist in 1.0.
# define BIO_get_data(BIO) BIO->ptr
# define BIO_set_data(BIO, VALUE) BIO->ptr = VALUE;
# define BIO_set_init(BIO, VALUE) BIO->init = VALUE;
+
+// These functions have been renamed in OpenSSL 1.1.
+# define OpenSSL_version SSLeay_version
+# define X509_getm_notAfter X509_get_notAfter
+# define X509_getm_notBefore X509_get_notBefore
+# define OPENSSL_init_ssl(OPTIONS, SETTINGS) \
+ SSL_library_init(); \
+ SSL_load_error_strings();
+
+// These macros have been renamed in OpenSSL 1.1.
+# define OPENSSL_VERSION SSLEAY_VERSION
+
#else
# define INSPIRCD_OPENSSL_OPAQUE_BIO
#endif
{
// Sane default options for OpenSSL see https://www.openssl.org/docs/ssl/SSL_CTX_set_options.html
// and when choosing a cipher, use the server's preferences instead of the client preferences.
- long opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_DH_USE;
+ long opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_DH_USE;
// Only turn options on if they exist
#ifdef SSL_OP_SINGLE_ECDH_USE
opts |= SSL_OP_SINGLE_ECDH_USE;
return (SSL_CTX_set_tmp_dh(ctx, dh.get()) >= 0);
}
-#ifdef INSPIRCD_OPENSSL_ENABLE_ECDH
+#ifndef OPENSSL_NO_ECDH
void SetECDH(const std::string& curvename)
{
int nid = OBJ_sn2nid(curvename.c_str());
return SSL_CTX_load_verify_locations(ctx, filename.c_str(), 0);
}
+ void SetCRL(const std::string& crlfile, const std::string& crlpath, const std::string& crlmode)
+ {
+ if (crlfile.empty() && crlpath.empty())
+ return;
+
+ /* Set CRL mode */
+ unsigned long crlflags = X509_V_FLAG_CRL_CHECK;
+ if (crlmode == "chain")
+ {
+ crlflags |= X509_V_FLAG_CRL_CHECK_ALL;
+ }
+ else if (crlmode != "leaf")
+ {
+ throw ModuleException("Unknown mode '" + crlmode + "'; expected either 'chain' (default) or 'leaf'");
+ }
+
+ /* Load CRL files */
+ X509_STORE* store = SSL_CTX_get_cert_store(ctx);
+ if (!store)
+ {
+ throw ModuleException("Unable to get X509_STORE from SSL context; this should never happen");
+ }
+ ERR_clear_error();
+ if (!X509_STORE_load_locations(store,
+ crlfile.empty() ? NULL : crlfile.c_str(),
+ crlpath.empty() ? NULL : crlpath.c_str()))
+ {
+ int err = ERR_get_error();
+ throw ModuleException("Unable to load CRL file '" + crlfile + "' or CRL path '" + crlpath + "': '" + (err ? ERR_error_string(err, NULL) : "unknown") + "'");
+ }
+
+ /* Set CRL mode */
+ if (X509_STORE_set_flags(store, crlflags) != 1)
+ {
+ throw ModuleException("Unable to set X509 CRL flags");
+ }
+ }
+
+
long GetDefaultContextOptions() const
{
return ctx_options;
*/
void SetContextOptions(const std::string& ctxname, ConfigTag* tag, Context& context)
{
- long setoptions = tag->getInt(ctxname + "setoptions");
- long clearoptions = tag->getInt(ctxname + "clearoptions");
+ long setoptions = tag->getInt(ctxname + "setoptions", 0);
+ long clearoptions = tag->getInt(ctxname + "clearoptions", 0);
#ifdef SSL_OP_NO_COMPRESSION
if (!tag->getBool("compression", false)) // Disable compression by default
setoptions |= SSL_OP_NO_COMPRESSION;
#endif
- if (!tag->getBool("sslv3", false)) // Disable SSLv3 by default
- setoptions |= SSL_OP_NO_SSLv3;
- if (!tag->getBool("tlsv1", true))
+ // Disable TLSv1.0 by default.
+ if (!tag->getBool("tlsv1", false))
setoptions |= SSL_OP_NO_TLSv1;
if (!setoptions && !clearoptions)
}
}
-#ifdef INSPIRCD_OPENSSL_ENABLE_ECDH
+#ifndef OPENSSL_NO_ECDH
std::string curvename = tag->getString("ecdhcurve", "prime256v1");
if (!curvename.empty())
ctx.SetECDH(curvename);
ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Can't read CA list from %s. This is only a problem if you want to verify client certificates, otherwise it's safe to ignore this message. Error: %s", filename.c_str(), lasterr.c_str());
}
+ // Load the CRLs.
+ std::string crlfile = tag->getString("crlfile");
+ std::string crlpath = tag->getString("crlpath");
+ std::string crlmode = tag->getString("crlmode", "chain");
+ ctx.SetCRL(crlfile, crlpath, crlmode);
+
clictx.SetVerifyCert();
if (tag->getBool("requestclientcert", true))
ctx.SetVerifyCert();
certinfo->fingerprint = BinToHex(md, n);
}
- if ((ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(cert), ServerInstance->Time()) == -1) || (ASN1_UTCTIME_cmp_time_t(X509_get_notBefore(cert), ServerInstance->Time()) == 0))
+ if ((ASN1_UTCTIME_cmp_time_t(X509_getm_notAfter(cert), ServerInstance->Time()) == -1) || (ASN1_UTCTIME_cmp_time_t(X509_getm_notBefore(cert), ServerInstance->Time()) == 0))
{
certinfo->error = "Not activated, or expired certificate";
}
ModuleSSLOpenSSL()
{
// Initialize OpenSSL
- SSL_library_init();
- SSL_load_error_strings();
+ OPENSSL_init_ssl(0, NULL);
#ifdef INSPIRCD_OPENSSL_OPAQUE_BIO
biomethods = OpenSSL::BIOMethod::alloc();
}
void init() CXX11_OVERRIDE
{
- ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "OpenSSL lib version \"%s\" module was compiled for \"" OPENSSL_VERSION_TEXT "\"", SSLeay_version(SSLEAY_VERSION));
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "OpenSSL lib version \"%s\" module was compiled for \"" OPENSSL_VERSION_TEXT "\"", OpenSSL_version(OPENSSL_VERSION));
// Register application specific data
char exdatastr[] = "inspircd";