From 03775fcdc5a118eb336d80d012a140f060053ab7 Mon Sep 17 00:00:00 2001 From: William Elwood Date: Sat, 3 Sep 2016 14:23:12 +0100 Subject: [PATCH 1/3] Fix compile errors caused by OpenSSL 1.1 --- modules/schat.cpp | 16 ++++++++-------- src/main.cpp | 10 +++++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/modules/schat.cpp b/modules/schat.cpp index 703cf844..328e096f 100644 --- a/modules/schat.cpp +++ b/modules/schat.cpp @@ -25,6 +25,12 @@ #include #include +#if !defined(OPENSSL_VERSION_NUMBER) || defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100007 +/* SSL_SESSION was made opaque in OpenSSL 1.1.0, cipher accessor was added 2 weeks before the public release. +See openssl/openssl@e92813234318635639dba0168c7ef5568757449b. */ +# define SSL_SESSION_get0_cipher(pSession) ((pSession)->cipher) +#endif + using std::pair; using std::stringstream; using std::map; @@ -226,9 +232,7 @@ public: Table.SetCell("Host", pSock->GetRemoteIP()); Table.SetCell("Port", CString(pSock->GetRemotePort())); SSL_SESSION *pSession = pSock->GetSSLSession(); - if (pSession && pSession->cipher && pSession->cipher->name) - Table.SetCell("Cipher", pSession->cipher->name); - + Table.SetCell("Cipher", SSL_CIPHER_get_name(pSession ? SSL_SESSION_get0_cipher(pSession) : NULL)); } else { Table.SetCell("Status", "Waiting"); Table.SetCell("Port", CString(pSock->GetLocalPort())); @@ -286,11 +290,7 @@ public: Table.SetCell("RemoteIP:Port", pSock->GetRemoteIP() + ":" + CString(pSock->GetRemotePort())); SSL_SESSION *pSession = pSock->GetSSLSession(); - if (pSession && pSession->cipher && pSession->cipher->name) - Table.SetCell("Cipher", pSession->cipher->name); - else - Table.SetCell("Cipher", "None"); - + Table.SetCell("Cipher", SSL_CIPHER_get_name(pSession ? SSL_SESSION_get0_cipher(pSession) : NULL)); } else { Table.SetCell("Type", "Listener"); Table.SetCell("LocalIP:Port", pSock->GetLocalIP() + diff --git a/src/main.cpp b/src/main.cpp index 09b2c9cd..6d89e78a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,7 +17,15 @@ #include #include -#if defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD) +#if defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD) && ( !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100004 ) +/* Starting with version 1.1.0-pre4, OpenSSL has a new threading implementation that doesn't need locking callbacks. + "OpenSSL now uses a new threading API. It is no longer necessary to + set locking callbacks to use OpenSSL in a multi-threaded environment. There + are two supported threading models: pthreads and windows threads. It is + also possible to configure OpenSSL at compile time for "no-threads". The + old threading API should no longer be used. The functions have been + replaced with "no-op" compatibility macros." +See openssl/openssl@2e52e7df518d80188c865ea3f7bb3526d14b0c08. */ #include #include #include From 6a5c2c649dded2e5577aa5e9b77edbf44e027501 Mon Sep 17 00:00:00 2001 From: William Elwood Date: Sat, 3 Sep 2016 14:27:56 +0100 Subject: [PATCH 2/3] Fix use of a feature deprecated in OpenSSL 0.9.8 If OpenSSL 1.1 is configured in such a way that features deprecated in 0.9.8 are not built, then compile errors would result here. I also noticed a potential memory leak where pRSA was not always freed before early return from this function - fixed by using C++11 unique_ptr. --- src/Utils.cpp | 94 +++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 52 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 63992ef1..327c2615 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -26,6 +26,7 @@ #include #ifdef HAVE_LIBSSL #include +#include #endif /* HAVE_LIBSSL */ #include #include @@ -59,79 +60,68 @@ constexpr const char* szDefaultDH2048 = "-----END DH PARAMETERS-----\n"; void CUtils::GenerateCert(FILE *pOut, const CString& sHost) { - EVP_PKEY *pKey = NULL; - X509 *pCert = NULL; - X509_NAME *pName = NULL; const int days = 365; const int years = 10; unsigned int uSeed = (unsigned int)time(NULL); int serial = (rand_r(&uSeed) % 9999); - RSA *pRSA = RSA_generate_key(2048, 0x10001, NULL, NULL); - if ((pKey = EVP_PKEY_new())) { - if (!EVP_PKEY_assign_RSA(pKey, pRSA)) { - EVP_PKEY_free(pKey); - return; - } + std::unique_ptr pExponent(BN_new(), ::BN_free); + if (!pExponent || !BN_set_word(pExponent.get(), 0x10001)) + return; - PEM_write_RSAPrivateKey(pOut, pRSA, NULL, NULL, 0, NULL, NULL); + std::unique_ptr pRSA(RSA_new(), ::RSA_free); + if (!pRSA || !RSA_generate_key_ex(pRSA.get(), 2048, pExponent.get(), NULL)) + return; - if (!(pCert = X509_new())) { - EVP_PKEY_free(pKey); - return; - } + std::unique_ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); + if (!pKey || !EVP_PKEY_set1_RSA(pKey.get(), pRSA.get())) + return; - X509_set_version(pCert, 2); - ASN1_INTEGER_set(X509_get_serialNumber(pCert), serial); - X509_gmtime_adj(X509_get_notBefore(pCert), 0); - X509_gmtime_adj(X509_get_notAfter(pCert), (long)60*60*24*days*years); - X509_set_pubkey(pCert, pKey); + std::unique_ptr pCert(X509_new(), ::X509_free); + if (!pCert) + return; - pName = X509_get_subject_name(pCert); + X509_set_version(pCert.get(), 2); + ASN1_INTEGER_set(X509_get_serialNumber(pCert.get()), serial); + X509_gmtime_adj(X509_get_notBefore(pCert.get()), 0); + X509_gmtime_adj(X509_get_notAfter(pCert.get()), (long)60*60*24*days*years); + X509_set_pubkey(pCert.get(), pKey.get()); - const char *pLogName = getenv("LOGNAME"); - const char *pHostName = NULL; + const char *pLogName = getenv("LOGNAME"); + const char *pHostName = NULL; - if (!sHost.empty()) { - pHostName = sHost.c_str(); - } + if (!pLogName) + pLogName = "Unknown"; - if (!pHostName) { - pHostName = getenv("HOSTNAME"); - } + if (!sHost.empty()) + pHostName = sHost.c_str(); - if (!pLogName) { - pLogName = "Unknown"; - } + if (!pHostName) + pHostName = getenv("HOSTNAME"); - if (!pHostName) { - pHostName = "host.unknown"; - } + if (!pHostName) + pHostName = "host.unknown"; - CString sEmailAddr = pLogName; - sEmailAddr += "@"; - sEmailAddr += pHostName; + CString sEmailAddr = pLogName; + sEmailAddr += "@"; + sEmailAddr += pHostName; - X509_NAME_add_entry_by_txt(pName, "OU", MBSTRING_ASC, (unsigned char *)pLogName, -1, -1, 0); - X509_NAME_add_entry_by_txt(pName, "CN", MBSTRING_ASC, (unsigned char *)pHostName, -1, -1, 0); - X509_NAME_add_entry_by_txt(pName, "emailAddress", MBSTRING_ASC, (unsigned char *)sEmailAddr.c_str(), -1, -1, 0); + X509_NAME *pName = X509_get_subject_name(pCert.get()); + X509_NAME_add_entry_by_txt(pName, "OU", MBSTRING_ASC, (unsigned char *)pLogName, -1, -1, 0); + X509_NAME_add_entry_by_txt(pName, "CN", MBSTRING_ASC, (unsigned char *)pHostName, -1, -1, 0); + X509_NAME_add_entry_by_txt(pName, "emailAddress", MBSTRING_ASC, (unsigned char *)sEmailAddr.c_str(), -1, -1, 0); - X509_set_subject_name(pCert, pName); - X509_set_issuer_name(pCert, pName); + X509_set_subject_name(pCert.get(), pName); + X509_set_issuer_name(pCert.get(), pName); - if (!X509_sign(pCert, pKey, EVP_sha256())) { - X509_free(pCert); - EVP_PKEY_free(pKey); - return; - } + if (!X509_sign(pCert.get(), pKey.get(), EVP_sha256())) + return; - PEM_write_X509(pOut, pCert); - X509_free(pCert); - EVP_PKEY_free(pKey); + PEM_write_RSAPrivateKey(pOut, pRSA.get(), NULL, NULL, 0, NULL, NULL); + PEM_write_X509(pOut, pCert.get()); - fprintf(pOut, "%s", szDefaultDH2048); - } + fprintf(pOut, "%s", szDefaultDH2048); } #endif /* HAVE_LIBSSL */ From 853dcc211d96453b18bbce8544bddcd52b82060c Mon Sep 17 00:00:00 2001 From: William Elwood Date: Sat, 3 Sep 2016 14:40:59 +0100 Subject: [PATCH 3/3] Fix use of a feature deprecated in OpenSSL 1.1 If OpenSSL 1.1 is configured in such a way that features deprecated in 1.1.0 are not built, then compile errors would result here. --- src/SSLVerifyHost.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/SSLVerifyHost.cpp b/src/SSLVerifyHost.cpp index 2b5af5ef..642dc7f7 100644 --- a/src/SSLVerifyHost.cpp +++ b/src/SSLVerifyHost.cpp @@ -17,6 +17,12 @@ #include #ifdef HAVE_LIBSSL +#if defined(OPENSSL_VERSION_NUMBER) && !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100007 +# define CONST_ASN1_STRING_DATA const /* 1.1.0-pre7: openssl/openssl@17ebf85abda18c3875b1ba6670fe7b393bc1f297 */ +#else +# define ASN1_STRING_get0_data( x ) ASN1_STRING_data( x ) +# define CONST_ASN1_STRING_DATA +#endif #include @@ -305,7 +311,7 @@ static HostnameValidationResult matches_common_name(const char *hostname, const int common_name_loc = -1; X509_NAME_ENTRY *common_name_entry = NULL; ASN1_STRING *common_name_asn1 = NULL; - char *common_name_str = NULL; + CONST_ASN1_STRING_DATA char *common_name_str = NULL; // Find the position of the CN field in the Subject field of the certificate common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name((X509 *) server_cert), NID_commonName, -1); @@ -324,7 +330,7 @@ static HostnameValidationResult matches_common_name(const char *hostname, const if (common_name_asn1 == NULL) { return Error; } - common_name_str = (char *) ASN1_STRING_data(common_name_asn1); + common_name_str = (CONST_ASN1_STRING_DATA char*) ASN1_STRING_get0_data(common_name_asn1); // Make sure there isn't an embedded NUL character in the CN if (ASN1_STRING_length(common_name_asn1) != static_cast(strlen(common_name_str))) { @@ -369,7 +375,7 @@ static HostnameValidationResult matches_subject_alternative_name(const char *hos if (current_name->type == GEN_DNS) { // Current name is a DNS name, let's check it - char *dns_name = (char *) ASN1_STRING_data(current_name->d.dNSName); + CONST_ASN1_STRING_DATA char *dns_name = (CONST_ASN1_STRING_DATA char*) ASN1_STRING_get0_data(current_name->d.dNSName); // Make sure there isn't an embedded NUL character in the DNS name if (ASN1_STRING_length(current_name->d.dNSName) != static_cast(strlen(dns_name))) {