changeset 447:828d3dc89f2d

Socket: use own tests for SSL
author David Demelier <markand@malikania.fr>
date Wed, 28 Oct 2015 21:16:27 +0100
parents 8396fd66e57a
children 5310aa051568
files C++/modules/Socket/Sockets.cpp C++/modules/Socket/Sockets.h C++/tests/Socket/main.cpp C++/tests/Socket/test.crt C++/tests/Socket/test.key CMakeLists.txt
diffstat 6 files changed, 99 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/C++/modules/Socket/Sockets.cpp	Mon Oct 26 21:32:17 2015 +0100
+++ b/C++/modules/Socket/Sockets.cpp	Wed Oct 28 21:16:27 2015 +0100
@@ -637,6 +637,7 @@
 
 		SSL_library_init();
 		SSL_load_error_strings();
+		OpenSSL_add_all_algorithms();
 
 #if !defined(SOCKET_NO_AUTO_SSL_INIT)
 		atexit(finish);
--- a/C++/modules/Socket/Sockets.h	Mon Oct 26 21:32:17 2015 +0100
+++ b/C++/modules/Socket/Sockets.h	Wed Oct 28 21:16:27 2015 +0100
@@ -315,7 +315,8 @@
 		WouldBlockRead,		///!< The operation would block for reading
 		WouldBlockWrite,	///!< The operation would block for writing
 		Timeout,		///!< The action did timeout
-		System			///!< There is a system error
+		System,			///!< There is a system error
+		Other			///!< Other custom error
 	};
 
 private:
@@ -415,8 +416,8 @@
 	 * @param address which type of address
 	 * @param type the type instance
 	 */
-	explicit inline Socket(const Address &address = {}, Type type = Type{}) noexcept
-		: Socket{address.domain(), Type::type(), 0}
+	explicit inline Socket(const Address &address = {}, Type type = Type{})
+		: Socket{address.domain(), type.type(), 0}
 	{
 		/* Some implementation requires more things */
 		m_type = std::move(type);
@@ -1214,7 +1215,7 @@
 	 *
 	 * @return SOCK_STREAM
 	 */
-	static inline int type() noexcept
+	inline int type() noexcept
 	{
 		return SOCK_STREAM;
 	}
@@ -1350,7 +1351,7 @@
 	 *
 	 * @return SOCK_DGRAM
 	 */
-	static inline int type() noexcept
+	inline int type() noexcept
 	{
 		return SOCK_DGRAM;
 	}
@@ -1474,7 +1475,7 @@
 	Ssl m_ssl{nullptr, nullptr};
 
 	/* Parameters */
-	Method m_method;
+	Method m_method{Tlsv1};
 	std::string m_key;
 	std::string m_certificate;
 	bool m_verify{false};
@@ -1487,14 +1488,16 @@
 
 	inline std::string error(int error)
 	{
-		return ERR_reason_error_string(error);
+		auto msg = ERR_reason_error_string(error);
+
+		return msg == nullptr ? "" : msg;
 	}
 
 public:
 	/**
 	 * @copydoc Tcp::type
 	 */
-	static inline int type() noexcept
+	inline int type() noexcept
 	{
 		return SOCK_STREAM;
 	}
@@ -1542,12 +1545,14 @@
 		SSL_set_fd(m_ssl.get(), sc.handle());
 
 		/* Load certificates */
-		if (m_certificate.size() > 0)
+		if (m_certificate.size() > 0) {
 			SSL_CTX_use_certificate_file(m_context.get(), m_certificate.c_str(), SSL_FILETYPE_PEM);
-		if (m_key.size() > 0)
+		}
+		if (m_key.size() > 0) {
 			SSL_CTX_use_PrivateKey_file(m_context.get(), m_key.c_str(), SSL_FILETYPE_PEM);
+		}
 		if (m_verify && !SSL_CTX_check_private_key(m_context.get())) {
-			throw Error(Error::System, "accept", "certificate failure");
+			throw Error{Error::System, "(openssl)", "unable to verify key"};
 		}
 	}
 
