浏览代码

Merge pull request #31 from bartbes/openssl3

Add OpenSSL 3 support
Miku AuahDark 1 年之前
父节点
当前提交
d0de6e20d0
共有 2 个文件被更改,包括 42 次插入24 次删除
  1. 40 24
      src/generic/OpenSSLConnection.cpp
  2. 2 0
      src/generic/OpenSSLConnection.h

+ 40 - 24
src/generic/OpenSSLConnection.cpp

@@ -7,37 +7,45 @@
 // Not present in openssl 1.1 headers
 #define SSL_CTRL_OPTIONS 32
 
+static bool TryOpenLibraries(const char *sslName, LibraryLoader::handle *& sslHandle, const char *cryptoName, LibraryLoader::handle *&cryptoHandle)
+{
+	sslHandle = LibraryLoader::OpenLibrary(sslName);
+	cryptoHandle = LibraryLoader::OpenLibrary(cryptoName);
+
+	if (sslHandle && cryptoHandle)
+		return true;
+
+	if (sslHandle)
+		LibraryLoader::CloseLibrary(sslHandle);
+	if (cryptoHandle)
+		LibraryLoader::CloseLibrary(cryptoHandle);
+	return false;
+}
+
 OpenSSLConnection::SSLFuncs::SSLFuncs()
 {
 	using namespace LibraryLoader;
 
-	valid = false;
+	handle *sslhandle = nullptr;
+	handle *cryptohandle = nullptr;
 
-	// Try OpenSSL 1.1
-	handle *sslhandle = OpenLibrary("libssl.so.1.1");
-	handle *cryptohandle = OpenLibrary("libcrypto.so.1.1");
-	// Try OpenSSL 1.0
-	if (!sslhandle || !cryptohandle)
-	{
-		sslhandle = OpenLibrary("libssl.so.1.0.0");
-		cryptohandle = OpenLibrary("libcrypto.so.1.0.0");
-	}
-	// Try OpenSSL without version
-	if (!sslhandle || !cryptohandle)
-	{
-		sslhandle = OpenLibrary("libssl.so");
-		cryptohandle = OpenLibrary("libcrypto.so");
-	}
-	// Give up
-	if (!sslhandle || !cryptohandle)
+	valid = TryOpenLibraries("libssl.so.3", sslhandle, "libcrypto.so.3", cryptohandle)
+		|| TryOpenLibraries("libssl.so.1.1", sslhandle, "libcrypto.so.1.1", cryptohandle)
+		|| TryOpenLibraries("libssl.so.1.0.0", sslhandle, "libcrypto.so.1.0.0", cryptohandle)
+		// Try the version-less name last, it may not be compatible or tested
+		|| TryOpenLibraries("libssl.so", sslhandle, "libcrypto.so", cryptohandle);
+	if (!valid)
 		return;
 
 	valid = true;
-	valid = valid && (LoadSymbol(library_init, sslhandle, "SSL_library_init") ||
-			LoadSymbol(init_ssl, sslhandle, "OPENSSL_init_ssl"));
+	valid = valid && (
+			LoadSymbol(init_ssl, sslhandle, "OPENSSL_init_ssl") ||
+			LoadSymbol(library_init, sslhandle, "SSL_library_init"));
 
 	valid = valid && LoadSymbol(CTX_new, sslhandle, "SSL_CTX_new");
 	valid = valid && LoadSymbol(CTX_ctrl, sslhandle, "SSL_CTX_ctrl");
+	if (valid)
+		LoadSymbol(CTX_set_options, sslhandle, "SSL_CTX_set_options");
 	valid = valid && LoadSymbol(CTX_set_verify, sslhandle, "SSL_CTX_set_verify");
 	valid = valid && LoadSymbol(CTX_set_default_verify_paths, sslhandle, "SSL_CTX_set_default_verify_paths");
 	valid = valid && LoadSymbol(CTX_free, sslhandle, "SSL_CTX_free");
@@ -50,12 +58,16 @@ OpenSSLConnection::SSLFuncs::SSLFuncs()
 	valid = valid && LoadSymbol(write, sslhandle, "SSL_write");
 	valid = valid && LoadSymbol(shutdown, sslhandle, "SSL_shutdown");
 	valid = valid && LoadSymbol(get_verify_result, sslhandle, "SSL_get_verify_result");
-	valid = valid && LoadSymbol(get_peer_certificate, sslhandle, "SSL_get_peer_certificate");
+	valid = valid && (LoadSymbol(get_peer_certificate, sslhandle, "SSL_get1_peer_certificate") ||
+			LoadSymbol(get_peer_certificate, sslhandle, "SSL_get_peer_certificate"));
 
-	valid = valid && (LoadSymbol(SSLv23_method, sslhandle, "SSLv23_method") ||
-			LoadSymbol(SSLv23_method, sslhandle, "TLS_method"));
+	valid = valid && (
+			LoadSymbol(SSLv23_method, sslhandle, "TLS_client_method") ||
+			LoadSymbol(SSLv23_method, sslhandle, "TLS_method") ||
+			LoadSymbol(SSLv23_method, sslhandle, "SSLv23_method"));
 
 	valid = valid && LoadSymbol(check_host, cryptohandle, "X509_check_host");
+	valid = valid && LoadSymbol(X509_free, cryptohandle, "X509_free");
 
 	if (library_init)
 		library_init();
@@ -76,7 +88,10 @@ OpenSSLConnection::OpenSSLConnection()
 	if (!context)
 		return;
 
-	ssl.CTX_ctrl(context, SSL_CTRL_OPTIONS, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3, nullptr);
+	if (ssl.CTX_set_options)
+		ssl.CTX_set_options(context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+	else
+		ssl.CTX_ctrl(context, SSL_CTRL_OPTIONS, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3, nullptr);
 	ssl.CTX_set_verify(context, SSL_VERIFY_PEER, nullptr);
 	ssl.CTX_set_default_verify_paths(context);
 }
@@ -118,6 +133,7 @@ bool OpenSSLConnection::connect(const std::string &hostname, uint16_t port)
 		close();
 		return false;
 	}
+	ssl.X509_free(cert);
 
 	return true;
 }

+ 2 - 0
src/generic/OpenSSLConnection.h

@@ -36,6 +36,7 @@ private:
 
 		SSL_CTX *(*CTX_new)(const SSL_METHOD *method);
 		long (*CTX_ctrl)(SSL_CTX *ctx, int cmd, long larg, void *parg);
+		long (*CTX_set_options)(SSL_CTX *ctx, long options);
 		void (*CTX_set_verify)(SSL_CTX *ctx, int mode, void *verify_callback);
 		int (*CTX_set_default_verify_paths)(SSL_CTX *ctx);
 		void (*CTX_free)(SSL_CTX *ctx);
@@ -53,6 +54,7 @@ private:
 		const SSL_METHOD *(*SSLv23_method)();
 
 		int (*check_host)(X509 *cert, const char *name, size_t namelen, unsigned int flags, char **peername);
+		void (*X509_free)(X509* cert);
 	};
 	static SSLFuncs ssl;
 };