@@ -1590,6 +1595,11 @@
 	template <typename Address>
 	Socket<Address, Tls> accept(Socket<Address, Tls> &sc, Address &address)
 	{
+		/* 0. We need to use this context */
+		if (!m_context) {
+			throw Error{Error::Other, "accept", "socket not prepared for accept"};
+		}
+
 		/* 1. Do standard accept */
 		sockaddr_storage ss;
 		socklen_t length = sizeof (sockaddr_storage);
@@ -1597,10 +1607,7 @@
 		address = Address{&ss, length};
 
 		/* 2. Create OpenSSL related stuff */
-		auto method = (m_method == Tlsv1) ? TLSv1_method() : SSLv3_method();
-		auto context = Context{SSL_CTX_new(method), SSL_CTX_free};
-		auto ssl = Ssl{SSL_new(context.get()), SSL_free};
-
+		auto ssl = Ssl{SSL_new(m_context.get()), SSL_free};
 		SSL_set_fd(ssl.get(), handle);
 
 		/* 3. Do the OpenSSL accept */
@@ -1618,7 +1625,7 @@
 			}
 		}
 
-		return Socket<Address, Tls>{handle, Tls{std::move(context), std::move(ssl)}};
+		return Socket<Address, Tls>{handle, Tls{{nullptr, nullptr}, std::move(ssl)}};
 	}
 
 	/**
--- a/C++/tests/Socket/main.cpp	Mon Oct 26 21:32:17 2015 +0100
+++ b/C++/tests/Socket/main.cpp	Wed Oct 28 21:16:27 2015 +0100
@@ -570,59 +570,58 @@
  * Socket SSL
  * -------------------------------------------------------- */
 
-class SslTest : public testing::Test {
+class TlsRecvTest : public testing::Test {
 protected:
-	SocketTls<Ipv4> client;
+	SocketTls<Ipv4> m_server;
+	SocketTls<Ipv4> m_client;
+
+	std::thread m_tserver;
+	std::thread m_tclient;
+
+public:
+	TlsRecvTest()
+		: m_server{Ipv4{}, Tls{Tls::Tlsv1, false, "Socket/test.key", "Socket/test.crt"}}
+		, m_client{Ipv4{}, Tls{Tls::Tlsv1, false, "", "Socket/test.crt"}}
+	{
+		m_server.set(SOL_SOCKET, SO_REUSEADDR, 1);
+		m_server.bind(Ipv4{"*", 16000});
+		m_server.listen();
+	}
+
+	~TlsRecvTest()
+	{
+		if (m_tserver.joinable())
+			m_tserver.join();
+		if (m_tclient.joinable())
+			m_tclient.join();
+	}
 };
 
-TEST_F(SslTest, connect)
-{
-	try {
-		client.connect(Ipv4{"google.fr", 443});
-	} catch (const Error &error) {
-		FAIL() << error.what();
-	}
-}
-
-TEST_F(SslTest, recv)
+TEST_F(TlsRecvTest, blockingSuccess)
 {
-	try {
-		client.connect(Ipv4{"google.fr", 443});
-		client.send("GET / HTTP/1.0\r\n\r\n");
+	m_tserver = std::thread([this] () {
+		try {
+			auto client = m_server.accept();
 
-		std::string msg = client.recv(512);
-		std::string content = msg.substr(0, 18);
-
-		ASSERT_EQ("HTTP/1.0 302 Found", content);
-	} catch (const Error &error) {
-		FAIL() << error.what();
-	}
-}
+			ASSERT_EQ("hello", client.recv(32));
+		} catch (const std::exception &ex) {
+			FAIL() << ex.what();
+		}
+	});
 
-#if 0
-
-/* --------------------------------------------------------
- * Operators
- * -------------------------------------------------------- */
-
-TEST(AddressOperator, less)
-{
-	Ipv4 ip1{"*", 8000};
-	Ipv4 ip2{"*", 8002};
+	std::this_thread::sleep_for(100ms);
 
-	ASSERT_LT(ip1, ip2);
+	m_tclient = std::thread([this] () {
+		try {
+			m_client.connect(Ipv4{"127.0.0.1", 16000});
+			m_client.send("hello");
+			m_client.close();
+		} catch (const std::exception &ex) {
+			FAIL() << ex.what();
+		}
+	});
 }
 
-TEST(AddressOperator, same)
-{
-	Ipv4 ip1{"*", 8000};
-	Ipv4 ip2{"*", 8000};
-
-	ASSERT_EQ(ip1, ip2);
-}
-
-#endif
-
 int main(int argc, char **argv)
 {
 	testing::InitGoogleTest(&argc, argv);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/tests/Socket/test.crt	Wed Oct 28 21:16:27 2015 +0100
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICITCCAYoCCQCGm4grkVCohjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJG
+UjEPMA0GA1UECAwGRnJhbmNlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0
+eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNTEwMjYyMDM0NThaFw0yNTEw
+MjMyMDM0NThaMFUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxITAfBgNV
+BAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDp13OqVyOWyv5QWD4xr+Duw6SZ
+gU7D5huzsAOcneSI6JUhf+7Ecu6BQ2JGkFn4srIVkMWGQuImETJ8JCpSQH7rk+xO
+L9fTTK+TwhP2hW/Rf/b2gWedhJAS+gilqt4JNT7v2wFv+aTtRt/lpTXVSdtpLa/m
+Pdy219f6MAPgODJ/7QIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAJSnn/IBn1ZblfzP
+rJO/lE1Jwpmx3B7+oR/e4fkZd6JR3s06umGYWr2H+TPl/5dj9x0gPokhoIL9zCGq
+SxCPnOeaxjBkw7yh3Ks6m3xKxmK4aMpAtBHtwmbfQyIcgz71/lfCzbJ3WcKpn1ig
+IZbByt5QSSPcFORRzJJa35eHBdfX
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/tests/Socket/test.key	Wed Oct 28 21:16:27 2015 +0100
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDp13OqVyOWyv5QWD4xr+Duw6SZgU7D5huzsAOcneSI6JUhf+7E
+cu6BQ2JGkFn4srIVkMWGQuImETJ8JCpSQH7rk+xOL9fTTK+TwhP2hW/Rf/b2gWed
+hJAS+gilqt4JNT7v2wFv+aTtRt/lpTXVSdtpLa/mPdy219f6MAPgODJ/7QIDAQAB
+AoGBANDt4ndQkgi56A1rOm50gVlzTg6lPPXFE/0xB5kYbcdxX0VmI7Q8KCMwTI9V
+jD2rk3e3OPSjr6FpfhzyxylkXMBz2BL5NRNPowCJbiMgZOUIzlcWPKo0tgf1bZJx
+YdB5U003ISGPPBjVOAjyizY7tJnaNvbpLQ0hbIAsvHPEAOnBAkEA9r3g8NQjPrvb
+oIr5SMIxM8HDJ1/q+MEBSFtRFzQpmur6P64Jsu96zCyencUYTxs0L/sottrj6dPC
+vjGCc6PjsQJBAPKdqK1knJv6Y95M2bnEwrymCFVdxCi7AxObStB+bg/+7mMCUqqX
+j2g71bfvhYakHV7CiaYrrORChwj6vTbimv0CQGpd2IZ5LOhyW2+N+YDgFg3Vzac/
+ti+eJEto8kAqgHUELvUctZmpmypBYe9pc91GQO0ePKL3IaE/ZIhRF4d6c0ECQH9A
+XiaD7PiKvjLs0A31u8ZCt4A+7BII9LYl73mntobBSbu4ji9Xyyn6qEAPa1ORZK49
+DwGPSuF2W2lESlYtSOkCQGrtczhx3IyJjk5e2Y1i/UddPKjviAysCSzcW6aVTNr9
+Y2L0sWmva2FKnkl9FDuEqxvmGr6OOkr5Ll7aWLzJri8=
+-----END RSA PRIVATE KEY-----
--- a/CMakeLists.txt	Mon Oct 26 21:32:17 2015 +0100
+++ b/CMakeLists.txt	Wed Oct 28 21:16:27 2015 +0100
@@ -316,6 +316,9 @@
 		SOURCES
 			${code_SOURCE_DIR}/C++/modules/Socket/Sockets.cpp
 			${code_SOURCE_DIR}/C++/modules/Socket/Sockets.h
+		RESOURCES
+			${code_SOURCE_DIR}/C++/tests/Socket/test.crt
+			${code_SOURCE_DIR}/C++/tests/Socket/test.key
 	)
 endif ()