From 68d7154cb033ed69d48998f40ec3ed5da6a1392a Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Mon, 4 Dec 2017 19:14:04 +0300 Subject: [PATCH 01/89] IGNITE-6810: Implemented SecureSocketClient --- .../odbc/ClientListenerProcessor.java | 47 ++- .../odbc-test/project/vs/odbc-test.vcxproj | 10 +- .../ignite/odbc/ssl/secure_socket_client.h | 135 ++++++++ .../cpp/odbc/project/vs/odbc.vcxproj | 22 +- .../cpp/odbc/project/vs/odbc.vcxproj.filters | 9 + .../cpp/odbc/src/ssl/secure_socket_client.cpp | 322 ++++++++++++++++++ 6 files changed, 531 insertions(+), 14 deletions(-) create mode 100644 modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h create mode 100644 modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java index ebd5156ff994f..81136e145c201 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java @@ -35,10 +35,12 @@ import org.apache.ignite.internal.util.nio.GridNioFilter; import org.apache.ignite.internal.util.nio.GridNioServer; import org.apache.ignite.internal.util.nio.GridNioSession; +import org.apache.ignite.internal.util.nio.ssl.GridNioSslFilter; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.spi.IgnitePortProtocol; import org.apache.ignite.thread.IgniteThreadPoolExecutor; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -110,6 +112,10 @@ public ClientListenerProcessor(GridKernalContext ctx) { if (portTo <= 0) // Handle int overflow. portTo = Integer.MAX_VALUE; + GridNioFilter[] filters = makeFilters(); + + int maxOpenCursors = cliConnCfg.getMaxOpenCursorsPerConnection(); + for (int port = cliConnCfg.getPort(); port <= portTo && port <= 65535; port++) { try { GridNioFilter[] filters = new GridNioFilter[] { @@ -174,6 +180,38 @@ public ClientListenerProcessor(GridKernalContext ctx) { } } + @NotNull private GridNioFilter[] makeFilters() { + GridNioFilter asyncNotifyFilter = new GridNioAsyncNotifyFilter(ctx.igniteInstanceName(), execSvc, log) { + @Override public void onSessionOpened(GridNioSession ses) + throws IgniteCheckedException { + proceedSessionOpened(ses); + } + }; + + GridNioFilter bufferParser = new GridNioCodecFilter(new ClientListenerBufferedParser(), log, false); + + if (isSslEnabled()) { + GridNioSslFilter sslFilter = new GridNioSslFilter(ctx.config().getSslContextFactory().create(), + true, ByteOrder.nativeOrder(), log); + + sslFilter.directMode(false); + + sslFilter.wantClientAuth(true); + sslFilter.needClientAuth(true); + + return new GridNioFilter[] { + asyncNotifyFilter, + bufferParser, + sslFilter + }; + } else { + return new GridNioFilter[] { + asyncNotifyFilter, + bufferParser + }; + } + } + /** {@inheritDoc} */ @Override public void onKernalStop(boolean cancel) { if (srv != null) { @@ -197,7 +235,7 @@ public ClientListenerProcessor(GridKernalContext ctx) { /** * Prepare connector configuration. * - * @param cfg Ignote configuration. + * @param cfg Ignite configuration. * @return Connector configuration. * @throws IgniteCheckedException If failed. */ @@ -318,4 +356,11 @@ private HostAndPortRange parseOdbcEndpoint(OdbcConfiguration odbcCfg) throws Ign private static boolean isNotDefault(ClientConnectorConfiguration cliConnCfg) { return cliConnCfg != null && !(cliConnCfg instanceof ClientConnectorConfigurationEx); } + + /** + * @return {@code True} if ssl enabled. + */ + private boolean isSslEnabled() { + return ctx.config().getSslContextFactory() != null; + } } diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj index d5653069a1bef..2f6dfcde048a4 100644 --- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj +++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj @@ -91,7 +91,7 @@ Level3 Disabled true - $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\jni\include;$(ProjectDir)\..\..\..\jni\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\..\core\include;$(ProjectDir)\..\..\..\odbc\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win;$(ProjectDir)\..\..\src;$(BOOST_HOME) + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\jni\include;$(ProjectDir)\..\..\..\jni\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\..\core\include;$(ProjectDir)\..\..\..\odbc\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win;$(ProjectDir)\..\..\src;$(BOOST_HOME);$(OPENSSL_HOME)\include _CRT_SECURE_NO_WARNINGS;BOOST_DATE_TIME_NO_LIB;BOOST_REGEX_NO_LIB;IGNITE_IMPL;IGNITE_FRIEND;IGNITE_TESTS_32;%(PreprocessorDefinitions) Async @@ -105,7 +105,7 @@ Level3 Disabled true - $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\jni\include;$(ProjectDir)\..\..\..\jni\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\..\core\include;$(ProjectDir)\..\..\..\odbc\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win;$(ProjectDir)\..\..\src;$(BOOST_HOME) + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\jni\include;$(ProjectDir)\..\..\..\jni\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\..\core\include;$(ProjectDir)\..\..\..\odbc\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win;$(ProjectDir)\..\..\src;$(BOOST_HOME);$(OPENSSL_HOME)\include _CRT_SECURE_NO_WARNINGS;BOOST_DATE_TIME_NO_LIB;BOOST_REGEX_NO_LIB;IGNITE_IMPL;IGNITE_FRIEND;%(PreprocessorDefinitions) Async @@ -122,7 +122,7 @@ true true true - $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\jni\include;$(ProjectDir)\..\..\..\jni\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\..\core\include;$(ProjectDir)\..\..\..\odbc\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win;$(ProjectDir)\..\..\src;$(BOOST_HOME) + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\jni\include;$(ProjectDir)\..\..\..\jni\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\..\core\include;$(ProjectDir)\..\..\..\odbc\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win;$(ProjectDir)\..\..\src;$(BOOST_HOME);$(OPENSSL_HOME)\include _CRT_SECURE_NO_WARNINGS;BOOST_DATE_TIME_NO_LIB;BOOST_REGEX_NO_LIB;IGNITE_IMPL;IGNITE_FRIEND;IGNITE_TESTS_32;%(PreprocessorDefinitions) Async @@ -140,7 +140,7 @@ true true true - $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\jni\include;$(ProjectDir)\..\..\..\jni\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\..\core\include;$(ProjectDir)\..\..\..\odbc\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win;$(ProjectDir)\..\..\src;$(BOOST_HOME) + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\jni\include;$(ProjectDir)\..\..\..\jni\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\..\core\include;$(ProjectDir)\..\..\..\odbc\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win;$(ProjectDir)\..\..\src;$(BOOST_HOME);$(OPENSSL_HOME)\include _CRT_SECURE_NO_WARNINGS;BOOST_DATE_TIME_NO_LIB;BOOST_REGEX_NO_LIB;IGNITE_IMPL;IGNITE_FRIEND;%(PreprocessorDefinitions) Async @@ -226,4 +226,4 @@ - \ No newline at end of file + diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h new file mode 100644 index 0000000000000..d399ec165b67d --- /dev/null +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_SSL_SECURE_SOCKET_CLIENT +#define _IGNITE_ODBC_SSL_SECURE_SOCKET_CLIENT + +#include +#include + +#include "ignite/odbc/diagnostic/diagnosable.h" + +namespace ignite +{ + namespace odbc + { + namespace ssl + { + /** + * Secure socket client. + */ + class SecureSocketClient + { + public: + /** + * Constructor. + * + * @param certPath Certificate file path. + * @param keyPath Private key file path. + * @param caPath Certificate authority file path. + * @param caDirPath Path to directory containing certificate authority files. + */ + SecureSocketClient(const std::string& certPath, const std::string& keyPath, const std::string& caPath, + const std::string& caDirPath); + + /** + * Destructor. + */ + ~SecureSocketClient(); + + /** + * Establish connection with the host. + * + * @param hostname Host name or address. + * @param port TCP port. + * @param diag Diagnostics collector to use for error-reporting. + * @return @c true on success and @c false on fail. + */ + bool Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag); + + /** + * Close the connection. + */ + void Close(); + + /** + * Send data using connection. + * @param data Data to send. + * @param size Number of bytes to send. + * @param timeout Timeout. + * @return Number of bytes that have been sent on success, + * WaitResult::TIMEOUT on timeout and -errno on failure. + */ + int Send(const int8_t* data, size_t size, int32_t timeout); + + /** + * Receive data from established connection. + * + * @param buffer Pointer to data buffer. + * @param size Size of the buffer in bytes. + * @param timeout Timeout. + * @return Number of bytes that have been sent on success, + * WaitResult::TIMEOUT on timeout and -errno on failure. + */ + int Receive(int8_t* buffer, size_t size, int32_t timeout); + + /** + * Check if the socket is blocking or not. + * @return @c true if the socket is blocking and false otherwise. + */ + bool IsBlocking() + { + return true; + } + + private: + /** + * Make new context instance. + * + * @param certPath Certificate file path. + * @param keyPath Private key file path. + * @param caPath Certificate authority file path. + * @param caDirPath Path to directory containing certificate authority files. + * @param diag Diagnostics collector to use for error-reporting. + * @return New context instance on success and null-opinter on fail. + */ + static void* MakeContext(const std::string& certPath, const std::string& keyPath, + const std::string& caPath, const std::string& caDirPath, diagnostic::Diagnosable& diag); + + /** Certificate file path. */ + std::string certPath; + + /** Private key file path. */ + std::string keyPath; + + /** Certificate authority file path. */ + std::string caPath; + + /** Path to directory containing certificate authority files. */ + std::string caDirPath; + + /** SSL context. */ + void* context; + + /** OpenSSL I/O stream abstraction */ + void* sslBio; + }; + } + } +} + +#endif //_IGNITE_ODBC_SSL_SECURE_SOCKET_CLIENT \ No newline at end of file diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj index c5783ff7dc780..0f54dd2198747 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj @@ -93,13 +93,14 @@ Level3 Disabled false - $(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win\include;$(ProjectDir)\..\..\src + $(OPENSSL_HOME)\include;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win\include;$(ProjectDir)\..\..\src _CRT_SECURE_NO_WARNINGS;IGNITE_IMPL;IGNITE_FRIEND;TARGET_MODULE_FULL_NAME="$(TargetFileName)";_DEBUG;ODBC_DEBUG;ODBC_LOG_PATH="D:\\odbc.log";%(PreprocessorDefinitions) true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;ssleay32MDd.lib;libeay32MDd.lib;%(AdditionalDependencies) + $(OPENSSL_HOME)\lib\VC @@ -107,13 +108,14 @@ Level3 Disabled false - $(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win\include;$(ProjectDir)\..\..\src + $(OPENSSL_HOME)\include;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win\include;$(ProjectDir)\..\..\src _CRT_SECURE_NO_WARNINGS;IGNITE_IMPL;IGNITE_FRIEND;TARGET_MODULE_FULL_NAME="$(TargetFileName)";_DEBUG;%(PreprocessorDefinitions) true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;ssleay32MDd.lib;libeay32MDd.lib;%(AdditionalDependencies) + $(OPENSSL_HOME)\lib\VC @@ -122,7 +124,7 @@ MaxSpeed true true - $(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win\include;$(ProjectDir)\..\..\src + $(OPENSSL_HOME)\include;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win\include;$(ProjectDir)\..\..\src _CRT_SECURE_NO_WARNINGS;IGNITE_IMPL;IGNITE_FRIEND;TARGET_MODULE_FULL_NAME="$(TargetFileName)";%(PreprocessorDefinitions) false @@ -131,7 +133,8 @@ true true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;ssleay32MD.lib;libeay32MD.lib;%(AdditionalDependencies) + $(OPENSSL_HOME)\lib\VC @@ -140,7 +143,7 @@ MaxSpeed true true - $(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win\include;$(ProjectDir)\..\..\src + $(OPENSSL_HOME)\include;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win\include;$(ProjectDir)\..\..\src _CRT_SECURE_NO_WARNINGS;IGNITE_IMPL;IGNITE_FRIEND;TARGET_MODULE_FULL_NAME="$(TargetFileName)";%(PreprocessorDefinitions) false @@ -149,7 +152,8 @@ true true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;ssleay32MD.lib;libeay32MD.lib;%(AdditionalDependencies) + $(OPENSSL_HOME)\lib\VC @@ -188,6 +192,7 @@ + @@ -231,6 +236,7 @@ + diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters index 8934625963e4b..fcc960fe439a7 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters @@ -29,6 +29,9 @@ {ff144e89-0a10-42c3-97dd-d22bfdbc7abb} + + {857734a3-6b29-412a-b75e-7fcc9d3fef8c} + @@ -148,6 +151,9 @@ Code + + Code\ssl + @@ -284,5 +290,8 @@ Code + + Code\ssl + \ No newline at end of file diff --git a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp new file mode 100644 index 0000000000000..8d3d3d995127d --- /dev/null +++ b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp @@ -0,0 +1,322 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +#include "ignite/common/concurrent.h" +#include "ignite/odbc/log.h" +#include "ignite/odbc/ssl/secure_socket_client.h" + +// Declaring constant used by OpenSSL for readability. +enum { SSL_OPERATION_SUCCESS = 1 }; + +namespace ignite +{ + namespace odbc + { + namespace ssl + { + SecureSocketClient::SecureSocketClient(const std::string& certPath, const std::string& keyPath, + const std::string& caPath, const std::string& caDirPath): + certPath(certPath), + keyPath(keyPath), + caPath(caPath), + caDirPath(caDirPath), + context(0), + sslBio(0) + { + // No-op. + } + + SecureSocketClient::~SecureSocketClient() + { + Close(); + + if (context) + SSL_CTX_free(reinterpret_cast(context)); + } + + bool SecureSocketClient::Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag) + { + if (!context) + { + context = MakeContext(certPath, keyPath, caPath, caDirPath, diag); + + if (!context) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, + "Can not create SSL context. Aborting connect."); + + return false; + } + } + + BIO* bio = BIO_new_ssl_connect(reinterpret_cast(context)); + if (!bio) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not create SSL connection."); + + return false; + } + + std::stringstream stream; + stream << hostname << ":" << port; + + std::string address = stream.str(); + + long res = BIO_set_conn_hostname(bio, address.c_str()); + if (res != SSL_OPERATION_SUCCESS) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set SSL connection hostname."); + + BIO_free_all(bio); + + return false; + } + + SSL* ssl = 0; + BIO_get_ssl(bio, &ssl); + if (!ssl) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not get SSL instance from BIO."); + + BIO_free_all(bio); + + return false; + } + + res = SSL_set_tlsext_host_name(ssl, hostname); + if (res != SSL_OPERATION_SUCCESS) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set host name for secure connection"); + + BIO_free_all(bio); + + return false; + } + + res = BIO_do_connect(bio); + if (res != SSL_OPERATION_SUCCESS) + { + diag.AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, + "Failed to establish secure connection with the host."); + + BIO_free_all(bio); + + return false; + } + + res = BIO_do_handshake(bio); + if (res != SSL_OPERATION_SUCCESS) + { + diag.AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "SSL handshake failed."); + + BIO_free_all(bio); + + return false; + } + + // Verify a server certificate was presented during the negotiation + X509* cert = SSL_get_peer_certificate(ssl); + if (cert) + X509_free(cert); + else + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Remote host did not provide certificate."); + + BIO_free_all(bio); + + return false; + } + + // Verify the result of chain verification + // Verification performed according to RFC 4158 + res = SSL_get_verify_result(ssl); + if (X509_V_OK != res) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Certificate chain verification failed."); + + BIO_free_all(bio); + + return false; + } + + sslBio = reinterpret_cast(bio); + + return true; + } + + void SecureSocketClient::Close() + { + if (sslBio) + { + BIO_free_all(reinterpret_cast(sslBio)); + + sslBio = 0; + } + } + + int SecureSocketClient::Send(const int8_t* data, size_t size, int32_t timeout) + { + if (!sslBio) + { + LOG_MSG("Trying to send data using closed connection"); + + return -1; + } + + (void)timeout; + BIO* sslBio0 = reinterpret_cast(sslBio); + + int res = 0; + + do + { + res = BIO_write(sslBio0, data, static_cast(size)); + } + while (BIO_should_retry(sslBio0)); + + return res; + } + + int SecureSocketClient::Receive(int8_t* buffer, size_t size, int32_t timeout) + { + if (!sslBio) + { + LOG_MSG("Trying to receive data using closed connection"); + + return -1; + } + + (void)timeout; + BIO* sslBio0 = reinterpret_cast(sslBio); + + int res = 0; + + do + { + res = BIO_read(sslBio0, buffer, static_cast(size)); + } + while (BIO_should_retry(sslBio0)); + + return res; + } + + void* SecureSocketClient::MakeContext(const std::string& certPath, const std::string& keyPath, + const std::string& caPath, const std::string& caDirPath, diagnostic::Diagnosable& diag) + { + static bool sslLibInited = false; + static common::concurrent::CriticalSection sslCs; + + if (!sslLibInited) + { + common::concurrent::CsLockGuard lock(sslCs); + + if (!sslLibInited) + { + LOG_MSG("Initializing SSL library"); + + (void)SSL_library_init(); + + SSL_load_error_strings(); + + OPENSSL_config(0); + + sslLibInited = true; + } + } + + const SSL_METHOD* method = SSLv23_method(); + if (!method) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not create new SSL method."); + + return 0; + } + + SSL_CTX* ctx = SSL_CTX_new(method); + if (!ctx) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not create new SSL context."); + + return 0; + } + + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0); + + SSL_CTX_set_verify_depth(ctx, 8); + + const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION; + SSL_CTX_set_options(ctx, flags); + + const char* cCaPath = caPath.empty() ? 0 : caPath.c_str(); + const char* cCaDirPath = caDirPath.empty() ? 0 : caDirPath.c_str(); + + long res = SSL_CTX_load_verify_locations(ctx, cCaPath, cCaDirPath); + if (res != SSL_OPERATION_SUCCESS) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, + "Can not set Certificate Authority path for secure connection."); + + SSL_CTX_free(ctx); + + return 0; + } + + res = SSL_CTX_use_certificate_chain_file(ctx, certPath.c_str()); + if (res != SSL_OPERATION_SUCCESS) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, + "Can not set client certificate file for secure connection."); + + SSL_CTX_free(ctx); + + return 0; + } + + res = SSL_CTX_use_RSAPrivateKey_file(ctx, keyPath.c_str(), SSL_FILETYPE_PEM); + if (res != SSL_OPERATION_SUCCESS) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, + "Can not set private key file for secure connection."); + + SSL_CTX_free(ctx); + + return 0; + } + + const char* const PREFERRED_CIPHERS = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4"; + res = SSL_CTX_set_cipher_list(ctx, PREFERRED_CIPHERS); + if (res != SSL_OPERATION_SUCCESS) + { + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, + "Can not set ciphers list for secure connection."); + + SSL_CTX_free(ctx); + + return false; + } + + return ctx; + } + } + } +} From 5cebaacb49a30dfba8ffc1f7f566a9fdd365a37a Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Thu, 21 Dec 2017 19:44:29 +0300 Subject: [PATCH 02/89] IGNITE-6810: Implemented SSL connection. --- modules/platforms/cpp/odbc-test/Makefile.am | 1 + .../cpp/odbc-test/config/queries-default.xml | 10 +- ...-test-noodbc-32.xml => queries-ssl-32.xml} | 15 +- ...eries-test-default.xml => queries-ssl.xml} | 23 +- .../cpp/odbc-test/config/queries-test-32.xml | 3 +- .../odbc-test/config/queries-test-noodbc.xml | 35 -- .../cpp/odbc-test/config/queries-test.xml | 3 +- .../platforms/cpp/odbc-test/config/ssl/ca.pem | 24 + .../cpp/odbc-test/config/ssl/client_full.pem | 84 +++ .../cpp/odbc-test/config/ssl/server.jks | Bin 0 -> 4256 bytes .../cpp/odbc-test/config/ssl/trust.jks | Bin 0 -> 1089 bytes .../cpp/odbc-test/include/test_utils.h | 5 + .../odbc-test/project/vs/odbc-test.vcxproj | 6 +- .../project/vs/odbc-test.vcxproj.filters | 14 +- .../cpp/odbc-test/src/queries_ssl_test.cpp | 537 ++++++++++++++++++ .../cpp/odbc-test/src/queries_test.cpp | 8 +- .../cpp/odbc-test/src/test_utils.cpp | 9 + .../ignite/odbc/config/configuration.h | 110 +++- .../cpp/odbc/include/ignite/odbc/connection.h | 9 +- .../odbc/include/ignite/odbc/socket_client.h | 109 ++++ .../ignite/odbc/ssl/secure_socket_client.h | 28 +- .../{socket_client.h => tcp_socket_client.h} | 44 +- .../odbc/system/ui/dsn_configuration_window.h | 2 +- ...ocket_client.cpp => tcp_socket_client.cpp} | 45 +- .../cpp/odbc/project/vs/odbc.vcxproj | 5 +- .../cpp/odbc/project/vs/odbc.vcxproj.filters | 15 +- .../cpp/odbc/src/config/configuration.cpp | 8 + modules/platforms/cpp/odbc/src/connection.cpp | 47 +- .../cpp/odbc/src/ssl/secure_socket_client.cpp | 15 +- 29 files changed, 1040 insertions(+), 174 deletions(-) rename modules/platforms/cpp/odbc-test/config/{queries-test-noodbc-32.xml => queries-ssl-32.xml} (81%) rename modules/platforms/cpp/odbc-test/config/{queries-test-default.xml => queries-ssl.xml} (57%) delete mode 100644 modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml create mode 100644 modules/platforms/cpp/odbc-test/config/ssl/ca.pem create mode 100644 modules/platforms/cpp/odbc-test/config/ssl/client_full.pem create mode 100644 modules/platforms/cpp/odbc-test/config/ssl/server.jks create mode 100644 modules/platforms/cpp/odbc-test/config/ssl/trust.jks create mode 100644 modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp create mode 100644 modules/platforms/cpp/odbc/include/ignite/odbc/socket_client.h rename modules/platforms/cpp/odbc/include/ignite/odbc/system/{socket_client.h => tcp_socket_client.h} (78%) rename modules/platforms/cpp/odbc/os/win/src/system/{socket_client.cpp => tcp_socket_client.cpp} (90%) diff --git a/modules/platforms/cpp/odbc-test/Makefile.am b/modules/platforms/cpp/odbc-test/Makefile.am index b025e2ce83bd9..3e6467c315426 100644 --- a/modules/platforms/cpp/odbc-test/Makefile.am +++ b/modules/platforms/cpp/odbc-test/Makefile.am @@ -65,6 +65,7 @@ ignite_odbc_tests_SOURCES = \ src/meta_queries_test.cpp \ src/utility_test.cpp \ src/queries_test.cpp \ + src/queries_ssl_test.cpp \ src/test_utils.cpp \ src/sql_test_suite_fixture.cpp \ src/sql_string_functions_test.cpp \ diff --git a/modules/platforms/cpp/odbc-test/config/queries-default.xml b/modules/platforms/cpp/odbc-test/config/queries-default.xml index 56040f1333e7e..dbe3a10fec8fc 100644 --- a/modules/platforms/cpp/odbc-test/config/queries-default.xml +++ b/modules/platforms/cpp/odbc-test/config/queries-default.xml @@ -26,10 +26,18 @@ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> - + + + + + + + + + diff --git a/modules/platforms/cpp/odbc-test/config/queries-test-noodbc-32.xml b/modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml similarity index 81% rename from modules/platforms/cpp/odbc-test/config/queries-test-noodbc-32.xml rename to modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml index b98d668068965..209f1330027e2 100644 --- a/modules/platforms/cpp/odbc-test/config/queries-test-noodbc-32.xml +++ b/modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml @@ -24,12 +24,17 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - - - - - + + + + + + + + + + diff --git a/modules/platforms/cpp/odbc-test/config/queries-test-default.xml b/modules/platforms/cpp/odbc-test/config/queries-ssl.xml similarity index 57% rename from modules/platforms/cpp/odbc-test/config/queries-test-default.xml rename to modules/platforms/cpp/odbc-test/config/queries-ssl.xml index 22524d2ab8f1b..24bb6d4ad725a 100644 --- a/modules/platforms/cpp/odbc-test/config/queries-test-default.xml +++ b/modules/platforms/cpp/odbc-test/config/queries-ssl.xml @@ -24,15 +24,24 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - - - - - - - + + + + + + + + + + + + + + diff --git a/modules/platforms/cpp/odbc-test/config/queries-test-32.xml b/modules/platforms/cpp/odbc-test/config/queries-test-32.xml index f7d9ff442b23c..a2bac82554034 100644 --- a/modules/platforms/cpp/odbc-test/config/queries-test-32.xml +++ b/modules/platforms/cpp/odbc-test/config/queries-test-32.xml @@ -24,8 +24,7 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - - + diff --git a/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml b/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml deleted file mode 100644 index 29fee2324a42c..0000000000000 --- a/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/modules/platforms/cpp/odbc-test/config/queries-test.xml b/modules/platforms/cpp/odbc-test/config/queries-test.xml index 882eb1e3ed91d..46e89aad7ab88 100644 --- a/modules/platforms/cpp/odbc-test/config/queries-test.xml +++ b/modules/platforms/cpp/odbc-test/config/queries-test.xml @@ -24,8 +24,7 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - - + diff --git a/modules/platforms/cpp/odbc-test/config/ssl/ca.pem b/modules/platforms/cpp/odbc-test/config/ssl/ca.pem new file mode 100644 index 0000000000000..10bf7af8488aa --- /dev/null +++ b/modules/platforms/cpp/odbc-test/config/ssl/ca.pem @@ -0,0 +1,24 @@ +-----BEGIN TRUSTED CERTIFICATE----- +MIID8DCCAtgCCQCo436SJYMUcjANBgkqhkiG9w0BAQsFADCBuTELMAkGA1UEBhMC +UlUxGTAXBgNVBAgMEFNhaW50LVBldGVyc2J1cmcxGTAXBgNVBAcMEFNhaW50LVBl +dGVyc2J1cmcxIzAhBgNVBAoMGkFwYWNoZSBTcGZ0d2FyZSBGb3VuZGF0aW9uMRYw +FAYDVQQLDA1BcGFjaGUgSWduaXRlMRQwEgYDVQQDDAtJZ29yIFNhcGVnbzEhMB8G +CSqGSIb3DQEJARYSaXNhcGVnb0BhcGFjaGUub3JnMB4XDTE3MTEyODE3MzExNloX +DTI3MTEyNjE3MzExNlowgbkxCzAJBgNVBAYTAlJVMRkwFwYDVQQIDBBTYWludC1Q +ZXRlcnNidXJnMRkwFwYDVQQHDBBTYWludC1QZXRlcnNidXJnMSMwIQYDVQQKDBpB +cGFjaGUgU3BmdHdhcmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIElnbml0 +ZTEUMBIGA1UEAwwLSWdvciBTYXBlZ28xITAfBgkqhkiG9w0BCQEWEmlzYXBlZ29A +YXBhY2hlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALMcDfYN +Ixc0o4bLX/3T5MQE4pk+Bv9Dfr7vBYNPJKSr/GKQJN+5QA/tr1uxTsMSBoE19y5e +N1vXFtlWMJ2um3ojNbGeqSGuzuDKk0htbgmisyctvEFTqtiYI7D+f7dalEM2KnLj +f0jIV6NJVilkFKmgsfuZpbZFRkqJDEx74ZqNAYQQ0qJ+zGv7diEak8FwWa4n6xe7 +VHt7VZIbKIkMgTljJLULbExxCRvTHpSeXPP5IMr5x1RGuSavCu4GDl+HmrXac7ot +L7sqIFHL9JGXTWO16accOQnQIdLQmhj6qh2Em8z41udabzUyIQmOSP6mmwnJEIdz +jNyWLA8XtYZOgcsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAT6jBgiQjCdQ02cxe +H9YDFw5+cfb6YQJcjJW94BspySftUGfJ6GQm/Ybcc/ZqW7lhEILKfifdpHPfWby/ +sqhwA0nsLt5hNCjMsDcBq5onggy9ymZYak0VVWT/XkHiK27sQLK6BXo6wqRDwT4h +F9CgUWNcLGDVAaVpjLaR8itZZgx98q9MAZ680oERUZWTsj17oO0RK/x9TBWUm7OR +f9g9VNRz3mwT5dTtuqrSq4NlF1nVD7BN3lRddZUW4KnU6et2mXtIKMnUT/+XyIW3 +g+f6LuhR+Q6yhmVdfBVa8opJQIR5trb0eKnQf4pEQcvT/EX+vWkThNJkdZ4qm0mY +eIl/jQ== +-----END TRUSTED CERTIFICATE----- diff --git a/modules/platforms/cpp/odbc-test/config/ssl/client_full.pem b/modules/platforms/cpp/odbc-test/config/ssl/client_full.pem new file mode 100644 index 0000000000000..9a54f43286474 --- /dev/null +++ b/modules/platforms/cpp/odbc-test/config/ssl/client_full.pem @@ -0,0 +1,84 @@ +Bag Attributes + friendlyName: client + localKeyID: 54 69 6D 65 20 31 35 31 31 39 36 35 31 38 31 32 33 37 +Key Attributes: +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAmm+QSwc1yvJWjTG8L4rAiHOg38rM1AtOFInzYizT/B6wzsmx +3Ql4fb+aHm3dPt5kjhQLZToq1QCUsS9B/47ZFd0waDHGgLiSNKn1WdX7Q+4GgplY +wznc5j+GM65F2aI3tRnn2Jorfss9OElzU5vLh0aD3e5cEpgYSAGEFl1O9t8b6dHq +YMERtdTCNQVeBUQPiaNNTwOXixtdsPvGKNgMZtVpvV+AMlgVmV+VTYUqQhlX+ro4 +9E4n00+iDIk/REwAiQi/Kb08kovLY9sF2pqC24zU5swyIopEijoa6Z2WYekq1fyL +P9NknOiMOmWaKqu5ThVbP6c2xGeCdAGbNi+74wIDAQABAoIBAH2oALPLbg1vGNVR +flkAgJ+F1YPBst9lQ2aayBk9eE5PenUGz12V8x/94hyYL8iTkyW3UX5P0cH18wYn ++X9Cb4fGrThaJ7VceDm5gBRUc1lWNp3Uv9A5KG9/iGZMijEGOGV2appm9rT4ERvX +R6rjvLqYuXq+EtReRINyGFNKIJHkuwM7Ycy9Rk7O6SrcjjUEj1Z5gEUP0B7Z0jVI +bsOGqghRflRVqnFT61+koFWBn8taemWmXNa835beN2lRIWezNqfd+9kL72UUt6sl +VmkqBydDQ+IXCOgLZDYUu3N0bfrKuYmilsRg9XuKTUv+jvwtfGUWTO1+6eSrFD+B +3j0YeKECgYEA0XrsUOGVl2O4JWBOa36TRHMz0tRBrZUJMK7apEEiGx7jc7q22PI+ +RyPrf9TR7JOLN1AdXoHrJsKCadnTr6g/CAOZSV1V+lUeQkcDmG4OkY814fESxlBA +jHg7FnJdjzs6VfA1Cv0eT2KxU0ld461AN77WBgG21E2Gw3AGSddbflcCgYEAvLtV +fhy3+WOUutFsLv1uTz/y+Emih6pmgwsuRG7WgQD9s2KZS+ejh5TQAq4sD+9MSkKk +XnvdbwGQkHppdtVP5wMeSfY6tG/9YmY7X5rTG9PTsrzAzNJwrnE9hFv7Xnj3SMnC +0D9eBnA8XWq49vsair7gxBWwhGYR/5WDicGn31UCgYEAgJb6lbPEhkgadCcoPGhY +sn4dY+AT6SBBofbUFFw/OXK+oP4O3CHoBPeRysizjIwNu4icXrVVyldAgwXKIlwf +RSYgZJ689oxlpL2/AUUeAFBu/SFlKwN8fD4Z12+g6xmqd7KafQJgJs8olz3EOszR +TOcCrnFC8BQfE72ivpVKfsUCgYBBZw3maR9cHiUxZFeAJTTv47JYVnQrXWKu8NX0 +wxA0nlpMqtOC2V/zIR/Afgko8H1YkqWRVI1U5Y7qcnFPy/YnkQ4TBXAsjU6apeDX +bbjQwORw4TZTBG4mFXoC/zkp8POI1tpa/kqgIo7YtJ4qgLQe9qy/ZuDH0PNVxcNS +nriFDQKBgF70vrmuYEobLpBD/whcOqMDjn3Zj+xx3TSRmjmjc4w5eRR4+9iquKs5 +lhY1NsAcq3SYA8P5rNDV39FpiPErFqDTjsf0AaOXbpaqo2jOANmvyT15CKW8325R +yEcxaA8sSbBaz8QRkydzpoKT+4WFJnYzCZtG+kUU+Pgu6uahAs4N +-----END RSA PRIVATE KEY----- +Bag Attributes + friendlyName: client + localKeyID: 54 69 6D 65 20 31 35 31 31 39 36 35 31 38 31 32 33 37 +subject=/CN=ODBC +issuer=/C=RU/ST=Saint-Petersburg/L=Saint-Petersburg/O=Apache Spftware Foundation/OU=Apache Ignite/CN=Igor Sapego/emailAddress=isapego@apache.org +-----BEGIN CERTIFICATE----- +MIIDPTCCAiUCAQIwDQYJKoZIhvcNAQEFBQAwgbkxCzAJBgNVBAYTAlJVMRkwFwYD +VQQIDBBTYWludC1QZXRlcnNidXJnMRkwFwYDVQQHDBBTYWludC1QZXRlcnNidXJn +MSMwIQYDVQQKDBpBcGFjaGUgU3BmdHdhcmUgRm91bmRhdGlvbjEWMBQGA1UECwwN +QXBhY2hlIElnbml0ZTEUMBIGA1UEAwwLSWdvciBTYXBlZ28xITAfBgkqhkiG9w0B +CQEWEmlzYXBlZ29AYXBhY2hlLm9yZzAeFw0xNzExMjkxNDAwNDhaFw0yNzExMjcx +NDAwNDhaMA8xDTALBgNVBAMTBE9EQkMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCab5BLBzXK8laNMbwvisCIc6DfyszUC04UifNiLNP8HrDOybHdCXh9 +v5oebd0+3mSOFAtlOirVAJSxL0H/jtkV3TBoMcaAuJI0qfVZ1ftD7gaCmVjDOdzm +P4YzrkXZoje1GefYmit+yz04SXNTm8uHRoPd7lwSmBhIAYQWXU723xvp0epgwRG1 +1MI1BV4FRA+Jo01PA5eLG12w+8Yo2Axm1Wm9X4AyWBWZX5VNhSpCGVf6ujj0TifT +T6IMiT9ETACJCL8pvTySi8tj2wXamoLbjNTmzDIiikSKOhrpnZZh6SrV/Is/02Sc +6Iw6ZZoqq7lOFVs/pzbEZ4J0AZs2L7vjAgMBAAEwDQYJKoZIhvcNAQEFBQADggEB +AH8heMPYkC/abqg9xtC5WFgYxnXWA6jwjKVuCSnrEhZGQem9HFvFXmZckJr25RXc +9i8WIehN5oeJgmPioK6j8ylwCJxo9lRii4NFBVpS6IjmqMdYHa+4K1R9Y7XdDEBL +nVzlL8Hjlv4ESjg+1LW4nSt8f4oBdAvfds4uNTtAwABqmfqXWaOKYdh9OJs84QJa +pA4PQvxqUz6c4tyPi/VucVAV8uKxR7P+uoy6qKKZK6NkY3RuXwHXxJ5lDr6ET1mb +St0BbAt4KSktPonCu0qoHWqcynw79KcoPhmQWpzbijVs+y/SlHmZje+H4R7j7xt7 +aw7dWxUa096x4vsi1WvlMOY= +-----END CERTIFICATE----- +Bag Attributes + friendlyName: 1.2.840.113549.1.9.1=#16126973617065676f406170616368652e6f7267,CN=Igor Sapego,OU=Apache Ignite,O=Apache Spftware Foundation,L=Saint-Petersburg,ST=Saint-Petersburg,C=RU +subject=/C=RU/ST=Saint-Petersburg/L=Saint-Petersburg/O=Apache Spftware Foundation/OU=Apache Ignite/CN=Igor Sapego/emailAddress=isapego@apache.org +issuer=/C=RU/ST=Saint-Petersburg/L=Saint-Petersburg/O=Apache Spftware Foundation/OU=Apache Ignite/CN=Igor Sapego/emailAddress=isapego@apache.org +-----BEGIN CERTIFICATE----- +MIID8DCCAtgCCQCo436SJYMUcjANBgkqhkiG9w0BAQsFADCBuTELMAkGA1UEBhMC +UlUxGTAXBgNVBAgMEFNhaW50LVBldGVyc2J1cmcxGTAXBgNVBAcMEFNhaW50LVBl +dGVyc2J1cmcxIzAhBgNVBAoMGkFwYWNoZSBTcGZ0d2FyZSBGb3VuZGF0aW9uMRYw +FAYDVQQLDA1BcGFjaGUgSWduaXRlMRQwEgYDVQQDDAtJZ29yIFNhcGVnbzEhMB8G +CSqGSIb3DQEJARYSaXNhcGVnb0BhcGFjaGUub3JnMB4XDTE3MTEyODE3MzExNloX +DTI3MTEyNjE3MzExNlowgbkxCzAJBgNVBAYTAlJVMRkwFwYDVQQIDBBTYWludC1Q +ZXRlcnNidXJnMRkwFwYDVQQHDBBTYWludC1QZXRlcnNidXJnMSMwIQYDVQQKDBpB +cGFjaGUgU3BmdHdhcmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIElnbml0 +ZTEUMBIGA1UEAwwLSWdvciBTYXBlZ28xITAfBgkqhkiG9w0BCQEWEmlzYXBlZ29A +YXBhY2hlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALMcDfYN +Ixc0o4bLX/3T5MQE4pk+Bv9Dfr7vBYNPJKSr/GKQJN+5QA/tr1uxTsMSBoE19y5e +N1vXFtlWMJ2um3ojNbGeqSGuzuDKk0htbgmisyctvEFTqtiYI7D+f7dalEM2KnLj +f0jIV6NJVilkFKmgsfuZpbZFRkqJDEx74ZqNAYQQ0qJ+zGv7diEak8FwWa4n6xe7 +VHt7VZIbKIkMgTljJLULbExxCRvTHpSeXPP5IMr5x1RGuSavCu4GDl+HmrXac7ot +L7sqIFHL9JGXTWO16accOQnQIdLQmhj6qh2Em8z41udabzUyIQmOSP6mmwnJEIdz +jNyWLA8XtYZOgcsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAT6jBgiQjCdQ02cxe +H9YDFw5+cfb6YQJcjJW94BspySftUGfJ6GQm/Ybcc/ZqW7lhEILKfifdpHPfWby/ +sqhwA0nsLt5hNCjMsDcBq5onggy9ymZYak0VVWT/XkHiK27sQLK6BXo6wqRDwT4h +F9CgUWNcLGDVAaVpjLaR8itZZgx98q9MAZ680oERUZWTsj17oO0RK/x9TBWUm7OR +f9g9VNRz3mwT5dTtuqrSq4NlF1nVD7BN3lRddZUW4KnU6et2mXtIKMnUT/+XyIW3 +g+f6LuhR+Q6yhmVdfBVa8opJQIR5trb0eKnQf4pEQcvT/EX+vWkThNJkdZ4qm0mY +eIl/jQ== +-----END CERTIFICATE----- diff --git a/modules/platforms/cpp/odbc-test/config/ssl/server.jks b/modules/platforms/cpp/odbc-test/config/ssl/server.jks new file mode 100644 index 0000000000000000000000000000000000000000..2632662c175974e8c31fdaf377fd4b9393854e83 GIT binary patch literal 4256 zcmeH~cU03^7RU2TNF*3~wbF|~LINZd1wjOXrARL_KxmPcgoKWO1jItI&_NI>Dlj0$ z&=CTPG#vzW03m>=bQqA1z@j_jnLWE_|KHvDYU~?}n0-6>R;01Dv`(}90u5=V=ETg8Sr ztWCzdUUV0+Aba=+;VJGSdZYlN8{XfOM8pW7`MxWN5#ir)8d?ee4)amjRzKmT}L^pT=-RB&>EdxmK7?Ft;i`7EqgWAm89=W zgy&UBBOA3XiU-og%XcGd?2~nHvXqHP{SKRa1M3rRd_}nx+Zlz`x_XA!5k_I-nF&A) zS6^O4kN0+<=;0&=*{)1_RRI|g7jFEsBSO>00DoF(0(%SM+g9!K4Q=$#Nlt02YVca-$4X9 zBK+32@L-4dl%}yGCpx9)&l5VQ+@yA5hpB5`7wYg_w5|y0kpk+dU1M|QBQnHb4#mVP z%k-410415yG(=OEhpm?}zm?mbqxJ_m;+$4xJv3CkwLpiVDJs~TYv$@8@B9`h^o*~* zy)0+vfe2rIYy{*q_C;}0-uO!-C z(C#f~xiQo7r+^fJv7$HAvw<05`ZAqwO!v|{uGBa1cjh! zEPH4U7@HgnU;$*o+`xWHvCvp%d&XPLqU4Zp8diS-+3Mr+FnSZyIIAlhnWQnhn(2HR z!?YFB>iuPoE`2HQ-TUs!;#Z?h#!EG@O2gMAI&GWpzWHTmqy*C>!kH$?xdN)Ir+)GE zon-P7Q&tydAGF_&==F$O2lwl{5O*`~ND9r`d*1VeafW)DYA(A5l`+ak#);sm8;ZOe z8rN~V%=k1@1Oz*BSDGiW{KAB`^a$2BQ8?X1)j<-bx)>w;G>!O7hTPg%&+o_Ke@RBO zY6S>yG)_Sr_BZq7rgwOK;vQmr9u@QY{1y^U0Z zU1$9ZrAS0nT>tXzwu(i1d!w=I@dX>V`Cf{*V;t&3?44_-9)oVTyxXZoA}2S{t7oKx z&vDz-1sPAt9Wr_?Ln!WIyn3>-1mNVGJCYB)=SO~iaEfv-;pPh@uJcu~r`AdF$U{wW zVUo>@D{V`jzAw|0_$|EK+cN3-wgu@rb@l2y;eD0~5nA09_VIZwo3yTrXK@Yj(h9ho z;&@F+Q+vi9{nL!#Gqrl&_YGjXc|Avm%i73(^$kn>>k6FQ2jTU1r9Z#a?x5kwHoD`6&A(Yoa&8J+COZ-yJbW@Xp?+GHQKWQ@c-6ARh35!E-F^Plo-*{; z;ktLuwy3e_b7|?w32%+pCc}y`O81nQINefbuf>&*Pfs&H2SN@ZLZyO83WeUjmah(% zWs7=tM#g64juMp-N{-h}&-&nqIIUiIks?4qg$# zNmft4n0jhEE(-5V91NWe2)c{t$}0Wjqd{gGD$4nc-3@3M=(iz&rgqYEJg|;yq$%hb z?%L3@Rr{7|xWMqn-fqjPRd6vl-UjyN7~4XGa)sUW;ToP%w+|tzoHJGP2_d1*FG4aD z9{Yr}``xOl?GQm7@#-CKbxDUW^wxOnqJzzws=j2ivi3R6ByOM6jDB>8MZP%`|3pl? z{g)bH*Oe9gTKtyo=Af&gsk@adf>_#3q9zZ&+Qoi)%5EI%lyZ3rj|k_@HHCBt5#uQX z*6Ujyj}`*I)-tHdd-t=NJ8DNZT?xsx2gveeIQ@}ck;aY4xW6IGnq$_#W;oJ_O6S!i zUvL?{6)!HE)~VjoSfc$j7?j(&(jfNp&q_8F?9g*?l^a2Lu1~kwE`P zs7MW?gjQ0*{y{}5ze}{h58&ecGjQ#b#eXJ_rod7u4%R$aN9`F`N6*You^qh7%-LSE z3q^5vco&_92hW);o6C5dkn^#2mb!Ahj=?f1r<~{E{dR)8mQ*WjYCki>gK|tP$ySu8 z2IoKnjath4p$*vjq1?JHryB~-@#}>r%qQ8r@&(%yjPoTd06*1SmB+2mnq=$fGFN&b zd{$uKjE}9g3$K{bw!tcF_cVM$#CT*`40qI+i~cTg@S62%!KM3&**7Z?8uNjjHwYKw zUw$wiZm%{hY4>VR9TLLzNo#h>GfUH%ajCP9n!8&p7Rc^bD^dP2IwwnaMh05d+Q3Q6 zCrygu5`Hw{ukodPn7S(fgK2o<__zAIRRZCOmK70LhUxfko%eLBXqo%0UBGOpW70Jf!_-)NI z3w`93t|w_h$FE!v&rLR*=1^{XT~MfHkT7a_PFHSifs$Knjh%gF_{++HNtZ>wt*(r$ zsmn=N=`Q1$Y2G1QLh;j&^fha03Cl}6H#XWNIM@nd3TO%(oe+!TQ)@CmESuq&;toAC zDmI&!c=5UPz58m)JV)EaS?-i@;~wnjnZ2b&n@9VFh2xR1=kw~j!bYXcifY&=JXBBB z-2Njf_EnpP$&wXQX^4NDIn;i-|Ms>~HS@uE>$|@ij=vg?zZ#DJ+lIpf^ESbNu+xpu P>lk0NnWR0ZSn~WGo?zNW literal 0 HcmV?d00001 diff --git a/modules/platforms/cpp/odbc-test/config/ssl/trust.jks b/modules/platforms/cpp/odbc-test/config/ssl/trust.jks new file mode 100644 index 0000000000000000000000000000000000000000..a0f3bcfc30787fbe400e3c794f039dbbdd3161e3 GIT binary patch literal 1089 zcmezO_TO6u1_mY|W(3nB$*DypnQ58Hi6yCtr6n2pMVTd)K*_C*_cCF*o2va zLJcJi#6cVm9)aM*%)AoafYg%IqT-~|qI8%PI~FNr14WQ7E*>ezg2d#ERE6Mzw370~ zqErR9{L;LX#FEVXJVP-95s)Ho9$u&-&-A>^l2k(x10j$&GY_|CdVY~YaAHAfdcL8e zfjr!$oQz^ZnZ;mnheWUidih1^26E!OhUSKbMiz$V#)gJwQR2KtAg&pdJEZ;A#HfTE zRgA0*%uS5^3NNJ01V`@{=Phk7nAj{dcb0_nx)cUuDVa zKS>i*?(cNqf4e?&`tmHQ6IKk8{yx zb=^IV!K-e}P~PybetXmuXEUv$$Mqg3!WVmnX{Ly*T(I%?%%$60-Ml(^e5xPL>Sb&Z zxU{J5O!n_GMXAXL3nJI4zZTyeQe7Q7Nm`?mr_nN5Wh-}%Pa&uDWw|NyVm|*=IQ8>* zh}%xJ^<3}R_~P4VZM{{zOILrlmO|j^FB7NxCU1SYT*i{~g5sqMvm}14l5LrN=Et?? zQTe7uiky8O|CY_>JSos#+;eA|4!`);HowNxOw5c7jL0DbOw7O#Vr1}Naj;26ne&Rt z%`I%R8N@R-ZnY#CZwB||mw*l!VU!|2W4-+IeprHtk}qvO2WH`JkPm z_=N?5$uT+!R~eUP_H3K@Njox)r}oo&AI5omE;R}UPMy5TwtB%^LG3@aKB7}*Z=P6x z!#3nf@x2`3r&r$YT6Jl4bECjTSZQGZMl^5!}TpUkd{^R;@Z>Dg|rIgZnTC+W8RCLz& aPIr=dbfVr#$@Hq`rNH^hlc!vtsRsa3Nt9gx literal 0 HcmV?d00001 diff --git a/modules/platforms/cpp/odbc-test/include/test_utils.h b/modules/platforms/cpp/odbc-test/include/test_utils.h index e65e187bc82ae..786c2be873057 100644 --- a/modules/platforms/cpp/odbc-test/include/test_utils.h +++ b/modules/platforms/cpp/odbc-test/include/test_utils.h @@ -67,6 +67,11 @@ namespace ignite_test */ std::string GetOdbcErrorMessage(SQLSMALLINT handleType, SQLHANDLE handle); + /** + * @return Test config directory path. + */ + std::string GetTestConfigDir(); + /** * Initialize configuration for a node. * diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj index 2f6dfcde048a4..7cf1675a133de 100644 --- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj +++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj @@ -172,6 +172,7 @@ + @@ -217,9 +218,8 @@ - - - + + diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters index 58cf0459c9256..417fac916439c 100644 --- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters +++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters @@ -139,6 +139,9 @@ Code + + Code + @@ -167,17 +170,14 @@ Configs - - Configs - - + Configs - + Configs - + Configs - \ No newline at end of file + diff --git a/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp new file mode 100644 index 0000000000000..4c5dcf3a14730 --- /dev/null +++ b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp @@ -0,0 +1,537 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef _WIN32 +# include +#endif + +#include +#include + +#include +#include +#include + +#ifndef _MSC_VER +# define BOOST_TEST_DYN_LINK +#endif + +#include +#include + +#include "ignite/ignite.h" +#include "ignite/common/fixed_size_array.h" +#include "ignite/ignition.h" +#include "ignite/impl/binary/binary_utils.h" +#include "ignite/binary/binary_object.h" + +#include "test_type.h" +#include "complex_type.h" +#include "test_utils.h" + +using namespace ignite; +using namespace ignite::cache; +using namespace ignite::cache::query; +using namespace ignite::common; +using namespace ignite_test; +using namespace ignite::binary; +using namespace ignite::impl::binary; +using namespace ignite::impl::interop; + +using namespace boost::unit_test; + +using ignite::impl::binary::BinaryUtils; + +/** + * Test setup fixture. + */ +struct SslQueriesTestSuiteFixture +{ + /** + * Establish connection to node. + * + * @param connectStr Connection string. + */ + void Connect(const std::string& connectStr) + { + // Allocate an environment handle + SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + + BOOST_REQUIRE(env != NULL); + + // We want ODBC 3 support + SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast(SQL_OV_ODBC3), 0); + + // Allocate a connection handle + SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); + + BOOST_REQUIRE(dbc != NULL); + + // Connect string + std::vector connectStr0; + + connectStr0.reserve(connectStr.size() + 1); + std::copy(connectStr.begin(), connectStr.end(), std::back_inserter(connectStr0)); + + SQLCHAR outstr[ODBC_BUFFER_SIZE]; + SQLSMALLINT outstrlen; + + // Connecting to ODBC server. + SQLRETURN ret = SQLDriverConnect(dbc, NULL, &connectStr0[0], static_cast(connectStr0.size()), + outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE); + + if (!SQL_SUCCEEDED(ret)) + { + Ignition::Stop(grid.GetName(), true); + + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc)); + } + + // Allocate a statement handle + SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); + + BOOST_REQUIRE(stmt != NULL); + } + + void Disconnect() + { + // Releasing statement handle. + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + + // Disconneting from the server. + SQLDisconnect(dbc); + + // Releasing allocated handles. + SQLFreeHandle(SQL_HANDLE_DBC, dbc); + SQLFreeHandle(SQL_HANDLE_ENV, env); + } + + static Ignite StartAdditionalNode(const char* name) + { +#ifdef IGNITE_TESTS_32 + return StartNode("queries-ssl-32.xml", name); +#else + return StartNode("queries-ssl.xml", name); +#endif + } + + /** + * Constructor. + */ + SslQueriesTestSuiteFixture() : + cache1(0), + cache2(0), + env(NULL), + dbc(NULL), + stmt(NULL) + { +#ifdef IGNITE_TESTS_32 + grid = StartNode("queries-ssl-32.xml", "NodeMain"); +#else + grid = StartNode("queries-ssl.xml", "NodeMain"); +#endif + + cache1 = grid.GetCache("cache"); + cache2 = grid.GetCache("cache2"); + } + + /** + * Destructor. + */ + ~SslQueriesTestSuiteFixture() + { + Disconnect(); + + Ignition::StopAll(true); + } + + void CheckParamsNum(const std::string& req, SQLSMALLINT expectedParamsNum) + { + std::vector req0(req.begin(), req.end()); + + SQLRETURN ret = SQLPrepare(stmt, &req0[0], static_cast(req0.size())); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + SQLSMALLINT paramsNum = -1; + + ret = SQLNumParams(stmt, ¶msNum); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECK_EQUAL(paramsNum, expectedParamsNum); + } + + int CountRows(SQLHSTMT stmt) + { + int res = 0; + + SQLRETURN ret = SQL_SUCCESS; + + while (ret == SQL_SUCCESS) + { + ret = SQLFetch(stmt); + + if (ret == SQL_NO_DATA) + break; + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ++res; + } + + return res; + } + + static std::string getTestString(int64_t ind) + { + std::stringstream builder; + + builder << "String#" << ind; + + return builder.str(); + } + + /** + * Insert requested number of TestType values with all defaults except + * for the strFields, which are generated using getTestString(). + * + * @param recordsNum Number of records to insert. + * @param merge Set to true to use merge instead. + */ + void InsertTestStrings(int recordsNum, bool merge = false) + { + SQLCHAR insertReq[] = "INSERT INTO TestType(_key, strField) VALUES(?, ?)"; + SQLCHAR mergeReq[] = "MERGE INTO TestType(_key, strField) VALUES(?, ?)"; + + SQLRETURN ret; + + ret = SQLPrepare(stmt, merge ? mergeReq : insertReq, SQL_NTS); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + int64_t key = 0; + char strField[1024] = { 0 }; + SQLLEN strFieldLen = 0; + + // Binding parameters. + ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(strField), + sizeof(strField), &strField, sizeof(strField), &strFieldLen); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + // Inserting values. + for (SQLSMALLINT i = 0; i < recordsNum; ++i) + { + key = i + 1; + std::string val = getTestString(i); + + strncpy(strField, val.c_str(), sizeof(strField)); + strFieldLen = SQL_NTS; + + ret = SQLExecute(stmt); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + SQLLEN affected = 0; + ret = SQLRowCount(stmt, &affected); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECK_EQUAL(affected, 1); + + ret = SQLMoreResults(stmt); + + if (ret != SQL_NO_DATA) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + } + + // Resetting parameters. + ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + } + + /** + * Insert requested number of TestType values in a batch. + * + * @param from Index to start from. + * @param to Index to stop. + * @param expectedToAffect Expected number of affected records. + * @param merge Set to true to use merge instead of insert. + * @return Records inserted. + */ + int InsertTestBatch(int from, int to, int expectedToAffect, bool merge = false) + { + SQLCHAR insertReq[] = "INSERT " + "INTO TestType(_key, i8Field, i16Field, i32Field, strField, floatField, doubleField, boolField, dateField, " + "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + SQLCHAR mergeReq[] = "MERGE " + "INTO TestType(_key, i8Field, i16Field, i32Field, strField, floatField, doubleField, boolField, dateField, " + "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + SQLRETURN ret; + + int recordsNum = to - from; + + ret = SQLPrepare(stmt, merge ? mergeReq : insertReq, SQL_NTS); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + FixedSizeArray keys(recordsNum); + FixedSizeArray i8Fields(recordsNum); + FixedSizeArray i16Fields(recordsNum); + FixedSizeArray i32Fields(recordsNum); + FixedSizeArray strFields(recordsNum * 1024); + FixedSizeArray floatFields(recordsNum); + FixedSizeArray doubleFields(recordsNum); + FixedSizeArray boolFields(recordsNum); + FixedSizeArray dateFields(recordsNum); + FixedSizeArray timeFields(recordsNum); + FixedSizeArray timestampFields(recordsNum); + FixedSizeArray i8ArrayFields(recordsNum * 42); + + FixedSizeArray strFieldsLen(recordsNum); + FixedSizeArray i8ArrayFieldsLen(recordsNum); + + BOOST_CHECKPOINT("Filling param data"); + + for (int i = 0; i < recordsNum; ++i) + { + int seed = from + i; + + keys[i] = seed; + i8Fields[i] = seed * 8; + i16Fields[i] = seed * 16; + i32Fields[i] = seed * 32; + + std::string val = getTestString(seed); + strncpy(strFields.GetData() + 1024 * i, val.c_str(), 1023); + strFieldsLen[i] = val.size(); + + floatFields[i] = seed * 0.5f; + doubleFields[i] = seed * 0.25f; + boolFields[i] = seed % 2 == 0; + + dateFields[i].year = 2017 + seed / 365; + dateFields[i].month = ((seed / 28) % 12) + 1; + dateFields[i].day = (seed % 28) + 1; + + timeFields[i].hour = (seed / 3600) % 24; + timeFields[i].minute = (seed / 60) % 60; + timeFields[i].second = seed % 60; + + timestampFields[i].year = dateFields[i].year; + timestampFields[i].month = dateFields[i].month; + timestampFields[i].day = dateFields[i].day; + timestampFields[i].hour = timeFields[i].hour; + timestampFields[i].minute = timeFields[i].minute; + timestampFields[i].second = timeFields[i].second; + timestampFields[i].fraction = std::abs(seed * 914873) % 1000000000; + + for (int j = 0; j < 42; ++j) + i8ArrayFields[i * 42 + j] = seed * 42 + j; + i8ArrayFieldsLen[i] = 42; + } + + SQLULEN setsProcessed = 0; + + BOOST_CHECKPOINT("Setting processed pointer"); + ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &setsProcessed, SQL_IS_POINTER); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding keys"); + ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, keys.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding i8Fields"); + ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_STINYINT, SQL_TINYINT, 0, 0, i8Fields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding i16Fields"); + ret = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_SMALLINT, 0, 0, i16Fields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding i32Fields"); + ret = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, i32Fields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding strFields"); + ret = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 1024, 0, strFields.GetData(), 1024, strFieldsLen.GetData()); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding floatFields"); + ret = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, 0, 0, floatFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding doubleFields"); + ret = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, doubleFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding boolFields"); + ret = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, 0, 0, boolFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding dateFields"); + ret = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_DATE, SQL_DATE, 0, 0, dateFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding timeFields"); + ret = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_TIME, SQL_TIME, 0, 0, timeFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding timestampFields"); + ret = SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 0, 0, timestampFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding i8ArrayFields"); + ret = SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_BINARY, 42, 0, i8ArrayFields.GetData(), 42, i8ArrayFieldsLen.GetData()); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Setting paramset size"); + ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast(recordsNum), 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Executing query"); + ret = SQLExecute(stmt); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + SQLLEN totallyAffected = 0; + + do + { + SQLLEN affected = 0; + ret = SQLRowCount(stmt, &affected); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + totallyAffected += affected; + + BOOST_CHECKPOINT("Getting next result set"); + + ret = SQLMoreResults(stmt); + + if (ret != SQL_SUCCESS && ret != SQL_NO_DATA) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + } while (ret != SQL_NO_DATA); + + BOOST_CHECK_EQUAL(totallyAffected, expectedToAffect); + + BOOST_CHECKPOINT("Resetting parameters."); + ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Setting paramset size"); + ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast(1), 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + return static_cast(setsProcessed); + } + + /** Node started during the test. */ + Ignite grid; + + /** Frist cache instance. */ + Cache cache1; + + /** Second cache instance. */ + Cache cache2; + + /** ODBC Environment. */ + SQLHENV env; + + /** ODBC Connect. */ + SQLHDBC dbc; + + /** ODBC Statement. */ + SQLHSTMT stmt; +}; + +BOOST_FIXTURE_TEST_SUITE(SslQueriesTestSuite, SslQueriesTestSuiteFixture) + +BOOST_AUTO_TEST_CASE(TestConnectionSsl) +{ + std::string cfgDirPath = GetTestConfigDir(); + + std::stringstream connectString; + + connectString << + "DRIVER={Apache Ignite};" + "ADDRESS=127.0.0.1:11110;" + "SCHEMA=cache;" + "SSL_MODE=require;" + "SSL_KEY_FILE=" << cfgDirPath << "/ssl/client_full.pem;" + "SSL_CERT_FILE=" << cfgDirPath << "/ssl/client_full.pem;" + "SSL_CA_FILE=" << cfgDirPath << "/ssl/ca.pem;"; + + Connect(connectString.str()); + + InsertTestStrings(10, false); + InsertTestBatch(11, 20, 9); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/platforms/cpp/odbc-test/src/queries_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_test.cpp index bf9876abcb644..6eee9a6f3d63b 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp @@ -1340,7 +1340,7 @@ void CheckObjectData(int8_t* data, int32_t len, T const& value) BinaryObject obj(BinaryObjectImpl::FromMemory(mem, 0, 0)); T actual = obj.Deserialize(); - + BOOST_CHECK_EQUAL(value, actual); } @@ -1374,7 +1374,7 @@ BOOST_AUTO_TEST_CASE(TestKeyVal) int8_t column6[ODBC_BUFFER_SIZE] = { 0 }; //strField char column7[ODBC_BUFFER_SIZE] = { 0 }; - + SQLLEN column1Len = sizeof(column1); SQLLEN column2Len = sizeof(column2); SQLLEN column3Len = sizeof(column3); @@ -1438,7 +1438,7 @@ BOOST_AUTO_TEST_CASE(TestKeyVal) CheckObjectData(column4, static_cast(column4Len), obj); BOOST_CHECK_EQUAL(column5, obj.i32Field); - + CheckObjectData(column6, static_cast(column6Len), obj.objField); BOOST_CHECK_EQUAL(column7, obj.strField); @@ -1534,7 +1534,7 @@ BOOST_AUTO_TEST_CASE(TestExecuteAfterCursorClose) BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); ret = SQLFetch(stmt); - + if (!SQL_SUCCEEDED(ret)) BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); diff --git a/modules/platforms/cpp/odbc-test/src/test_utils.cpp b/modules/platforms/cpp/odbc-test/src/test_utils.cpp index eb0866030e0bd..6d9ed6b6484a8 100644 --- a/modules/platforms/cpp/odbc-test/src/test_utils.cpp +++ b/modules/platforms/cpp/odbc-test/src/test_utils.cpp @@ -17,6 +17,8 @@ #include +#include + #include "test_utils.h" namespace ignite_test @@ -54,6 +56,11 @@ namespace ignite_test return res; } + std::string GetTestConfigDir() + { + return ignite::common::GetEnv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH"); + } + void InitConfig(ignite::IgniteConfiguration& cfg, const char* cfgFile) { using namespace ignite; @@ -70,6 +77,8 @@ namespace ignite_test cfg.jvmOpts.push_back("-DIGNITE_CONSOLE_APPENDER=false"); cfg.jvmOpts.push_back("-DIGNITE_UPDATE_NOTIFIER=false"); cfg.jvmOpts.push_back("-Duser.language=en"); + // Un-comment to debug SSL + //cfg.jvmOpts.push_back("-Djavax.net.debug=ssl"); cfg.igniteHome = jni::ResolveIgniteHome(); cfg.jvmClassPath = jni::CreateIgniteHomeClasspath(cfg.igniteHome, true); diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h b/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h index 419a65e72a09b..89018f574608e 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h @@ -85,6 +85,18 @@ namespace ignite /** Connection attribute keyword for skipReducerOnUpdate attribute. */ static const std::string skipReducerOnUpdate; + + /** Connection attribute keyword for sslMode attribute. */ + static const std::string sslMode; + + /** Connection attribute keyword for sslKeyFile attribute. */ + static const std::string sslKeyFile; + + /** Connection attribute keyword for sslCertFile attribute. */ + static const std::string sslCertFile; + + /** Connection attribute keyword for sslCaFile attribute. */ + static const std::string sslCaFile; }; /** Default values for configuration. */ @@ -105,6 +117,18 @@ namespace ignite /** Default value for server attribute. */ static const std::string server; + /** Default value for sslMode attribute. */ + static const std::string sslMode; + + /** Default value for sslKeyFile attribute. */ + static const std::string sslKeyFile; + + /** Default value for sslCertFile attribute. */ + static const std::string sslCertFile; + + /** Default value for sslCaFile attribute. */ + static const std::string sslCaFile; + /** Default value for protocol version. */ static const ProtocolVersion& protocolVersion; @@ -183,8 +207,8 @@ namespace ignite /** * Fill configuration data using config attributes string. * - * @param str Pointer to list of zero-terminated strings. - * Terminated by two zero bytes. + * @param attributes Pointer to list of zero-terminated strings. + * Terminated by two zero bytes. */ void FillFromConfigAttributes(const char* attributes); @@ -289,6 +313,86 @@ namespace ignite */ void SetAddress(const std::string& address); + /** + * Get SSL mode. + * + * @return SSL mode. + */ + const std::string& GetSslMode() const + { + return GetStringValue(Key::sslMode, DefaultValue::sslMode); + } + + /** + * Set SSL mode. + * + * @param sslMode SSL mode. + */ + void SetSslMode(const std::string& sslMode) + { + arguments[Key::sslMode] = sslMode; + } + + /** + * Get SSL key file path. + * + * @return SSL key file path. + */ + const std::string& GetSslKeyFile() const + { + return GetStringValue(Key::sslKeyFile, DefaultValue::sslKeyFile); + } + + /** + * Set SSL key file path. + * + * @param sslKeyFile SSL key file path. + */ + void SetSslKeyFile(const std::string& sslKeyFile) + { + arguments[Key::sslKeyFile] = sslKeyFile; + } + + /** + * Get SSL certificate file path. + * + * @return SSL certificate file path. + */ + const std::string& GetSslCertFile() const + { + return GetStringValue(Key::sslCertFile, DefaultValue::sslCertFile); + } + + /** + * Set SSL certificate file path. + * + * @param sslCertFile SSL certificate file path. + */ + void SetSslCertFile(const std::string& sslCertFile) + { + arguments[Key::sslCertFile] = sslCertFile; + } + + /** + * Get SSL certificate authority file path. + * + * @return SSL certificate authority file path. + */ + const std::string& GetSslCaFile() const + { + return GetStringValue(Key::sslCaFile, DefaultValue::sslCaFile); + } + + /** + * Set SSL certificate authority file path. + * + * @param sslCaFile SSL certificate authority file path. + */ + void SetSslCaFile(const std::string& sslCaFile) + { + arguments[Key::sslCaFile] = sslCaFile; + } + /** * Check distributed joins flag. * @@ -495,7 +599,7 @@ namespace ignite * * @param str String to parse. * @param len String length. - * @param params Parsing result. + * @param args Parsing result. */ static void ParseAttributeList(const char* str, size_t len, char delimeter, ArgumentMap& args); diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h index 1577ee7fe7f79..025b855881f57 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h @@ -23,7 +23,7 @@ #include #include "ignite/odbc/parser.h" -#include "ignite/odbc/system/socket_client.h" +#include "ignite/odbc/socket_client.h" #include "ignite/odbc/config/connection_info.h" #include "ignite/odbc/config/configuration.h" #include "ignite/odbc/diagnostic/diagnosable_adapter.h" @@ -367,11 +367,8 @@ namespace ignite */ Connection(); - /** Socket. */ - tcp::SocketClient socket; - - /** State flag. */ - bool connected; + /** Client Socket. */ + std::auto_ptr socket; /** Connection timeout in seconds. */ int32_t timeout; diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/socket_client.h new file mode 100644 index 0000000000000..349f0475805dc --- /dev/null +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/socket_client.h @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_SOCKET_CLIENT +#define _IGNITE_ODBC_SOCKET_CLIENT + +#include + +#include "ignite/odbc/diagnostic/diagnosable.h" + +namespace ignite +{ + namespace odbc + { + /** + * Socket client implementation. + */ + class SocketClient + { + public: + /** Connection establishment timeout in seconds. */ + enum { CONNECT_TIMEOUT = 5 }; + + /** + * Non-negative timeout operation result. + */ + struct WaitResult + { + enum T + { + /** Timeout. */ + TIMEOUT = 0, + + /** Success. */ + SUCCESS = 1 + }; + }; + + /** + * Destructor. + */ + virtual ~SocketClient() + { + // No-op. + } + + /** + * Establish connection with remote service. + * + * @param hostname Remote host name. + * @param port Service port. + * @param diag Diagnostics collector. + * @return True on success. + */ + virtual bool Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag) = 0; + + /** + * Close established connection. + * + * @return True on success. + */ + virtual void Close() = 0; + + /** + * Send data by established connection. + * + * @param data Pointer to data to be sent. + * @param size Size of the data in bytes. + * @param timeout Timeout. + * @return Number of bytes that have been sent on success, + * WaitResult::TIMEOUT on timeout and -errno on failure. + */ + virtual int Send(const int8_t* data, size_t size, int32_t timeout) = 0; + + /** + * Receive data from established connection. + * + * @param buffer Pointer to data buffer. + * @param size Size of the buffer in bytes. + * @param timeout Timeout. + * @return Number of bytes that have been sent on success, + * WaitResult::TIMEOUT on timeout and -errno on failure. + */ + virtual int Receive(int8_t* buffer, size_t size, int32_t timeout) = 0; + + /** + * Check if the socket is blocking or not. + * @return @c true if the socket is blocking and false otherwise. + */ + virtual bool IsBlocking() const = 0; + }; + } +} + +#endif //_IGNITE_ODBC_SYSTEM_SOCKET_CLIENT \ No newline at end of file diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h index d399ec165b67d..5375bb11daddf 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h @@ -22,6 +22,7 @@ #include #include "ignite/odbc/diagnostic/diagnosable.h" +#include "ignite/odbc/socket_client.h" namespace ignite { @@ -32,7 +33,7 @@ namespace ignite /** * Secure socket client. */ - class SecureSocketClient + class SecureSocketClient : public SocketClient { public: /** @@ -41,15 +42,13 @@ namespace ignite * @param certPath Certificate file path. * @param keyPath Private key file path. * @param caPath Certificate authority file path. - * @param caDirPath Path to directory containing certificate authority files. */ - SecureSocketClient(const std::string& certPath, const std::string& keyPath, const std::string& caPath, - const std::string& caDirPath); + SecureSocketClient(const std::string& certPath, const std::string& keyPath, const std::string& caPath); /** * Destructor. */ - ~SecureSocketClient(); + virtual ~SecureSocketClient(); /** * Establish connection with the host. @@ -59,12 +58,12 @@ namespace ignite * @param diag Diagnostics collector to use for error-reporting. * @return @c true on success and @c false on fail. */ - bool Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag); + virtual bool Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag); /** * Close the connection. */ - void Close(); + virtual void Close(); /** * Send data using connection. @@ -74,7 +73,7 @@ namespace ignite * @return Number of bytes that have been sent on success, * WaitResult::TIMEOUT on timeout and -errno on failure. */ - int Send(const int8_t* data, size_t size, int32_t timeout); + virtual int Send(const int8_t* data, size_t size, int32_t timeout); /** * Receive data from established connection. @@ -85,16 +84,13 @@ namespace ignite * @return Number of bytes that have been sent on success, * WaitResult::TIMEOUT on timeout and -errno on failure. */ - int Receive(int8_t* buffer, size_t size, int32_t timeout); + virtual int Receive(int8_t* buffer, size_t size, int32_t timeout); /** * Check if the socket is blocking or not. * @return @c true if the socket is blocking and false otherwise. */ - bool IsBlocking() - { - return true; - } + virtual bool IsBlocking() const; private: /** @@ -103,12 +99,11 @@ namespace ignite * @param certPath Certificate file path. * @param keyPath Private key file path. * @param caPath Certificate authority file path. - * @param caDirPath Path to directory containing certificate authority files. * @param diag Diagnostics collector to use for error-reporting. * @return New context instance on success and null-opinter on fail. */ static void* MakeContext(const std::string& certPath, const std::string& keyPath, - const std::string& caPath, const std::string& caDirPath, diagnostic::Diagnosable& diag); + const std::string& caPath, diagnostic::Diagnosable& diag); /** Certificate file path. */ std::string certPath; @@ -119,9 +114,6 @@ namespace ignite /** Certificate authority file path. */ std::string caPath; - /** Path to directory containing certificate authority files. */ - std::string caDirPath; - /** SSL context. */ void* context; diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h similarity index 78% rename from modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h rename to modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h index 2a3cfa3c7528f..ac3db7be849d4 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h @@ -15,24 +15,25 @@ * limitations under the License. */ -#ifndef _IGNITE_ODBC_SYSTEM_SOCKET_CLIENT -#define _IGNITE_ODBC_SYSTEM_SOCKET_CLIENT +#ifndef _IGNITE_ODBC_SYSTEM_TCP_SOCKET_CLIENT +#define _IGNITE_ODBC_SYSTEM_TCP_SOCKET_CLIENT #include #include "ignite/common/common.h" #include "ignite/odbc/diagnostic/diagnosable.h" +#include "ignite/odbc/socket_client.h" namespace ignite { namespace odbc { - namespace tcp + namespace system { /** * Socket client implementation. */ - class SocketClient + class TcpSocketClient : public SocketClient { public: /** Buffers size */ @@ -44,31 +45,15 @@ namespace ignite /** The time in seconds between individual keepalive probes. */ enum { KEEP_ALIVE_PROBES_PERIOD = 1 }; - /** Connection establishment timeout in seconds. */ - enum { CONNECT_TIMEOUT = 5 }; - - /** - * Non-negative timeout operation result. - */ - struct WaitResult - { - enum T - { - TIMEOUT = 0, - - SUCCESS = 1 - }; - }; - /** * Constructor. */ - SocketClient(); + TcpSocketClient(); /** * Destructor. */ - ~SocketClient(); + virtual ~TcpSocketClient(); /** * Establish connection with remote TCP service. @@ -78,14 +63,14 @@ namespace ignite * @param diag Diagnostics collector. * @return True on success. */ - bool Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag); + virtual bool Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag); /** * Close established connection. * * @return True on success. */ - void Close(); + virtual void Close(); /** * Send data by established connection. @@ -96,7 +81,7 @@ namespace ignite * @return Number of bytes that have been sent on success, * WaitResult::TIMEOUT on timeout and -errno on failure. */ - int Send(const int8_t* data, size_t size, int32_t timeout); + virtual int Send(const int8_t* data, size_t size, int32_t timeout); /** * Receive data from established connection. @@ -107,16 +92,13 @@ namespace ignite * @return Number of bytes that have been sent on success, * WaitResult::TIMEOUT on timeout and -errno on failure. */ - int Receive(int8_t* buffer, size_t size, int32_t timeout); + virtual int Receive(int8_t* buffer, size_t size, int32_t timeout); /** * Check if the socket is blocking or not. * @return @c true if the socket is blocking and false otherwise. */ - bool IsBlocking() const - { - return blocking; - } + virtual bool IsBlocking() const; private: /** @@ -142,7 +124,7 @@ namespace ignite /** Blocking flag. */ bool blocking; - IGNITE_NO_COPY_ASSIGNMENT(SocketClient) + IGNITE_NO_COPY_ASSIGNMENT(TcpSocketClient) }; } } diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 90286b941fcb7..a89a2ab320a04 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -176,4 +176,4 @@ namespace ignite } } -#endif //_IGNITE_ODBC_SYSTEM_UI_DSN_CONFIGURATION_WINDOW \ No newline at end of file +#endif //_IGNITE_ODBC_SYSTEM_UI_DSN_CONFIGURATION_WINDOW diff --git a/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp b/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp similarity index 90% rename from modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp rename to modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp index 6f87b9323dc54..b51895cf9a428 100644 --- a/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp +++ b/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp @@ -27,7 +27,8 @@ #include -#include "ignite/odbc/system/socket_client.h" +#include "ignite/common/concurrent.h" +#include "ignite/odbc/system/tcp_socket_client.h" #include "ignite/odbc/utility.h" #include "ignite/odbc/log.h" @@ -94,39 +95,44 @@ namespace ignite { namespace odbc { - namespace tcp + namespace system { - SocketClient::SocketClient() : + TcpSocketClient::TcpSocketClient() : socketHandle(INVALID_SOCKET), blocking(true) { // No-op. } - SocketClient::~SocketClient() + TcpSocketClient::~TcpSocketClient() { Close(); } - bool SocketClient::Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag) + bool TcpSocketClient::Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag) { + static common::concurrent::CriticalSection initCs; static bool networkInited = false; // Initing networking if is not inited. if (!networkInited) { - WSADATA wsaData; - - networkInited = (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0); - + common::concurrent::CsLockGuard lock(initCs); if (!networkInited) { - LOG_MSG("Networking initialisation failed: " << GetLastSocketErrorMessage()); + WSADATA wsaData; - diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not initialize Windows networking."); + networkInited = (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0); - return false; + if (!networkInited) + { + LOG_MSG("Networking initialisation failed: " << GetLastSocketErrorMessage()); + + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not initialize Windows networking."); + + return false; + } } } @@ -213,7 +219,7 @@ namespace ignite return socketHandle != INVALID_SOCKET; } - void SocketClient::Close() + void TcpSocketClient::Close() { if (socketHandle != INVALID_SOCKET) { @@ -223,7 +229,7 @@ namespace ignite } } - int SocketClient::Send(const int8_t* data, size_t size, int32_t timeout) + int TcpSocketClient::Send(const int8_t* data, size_t size, int32_t timeout) { if (!blocking) { @@ -236,7 +242,7 @@ namespace ignite return send(socketHandle, reinterpret_cast(data), static_cast(size), 0); } - int SocketClient::Receive(int8_t* buffer, size_t size, int32_t timeout) + int TcpSocketClient::Receive(int8_t* buffer, size_t size, int32_t timeout) { if (!blocking) { @@ -249,7 +255,12 @@ namespace ignite return recv(socketHandle, reinterpret_cast(buffer), static_cast(size), 0); } - void SocketClient::TrySetOptions(diagnostic::Diagnosable& diag) + bool TcpSocketClient::IsBlocking() const + { + return blocking; + } + + void TcpSocketClient::TrySetOptions(diagnostic::Diagnosable& diag) { BOOL trueOpt = TRUE; ULONG uTrueOpt = TRUE; @@ -388,7 +399,7 @@ namespace ignite #endif } - int SocketClient::WaitOnSocket(int32_t timeout, bool rd) + int TcpSocketClient::WaitOnSocket(int32_t timeout, bool rd) { int ready = 0; int lastError = 0; diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj index 0f54dd2198747..4c14b834a8141 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj @@ -158,7 +158,7 @@ - + @@ -236,10 +236,11 @@ + - + diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters index fcc960fe439a7..18656cc85d74c 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters @@ -109,9 +109,6 @@ Code\diagnostic - - Code\system - Code\query @@ -154,6 +151,9 @@ Code\ssl + + Code\system + @@ -251,9 +251,6 @@ Code\system - - Code\system - Code\query @@ -293,5 +290,11 @@ Code\ssl + + Code + + + Code\system + \ No newline at end of file diff --git a/modules/platforms/cpp/odbc/src/config/configuration.cpp b/modules/platforms/cpp/odbc/src/config/configuration.cpp index be5a7814fb46d..769e167fc152f 100644 --- a/modules/platforms/cpp/odbc/src/config/configuration.cpp +++ b/modules/platforms/cpp/odbc/src/config/configuration.cpp @@ -46,12 +46,20 @@ namespace ignite const std::string Configuration::Key::collocated = "collocated"; const std::string Configuration::Key::lazy = "lazy"; const std::string Configuration::Key::skipReducerOnUpdate = "skip_reducer_on_update"; + const std::string Configuration::Key::sslMode = "ssl_mode"; + const std::string Configuration::Key::sslKeyFile = "ssl_key_file"; + const std::string Configuration::Key::sslCertFile = "ssl_cert_file"; + const std::string Configuration::Key::sslCaFile = "ssl_ca_file"; const std::string Configuration::DefaultValue::dsn = "Apache Ignite DSN"; const std::string Configuration::DefaultValue::driver = "Apache Ignite"; const std::string Configuration::DefaultValue::schema = "PUBLIC"; const std::string Configuration::DefaultValue::address = ""; const std::string Configuration::DefaultValue::server = ""; + const std::string Configuration::DefaultValue::sslMode = "disable"; + const std::string Configuration::DefaultValue::sslKeyFile = ""; + const std::string Configuration::DefaultValue::sslCertFile = ""; + const std::string Configuration::DefaultValue::sslCaFile = ""; const uint16_t Configuration::DefaultValue::port = 10800; const int32_t Configuration::DefaultValue::pageSize = 1024; diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp index 8b0387627d20d..e8ecb25de719e 100644 --- a/modules/platforms/cpp/odbc/src/connection.cpp +++ b/modules/platforms/cpp/odbc/src/connection.cpp @@ -28,6 +28,8 @@ #include "ignite/odbc/connection.h" #include "ignite/odbc/message.h" #include "ignite/odbc/config/configuration.h" +#include "ignite/odbc/ssl/secure_socket_client.h" +#include "ignite/odbc/system/tcp_socket_client.h" namespace { @@ -45,7 +47,6 @@ namespace ignite { Connection::Connection() : socket(), - connected(false), timeout(0), parser(), config(), @@ -120,19 +121,28 @@ namespace ignite { config = cfg; - if (connected) + if (socket.get() != 0) { AddStatusRecord(SqlState::S08002_ALREADY_CONNECTED, "Already connected."); return SqlResult::AI_ERROR; } - connected = socket.Connect(cfg.GetHost().c_str(), cfg.GetTcpPort(), *this); + // "c:/work/ssl/client_full.pem", "c:/work/ssl/client_full.pem", "c:/work/ssl/ca.pem" + + if (cfg.GetSslMode() != "disable") + socket.reset(new ssl::SecureSocketClient(cfg.GetSslCertFile(), cfg.GetSslKeyFile(), cfg.GetSslCaFile())); + else + socket.reset(new system::TcpSocketClient()); + + bool connected = socket->Connect(cfg.GetHost().c_str(), cfg.GetTcpPort(), *this); if (!connected) { AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "Failed to establish connection with the host."); + Close(); + return SqlResult::AI_ERROR; } @@ -153,7 +163,7 @@ namespace ignite SqlResult::Type Connection::InternalRelease() { - if (!connected) + if (socket.get() == 0) { AddStatusRecord(SqlState::S08003_NOT_CONNECTED, "Connection is not open."); @@ -167,9 +177,9 @@ namespace ignite void Connection::Close() { - socket.Close(); + socket->Close(); - connected = false; + socket.reset(); } Statement* Connection::CreateStatement() @@ -197,7 +207,7 @@ namespace ignite bool Connection::Send(const int8_t* data, size_t len, int32_t timeout) { - if (!connected) + if (socket.get() == 0) throw OdbcError(SqlState::S08003_NOT_CONNECTED, "Connection is not established"); int32_t newLen = static_cast(len + sizeof(OdbcProtocolHeader)); @@ -229,11 +239,11 @@ namespace ignite while (sent != static_cast(len)) { - int res = socket.Send(data + sent, len - sent, timeout); + int res = socket->Send(data + sent, len - sent, timeout); LOG_MSG("Sent: " << res); - if (res < 0 || res == tcp::SocketClient::WaitResult::TIMEOUT) + if (res < 0 || res == SocketClient::WaitResult::TIMEOUT) { Close(); @@ -250,7 +260,7 @@ namespace ignite bool Connection::Receive(std::vector& msg, int32_t timeout) { - if (!connected) + if (socket.get() == 0) throw OdbcError(SqlState::S08003_NOT_CONNECTED, "Connection is not established"); msg.clear(); @@ -299,10 +309,10 @@ namespace ignite { size_t received = len - remain; - int res = socket.Receive(buffer + received, remain, timeout); + int res = socket->Receive(buffer + received, remain, timeout); LOG_MSG("Receive res: " << res << " remain: " << remain); - if (res < 0 || res == tcp::SocketClient::WaitResult::TIMEOUT) + if (res < 0 || res == SocketClient::WaitResult::TIMEOUT) { Close(); @@ -374,7 +384,7 @@ namespace ignite { SQLUINTEGER *val = reinterpret_cast(buf); - *val = connected ? SQL_CD_FALSE : SQL_CD_TRUE; + *val = socket.get() != 0 ? SQL_CD_FALSE : SQL_CD_TRUE; if (valueLen) *valueLen = SQL_IS_INTEGER; @@ -433,7 +443,7 @@ namespace ignite { SQLUINTEGER uTimeout = static_cast(reinterpret_cast(value)); - if (uTimeout != 0 && connected && socket.IsBlocking()) + if (uTimeout != 0 && socket.get() != 0 && socket->IsBlocking()) { timeout = 0; @@ -516,12 +526,13 @@ namespace ignite try { // Workaround for some Linux systems that report connection on non-blocking - // sockets as successfull but fail to establish real connection. - bool sent = SyncMessage(req, rsp, tcp::SocketClient::CONNECT_TIMEOUT); + // sockets as successful but fail to establish real connection. + bool sent = SyncMessage(req, rsp, SocketClient::CONNECT_TIMEOUT); if (!sent) { - AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "Failed to establish connection with the host."); + AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, + "Failed to get handshake response (Did you forget to enable SSL?)."); return SqlResult::AI_ERROR; } @@ -541,7 +552,7 @@ namespace ignite if (!rsp.IsAccepted()) { - LOG_MSG("Hanshake message has been rejected."); + LOG_MSG("Handshake message has been rejected."); std::stringstream constructor; diff --git a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp index 8d3d3d995127d..e4c803bdc308d 100644 --- a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp +++ b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp @@ -35,11 +35,10 @@ namespace ignite namespace ssl { SecureSocketClient::SecureSocketClient(const std::string& certPath, const std::string& keyPath, - const std::string& caPath, const std::string& caDirPath): + const std::string& caPath): certPath(certPath), keyPath(keyPath), caPath(caPath), - caDirPath(caDirPath), context(0), sslBio(0) { @@ -58,7 +57,7 @@ namespace ignite { if (!context) { - context = MakeContext(certPath, keyPath, caPath, caDirPath, diag); + context = MakeContext(certPath, keyPath, caPath, diag); if (!context) { @@ -220,8 +219,13 @@ namespace ignite return res; } + bool SecureSocketClient::IsBlocking() const + { + return true; + } + void* SecureSocketClient::MakeContext(const std::string& certPath, const std::string& keyPath, - const std::string& caPath, const std::string& caDirPath, diagnostic::Diagnosable& diag) + const std::string& caPath, diagnostic::Diagnosable& diag) { static bool sslLibInited = false; static common::concurrent::CriticalSection sslCs; @@ -268,9 +272,8 @@ namespace ignite SSL_CTX_set_options(ctx, flags); const char* cCaPath = caPath.empty() ? 0 : caPath.c_str(); - const char* cCaDirPath = caDirPath.empty() ? 0 : caDirPath.c_str(); - long res = SSL_CTX_load_verify_locations(ctx, cCaPath, cCaDirPath); + long res = SSL_CTX_load_verify_locations(ctx, cCaPath, 0); if (res != SSL_OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, From 955dd22930b35b3d54d98f4932229223537bcd53 Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Fri, 22 Dec 2017 18:16:58 +0300 Subject: [PATCH 03/89] IGNITE-6810: Added saving SSL parameters to DSN --- .../cpp/odbc-test/src/queries_ssl_test.cpp | 2 +- modules/platforms/cpp/odbc/src/connection.cpp | 2 -- modules/platforms/cpp/odbc/src/dsn_config.cpp | 24 ++++++++++++++----- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp index 4c5dcf3a14730..00f18480aacb0 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp @@ -531,7 +531,7 @@ BOOST_AUTO_TEST_CASE(TestConnectionSsl) Connect(connectString.str()); InsertTestStrings(10, false); - InsertTestBatch(11, 20, 9); + InsertTestBatch(11, 2000, 1989); } BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp index e8ecb25de719e..3cde842252cb5 100644 --- a/modules/platforms/cpp/odbc/src/connection.cpp +++ b/modules/platforms/cpp/odbc/src/connection.cpp @@ -128,8 +128,6 @@ namespace ignite return SqlResult::AI_ERROR; } - // "c:/work/ssl/client_full.pem", "c:/work/ssl/client_full.pem", "c:/work/ssl/ca.pem" - if (cfg.GetSslMode() != "disable") socket.reset(new ssl::SecureSocketClient(cfg.GetSslCertFile(), cfg.GetSslKeyFile(), cfg.GetSslCaFile())); else diff --git a/modules/platforms/cpp/odbc/src/dsn_config.cpp b/modules/platforms/cpp/odbc/src/dsn_config.cpp index 536f6797319b1..845c8bddd621b 100644 --- a/modules/platforms/cpp/odbc/src/dsn_config.cpp +++ b/modules/platforms/cpp/odbc/src/dsn_config.cpp @@ -51,13 +51,13 @@ namespace ignite ThrowLastSetupError(); } - std::string ReadDsnString(const char* dsn, const std::string& key, const char* dflt) + std::string ReadDsnString(const char* dsn, const std::string& key, const std::string& dflt) { char buf[BUFFER_SIZE]; memset(buf, 0, sizeof(buf)); - SQLGetPrivateProfileString(dsn, key.c_str(), dflt, buf, sizeof(buf), CONFIG_FILE); + SQLGetPrivateProfileString(dsn, key.c_str(), dflt.c_str(), buf, sizeof(buf), CONFIG_FILE); return std::string(buf); } @@ -90,13 +90,13 @@ namespace ignite void ReadDsnConfiguration(const char* dsn, Configuration& config) { - std::string address = ReadDsnString(dsn, Configuration::Key::address, config.GetAddress().c_str()); + std::string address = ReadDsnString(dsn, Configuration::Key::address, config.GetAddress()); - std::string server = ReadDsnString(dsn, Configuration::Key::server, config.GetHost().c_str()); + std::string server = ReadDsnString(dsn, Configuration::Key::server, config.GetHost()); uint16_t port = ReadDsnInt(dsn, Configuration::Key::port, config.GetTcpPort()); - std::string schema = ReadDsnString(dsn, Configuration::Key::schema, config.GetSchema().c_str()); + std::string schema = ReadDsnString(dsn, Configuration::Key::schema, config.GetSchema()); bool distributedJoins = ReadDsnBool(dsn, Configuration::Key::distributedJoins, config.IsDistributedJoins()); @@ -112,13 +112,21 @@ namespace ignite ReadDsnBool(dsn, Configuration::Key::skipReducerOnUpdate, config.IsSkipReducerOnUpdate()); std::string version = ReadDsnString(dsn, Configuration::Key::protocolVersion, - config.GetProtocolVersion().ToString().c_str()); + config.GetProtocolVersion().ToString()); int32_t pageSize = ReadDsnInt(dsn, Configuration::Key::pageSize, config.GetPageSize()); if (pageSize <= 0) pageSize = config.GetPageSize(); + std::string sslMode = ReadDsnString(dsn, Configuration::Key::sslMode, config.GetSslMode()); + + std::string sslKeyFile = ReadDsnString(dsn, Configuration::Key::sslKeyFile, config.GetSslKeyFile()); + + std::string sslCertFile = ReadDsnString(dsn, Configuration::Key::sslCertFile, config.GetSslCertFile()); + + std::string sslCaFile = ReadDsnString(dsn, Configuration::Key::sslCaFile, config.GetSslCaFile()); + config.SetAddress(address); config.SetHost(server); config.SetTcpPort(port); @@ -131,6 +139,10 @@ namespace ignite config.SetSkipReducerOnUpdate(skipReducerOnUpdate); config.SetProtocolVersion(version); config.SetPageSize(pageSize); + config.SetSslMode(sslMode); + config.SetSslKeyFile(sslKeyFile); + config.SetSslCertFile(sslCertFile); + config.SetSslCaFile(sslCaFile); } } } \ No newline at end of file From 8876df39efbf0061b611ee16479a3d032d7d2676 Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Mon, 25 Dec 2017 19:24:24 +0300 Subject: [PATCH 04/89] IGNITE-6810: Changed UI layout --- .../odbc/system/ui/dsn_configuration_window.h | 87 +++++++- .../system/ui/dsn_configuration_window.cpp | 190 +++++++++++++----- .../cpp/odbc/project/vs/odbc.vcxproj | 8 +- 3 files changed, 225 insertions(+), 60 deletions(-) diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index a89a2ab320a04..78b15f9e07f94 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -41,7 +41,9 @@ namespace ignite { enum Type { - CONNECTION_SETTINGS_GROUP_BOX, + CONNECTION_SETTINGS_GROUP_BOX = 100, + SSL_SETTINGS_GROUP_BOX, + ADDITIONAL_SETTINGS_GROUP_BOX, NAME_EDIT, NAME_LABEL, ADDRESS_EDIT, @@ -58,11 +60,34 @@ namespace ignite SKIP_REDUCER_ON_UPDATE_CHECK_BOX, PROTOCOL_VERSION_LABEL, PROTOCOL_VERSION_COMBO_BOX, + SSL_MODE_LABEL, + SSL_MODE_COMBO_BOX, + SSL_KEY_FILE_LABEL, + SSL_KEY_FILE_EDIT, + SSL_CERT_FILE_LABEL, + SSL_CERT_FILE_EDIT, + SSL_CA_FILE_LABEL, + SSL_CA_FILE_EDIT, OK_BUTTON, CANCEL_BUTTON }; }; + // Window margin size. + enum { MARGIN = 10 }; + + // Standard interval between UI elements. + enum { INTERVAL = 10 }; + + // Standard row height. + enum { ROW_HEIGHT = 20 }; + + // Standard button width. + enum { BUTTON_WIDTH = 80 }; + + // Standard button height. + enum { BUTTON_HEIGHT = 25 }; + public: /** * Constructor. @@ -102,6 +127,36 @@ namespace ignite */ void RetrieveParameters(config::Configuration& cfg) const; + /** + * Create connection settings group box. + * + * @param posX X position. + * @param posY Y position. + * @param sizeX Width. + * @return Size by Y. + */ + int CreateConnectionSettingsGroup(int posX, int posY, int sizeX); + + /** + * Create SSL settings group box. + * + * @param posX X position. + * @param posY Y position. + * @param sizeX Width. + * @return Size by Y. + */ + int CreateSslSettingsGroup(int posX, int posY, int sizeX); + + /** + * Create additional settings group box. + * + * @param posX X position. + * @param posY Y position. + * @param sizeX Width. + * @return Size by Y. + */ + int CreateAdditionalSettingsGroup(int posX, int posY, int sizeX); + /** Window width. */ int width; @@ -111,6 +166,12 @@ namespace ignite /** Connection settings group box. */ std::auto_ptr connectionSettingsGroupBox; + /** SSL settings group box. */ + std::auto_ptr sslSettingsGroupBox; + + /** Additional settings group box. */ + std::auto_ptr additionalSettingsGroupBox; + /** DSN name edit field label. */ std::auto_ptr nameLabel; @@ -165,6 +226,30 @@ namespace ignite /** Cancel button. */ std::auto_ptr cancelButton; + /** SSL Mode label. */ + std::auto_ptr sslModeLabel; + + /** SSL Mode ComboBox. */ + std::auto_ptr sslModeComboBox; + + /** SSL Private Key File label. */ + std::auto_ptr sslKeyFileLabel; + + /** SSL Private Key File edit. */ + std::auto_ptr sslKeyFileEdit; + + /** SSL Certificate File label. */ + std::auto_ptr sslCertFileLabel; + + /** SSL Certificate File edit. */ + std::auto_ptr sslCertFileEdit; + + /** SSL Certificate Authority File label. */ + std::auto_ptr sslCaFileLabel; + + /** SSL Certificate Authority File edit. */ + std::auto_ptr sslCaFileEdit; + /** Configuration. */ config::Configuration& config; diff --git a/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index d5aa0dbd723b8..bd6fd4783ad95 100644 --- a/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -16,6 +16,7 @@ */ #include +#include #include "ignite/odbc/log.h" @@ -32,7 +33,7 @@ namespace ignite DsnConfigurationWindow::DsnConfigurationWindow(Window* parent, config::Configuration& config): CustomWindow(parent, "IgniteConfigureDsn", "Configure Apache Ignite DSN"), width(360), - height(300), + height(480), connectionSettingsGroupBox(), nameLabel(), nameEdit(), @@ -89,53 +90,56 @@ namespace ignite void DsnConfigurationWindow::OnCreate() { - int margin = 10; - int interval = 10; + int groupPosY = MARGIN; + int groupSizeY = width - 2 * MARGIN; - int labelSizeX = 80; - int labelPosX = margin + interval; + groupPosY += INTERVAL + CreateConnectionSettingsGroup(MARGIN, groupPosY, groupSizeY); + groupPosY += INTERVAL + CreateSslSettingsGroup(MARGIN, groupPosY, groupSizeY); + groupPosY += INTERVAL + CreateAdditionalSettingsGroup(MARGIN, groupPosY, groupSizeY); - int editSizeX = width - labelSizeX - 2 * margin - 3 * interval; - int editPosX = margin + labelSizeX + 2 * interval; + int cancelPosX = width - MARGIN - BUTTON_WIDTH; + int okPosX = cancelPosX - INTERVAL - BUTTON_WIDTH; - int rowSize = 20; - int rowPos = margin + 2 * interval; + okButton = CreateButton(okPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, "Ok", ChildId::OK_BUTTON); + cancelButton = CreateButton(cancelPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, + "Cancel", ChildId::CANCEL_BUTTON); + } + + int DsnConfigurationWindow::CreateConnectionSettingsGroup(int posX, int posY, int sizeX) + { + enum { LABEL_WIDTH = 100 }; - int checkBoxSize = (editSizeX - interval) / 2; + int labelPosX = posX + INTERVAL; - int sectionBegin = margin; + int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; + int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; + + int rowPos = posY + 2 * INTERVAL; const char* val = config.GetDsn().c_str(); - nameLabel = CreateLabel(labelPosX, rowPos, labelSizeX, rowSize, "DSN name:", ChildId::NAME_LABEL); - nameEdit = CreateEdit(editPosX, rowPos, editSizeX, rowSize, val, ChildId::NAME_EDIT); + nameLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Data Source Name:", ChildId::NAME_LABEL); + nameEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::NAME_EDIT); - rowPos += interval + rowSize; + rowPos += INTERVAL + ROW_HEIGHT; val = config.GetAddress().c_str(); - addressLabel = CreateLabel(labelPosX, rowPos, labelSizeX, rowSize, "Address:", ChildId::ADDRESS_LABEL); - addressEdit = CreateEdit(editPosX, rowPos, editSizeX, rowSize, val, ChildId::ADDRESS_EDIT); + addressLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Address:", ChildId::ADDRESS_LABEL); + addressEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::ADDRESS_EDIT); - rowPos += interval + rowSize; + rowPos += INTERVAL + ROW_HEIGHT; val = config.GetSchema().c_str(); - schemaLabel = CreateLabel(labelPosX, rowPos, labelSizeX, rowSize, "Schema name:", ChildId::SCHEMA_LABEL); - schemaEdit = CreateEdit(editPosX, rowPos, editSizeX, rowSize, val, ChildId::SCHEMA_EDIT); - - rowPos += interval + rowSize; - - std::string tmp = common::LexicalCast(config.GetPageSize()); - val = tmp.c_str(); - pageSizeLabel = CreateLabel(labelPosX, rowPos, labelSizeX, - rowSize, "Page size:", ChildId::PAGE_SIZE_LABEL); - - pageSizeEdit = CreateEdit(editPosX, rowPos, editSizeX, - rowSize, val, ChildId::PAGE_SIZE_EDIT, ES_NUMBER); + schemaLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Schema name:", ChildId::SCHEMA_LABEL); + schemaEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SCHEMA_EDIT); - rowPos += interval + rowSize; + rowPos += INTERVAL + ROW_HEIGHT; - protocolVersionLabel = CreateLabel(labelPosX, rowPos, labelSizeX, rowSize, + protocolVersionLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Protocol version:", ChildId::PROTOCOL_VERSION_LABEL); - protocolVersionComboBox = CreateComboBox(editPosX, rowPos, editSizeX, rowSize, + protocolVersionComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, "Protocol version", ChildId::PROTOCOL_VERSION_COMBO_BOX); int id = 0; @@ -157,48 +161,124 @@ namespace ignite ++id; } - rowPos += interval + rowSize; + rowPos += INTERVAL + ROW_HEIGHT; + + connectionSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, + "Connection settings", ChildId::CONNECTION_SETTINGS_GROUP_BOX); + + return rowPos - posY; + } + + int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) + { + enum { LABEL_WIDTH = 120 }; + + int labelPosX = posX + INTERVAL; + + int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; + int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; + + int rowPos = posY + 2 * INTERVAL; + + const char* val = config.GetSslMode().c_str(); + sslModeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSL Mode:", ChildId::SSL_MODE_LABEL); + sslModeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSL_MODE_COMBO_BOX); + + sslModeComboBox->AddString("disable"); + sslModeComboBox->AddString("require"); + + sslModeComboBox->SetSelection(0); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetSslKeyFile().c_str(); + sslKeyFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSL Private Key:", ChildId::SSL_KEY_FILE_LABEL); + sslKeyFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSL_KEY_FILE_EDIT); + + SHAutoComplete(sslKeyFileEdit->GetHandle(), SHACF_DEFAULT); + + rowPos += INTERVAL + ROW_HEIGHT; - distributedJoinsCheckBox = CreateCheckBox(editPosX, rowPos, checkBoxSize, rowSize, + val = config.GetSslCertFile().c_str(); + sslCertFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSL Certificate:", ChildId::SSL_CERT_FILE_LABEL); + sslCertFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSL_CERT_FILE_EDIT); + + SHAutoComplete(sslCertFileEdit->GetHandle(), SHACF_DEFAULT); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetSslCaFile().c_str(); + sslCaFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSL Certificate Authority:", ChildId::SSL_CA_FILE_LABEL); + sslCaFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSL_CA_FILE_EDIT); + + SHAutoComplete(sslCaFileEdit->GetHandle(), SHACF_DEFAULT); + + rowPos += INTERVAL + ROW_HEIGHT; + + sslSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, + "SSL settings", ChildId::SSL_SETTINGS_GROUP_BOX); + + return rowPos - posY; + } + + int DsnConfigurationWindow::CreateAdditionalSettingsGroup(int posX, int posY, int sizeX) + { + enum { LABEL_WIDTH = 80 }; + + int labelPosX = posX + INTERVAL; + + int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; + int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; + + int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; + + const ProtocolVersion version = config.GetProtocolVersion(); + + int rowPos = posY + 2 * INTERVAL; + + std::string tmp = common::LexicalCast(config.GetPageSize()); + const char* val = tmp.c_str(); + pageSizeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, + ROW_HEIGHT, "Page size:", ChildId::PAGE_SIZE_LABEL); + + pageSizeEdit = CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT, val, ChildId::PAGE_SIZE_EDIT, ES_NUMBER); + + rowPos += INTERVAL + ROW_HEIGHT; + + distributedJoinsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "Distributed Joins", ChildId::DISTRIBUTED_JOINS_CHECK_BOX, config.IsDistributedJoins()); - enforceJoinOrderCheckBox = CreateCheckBox(editPosX + checkBoxSize + interval, rowPos, checkBoxSize, - rowSize, "Enforce Join Order", ChildId::ENFORCE_JOIN_ORDER_CHECK_BOX, config.IsEnforceJoinOrder()); + enforceJoinOrderCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, checkBoxSize, + ROW_HEIGHT, "Enforce Join Order", ChildId::ENFORCE_JOIN_ORDER_CHECK_BOX, config.IsEnforceJoinOrder()); - rowPos += rowSize; + rowPos += ROW_HEIGHT; - replicatedOnlyCheckBox = CreateCheckBox(editPosX, rowPos, checkBoxSize, rowSize, + replicatedOnlyCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "Replicated Only", ChildId::REPLICATED_ONLY_CHECK_BOX, config.IsReplicatedOnly()); - collocatedCheckBox = CreateCheckBox(editPosX + checkBoxSize + interval, rowPos, checkBoxSize, - rowSize, "Collocated", ChildId::COLLOCATED_CHECK_BOX, config.IsCollocated()); + collocatedCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, checkBoxSize, + ROW_HEIGHT, "Collocated", ChildId::COLLOCATED_CHECK_BOX, config.IsCollocated()); - rowPos += rowSize; + rowPos += ROW_HEIGHT; - lazyCheckBox = CreateCheckBox(editPosX, rowPos, checkBoxSize, rowSize, + lazyCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "Lazy", ChildId::LAZY_CHECK_BOX, config.IsLazy()); lazyCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_1_5); - skipReducerOnUpdateCheckBox = CreateCheckBox(editPosX + checkBoxSize + interval, rowPos, - checkBoxSize, rowSize, "Skip reducer on update", ChildId::SKIP_REDUCER_ON_UPDATE_CHECK_BOX, + skipReducerOnUpdateCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, + checkBoxSize, ROW_HEIGHT, "Skip reducer on update", ChildId::SKIP_REDUCER_ON_UPDATE_CHECK_BOX, config.IsSkipReducerOnUpdate()); skipReducerOnUpdateCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_3_0); - rowPos += interval * 2 + rowSize; - - connectionSettingsGroupBox = CreateGroupBox(margin, sectionBegin, width - 2 * margin, - rowPos - interval - sectionBegin, "Connection settings", ChildId::CONNECTION_SETTINGS_GROUP_BOX); - - int buttonSizeX = 80; - int cancelPosX = width - margin - buttonSizeX; - int okPosX = cancelPosX - interval - buttonSizeX; + rowPos += ROW_HEIGHT + INTERVAL; - rowSize = 25; + additionalSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, + "Additional settings", ChildId::ADDITIONAL_SETTINGS_GROUP_BOX); - okButton = CreateButton(okPosX, rowPos, buttonSizeX, rowSize, "Ok", ChildId::OK_BUTTON); - cancelButton = CreateButton(cancelPosX, rowPos, buttonSizeX, rowSize, "Cancel", ChildId::CANCEL_BUTTON); + return rowPos - posY; } bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM wParam, LPARAM lParam) diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj index 4c14b834a8141..6662a2996a500 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj @@ -99,7 +99,7 @@ true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;ssleay32MDd.lib;libeay32MDd.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;ssleay32MDd.lib;libeay32MDd.lib;%(AdditionalDependencies) $(OPENSSL_HOME)\lib\VC @@ -114,7 +114,7 @@ true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;ssleay32MDd.lib;libeay32MDd.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;ssleay32MDd.lib;libeay32MDd.lib;%(AdditionalDependencies) $(OPENSSL_HOME)\lib\VC @@ -133,7 +133,7 @@ true true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;ssleay32MD.lib;libeay32MD.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;ssleay32MD.lib;libeay32MD.lib;%(AdditionalDependencies) $(OPENSSL_HOME)\lib\VC @@ -152,7 +152,7 @@ true true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;ssleay32MD.lib;libeay32MD.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;ssleay32MD.lib;libeay32MD.lib;%(AdditionalDependencies) $(OPENSSL_HOME)\lib\VC From 089c81b9b971c1d8270987d5a6bcac94383212bc Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Tue, 26 Dec 2017 15:26:44 +0300 Subject: [PATCH 05/89] IGNITE-6810: Added values retrieval --- .../odbc/system/ui/dsn_configuration_window.h | 24 +++++ .../system/ui/dsn_configuration_window.cpp | 102 ++++++++++++------ .../cpp/odbc/os/win/src/system/ui/window.cpp | 9 +- 3 files changed, 102 insertions(+), 33 deletions(-) diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 78b15f9e07f94..b90341418a2b3 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -127,6 +127,30 @@ namespace ignite */ void RetrieveParameters(config::Configuration& cfg) const; + /** + * Retrieves current values from the connection UI group and + * stores them to the specified configuration. + * + * @param cfg Configuration. + */ + void RetrieveConnectionParameters(config::Configuration& cfg) const; + + /** + * Retrieves current values from the SSL UI group and + * stores them to the specified configuration. + * + * @param cfg Configuration. + */ + void RetrieveSslParameters(config::Configuration& cfg) const; + + /** + * Retrieves current values from the additional UI group and + * stores them to the specified configuration. + * + * @param cfg Configuration. + */ + void RetrieveAdditionalParameters(config::Configuration& cfg) const; + /** * Create connection settings group box. * diff --git a/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index bd6fd4783ad95..5c7cb1f468d2d 100644 --- a/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -182,7 +182,7 @@ namespace ignite const char* val = config.GetSslMode().c_str(); sslModeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSL Mode:", ChildId::SSL_MODE_LABEL); - sslModeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSL_MODE_COMBO_BOX); + sslModeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, "", ChildId::SSL_MODE_COMBO_BOX); sslModeComboBox->AddString("disable"); sslModeComboBox->AddString("require"); @@ -391,55 +391,33 @@ namespace ignite } void DsnConfigurationWindow::RetrieveParameters(config::Configuration& cfg) const + { + RetrieveConnectionParameters(cfg); + RetrieveSslParameters(cfg); + RetrieveAdditionalParameters(cfg); + } + + void DsnConfigurationWindow::RetrieveConnectionParameters(config::Configuration& cfg) const { std::string dsn; std::string address; std::string schema; - std::string pageSizeStr; std::string version; - bool distributedJoins; - bool enforceJoinOrder; - bool replicatedOnly; - bool collocated; - bool lazy; - bool skipReducerOnUpdate; - nameEdit->GetText(dsn); addressEdit->GetText(address); schemaEdit->GetText(schema); protocolVersionComboBox->GetText(version); - pageSizeEdit->GetText(pageSizeStr); - - int32_t pageSize = common::LexicalCast(pageSizeStr); - - if (pageSize <= 0) - pageSize = config.GetPageSize(); common::StripSurroundingWhitespaces(address); common::StripSurroundingWhitespaces(dsn); - - distributedJoins = distributedJoinsCheckBox->IsEnabled() && distributedJoinsCheckBox->IsChecked(); - enforceJoinOrder = enforceJoinOrderCheckBox->IsEnabled() && enforceJoinOrderCheckBox->IsChecked(); - replicatedOnly = replicatedOnlyCheckBox->IsEnabled() && replicatedOnlyCheckBox->IsChecked(); - collocated = collocatedCheckBox->IsEnabled() && collocatedCheckBox->IsChecked(); - lazy = lazyCheckBox->IsEnabled() && lazyCheckBox->IsChecked(); - - skipReducerOnUpdate = - skipReducerOnUpdateCheckBox->IsEnabled() && skipReducerOnUpdateCheckBox->IsChecked(); + // Stripping of whitespaces off the schema skipped intentionally LOG_MSG("Retriving arguments:"); LOG_MSG("DSN: " << dsn); LOG_MSG("Address: " << address); LOG_MSG("Schema: " << schema); - LOG_MSG("Page size: " << pageSize); LOG_MSG("Protocol version: " << version); - LOG_MSG("Distributed Joins: " << (distributedJoins ? "true" : "false")); - LOG_MSG("Enforce Join Order: " << (enforceJoinOrder ? "true" : "false")); - LOG_MSG("Replicated only: " << (replicatedOnly ? "true" : "false")); - LOG_MSG("Collocated: " << (collocated ? "true" : "false")); - LOG_MSG("Lazy: " << (lazy ? "true" : "false")); - LOG_MSG("Skip reducer on update: " << (skipReducerOnUpdate ? "true" : "false")); if (dsn.empty()) throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "DSN name can not be empty."); @@ -447,8 +425,68 @@ namespace ignite cfg.SetDsn(dsn); cfg.SetAddress(address); cfg.SetSchema(schema); - cfg.SetPageSize(pageSize); cfg.SetProtocolVersion(version); + } + + void DsnConfigurationWindow::RetrieveSslParameters(config::Configuration& cfg) const + { + std::string sslMode; + std::string sslKey; + std::string sslCert; + std::string sslCa; + + sslModeComboBox->GetText(sslMode); + sslKeyFileEdit->GetText(sslKey); + sslCertFileEdit->GetText(sslCert); + sslCaFileEdit->GetText(sslCa); + + LOG_MSG("Retriving arguments:"); + LOG_MSG("SSL Mode: " << sslMode); + LOG_MSG("SSL Key: " << sslKey); + LOG_MSG("SSL Certificate: " << sslCert); + LOG_MSG("SSL CA: " << sslCa); + + cfg.SetSslMode(sslMode); + cfg.SetSslKeyFile(sslKey); + cfg.SetSslCertFile(sslCert); + cfg.SetSslCaFile(sslCa); + } + + void DsnConfigurationWindow::RetrieveAdditionalParameters(config::Configuration& cfg) const + { + std::string pageSizeStr; + + bool distributedJoins; + bool enforceJoinOrder; + bool replicatedOnly; + bool collocated; + bool lazy; + bool skipReducerOnUpdate; + + pageSizeEdit->GetText(pageSizeStr); + + int32_t pageSize = common::LexicalCast(pageSizeStr); + + if (pageSize <= 0) + pageSize = config.GetPageSize(); + + distributedJoins = distributedJoinsCheckBox->IsChecked(); + enforceJoinOrder = enforceJoinOrderCheckBox->IsChecked(); + replicatedOnly = replicatedOnlyCheckBox->IsChecked(); + collocated = collocatedCheckBox->IsChecked(); + lazy = lazyCheckBox->IsChecked(); + skipReducerOnUpdate = skipReducerOnUpdateCheckBox->IsChecked(); + + LOG_MSG("Retriving arguments:"); + LOG_MSG("Page size: " << pageSize); + LOG_MSG("Distributed Joins: " << (distributedJoins ? "true" : "false")); + LOG_MSG("Enforce Join Order: " << (enforceJoinOrder ? "true" : "false")); + LOG_MSG("Replicated only: " << (replicatedOnly ? "true" : "false")); + LOG_MSG("Collocated: " << (collocated ? "true" : "false")); + LOG_MSG("Lazy: " << (lazy ? "true" : "false")); + LOG_MSG("Skip reducer on update: " << (skipReducerOnUpdate ? "true" : "false")); + + cfg.SetPageSize(pageSize); cfg.SetDistributedJoins(distributedJoins); cfg.SetEnforceJoinOrder(enforceJoinOrder); cfg.SetReplicatedOnly(replicatedOnly); diff --git a/modules/platforms/cpp/odbc/os/win/src/system/ui/window.cpp b/modules/platforms/cpp/odbc/os/win/src/system/ui/window.cpp index aca23eb99deaf..8f2340a1214ed 100644 --- a/modules/platforms/cpp/odbc/os/win/src/system/ui/window.cpp +++ b/modules/platforms/cpp/odbc/os/win/src/system/ui/window.cpp @@ -130,6 +130,13 @@ namespace ignite void Window::GetText(std::string& text) const { + if (!IsEnabled()) + { + text.clear(); + + return; + } + int len = GetWindowTextLength(handle); if (len <= 0) @@ -154,7 +161,7 @@ namespace ignite bool Window::IsChecked() const { - return Button_GetCheck(handle) == BST_CHECKED; + return IsEnabled() && Button_GetCheck(handle) == BST_CHECKED; } void Window::SetChecked(bool state) From 817584dc9de401d523af8c301ec5982d3ad8f249 Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Tue, 26 Dec 2017 16:05:59 +0300 Subject: [PATCH 06/89] IGNITE-6810: Implmented disabling of SSL options on choosing "disable" mode --- .../odbc/include/ignite/odbc/ssl/ssl_mode.h | 55 +++++++++++++++++++ .../system/ui/dsn_configuration_window.cpp | 27 ++++++++- .../cpp/odbc/project/vs/odbc.vcxproj | 2 + .../cpp/odbc/project/vs/odbc.vcxproj.filters | 6 ++ modules/platforms/cpp/odbc/src/connection.cpp | 7 ++- .../platforms/cpp/odbc/src/ssl/ssl_mode.cpp | 43 +++++++++++++++ 6 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_mode.h create mode 100644 modules/platforms/cpp/odbc/src/ssl/ssl_mode.cpp diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_mode.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_mode.h new file mode 100644 index 0000000000000..20472c31af133 --- /dev/null +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_mode.h @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_SSL_SSL_MODE +#define _IGNITE_ODBC_SSL_SSL_MODE + +#include + +#include "ignite/odbc/diagnostic/diagnosable.h" + +namespace ignite +{ + namespace odbc + { + namespace ssl + { + /** SSL Mode enum. */ + struct SslMode + { + enum T + { + DISABLE = 0, + + REQUIRE = 1, + + UNKNOWN = 100 + }; + + /** + * Convert mode from string. + * @param val String value. + * @param dflt Default value to return on error. + * @return Corresponding enum value. + */ + static T FromString(const std::string& val, T dflt = UNKNOWN); + }; + } + } +} + +#endif //_IGNITE_ODBC_SSL_SSL_MODE \ No newline at end of file diff --git a/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 5c7cb1f468d2d..0e742be2f8f50 100644 --- a/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -19,6 +19,7 @@ #include #include "ignite/odbc/log.h" +#include "ignite/odbc/ssl/ssl_mode.h" #include "ignite/odbc/system/ui/dsn_configuration_window.h" @@ -171,6 +172,8 @@ namespace ignite int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) { + using ssl::SslMode; + enum { LABEL_WIDTH = 120 }; int labelPosX = posX + INTERVAL; @@ -181,13 +184,15 @@ namespace ignite int rowPos = posY + 2 * INTERVAL; const char* val = config.GetSslMode().c_str(); + SslMode::T sslMode = SslMode::FromString(val, SslMode::DISABLE); + sslModeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSL Mode:", ChildId::SSL_MODE_LABEL); sslModeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, "", ChildId::SSL_MODE_COMBO_BOX); sslModeComboBox->AddString("disable"); sslModeComboBox->AddString("require"); - sslModeComboBox->SetSelection(0); + sslModeComboBox->SetSelection(sslMode); rowPos += INTERVAL + ROW_HEIGHT; @@ -218,6 +223,10 @@ namespace ignite sslSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, "SSL settings", ChildId::SSL_SETTINGS_GROUP_BOX); + sslKeyFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + sslCertFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + sslCaFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + return rowPos - posY; } @@ -369,6 +378,22 @@ namespace ignite break; } + case ChildId::SSL_MODE_COMBO_BOX: + { + using ssl::SslMode; + + std::string sslModeStr; + sslModeComboBox->GetText(sslModeStr); + + SslMode::T sslMode = SslMode::FromString(sslModeStr, SslMode::DISABLE); + + sslKeyFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + sslCertFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + sslCaFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + + break; + } + default: return false; } diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj index 6662a2996a500..706614278721c 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj @@ -193,6 +193,7 @@ + @@ -238,6 +239,7 @@ + diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters index 18656cc85d74c..fcf46b11d7724 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters @@ -154,6 +154,9 @@ Code\system + + Code\ssl + @@ -296,5 +299,8 @@ Code\system + + Code\ssl + \ No newline at end of file diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp index 3cde842252cb5..430af66fee800 100644 --- a/modules/platforms/cpp/odbc/src/connection.cpp +++ b/modules/platforms/cpp/odbc/src/connection.cpp @@ -28,6 +28,7 @@ #include "ignite/odbc/connection.h" #include "ignite/odbc/message.h" #include "ignite/odbc/config/configuration.h" +#include "ignite/odbc/ssl/ssl_mode.h" #include "ignite/odbc/ssl/secure_socket_client.h" #include "ignite/odbc/system/tcp_socket_client.h" @@ -119,6 +120,8 @@ namespace ignite SqlResult::Type Connection::InternalEstablish(const config::Configuration cfg) { + using ssl::SslMode; + config = cfg; if (socket.get() != 0) @@ -128,7 +131,9 @@ namespace ignite return SqlResult::AI_ERROR; } - if (cfg.GetSslMode() != "disable") + SslMode::T sslMode = SslMode::FromString(cfg.GetSslMode(), SslMode::DISABLE); + + if (sslMode != SslMode::DISABLE) socket.reset(new ssl::SecureSocketClient(cfg.GetSslCertFile(), cfg.GetSslKeyFile(), cfg.GetSslCaFile())); else socket.reset(new system::TcpSocketClient()); diff --git a/modules/platforms/cpp/odbc/src/ssl/ssl_mode.cpp b/modules/platforms/cpp/odbc/src/ssl/ssl_mode.cpp new file mode 100644 index 0000000000000..0bdbc60098818 --- /dev/null +++ b/modules/platforms/cpp/odbc/src/ssl/ssl_mode.cpp @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ignite/common/utils.h" +#include "ignite/odbc/ssl/ssl_mode.h" + +namespace ignite +{ + namespace odbc + { + namespace ssl + { + SslMode::T SslMode::FromString(const std::string& val, T dflt) + { + std::string lowerVal = common::ToLower(val); + + common::StripSurroundingWhitespaces(lowerVal); + + if (lowerVal == "disable") + return SslMode::DISABLE; + + if (lowerVal == "require") + return SslMode::REQUIRE; + + return dflt; + } + } + } +} From a780fd1f36903549199cdcbef0d963b79f00b462 Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Tue, 26 Dec 2017 16:40:42 +0300 Subject: [PATCH 07/89] IGNITE-6810: Merge-related fixes --- .../cpp/odbc-test/include/odbc_test_suite.h | 5 + .../cpp/odbc-test/src/api_robustness_test.cpp | 96 +------------------ .../cpp/odbc-test/src/meta_queries_test.cpp | 92 ++---------------- .../cpp/odbc-test/src/odbc_test_suite.cpp | 7 +- .../cpp/odbc-test/src/queries_test.cpp | 2 +- 5 files changed, 23 insertions(+), 179 deletions(-) diff --git a/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h b/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h index f79d65ff7078c..a82dab291176d 100644 --- a/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h +++ b/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h @@ -41,6 +41,11 @@ namespace ignite */ struct OdbcTestSuite { + /** + * Prepare environment. + */ + void Prepare(); + /** * Establish connection to node. * diff --git a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp index c17e079e25f10..8f80dfb9845e4 100644 --- a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp @@ -37,6 +37,7 @@ #include "test_type.h" #include "test_utils.h" +#include "odbc_test_suite.h" using namespace ignite; using namespace ignite::cache; @@ -51,98 +52,20 @@ using ignite::impl::binary::BinaryUtils; /** * Test setup fixture. */ -struct ApiRobustnessTestSuiteFixture +struct ApiRobustnessTestSuiteFixture : public odbc::OdbcTestSuite { - void Prepare() - { - // Allocate an environment handle - SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); - - BOOST_REQUIRE(env != NULL); - - // We want ODBC 3 support - SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast(SQL_OV_ODBC3), 0); - - // Allocate a connection handle - SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); - - BOOST_REQUIRE(dbc != NULL); - } - - /** - * Establish connection to node. - * - * @param connectStr Connection string. - */ - void Connect(const std::string& connectStr) - { - Prepare(); - - // Connect string - std::vector connectStr0; - - connectStr0.reserve(connectStr.size() + 1); - std::copy(connectStr.begin(), connectStr.end(), std::back_inserter(connectStr0)); - - SQLCHAR outstr[ODBC_BUFFER_SIZE]; - SQLSMALLINT outstrlen; - - // Connecting to ODBC server. - SQLRETURN ret = SQLDriverConnect(dbc, NULL, &connectStr0[0], static_cast(connectStr0.size()), - outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE); - - ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc); - - // Allocate a statement handle - SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); - - BOOST_REQUIRE(stmt != NULL); - } - - void Disconnect() - { - // Releasing statement handle. - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - - // Disconneting from the server. - SQLDisconnect(dbc); - - // Releasing allocated handles. - SQLFreeHandle(SQL_HANDLE_DBC, dbc); - SQLFreeHandle(SQL_HANDLE_ENV, env); - } - static Ignite StartAdditionalNode(const char* name) { - const char* config = NULL; - -#ifdef IGNITE_TESTS_32 - config = "queries-test-noodbc-32.xml"; -#else - config = "queries-test-noodbc.xml"; -#endif - - return StartNode(config, name); + return StartTestNode("queries-test.xml", name); } /** * Constructor. */ ApiRobustnessTestSuiteFixture() : - testCache(0), - env(NULL), - dbc(NULL), - stmt(NULL) + testCache(0) { - const char* config = NULL; - -#ifdef IGNITE_TESTS_32 - config = "queries-test-32.xml"; -#else - config = "queries-test.xml"; -#endif - - grid = StartNode(config, "NodeMain"); + grid = StartNode("queries-test.xml", "NodeMain"); testCache = grid.GetCache("cache"); } @@ -237,15 +160,6 @@ struct ApiRobustnessTestSuiteFixture /** Test cache instance. */ Cache testCache; - - /** ODBC Environment. */ - SQLHENV env; - - /** ODBC Connect. */ - SQLHDBC dbc; - - /** ODBC Statement. */ - SQLHSTMT stmt; }; SQLSMALLINT unsupportedC[] = { diff --git a/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp b/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp index ba9fd04032809..b737cd9c9bd18 100644 --- a/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp @@ -40,6 +40,7 @@ #include "test_type.h" #include "complex_type.h" #include "test_utils.h" +#include "odbc_test_suite.h" using namespace ignite; using namespace ignite::cache; @@ -55,70 +56,8 @@ using namespace boost::unit_test; /** * Test setup fixture. */ -struct MetaQueriesTestSuiteFixture +struct MetaQueriesTestSuiteFixture : public odbc::OdbcTestSuite { - /** - * Establish connection to node. - * - * @param connectStr Connection string. - */ - void Connect(const std::string& connectStr) - { - // Allocate an environment handle - SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); - - BOOST_REQUIRE(env != NULL); - - // We want ODBC 3 support - SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast(SQL_OV_ODBC3), 0); - - // Allocate a connection handle - SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); - - BOOST_REQUIRE(dbc != NULL); - - // Connect string - std::vector connectStr0; - - connectStr0.reserve(connectStr.size() + 1); - std::copy(connectStr.begin(), connectStr.end(), std::back_inserter(connectStr0)); - - SQLCHAR outstr[ODBC_BUFFER_SIZE]; - SQLSMALLINT outstrlen; - - // Connecting to ODBC server. - SQLRETURN ret = SQLDriverConnect(dbc, NULL, &connectStr0[0], static_cast(connectStr0.size()), - outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE); - - if (!SQL_SUCCEEDED(ret)) - { - Ignition::Stop(grid.GetName(), true); - - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc)); - } - - // Allocate a statement handle - SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); - - BOOST_REQUIRE(stmt != NULL); - } - - /** - * Disconnect. - */ - void Disconnect() - { - // Releasing statement handle. - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - - // Disconneting from the server. - SQLDisconnect(dbc); - - // Releasing allocated handles. - SQLFreeHandle(SQL_HANDLE_DBC, dbc); - SQLFreeHandle(SQL_HANDLE_ENV, env); - } - /** * Start additional node with the specified name. * @@ -126,11 +65,7 @@ struct MetaQueriesTestSuiteFixture */ static Ignite StartAdditionalNode(const char* name) { -#ifdef IGNITE_TESTS_32 - return StartNode("queries-test-noodbc-32.xml", name); -#else - return StartNode("queries-test-noodbc.xml", name); -#endif + return StartTestNode("queries-test.xml", name); } /** @@ -190,17 +125,11 @@ struct MetaQueriesTestSuiteFixture * Constructor. */ MetaQueriesTestSuiteFixture() : + grid(0), cache1(0), - cache2(0), - env(NULL), - dbc(NULL), - stmt(NULL) + cache2(0) { -#ifdef IGNITE_TESTS_32 - grid = StartNode("queries-test-32.xml", "NodeMain"); -#else - grid = StartNode("queries-test.xml", "NodeMain"); -#endif + grid = StartTestNode("queries-test.xml", "NodeMain"); cache1 = grid.GetCache("cache"); cache2 = grid.GetCache("cache2"); @@ -224,15 +153,6 @@ struct MetaQueriesTestSuiteFixture /** Second cache instance. */ Cache cache2; - - /** ODBC Environment. */ - SQLHENV env; - - /** ODBC Connect. */ - SQLHDBC dbc; - - /** ODBC Statement. */ - SQLHSTMT stmt; }; BOOST_FIXTURE_TEST_SUITE(MetaQueriesTestSuite, MetaQueriesTestSuiteFixture) diff --git a/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp b/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp index a967b4f10bc6d..09b2182885185 100644 --- a/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp +++ b/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp @@ -40,7 +40,7 @@ namespace ignite { namespace odbc { - void OdbcTestSuite::Connect(const std::string& connectStr) + void OdbcTestSuite::Prepare() { // Allocate an environment handle SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); @@ -54,6 +54,11 @@ namespace ignite SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); BOOST_REQUIRE(dbc != NULL); + } + + void OdbcTestSuite::Connect(const std::string& connectStr) + { + Prepare(); // Connect string std::vector connectStr0; diff --git a/modules/platforms/cpp/odbc-test/src/queries_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_test.cpp index 6eee9a6f3d63b..591d69d46a564 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp @@ -228,7 +228,7 @@ struct QueriesTestSuiteFixture : odbc::OdbcTestSuite static Ignite StartAdditionalNode(const char* name) { - return StartTestNode("queries-test-noodbc.xml", name); + return StartTestNode("queries-test.xml", name); } /** Node started during the test. */ From 26a882eb5795b7b86e94dedc50c81791a7d04ddd Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Wed, 27 Dec 2017 15:26:25 +0300 Subject: [PATCH 08/89] IGNITE-6810: Fix for SecureSocketClient disconnect. --- .../ignite/odbc/ssl/secure_socket_client.h | 6 ++++++ .../cpp/odbc/src/ssl/secure_socket_client.cpp | 19 ++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h index 5375bb11daddf..9fb82167cb8a9 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h @@ -105,6 +105,12 @@ namespace ignite static void* MakeContext(const std::string& certPath, const std::string& keyPath, const std::string& caPath, diagnostic::Diagnosable& diag); + /** + * Close the connection. + * Internal call. + */ + void CloseInteral(); + /** Certificate file path. */ std::string certPath; diff --git a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp index e4c803bdc308d..ed00dbed52ffb 100644 --- a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp +++ b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp @@ -47,7 +47,7 @@ namespace ignite SecureSocketClient::~SecureSocketClient() { - Close(); + CloseInteral(); if (context) SSL_CTX_free(reinterpret_cast(context)); @@ -165,12 +165,7 @@ namespace ignite void SecureSocketClient::Close() { - if (sslBio) - { - BIO_free_all(reinterpret_cast(sslBio)); - - sslBio = 0; - } + CloseInteral(); } int SecureSocketClient::Send(const int8_t* data, size_t size, int32_t timeout) @@ -320,6 +315,16 @@ namespace ignite return ctx; } + + void SecureSocketClient::CloseInteral() + { + if (sslBio) + { + BIO_free_all(reinterpret_cast(sslBio)); + + sslBio = 0; + } + } } } } From 64e3c89a8c626ab5c77da8aefe2106473cfcc078 Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Thu, 28 Dec 2017 20:54:17 +0300 Subject: [PATCH 09/89] IGNITE-6810: Implemented OpenSSL dynamic loading. --- .../include/ignite/common/platform_utils.h | 16 ++ .../cpp/common/include/ignite/common/utils.h | 7 + .../os/win/src/common/dynamic_load_os.cpp | 4 + .../os/win/src/common/platform_utils.cpp | 15 ++ .../platforms/cpp/common/src/common/utils.cpp | 9 + .../include/ignite/odbc/ssl/ssl_bindings.h | 252 ++++++++++++++++++ .../include/ignite/odbc/ssl/ssl_gateway.h | 140 ++++++++++ .../cpp/odbc/project/vs/odbc.vcxproj | 15 +- .../cpp/odbc/project/vs/odbc.vcxproj.filters | 9 + modules/platforms/cpp/odbc/src/connection.cpp | 13 + .../cpp/odbc/src/ssl/secure_socket_client.cpp | 75 +++--- .../cpp/odbc/src/ssl/ssl_gateway.cpp | 199 ++++++++++++++ 12 files changed, 712 insertions(+), 42 deletions(-) create mode 100644 modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h create mode 100644 modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h create mode 100644 modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp diff --git a/modules/platforms/cpp/common/include/ignite/common/platform_utils.h b/modules/platforms/cpp/common/include/ignite/common/platform_utils.h index b8c6aa63c11de..caaccee42f399 100644 --- a/modules/platforms/cpp/common/include/ignite/common/platform_utils.h +++ b/modules/platforms/cpp/common/include/ignite/common/platform_utils.h @@ -23,6 +23,8 @@ namespace ignite { namespace common { + typedef std::basic_ostream > StdCharOutStream; + /** * Convert struct tm to time_t (UTC). * @@ -87,6 +89,20 @@ namespace ignite * @return @c true if the provided path is the valid directory. */ IGNITE_IMPORT_EXPORT bool IsValidDirectory(const std::string& path); + + /** + * Write file separator to a stream. + * @param ostr Stream. + * @return The same stream for chaining. + */ + IGNITE_IMPORT_EXPORT StdCharOutStream& Fs(StdCharOutStream& ostr); + + /** + * Write dynamic library expansion to a stream. + * @param ostr Stream. + * @return The same stream for chaining. + */ + IGNITE_IMPORT_EXPORT StdCharOutStream& Dle(StdCharOutStream& ostr); } } diff --git a/modules/platforms/cpp/common/include/ignite/common/utils.h b/modules/platforms/cpp/common/include/ignite/common/utils.h index 5022897095a81..792bd60b7e78a 100644 --- a/modules/platforms/cpp/common/include/ignite/common/utils.h +++ b/modules/platforms/cpp/common/include/ignite/common/utils.h @@ -476,6 +476,13 @@ namespace ignite { return BoundInstance(instance, mfunc); } + + /** + * Get dynamic library full name. + * @param name Name without extension. + * @return Full name. + */ + IGNITE_IMPORT_EXPORT std::string GetDynamicLibraryName(const char* name); } } diff --git a/modules/platforms/cpp/common/os/win/src/common/dynamic_load_os.cpp b/modules/platforms/cpp/common/os/win/src/common/dynamic_load_os.cpp index f7812cde61a83..76ca28b25c143 100644 --- a/modules/platforms/cpp/common/os/win/src/common/dynamic_load_os.cpp +++ b/modules/platforms/cpp/common/os/win/src/common/dynamic_load_os.cpp @@ -85,7 +85,11 @@ namespace ignite void Module::Unload() { if (IsLoaded()) + { FreeLibrary(handle); + + handle = NULL; + } } Module LoadModule(const char* path) diff --git a/modules/platforms/cpp/common/os/win/src/common/platform_utils.cpp b/modules/platforms/cpp/common/os/win/src/common/platform_utils.cpp index a0f4505c46b71..057a3d46315eb 100644 --- a/modules/platforms/cpp/common/os/win/src/common/platform_utils.cpp +++ b/modules/platforms/cpp/common/os/win/src/common/platform_utils.cpp @@ -91,5 +91,20 @@ namespace ignite return attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0; } + + StdCharOutStream& Fs(StdCharOutStream& ostr) + { + ostr.put('\\'); + return ostr; + } + + StdCharOutStream& Dle(StdCharOutStream& ostr) + { + static const char expansion[] = ".dll"; + + ostr.write(expansion, sizeof(expansion) - 1); + + return ostr; + } } } diff --git a/modules/platforms/cpp/common/src/common/utils.cpp b/modules/platforms/cpp/common/src/common/utils.cpp index 786d0fb0275c3..54a7d03153170 100644 --- a/modules/platforms/cpp/common/src/common/utils.cpp +++ b/modules/platforms/cpp/common/src/common/utils.cpp @@ -180,5 +180,14 @@ namespace ignite return CTimeToTimestamp(localTime, ns); } + + std::string GetDynamicLibraryName(const char* name) + { + std::stringstream libNameBuffer; + + libNameBuffer << name << Dle; + + return libNameBuffer.str(); + } } } diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h new file mode 100644 index 0000000000000..97996f9cd2b84 --- /dev/null +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h @@ -0,0 +1,252 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_SSL_SSL_BINDINGS +#define _IGNITE_ODBC_SSL_SSL_BINDINGS + +#include +#include + +#include "ignite/odbc/ssl/ssl_gateway.h" + +namespace ignite +{ + namespace odbc + { + namespace ssl + { + inline SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) + { + typedef SSL_CTX*(FuncType)(const SSL_METHOD*); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpSSL_CTX_new); + + return fp(meth); + } + + inline void SSL_CTX_free(SSL_CTX *ctx) + { + typedef void(FuncType)(SSL_CTX*); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpSSL_CTX_free); + + fp(ctx); + } + + inline void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int(*callback) (int, X509_STORE_CTX *)) + { + typedef void(FuncType)(SSL_CTX*, int, int(*)(int, X509_STORE_CTX*)); + + FuncType* fp = reinterpret_cast( + SslGateway::GetInstance().GetFunctions().fpSSL_CTX_set_verify); + + fp(ctx, mode, callback); + } + + inline void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) + { + typedef void(FuncType)(SSL_CTX*, int); + + FuncType* fp = reinterpret_cast( + SslGateway::GetInstance().GetFunctions().fpSSL_CTX_set_verify_depth); + + fp(ctx, depth); + } + + inline int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *cAfile, const char *cApath) + { + typedef int(FuncType)(SSL_CTX*, const char*, const char*); + + FuncType* fp = reinterpret_cast( + SslGateway::GetInstance().GetFunctions().fpSSL_CTX_load_verify_locations); + + return fp(ctx, cAfile, cApath); + } + + inline int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) + { + typedef int(FuncType)(SSL_CTX*, const char*); + + FuncType* fp = reinterpret_cast( + SslGateway::GetInstance().GetFunctions().fpSSL_CTX_use_certificate_chain_file); + + return fp(ctx, file); + } + + inline int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) + { + typedef int(FuncType)(SSL_CTX*, const char*, int); + + FuncType* fp = reinterpret_cast( + SslGateway::GetInstance().GetFunctions().fpSSL_CTX_use_RSAPrivateKey_file); + + return fp(ctx, file, type); + } + + inline int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) + { + typedef int(FuncType)(SSL_CTX*, const char*); + + FuncType* fp = reinterpret_cast( + SslGateway::GetInstance().GetFunctions().fpSSL_CTX_set_cipher_list); + + return fp(ctx, str); + } + + inline long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) + { + typedef long(FuncType)(SSL_CTX*, int, long, void*); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpSSL_CTX_ctrl); + + return fp(ctx, cmd, larg, parg); + } + + inline long SSL_get_verify_result(const SSL *s) + { + typedef long(FuncType)(const SSL*); + + FuncType* fp = reinterpret_cast( + SslGateway::GetInstance().GetFunctions().fpSSL_get_verify_result); + + return fp(s); + } + + inline int SSL_library_init() + { + typedef int(FuncType)(); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpSSL_library_init); + + return fp(); + } + + inline void SSL_load_error_strings() + { + typedef void(FuncType)(); + + FuncType* fp = reinterpret_cast( + SslGateway::GetInstance().GetFunctions().fpSSL_load_error_strings); + + fp(); + } + + inline X509 *SSL_get_peer_certificate(const SSL *s) + { + typedef X509*(FuncType)(const SSL*); + + FuncType* fp = reinterpret_cast( + SslGateway::GetInstance().GetFunctions().fpSSL_get_peer_certificate); + + return fp(s); + } + + inline long SSL_ctrl(SSL *s, int cmd, long larg, void *parg) + { + typedef long(FuncType)(SSL*, int, long, void*); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpSSL_ctrl); + + return fp(s, cmd, larg ,parg); + } + + inline const SSL_METHOD *SSLv23_method() + { + typedef const SSL_METHOD*(FuncType)(); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpSSLv23_method); + + return fp(); + } + + inline void OPENSSL_config(const char *configName) + { + typedef void(FuncType)(const char*); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpOPENSSL_config); + + fp(configName); + } + + inline void X509_free(X509 *a) + { + typedef void(FuncType)(X509*); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpX509_free); + + fp(a); + } + + inline BIO *BIO_new_ssl_connect(SSL_CTX *ctx) + { + typedef BIO*(FuncType)(SSL_CTX*); + + FuncType* fp = reinterpret_cast( + SslGateway::GetInstance().GetFunctions().fpBIO_new_ssl_connect); + + return fp(ctx); + } + + inline int BIO_write(BIO *b, const void *data, int len) + { + typedef int(FuncType)(BIO*, const void*, int); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpBIO_write); + + return fp(b, data, len); + } + + inline int BIO_read(BIO *b, void *data, int len) + { + typedef int(FuncType)(BIO*, const void*, int); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpBIO_read); + + return fp(b, data, len); + } + + inline void BIO_free_all(BIO *a) + { + typedef void(FuncType)(BIO*); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpBIO_free_all); + + fp(a); + } + + inline int BIO_test_flags(const BIO *b, int flags) + { + typedef int(FuncType)(const BIO*, int); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpBIO_test_flags); + + return fp(b, flags); + } + + inline long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg) + { + typedef long(FuncType)(BIO*, int, long, void*); + + FuncType* fp = reinterpret_cast(SslGateway::GetInstance().GetFunctions().fpBIO_ctrl); + + return fp(bp, cmd, larg, parg); + } + } + } +} + +#endif //_IGNITE_ODBC_SSL_SSL_BINDINGS \ No newline at end of file diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h new file mode 100644 index 0000000000000..844871a8bed21 --- /dev/null +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_SSL_SSL_LIBRARY +#define _IGNITE_ODBC_SSL_SSL_LIBRARY + +#include "ignite/common/concurrent.h" +#include "ignite/common/dynamic_load_os.h" + +namespace ignite +{ + namespace odbc + { + namespace ssl + { + /** + * Functions collection. + */ + struct SslFunctions + { + void *fpSSL_CTX_new; + void *fpSSL_CTX_free; + void *fpSSL_CTX_set_verify; + void *fpSSL_CTX_set_verify_depth; + void *fpSSL_CTX_load_verify_locations; + void *fpSSL_CTX_use_certificate_chain_file; + void *fpSSL_CTX_use_RSAPrivateKey_file; + void *fpSSL_CTX_set_cipher_list; + void *fpSSL_CTX_ctrl; + void *fpSSL_get_verify_result; + void *fpSSL_library_init; + void *fpSSL_load_error_strings; + void *fpSSL_get_peer_certificate; + void *fpSSL_ctrl; + void *fpSSLv23_method; + void *fpOPENSSL_config; + void *fpX509_free; + void *fpBIO_new_ssl_connect; + void *fpBIO_write; + void *fpBIO_read; + void *fpBIO_free_all; + void *fpBIO_test_flags; + void *fpBIO_ctrl; + }; + + /** + * SSL Gateway abstraction. + * Used as a factory for secure sockets. Needed for dynamic loading + * of the SSL libraries. + */ + class SslGateway + { + public: + /** + * Get class instance. + * @return SslLibrary instance. + */ + static SslGateway& GetInstance(); + + /** + * Try loading SSL library. + * @return @c true if loaded successfully, and false otherwise. + */ + bool LoadAll(); + + /** + * Get functions. + * @return Functions structure. + */ + SslFunctions& GetFunctions() + { + return functions; + } + + private: + /** + * Constructor. + */ + SslGateway(); + + /** + * Destructor. + */ + ~SslGateway(); + + /** + * Load SSL library. + * @param name Name. + * @return Module. + */ + common::dynamic::Module LoadSslLibrary(const char* name); + + /** + * Load SSL method. + * @param mod Module. + * @param name Name. + * @return Method pointer. + */ + static void* LoadSslMethod(common::dynamic::Module mod, const char* name); + + /** Singlton instance. */ + static SslGateway* self; + + /** Critical section to prevent multiple instance creation. */ + static common::concurrent::CriticalSection constructionCs; + + /** Indicates whether the library was inited. */ + bool inited; + + /** Critical section to prevent multiple instance creation. */ + common::concurrent::CriticalSection initCs; + + /** libeay32 module. */ + common::dynamic::Module libeay32; + + /** ssleay32 module. */ + common::dynamic::Module ssleay32; + + /** Functions. */ + SslFunctions functions; + }; + } + } +} + +#endif //_IGNITE_ODBC_SSL_SSL_LIBRARY \ No newline at end of file diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj index 706614278721c..239a30fc2989e 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj @@ -99,8 +99,10 @@ true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;ssleay32MDd.lib;libeay32MDd.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;%(AdditionalDependencies) $(OPENSSL_HOME)\lib\VC + + @@ -114,8 +116,10 @@ true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;ssleay32MDd.lib;libeay32MDd.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;%(AdditionalDependencies) $(OPENSSL_HOME)\lib\VC + + @@ -133,7 +137,7 @@ true true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;ssleay32MD.lib;libeay32MD.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;%(AdditionalDependencies) $(OPENSSL_HOME)\lib\VC @@ -152,7 +156,7 @@ true true module.def - Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;ssleay32MD.lib;libeay32MD.lib;%(AdditionalDependencies) + Ws2_32.lib;Mswsock.lib;Advapi32.lib;Shlwapi.lib;%(AdditionalDependencies) $(OPENSSL_HOME)\lib\VC @@ -193,6 +197,7 @@ + @@ -239,6 +244,8 @@ + + diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters index fcf46b11d7724..b203b2141cd73 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters @@ -157,6 +157,9 @@ Code\ssl + + Code\ssl + @@ -302,5 +305,11 @@ Code\ssl + + Code\ssl + + + Code\ssl + \ No newline at end of file diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp index 430af66fee800..b39a5993a82fd 100644 --- a/modules/platforms/cpp/odbc/src/connection.cpp +++ b/modules/platforms/cpp/odbc/src/connection.cpp @@ -29,6 +29,7 @@ #include "ignite/odbc/message.h" #include "ignite/odbc/config/configuration.h" #include "ignite/odbc/ssl/ssl_mode.h" +#include "ignite/odbc/ssl/ssl_gateway.h" #include "ignite/odbc/ssl/secure_socket_client.h" #include "ignite/odbc/system/tcp_socket_client.h" @@ -134,7 +135,19 @@ namespace ignite SslMode::T sslMode = SslMode::FromString(cfg.GetSslMode(), SslMode::DISABLE); if (sslMode != SslMode::DISABLE) + { + bool loaded = ssl::SslGateway::GetInstance().LoadAll(); + + if (!loaded) + { + AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, + "Can not load OpenSSL library (have you set OPENSSL_HOME?)."); + + return SqlResult::AI_ERROR; + } + socket.reset(new ssl::SecureSocketClient(cfg.GetSslCertFile(), cfg.GetSslKeyFile(), cfg.GetSslCaFile())); + } else socket.reset(new system::TcpSocketClient()); diff --git a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp index ed00dbed52ffb..97b2ff41e64e0 100644 --- a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp +++ b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp @@ -18,12 +18,10 @@ #include #include -#include -#include - -#include "ignite/common/concurrent.h" #include "ignite/odbc/log.h" +#include "ignite/common/concurrent.h" #include "ignite/odbc/ssl/secure_socket_client.h" +#include "ignite/odbc/ssl/ssl_bindings.h" // Declaring constant used by OpenSSL for readability. enum { SSL_OPERATION_SUCCESS = 1 }; @@ -50,7 +48,7 @@ namespace ignite CloseInteral(); if (context) - SSL_CTX_free(reinterpret_cast(context)); + ssl::SSL_CTX_free(reinterpret_cast(context)); } bool SecureSocketClient::Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag) @@ -68,7 +66,7 @@ namespace ignite } } - BIO* bio = BIO_new_ssl_connect(reinterpret_cast(context)); + BIO* bio = ssl::BIO_new_ssl_connect(reinterpret_cast(context)); if (!bio) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not create SSL connection."); @@ -81,79 +79,80 @@ namespace ignite std::string address = stream.str(); - long res = BIO_set_conn_hostname(bio, address.c_str()); + long res = ssl::BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, const_cast(address.c_str())); if (res != SSL_OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set SSL connection hostname."); - BIO_free_all(bio); + ssl::BIO_free_all(bio); return false; } SSL* ssl = 0; - BIO_get_ssl(bio, &ssl); + ssl::BIO_ctrl(bio, BIO_C_GET_SSL, 0, reinterpret_cast(&ssl)); if (!ssl) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not get SSL instance from BIO."); - BIO_free_all(bio); + ssl::BIO_free_all(bio); return false; } - res = SSL_set_tlsext_host_name(ssl, hostname); + res = ssl::SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, + TLSEXT_NAMETYPE_host_name, const_cast(hostname)); if (res != SSL_OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set host name for secure connection"); - BIO_free_all(bio); + ssl::BIO_free_all(bio); return false; } - res = BIO_do_connect(bio); + res = ssl::BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL); if (res != SSL_OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "Failed to establish secure connection with the host."); - BIO_free_all(bio); + ssl::BIO_free_all(bio); return false; } - res = BIO_do_handshake(bio); + res = ssl::BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL); if (res != SSL_OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "SSL handshake failed."); - BIO_free_all(bio); + ssl::BIO_free_all(bio); return false; } // Verify a server certificate was presented during the negotiation - X509* cert = SSL_get_peer_certificate(ssl); + X509* cert = ssl::SSL_get_peer_certificate(ssl); if (cert) - X509_free(cert); + ssl::X509_free(cert); else { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Remote host did not provide certificate."); - BIO_free_all(bio); + ssl::BIO_free_all(bio); return false; } // Verify the result of chain verification // Verification performed according to RFC 4158 - res = SSL_get_verify_result(ssl); + res = ssl::SSL_get_verify_result(ssl); if (X509_V_OK != res) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Certificate chain verification failed."); - BIO_free_all(bio); + ssl::BIO_free_all(bio); return false; } @@ -184,9 +183,9 @@ namespace ignite do { - res = BIO_write(sslBio0, data, static_cast(size)); + res = ssl::BIO_write(sslBio0, data, static_cast(size)); } - while (BIO_should_retry(sslBio0)); + while (ssl::BIO_test_flags(sslBio0, BIO_FLAGS_SHOULD_RETRY)); return res; } @@ -207,9 +206,9 @@ namespace ignite do { - res = BIO_read(sslBio0, buffer, static_cast(size)); + res = ssl::BIO_read(sslBio0, buffer, static_cast(size)); } - while (BIO_should_retry(sslBio0)); + while (ssl::BIO_test_flags(sslBio0, BIO_FLAGS_SHOULD_RETRY)); return res; } @@ -251,7 +250,7 @@ namespace ignite return 0; } - SSL_CTX* ctx = SSL_CTX_new(method); + SSL_CTX* ctx = ssl::SSL_CTX_new(method); if (!ctx) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not create new SSL context."); @@ -259,56 +258,56 @@ namespace ignite return 0; } - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0); + ssl::SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0); - SSL_CTX_set_verify_depth(ctx, 8); + ssl::SSL_CTX_set_verify_depth(ctx, 8); const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION; - SSL_CTX_set_options(ctx, flags); + ssl::SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, flags, NULL); const char* cCaPath = caPath.empty() ? 0 : caPath.c_str(); - long res = SSL_CTX_load_verify_locations(ctx, cCaPath, 0); + long res = ssl::SSL_CTX_load_verify_locations(ctx, cCaPath, 0); if (res != SSL_OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set Certificate Authority path for secure connection."); - SSL_CTX_free(ctx); + ssl::SSL_CTX_free(ctx); return 0; } - res = SSL_CTX_use_certificate_chain_file(ctx, certPath.c_str()); + res = ssl::SSL_CTX_use_certificate_chain_file(ctx, certPath.c_str()); if (res != SSL_OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set client certificate file for secure connection."); - SSL_CTX_free(ctx); + ssl::SSL_CTX_free(ctx); return 0; } - res = SSL_CTX_use_RSAPrivateKey_file(ctx, keyPath.c_str(), SSL_FILETYPE_PEM); + res = ssl::SSL_CTX_use_RSAPrivateKey_file(ctx, keyPath.c_str(), SSL_FILETYPE_PEM); if (res != SSL_OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set private key file for secure connection."); - SSL_CTX_free(ctx); + ssl::SSL_CTX_free(ctx); return 0; } const char* const PREFERRED_CIPHERS = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4"; - res = SSL_CTX_set_cipher_list(ctx, PREFERRED_CIPHERS); + res = ssl::SSL_CTX_set_cipher_list(ctx, PREFERRED_CIPHERS); if (res != SSL_OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set ciphers list for secure connection."); - SSL_CTX_free(ctx); + ssl::SSL_CTX_free(ctx); return false; } @@ -320,7 +319,7 @@ namespace ignite { if (sslBio) { - BIO_free_all(reinterpret_cast(sslBio)); + ssl::BIO_free_all(reinterpret_cast(sslBio)); sslBio = 0; } diff --git a/modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp b/modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp new file mode 100644 index 0000000000000..d08402c1a8ef7 --- /dev/null +++ b/modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp @@ -0,0 +1,199 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#include "ignite/common/utils.h" + +#include "ignite/odbc/ssl/ssl_gateway.h" +#include "ignite/odbc/log.h" + +namespace ignite +{ + namespace odbc + { + namespace ssl + { + SslGateway* SslGateway::self = 0; + common::concurrent::CriticalSection SslGateway::constructionCs; + + SslGateway::SslGateway() : + inited(false), + functions() + { + // No-op. + } + + SslGateway::~SslGateway() + { + // No-op. + } + + common::dynamic::Module SslGateway::LoadSslLibrary(const char* name) + { + using namespace common; + using namespace dynamic; + + std::string fullName = GetDynamicLibraryName(name); + + Module libModule = LoadModule(fullName); + + if (libModule.IsLoaded()) + return libModule; + + std::string home = GetEnv("OPEN_SSL_HOME"); + + if (home.empty()) + home = GetEnv("OPENSSL_HOME"); + + if (home.empty()) + return libModule; + + std::stringstream constructor; + + constructor << home << Fs << "bin" << Fs << fullName; + + std::string fullPath = constructor.str(); + + return LoadModule(fullPath); + } + + SslGateway& SslGateway::GetInstance() + { + if (!self) + { + common::concurrent::CsLockGuard lock(constructionCs); + + if (!self) + self = new SslGateway(); + } + + return *self; + } + + bool SslGateway::LoadAll() + { + using namespace common::dynamic; + + if (inited) + return true; + + common::concurrent::CsLockGuard lock(initCs); + + if (inited) + return true; + + libeay32 = LoadSslLibrary("libeay32"); + + if (!libeay32.IsLoaded()) + { + LOG_MSG("Can not load libeay32."); + + return false; + } + + ssleay32 = LoadSslLibrary("ssleay32"); + + if (!ssleay32.IsLoaded()) + { + LOG_MSG("Can not load ssleay32."); + + libeay32.Unload(); + + return false; + } + + functions.fpSSL_CTX_new = LoadSslMethod(ssleay32, "SSL_CTX_new"); + functions.fpSSL_CTX_free = LoadSslMethod(ssleay32, "SSL_CTX_free"); + functions.fpSSL_CTX_set_verify = LoadSslMethod(ssleay32, "SSL_CTX_set_verify"); + functions.fpSSL_CTX_set_verify_depth = LoadSslMethod(ssleay32, "SSL_CTX_set_verify_depth"); + functions.fpSSL_CTX_load_verify_locations = LoadSslMethod(ssleay32, "SSL_CTX_load_verify_locations"); + functions.fpSSL_CTX_use_certificate_chain_file = + LoadSslMethod(ssleay32, "SSL_CTX_use_certificate_chain_file"); + functions.fpSSL_CTX_use_RSAPrivateKey_file = LoadSslMethod(ssleay32, "SSL_CTX_use_RSAPrivateKey_file"); + functions.fpSSL_CTX_set_cipher_list = LoadSslMethod(ssleay32, "SSL_CTX_set_cipher_list"); + + functions.fpSSL_get_verify_result = LoadSslMethod(ssleay32, "SSL_get_verify_result"); + functions.fpSSL_library_init = LoadSslMethod(ssleay32, "SSL_library_init"); + functions.fpSSL_load_error_strings = LoadSslMethod(ssleay32, "SSL_load_error_strings"); + functions.fpSSL_get_peer_certificate = LoadSslMethod(ssleay32, "SSL_get_peer_certificate"); + functions.fpSSL_ctrl = LoadSslMethod(ssleay32, "SSL_ctrl"); + functions.fpSSL_CTX_ctrl = LoadSslMethod(ssleay32, "SSL_CTX_ctrl"); + + functions.fpSSLv23_method = LoadSslMethod(ssleay32, "SSLv23_method"); + functions.fpBIO_new_ssl_connect = LoadSslMethod(ssleay32, "BIO_new_ssl_connect"); + + functions.fpOPENSSL_config = LoadSslMethod(libeay32, "OPENSSL_config"); + functions.fpX509_free = LoadSslMethod(libeay32, "X509_free"); + + functions.fpBIO_write = LoadSslMethod(libeay32, "BIO_write"); + functions.fpBIO_read = LoadSslMethod(libeay32, "BIO_read"); + functions.fpBIO_free_all = LoadSslMethod(libeay32, "BIO_free_all"); + functions.fpBIO_test_flags = LoadSslMethod(libeay32, "BIO_test_flags"); + functions.fpBIO_ctrl = LoadSslMethod(libeay32, "BIO_ctrl"); + + bool allLoaded = + functions.fpSSL_CTX_new != 0 && + functions.fpSSL_CTX_free != 0 && + functions.fpSSL_CTX_set_verify != 0 && + functions.fpSSL_CTX_set_verify_depth != 0 && + functions.fpSSL_CTX_load_verify_locations != 0 && + functions.fpSSL_CTX_use_certificate_chain_file != 0 && + functions.fpSSL_CTX_use_RSAPrivateKey_file != 0 && + functions.fpSSL_CTX_set_cipher_list != 0 && + functions.fpSSL_get_verify_result != 0 && + functions.fpSSL_library_init != 0 && + functions.fpSSL_load_error_strings != 0 && + functions.fpSSL_get_peer_certificate != 0 && + functions.fpSSL_ctrl != 0 && + functions.fpSSL_CTX_ctrl != 0 && + functions.fpSSLv23_method != 0 && + functions.fpBIO_new_ssl_connect != 0 && + functions.fpOPENSSL_config != 0 && + functions.fpX509_free != 0 && + functions.fpBIO_write != 0 && + functions.fpBIO_read != 0 && + functions.fpBIO_free_all != 0 && + functions.fpBIO_test_flags != 0 && + functions.fpBIO_ctrl != 0; + + if (!allLoaded) + { + libeay32.Unload(); + ssleay32.Unload(); + } + + inited = allLoaded; + + return inited; + } + + void* SslGateway::LoadSslMethod(common::dynamic::Module mod, const char* name) + { + void* fp = mod.FindSymbol(name); + + if (!fp) + LOG_MSG("Can not load function " << name); + + return fp; + } + } + } +} From 92e3febdd2d54dc0cfb16e6d8d9299dc571b6855 Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Wed, 10 Jan 2018 18:54:49 +0300 Subject: [PATCH 10/89] IGNITE-6810: Minor fixes --- .../cpp/odbc-test/src/queries_ssl_test.cpp | 11 ++++------- .../odbc/include/ignite/odbc/ssl/ssl_gateway.h | 15 +++++++++------ modules/platforms/cpp/odbc/src/connection.cpp | 2 +- modules/platforms/cpp/odbc/src/odbc.cpp | 2 +- .../cpp/odbc/src/ssl/secure_socket_client.cpp | 10 ++++++++++ .../platforms/cpp/odbc/src/ssl/ssl_gateway.cpp | 13 ++----------- 6 files changed, 27 insertions(+), 26 deletions(-) diff --git a/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp index 00f18480aacb0..d8f33a6a23048 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp @@ -82,10 +82,7 @@ struct SslQueriesTestSuiteFixture BOOST_REQUIRE(dbc != NULL); // Connect string - std::vector connectStr0; - - connectStr0.reserve(connectStr.size() + 1); - std::copy(connectStr.begin(), connectStr.end(), std::back_inserter(connectStr0)); + std::vector connectStr0(connectStr.begin(), connectStr.end()); SQLCHAR outstr[ODBC_BUFFER_SIZE]; SQLSMALLINT outstrlen; @@ -524,9 +521,9 @@ BOOST_AUTO_TEST_CASE(TestConnectionSsl) "ADDRESS=127.0.0.1:11110;" "SCHEMA=cache;" "SSL_MODE=require;" - "SSL_KEY_FILE=" << cfgDirPath << "/ssl/client_full.pem;" - "SSL_CERT_FILE=" << cfgDirPath << "/ssl/client_full.pem;" - "SSL_CA_FILE=" << cfgDirPath << "/ssl/ca.pem;"; + "SSL_KEY_FILE=" << cfgDirPath << Fs << "ssl" << Fs << "client_full.pem;" + "SSL_CERT_FILE=" << cfgDirPath << Fs << "ssl" << Fs << "client_full.pem;" + "SSL_CA_FILE=" << cfgDirPath << Fs << "ssl" << Fs << "ca.pem;"; Connect(connectString.str()); diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h index 844871a8bed21..c1118e7ba49d7 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h @@ -86,6 +86,15 @@ namespace ignite return functions; } + /** + * Check whether the libraries are loaded. + * @return @c true if loaded. + */ + bool Loaded() const + { + return inited; + } + private: /** * Constructor. @@ -112,12 +121,6 @@ namespace ignite */ static void* LoadSslMethod(common::dynamic::Module mod, const char* name); - /** Singlton instance. */ - static SslGateway* self; - - /** Critical section to prevent multiple instance creation. */ - static common::concurrent::CriticalSection constructionCs; - /** Indicates whether the library was inited. */ bool inited; diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp index b39a5993a82fd..68be8bf244a20 100644 --- a/modules/platforms/cpp/odbc/src/connection.cpp +++ b/modules/platforms/cpp/odbc/src/connection.cpp @@ -141,7 +141,7 @@ namespace ignite if (!loaded) { AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, - "Can not load OpenSSL library (have you set OPENSSL_HOME?)."); + "Can not load OpenSSL library (did you set OPENSSL_HOME environment variable?)."); return SqlResult::AI_ERROR; } diff --git a/modules/platforms/cpp/odbc/src/odbc.cpp b/modules/platforms/cpp/odbc/src/odbc.cpp index 1480d0b9c9e3a..e4b47b985ef2a 100644 --- a/modules/platforms/cpp/odbc/src/odbc.cpp +++ b/modules/platforms/cpp/odbc/src/odbc.cpp @@ -180,7 +180,7 @@ namespace ignite { using odbc::Environment; - LOG_MSG("SQLFreeEnv called"); + LOG_MSG("SQLFreeEnv called: " << env); Environment *environment = reinterpret_cast(env); diff --git a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp index 97b2ff41e64e0..917c141a8ce72 100644 --- a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp +++ b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp @@ -53,6 +53,8 @@ namespace ignite bool SecureSocketClient::Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag) { + assert(SslGateway::GetInstance().Loaded()); + if (!context) { context = MakeContext(certPath, keyPath, caPath, diag); @@ -169,6 +171,8 @@ namespace ignite int SecureSocketClient::Send(const int8_t* data, size_t size, int32_t timeout) { + assert(SslGateway::GetInstance().Loaded()); + if (!sslBio) { LOG_MSG("Trying to send data using closed connection"); @@ -192,6 +196,8 @@ namespace ignite int SecureSocketClient::Receive(int8_t* buffer, size_t size, int32_t timeout) { + assert(SslGateway::GetInstance().Loaded()); + if (!sslBio) { LOG_MSG("Trying to receive data using closed connection"); @@ -221,6 +227,8 @@ namespace ignite void* SecureSocketClient::MakeContext(const std::string& certPath, const std::string& keyPath, const std::string& caPath, diagnostic::Diagnosable& diag) { + assert(SslGateway::GetInstance().Loaded()); + static bool sslLibInited = false; static common::concurrent::CriticalSection sslCs; @@ -317,6 +325,8 @@ namespace ignite void SecureSocketClient::CloseInteral() { + assert(SslGateway::GetInstance().Loaded()); + if (sslBio) { ssl::BIO_free_all(reinterpret_cast(sslBio)); diff --git a/modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp b/modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp index d08402c1a8ef7..0ebe9da65983c 100644 --- a/modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp +++ b/modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp @@ -31,9 +31,6 @@ namespace ignite { namespace ssl { - SslGateway* SslGateway::self = 0; - common::concurrent::CriticalSection SslGateway::constructionCs; - SslGateway::SslGateway() : inited(false), functions() @@ -77,15 +74,9 @@ namespace ignite SslGateway& SslGateway::GetInstance() { - if (!self) - { - common::concurrent::CsLockGuard lock(constructionCs); - - if (!self) - self = new SslGateway(); - } + static SslGateway self; - return *self; + return self; } bool SslGateway::LoadAll() From 517ff46c5e3dff8ea0969c71963649aa0e709225 Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Thu, 11 Jan 2018 18:37:26 +0300 Subject: [PATCH 11/89] IGNITE-6810: Fixes for Linux --- .../include/ignite/common/platform_utils.h | 1 + .../os/linux/src/common/platform_utils.cpp | 15 + .../cpp/odbc-test/src/api_robustness_test.cpp | 4 +- .../cpp/odbc-test/src/errors_test.cpp | 88 +--- .../cpp/odbc-test/src/meta_queries_test.cpp | 4 +- .../cpp/odbc-test/src/odbc_test_suite.cpp | 21 +- .../cpp/odbc-test/src/queries_ssl_test.cpp | 425 +----------------- .../cpp/odbc-test/src/queries_test.cpp | 4 + .../odbc-test/src/sql_test_suite_fixture.cpp | 4 + modules/platforms/cpp/odbc/Makefile.am | 5 +- .../platforms/cpp/odbc/include/Makefile.am | 6 +- ...ocket_client.cpp => tcp_socket_client.cpp} | 25 +- 12 files changed, 77 insertions(+), 525 deletions(-) rename modules/platforms/cpp/odbc/os/linux/src/system/{socket_client.cpp => tcp_socket_client.cpp} (93%) diff --git a/modules/platforms/cpp/common/include/ignite/common/platform_utils.h b/modules/platforms/cpp/common/include/ignite/common/platform_utils.h index caaccee42f399..83da6ec5dff06 100644 --- a/modules/platforms/cpp/common/include/ignite/common/platform_utils.h +++ b/modules/platforms/cpp/common/include/ignite/common/platform_utils.h @@ -17,6 +17,7 @@ #ifndef _IGNITE_COMMON_PLATFORM_UTILS #define _IGNITE_COMMON_PLATFORM_UTILS +#include #include namespace ignite diff --git a/modules/platforms/cpp/common/os/linux/src/common/platform_utils.cpp b/modules/platforms/cpp/common/os/linux/src/common/platform_utils.cpp index b74f11c9fe01f..88ba8ed27a474 100644 --- a/modules/platforms/cpp/common/os/linux/src/common/platform_utils.cpp +++ b/modules/platforms/cpp/common/os/linux/src/common/platform_utils.cpp @@ -89,5 +89,20 @@ namespace ignite return stat(path.c_str(), &pathStat) != -1 && S_ISDIR(pathStat.st_mode); } + + StdCharOutStream& Fs(StdCharOutStream& ostr) + { + ostr.put('/'); + return ostr; + } + + StdCharOutStream& Dle(StdCharOutStream& ostr) + { + static const char expansion[] = ".so"; + + ostr.write(expansion, sizeof(expansion) - 1); + + return ostr; + } } } diff --git a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp index 8f80dfb9845e4..1438e167a67ee 100644 --- a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp @@ -150,9 +150,7 @@ struct ApiRobustnessTestSuiteFixture : public odbc::OdbcTestSuite */ ~ApiRobustnessTestSuiteFixture() { - Disconnect(); - - Ignition::StopAll(true); + // No-op. } /** Node started during the test. */ diff --git a/modules/platforms/cpp/odbc-test/src/errors_test.cpp b/modules/platforms/cpp/odbc-test/src/errors_test.cpp index bac9fd466da47..6f54afa6d75a7 100644 --- a/modules/platforms/cpp/odbc-test/src/errors_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/errors_test.cpp @@ -42,6 +42,7 @@ #include "test_type.h" #include "complex_type.h" #include "test_utils.h" +#include "odbc_test_suite.h" using namespace ignite; using namespace ignite::cache; @@ -59,83 +60,18 @@ using ignite::impl::binary::BinaryUtils; /** * Test setup fixture. */ -struct ErrorTestSuiteFixture +struct ErrorTestSuiteFixture : odbc::OdbcTestSuite { - /** - * Establish connection to node. - * - * @param connectStr Connection string. - */ - void Connect(const std::string& connectStr) - { - // Allocate an environment handle - SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); - - BOOST_REQUIRE(env != NULL); - - // We want ODBC 3 support - SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast(SQL_OV_ODBC3), 0); - - // Allocate a connection handle - SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); - - BOOST_REQUIRE(dbc != NULL); - - // Connect string - std::vector connectStr0; - - connectStr0.reserve(connectStr.size() + 1); - std::copy(connectStr.begin(), connectStr.end(), std::back_inserter(connectStr0)); - - SQLCHAR outstr[ODBC_BUFFER_SIZE]; - SQLSMALLINT outstrlen; - - // Connecting to ODBC server. - SQLRETURN ret = SQLDriverConnect(dbc, NULL, &connectStr0[0], static_cast(connectStr0.size()), - outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE); - - if (!SQL_SUCCEEDED(ret)) - { - Ignition::StopAll(true); - - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc)); - } - - // Allocate a statement handle - SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); - - BOOST_REQUIRE(stmt != NULL); - } - - void Disconnect() - { - // Releasing statement handle. - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - - // Disconneting from the server. - SQLDisconnect(dbc); - - // Releasing allocated handles. - SQLFreeHandle(SQL_HANDLE_DBC, dbc); - SQLFreeHandle(SQL_HANDLE_ENV, env); - } - static Ignite StartAdditionalNode(const char* name) { -#ifdef IGNITE_TESTS_32 - return StartNode("queries-test-32.xml", name); -#else - return StartNode("queries-test.xml", name); -#endif + return StartTestNode("queries-test.xml", name); } /** * Constructor. */ ErrorTestSuiteFixture() : - env(NULL), - dbc(NULL), - stmt(NULL) + OdbcTestSuite() { // No-op. } @@ -145,22 +81,8 @@ struct ErrorTestSuiteFixture */ ~ErrorTestSuiteFixture() { - Disconnect(); - - Ignition::StopAll(true); + // No-op. } - - /** Frist cache instance. */ - //Cache cache; - - /** ODBC Environment. */ - SQLHENV env; - - /** ODBC Connect. */ - SQLHDBC dbc; - - /** ODBC Statement. */ - SQLHSTMT stmt; }; BOOST_FIXTURE_TEST_SUITE(ErrorTestSuite, ErrorTestSuiteFixture) diff --git a/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp b/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp index b737cd9c9bd18..8e22e3dfd755f 100644 --- a/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp @@ -140,9 +140,7 @@ struct MetaQueriesTestSuiteFixture : public odbc::OdbcTestSuite */ ~MetaQueriesTestSuiteFixture() { - Disconnect(); - - Ignition::StopAll(true); + // No-op. } /** Node started during the test. */ diff --git a/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp b/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp index 09b2182885185..6d0edc9212404 100644 --- a/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp +++ b/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp @@ -86,15 +86,22 @@ namespace ignite void OdbcTestSuite::Disconnect() { - // Releasing statement handle. - SQLFreeHandle(SQL_HANDLE_STMT, stmt); + if (stmt) + { + // Releasing statement handle. + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + + // Disconneting from the server. + SQLDisconnect(dbc); - // Disconneting from the server. - SQLDisconnect(dbc); + // Releasing allocated handles. + SQLFreeHandle(SQL_HANDLE_DBC, dbc); + SQLFreeHandle(SQL_HANDLE_ENV, env); - // Releasing allocated handles. - SQLFreeHandle(SQL_HANDLE_DBC, dbc); - SQLFreeHandle(SQL_HANDLE_ENV, env); + stmt = NULL; + dbc = NULL; + env = NULL; + } } Ignite OdbcTestSuite::StartTestNode(const char* cfg, const char* name) diff --git a/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp index d8f33a6a23048..c51a5c735e2cb 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp @@ -42,6 +42,7 @@ #include "test_type.h" #include "complex_type.h" #include "test_utils.h" +#include "odbc_test_suite.h" using namespace ignite; using namespace ignite::cache; @@ -59,88 +60,22 @@ using ignite::impl::binary::BinaryUtils; /** * Test setup fixture. */ -struct SslQueriesTestSuiteFixture +struct SslQueriesTestSuiteFixture : odbc::OdbcTestSuite { - /** - * Establish connection to node. - * - * @param connectStr Connection string. - */ - void Connect(const std::string& connectStr) - { - // Allocate an environment handle - SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); - - BOOST_REQUIRE(env != NULL); - - // We want ODBC 3 support - SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast(SQL_OV_ODBC3), 0); - - // Allocate a connection handle - SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); - - BOOST_REQUIRE(dbc != NULL); - - // Connect string - std::vector connectStr0(connectStr.begin(), connectStr.end()); - - SQLCHAR outstr[ODBC_BUFFER_SIZE]; - SQLSMALLINT outstrlen; - - // Connecting to ODBC server. - SQLRETURN ret = SQLDriverConnect(dbc, NULL, &connectStr0[0], static_cast(connectStr0.size()), - outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE); - - if (!SQL_SUCCEEDED(ret)) - { - Ignition::Stop(grid.GetName(), true); - - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc)); - } - - // Allocate a statement handle - SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); - - BOOST_REQUIRE(stmt != NULL); - } - - void Disconnect() - { - // Releasing statement handle. - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - - // Disconneting from the server. - SQLDisconnect(dbc); - - // Releasing allocated handles. - SQLFreeHandle(SQL_HANDLE_DBC, dbc); - SQLFreeHandle(SQL_HANDLE_ENV, env); - } - static Ignite StartAdditionalNode(const char* name) { -#ifdef IGNITE_TESTS_32 - return StartNode("queries-ssl-32.xml", name); -#else - return StartNode("queries-ssl.xml", name); -#endif + return StartTestNode("queries-ssl.xml", name); } /** * Constructor. */ SslQueriesTestSuiteFixture() : + OdbcTestSuite(), cache1(0), - cache2(0), - env(NULL), - dbc(NULL), - stmt(NULL) + cache2(0) { -#ifdef IGNITE_TESTS_32 - grid = StartNode("queries-ssl-32.xml", "NodeMain"); -#else - grid = StartNode("queries-ssl.xml", "NodeMain"); -#endif + grid = StartAdditionalNode("NodeMain"); cache1 = grid.GetCache("cache"); cache2 = grid.GetCache("cache2"); @@ -149,344 +84,9 @@ struct SslQueriesTestSuiteFixture /** * Destructor. */ - ~SslQueriesTestSuiteFixture() - { - Disconnect(); - - Ignition::StopAll(true); - } - - void CheckParamsNum(const std::string& req, SQLSMALLINT expectedParamsNum) - { - std::vector req0(req.begin(), req.end()); - - SQLRETURN ret = SQLPrepare(stmt, &req0[0], static_cast(req0.size())); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - SQLSMALLINT paramsNum = -1; - - ret = SQLNumParams(stmt, ¶msNum); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECK_EQUAL(paramsNum, expectedParamsNum); - } - - int CountRows(SQLHSTMT stmt) - { - int res = 0; - - SQLRETURN ret = SQL_SUCCESS; - - while (ret == SQL_SUCCESS) - { - ret = SQLFetch(stmt); - - if (ret == SQL_NO_DATA) - break; - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - ++res; - } - - return res; - } - - static std::string getTestString(int64_t ind) + virtual ~SslQueriesTestSuiteFixture() { - std::stringstream builder; - - builder << "String#" << ind; - - return builder.str(); - } - - /** - * Insert requested number of TestType values with all defaults except - * for the strFields, which are generated using getTestString(). - * - * @param recordsNum Number of records to insert. - * @param merge Set to true to use merge instead. - */ - void InsertTestStrings(int recordsNum, bool merge = false) - { - SQLCHAR insertReq[] = "INSERT INTO TestType(_key, strField) VALUES(?, ?)"; - SQLCHAR mergeReq[] = "MERGE INTO TestType(_key, strField) VALUES(?, ?)"; - - SQLRETURN ret; - - ret = SQLPrepare(stmt, merge ? mergeReq : insertReq, SQL_NTS); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - int64_t key = 0; - char strField[1024] = { 0 }; - SQLLEN strFieldLen = 0; - - // Binding parameters. - ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(strField), - sizeof(strField), &strField, sizeof(strField), &strFieldLen); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - // Inserting values. - for (SQLSMALLINT i = 0; i < recordsNum; ++i) - { - key = i + 1; - std::string val = getTestString(i); - - strncpy(strField, val.c_str(), sizeof(strField)); - strFieldLen = SQL_NTS; - - ret = SQLExecute(stmt); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - SQLLEN affected = 0; - ret = SQLRowCount(stmt, &affected); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECK_EQUAL(affected, 1); - - ret = SQLMoreResults(stmt); - - if (ret != SQL_NO_DATA) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - } - - // Resetting parameters. - ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - } - - /** - * Insert requested number of TestType values in a batch. - * - * @param from Index to start from. - * @param to Index to stop. - * @param expectedToAffect Expected number of affected records. - * @param merge Set to true to use merge instead of insert. - * @return Records inserted. - */ - int InsertTestBatch(int from, int to, int expectedToAffect, bool merge = false) - { - SQLCHAR insertReq[] = "INSERT " - "INTO TestType(_key, i8Field, i16Field, i32Field, strField, floatField, doubleField, boolField, dateField, " - "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - - SQLCHAR mergeReq[] = "MERGE " - "INTO TestType(_key, i8Field, i16Field, i32Field, strField, floatField, doubleField, boolField, dateField, " - "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - - SQLRETURN ret; - - int recordsNum = to - from; - - ret = SQLPrepare(stmt, merge ? mergeReq : insertReq, SQL_NTS); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - FixedSizeArray keys(recordsNum); - FixedSizeArray i8Fields(recordsNum); - FixedSizeArray i16Fields(recordsNum); - FixedSizeArray i32Fields(recordsNum); - FixedSizeArray strFields(recordsNum * 1024); - FixedSizeArray floatFields(recordsNum); - FixedSizeArray doubleFields(recordsNum); - FixedSizeArray boolFields(recordsNum); - FixedSizeArray dateFields(recordsNum); - FixedSizeArray timeFields(recordsNum); - FixedSizeArray timestampFields(recordsNum); - FixedSizeArray i8ArrayFields(recordsNum * 42); - - FixedSizeArray strFieldsLen(recordsNum); - FixedSizeArray i8ArrayFieldsLen(recordsNum); - - BOOST_CHECKPOINT("Filling param data"); - - for (int i = 0; i < recordsNum; ++i) - { - int seed = from + i; - - keys[i] = seed; - i8Fields[i] = seed * 8; - i16Fields[i] = seed * 16; - i32Fields[i] = seed * 32; - - std::string val = getTestString(seed); - strncpy(strFields.GetData() + 1024 * i, val.c_str(), 1023); - strFieldsLen[i] = val.size(); - - floatFields[i] = seed * 0.5f; - doubleFields[i] = seed * 0.25f; - boolFields[i] = seed % 2 == 0; - - dateFields[i].year = 2017 + seed / 365; - dateFields[i].month = ((seed / 28) % 12) + 1; - dateFields[i].day = (seed % 28) + 1; - - timeFields[i].hour = (seed / 3600) % 24; - timeFields[i].minute = (seed / 60) % 60; - timeFields[i].second = seed % 60; - - timestampFields[i].year = dateFields[i].year; - timestampFields[i].month = dateFields[i].month; - timestampFields[i].day = dateFields[i].day; - timestampFields[i].hour = timeFields[i].hour; - timestampFields[i].minute = timeFields[i].minute; - timestampFields[i].second = timeFields[i].second; - timestampFields[i].fraction = std::abs(seed * 914873) % 1000000000; - - for (int j = 0; j < 42; ++j) - i8ArrayFields[i * 42 + j] = seed * 42 + j; - i8ArrayFieldsLen[i] = 42; - } - - SQLULEN setsProcessed = 0; - - BOOST_CHECKPOINT("Setting processed pointer"); - ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &setsProcessed, SQL_IS_POINTER); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding keys"); - ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, keys.GetData(), 0, 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding i8Fields"); - ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_STINYINT, SQL_TINYINT, 0, 0, i8Fields.GetData(), 0, 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding i16Fields"); - ret = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_SMALLINT, 0, 0, i16Fields.GetData(), 0, 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding i32Fields"); - ret = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, i32Fields.GetData(), 0, 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding strFields"); - ret = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 1024, 0, strFields.GetData(), 1024, strFieldsLen.GetData()); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding floatFields"); - ret = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, 0, 0, floatFields.GetData(), 0, 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding doubleFields"); - ret = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, doubleFields.GetData(), 0, 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding boolFields"); - ret = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, 0, 0, boolFields.GetData(), 0, 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding dateFields"); - ret = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_DATE, SQL_DATE, 0, 0, dateFields.GetData(), 0, 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding timeFields"); - ret = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_TIME, SQL_TIME, 0, 0, timeFields.GetData(), 0, 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding timestampFields"); - ret = SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 0, 0, timestampFields.GetData(), 0, 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Binding i8ArrayFields"); - ret = SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_BINARY, 42, 0, i8ArrayFields.GetData(), 42, i8ArrayFieldsLen.GetData()); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Setting paramset size"); - ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast(recordsNum), 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Executing query"); - ret = SQLExecute(stmt); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - SQLLEN totallyAffected = 0; - - do - { - SQLLEN affected = 0; - ret = SQLRowCount(stmt, &affected); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - totallyAffected += affected; - - BOOST_CHECKPOINT("Getting next result set"); - - ret = SQLMoreResults(stmt); - - if (ret != SQL_SUCCESS && ret != SQL_NO_DATA) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - } while (ret != SQL_NO_DATA); - - BOOST_CHECK_EQUAL(totallyAffected, expectedToAffect); - - BOOST_CHECKPOINT("Resetting parameters."); - ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - BOOST_CHECKPOINT("Setting paramset size"); - ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast(1), 0); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - return static_cast(setsProcessed); + // No-op. } /** Node started during the test. */ @@ -497,15 +97,6 @@ struct SslQueriesTestSuiteFixture /** Second cache instance. */ Cache cache2; - - /** ODBC Environment. */ - SQLHENV env; - - /** ODBC Connect. */ - SQLHDBC dbc; - - /** ODBC Statement. */ - SQLHSTMT stmt; }; BOOST_FIXTURE_TEST_SUITE(SslQueriesTestSuite, SslQueriesTestSuiteFixture) diff --git a/modules/platforms/cpp/odbc-test/src/queries_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_test.cpp index 591d69d46a564..639e16f749554 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp @@ -1446,6 +1446,10 @@ BOOST_AUTO_TEST_CASE(TestKeyVal) ret = SQLFetch(stmt); BOOST_CHECK(ret == SQL_NO_DATA); + ret = SQLFreeStmt(stmt, SQL_CLOSE); + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + SQLCHAR requestStar[] = "SELECT _key, _val, * FROM ComplexType"; ret = SQLExecDirect(stmt, requestStar, SQL_NTS); diff --git a/modules/platforms/cpp/odbc-test/src/sql_test_suite_fixture.cpp b/modules/platforms/cpp/odbc-test/src/sql_test_suite_fixture.cpp index f905ff7449760..42dd3f72066e7 100644 --- a/modules/platforms/cpp/odbc-test/src/sql_test_suite_fixture.cpp +++ b/modules/platforms/cpp/odbc-test/src/sql_test_suite_fixture.cpp @@ -110,6 +110,10 @@ namespace ignite ret = SQLFetch(stmt); BOOST_CHECK(ret == SQL_NO_DATA); + + ret = SQLFreeStmt(stmt, SQL_CLOSE); + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); } template<> diff --git a/modules/platforms/cpp/odbc/Makefile.am b/modules/platforms/cpp/odbc/Makefile.am index 8d7693c7a5d1a..ea74c34c6c2a0 100644 --- a/modules/platforms/cpp/odbc/Makefile.am +++ b/modules/platforms/cpp/odbc/Makefile.am @@ -49,7 +49,7 @@ libignite_odbc_la_DEPENDENCIES = \ @top_srcdir@/binary/libignite-binary.la libignite_odbc_la_SOURCES = \ - os/linux/src/system/socket_client.cpp \ + os/linux/src/system/tcp_socket_client.cpp \ src/app/application_data_buffer.cpp \ src/app/parameter.cpp \ src/app/parameter_set.cpp \ @@ -75,6 +75,9 @@ libignite_odbc_la_SOURCES = \ src/query/table_metadata_query.cpp \ src/query/type_info_query.cpp \ src/query/special_columns_query.cpp \ + src/ssl/ssl_gateway.cpp \ + src/ssl/secure_socket_client.cpp \ + src/ssl/ssl_mode.cpp \ src/protocol_version.cpp \ src/result_page.cpp \ src/row.cpp \ diff --git a/modules/platforms/cpp/odbc/include/Makefile.am b/modules/platforms/cpp/odbc/include/Makefile.am index 7c64754324833..9bdb8035e20da 100644 --- a/modules/platforms/cpp/odbc/include/Makefile.am +++ b/modules/platforms/cpp/odbc/include/Makefile.am @@ -42,7 +42,7 @@ noinst_HEADERS = \ ignite/odbc/environment.h \ ignite/odbc/dsn_config.h \ ignite/odbc/system/odbc_constants.h \ - ignite/odbc/system/socket_client.h \ + ignite/odbc/system/tcp_socket_client.h \ ignite/odbc/meta/primary_key_meta.h \ ignite/odbc/meta/column_meta.h \ ignite/odbc/meta/table_meta.h \ @@ -50,6 +50,10 @@ noinst_HEADERS = \ ignite/odbc/diagnostic/diagnostic_record_storage.h \ ignite/odbc/diagnostic/diagnosable.h \ ignite/odbc/diagnostic/diagnosable_adapter.h \ + ignite/odbc/ssl/ssl_mode.h \ + ignite/odbc/ssl/ssl_bindings.h \ + ignite/odbc/ssl/secure_socket_client.h \ + ignite/odbc/ssl/ssl_gateway.h \ ignite/odbc/connection.h \ ignite/odbc/odbc_error.h \ ignite/odbc/message.h \ diff --git a/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp b/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp similarity index 93% rename from modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp rename to modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp index a6d61514f8699..6845ae02bc5cd 100644 --- a/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp +++ b/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp @@ -26,7 +26,7 @@ #include -#include "ignite/odbc/system/socket_client.h" +#include "ignite/odbc/system/tcp_socket_client.h" #include "ignite/odbc/utility.h" #include "ignite/odbc/log.h" @@ -72,22 +72,22 @@ namespace ignite { namespace odbc { - namespace tcp + namespace system { - SocketClient::SocketClient() : + TcpSocketClient::TcpSocketClient() : socketHandle(SOCKET_ERROR), blocking(true) { // No-op. } - SocketClient::~SocketClient() + TcpSocketClient::~TcpSocketClient() { Close(); } - bool SocketClient::Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag) + bool TcpSocketClient::Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag) { LOG_MSG("Host: " << hostname << ", port: " << port); @@ -172,7 +172,7 @@ namespace ignite return socketHandle != SOCKET_ERROR; } - void SocketClient::Close() + void TcpSocketClient::Close() { if (socketHandle != SOCKET_ERROR) { @@ -182,7 +182,7 @@ namespace ignite } } - int SocketClient::Send(const int8_t* data, size_t size, int32_t timeout) + int TcpSocketClient::Send(const int8_t* data, size_t size, int32_t timeout) { if (!blocking) { @@ -195,7 +195,7 @@ namespace ignite return send(socketHandle, reinterpret_cast(data), static_cast(size), 0); } - int SocketClient::Receive(int8_t* buffer, size_t size, int32_t timeout) + int TcpSocketClient::Receive(int8_t* buffer, size_t size, int32_t timeout) { if (!blocking) { @@ -208,7 +208,12 @@ namespace ignite return recv(socketHandle, reinterpret_cast(buffer), static_cast(size), 0); } - void SocketClient::TrySetOptions(diagnostic::Diagnosable& diag) + bool TcpSocketClient::IsBlocking() const + { + return blocking; + } + + void TcpSocketClient::TrySetOptions(diagnostic::Diagnosable& diag) { int trueOpt = 1; int bufSizeOpt = BUFFER_SIZE; @@ -310,7 +315,7 @@ namespace ignite } - int SocketClient::WaitOnSocket(int32_t timeout, bool rd) + int TcpSocketClient::WaitOnSocket(int32_t timeout, bool rd) { int ready = 0; int lastError = 0; From 56b2d1046a85bed85e3e3955f974f507cdfa8e61 Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Thu, 11 Jan 2018 18:41:06 +0300 Subject: [PATCH 12/89] IGNITE-6810: Fixed test --- modules/platforms/cpp/odbc-test/src/errors_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/platforms/cpp/odbc-test/src/errors_test.cpp b/modules/platforms/cpp/odbc-test/src/errors_test.cpp index 6f54afa6d75a7..9c640ba9e3689 100644 --- a/modules/platforms/cpp/odbc-test/src/errors_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/errors_test.cpp @@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE(TestConnectFail) BOOST_REQUIRE(dbc != NULL); // Connect string - SQLCHAR connectStr[] = "DRIVER={Apache Ignite};ADDRESS=127.0.0.1:9999;SCHEMA=cache"; + SQLCHAR connectStr[] = "DRIVER={Apache Ignite};ADDRESS=127.0.0.1:1111;SCHEMA=cache"; SQLCHAR outstr[ODBC_BUFFER_SIZE]; SQLSMALLINT outstrlen; From 9f719cd720e798a3f9e128a7eae7ae7adb855acb Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Thu, 11 Jan 2018 19:42:55 +0300 Subject: [PATCH 13/89] IGNITE-6810: Changes for Linux --- .../include/ignite/odbc/ssl/ssl_gateway.h | 10 +- .../cpp/odbc/src/ssl/secure_socket_client.cpp | 2 +- .../cpp/odbc/src/ssl/ssl_gateway.cpp | 110 +++++++++++------- 3 files changed, 75 insertions(+), 47 deletions(-) diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h index c1118e7ba49d7..b131228f01fad 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_gateway.h @@ -113,13 +113,18 @@ namespace ignite */ common::dynamic::Module LoadSslLibrary(const char* name); + /** + * Load all SSL libraries. + */ + bool LoadSslLibraries(); + /** * Load SSL method. * @param mod Module. * @param name Name. * @return Method pointer. */ - static void* LoadSslMethod(common::dynamic::Module mod, const char* name); + void* LoadSslMethod(const char* name); /** Indicates whether the library was inited. */ bool inited; @@ -133,6 +138,9 @@ namespace ignite /** ssleay32 module. */ common::dynamic::Module ssleay32; + /** libssl module. */ + common::dynamic::Module libssl; + /** Functions. */ SslFunctions functions; }; diff --git a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp index 917c141a8ce72..68cbced529537 100644 --- a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp +++ b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp @@ -317,7 +317,7 @@ namespace ignite ssl::SSL_CTX_free(ctx); - return false; + return 0; } return ctx; diff --git a/modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp b/modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp index 0ebe9da65983c..c91d44ed08902 100644 --- a/modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp +++ b/modules/platforms/cpp/odbc/src/ssl/ssl_gateway.cpp @@ -72,6 +72,33 @@ namespace ignite return LoadModule(fullPath); } + bool SslGateway::LoadSslLibraries() + { + libeay32 = LoadSslLibrary("libeay32"); + ssleay32 = LoadSslLibrary("ssleay32"); + libssl = LoadSslLibrary("libssl"); + + if (!libssl.IsLoaded() && (!libeay32.IsLoaded() || !ssleay32.IsLoaded())) + { + if (!libeay32.IsLoaded()) + LOG_MSG("Can not load libeay32."); + + if (!ssleay32.IsLoaded()) + LOG_MSG("Can not load ssleay32."); + + if (!libssl.IsLoaded()) + LOG_MSG("Can not load libssl."); + + libeay32.Unload(); + ssleay32.Unload(); + libssl.Unload(); + + return false; + } + + return true; + } + SslGateway& SslGateway::GetInstance() { static SslGateway self; @@ -91,54 +118,40 @@ namespace ignite if (inited) return true; - libeay32 = LoadSslLibrary("libeay32"); - - if (!libeay32.IsLoaded()) + if (!LoadSslLibraries()) { - LOG_MSG("Can not load libeay32."); + LOG_MSG("Can not load neccessary OpenSSL libraries."); return false; } - ssleay32 = LoadSslLibrary("ssleay32"); - - if (!ssleay32.IsLoaded()) - { - LOG_MSG("Can not load ssleay32."); - - libeay32.Unload(); - - return false; - } - - functions.fpSSL_CTX_new = LoadSslMethod(ssleay32, "SSL_CTX_new"); - functions.fpSSL_CTX_free = LoadSslMethod(ssleay32, "SSL_CTX_free"); - functions.fpSSL_CTX_set_verify = LoadSslMethod(ssleay32, "SSL_CTX_set_verify"); - functions.fpSSL_CTX_set_verify_depth = LoadSslMethod(ssleay32, "SSL_CTX_set_verify_depth"); - functions.fpSSL_CTX_load_verify_locations = LoadSslMethod(ssleay32, "SSL_CTX_load_verify_locations"); - functions.fpSSL_CTX_use_certificate_chain_file = - LoadSslMethod(ssleay32, "SSL_CTX_use_certificate_chain_file"); - functions.fpSSL_CTX_use_RSAPrivateKey_file = LoadSslMethod(ssleay32, "SSL_CTX_use_RSAPrivateKey_file"); - functions.fpSSL_CTX_set_cipher_list = LoadSslMethod(ssleay32, "SSL_CTX_set_cipher_list"); - - functions.fpSSL_get_verify_result = LoadSslMethod(ssleay32, "SSL_get_verify_result"); - functions.fpSSL_library_init = LoadSslMethod(ssleay32, "SSL_library_init"); - functions.fpSSL_load_error_strings = LoadSslMethod(ssleay32, "SSL_load_error_strings"); - functions.fpSSL_get_peer_certificate = LoadSslMethod(ssleay32, "SSL_get_peer_certificate"); - functions.fpSSL_ctrl = LoadSslMethod(ssleay32, "SSL_ctrl"); - functions.fpSSL_CTX_ctrl = LoadSslMethod(ssleay32, "SSL_CTX_ctrl"); - - functions.fpSSLv23_method = LoadSslMethod(ssleay32, "SSLv23_method"); - functions.fpBIO_new_ssl_connect = LoadSslMethod(ssleay32, "BIO_new_ssl_connect"); - - functions.fpOPENSSL_config = LoadSslMethod(libeay32, "OPENSSL_config"); - functions.fpX509_free = LoadSslMethod(libeay32, "X509_free"); - - functions.fpBIO_write = LoadSslMethod(libeay32, "BIO_write"); - functions.fpBIO_read = LoadSslMethod(libeay32, "BIO_read"); - functions.fpBIO_free_all = LoadSslMethod(libeay32, "BIO_free_all"); - functions.fpBIO_test_flags = LoadSslMethod(libeay32, "BIO_test_flags"); - functions.fpBIO_ctrl = LoadSslMethod(libeay32, "BIO_ctrl"); + functions.fpSSL_CTX_new = LoadSslMethod("SSL_CTX_new"); + functions.fpSSL_CTX_free = LoadSslMethod("SSL_CTX_free"); + functions.fpSSL_CTX_set_verify = LoadSslMethod("SSL_CTX_set_verify"); + functions.fpSSL_CTX_set_verify_depth = LoadSslMethod("SSL_CTX_set_verify_depth"); + functions.fpSSL_CTX_load_verify_locations = LoadSslMethod("SSL_CTX_load_verify_locations"); + functions.fpSSL_CTX_use_certificate_chain_file = LoadSslMethod("SSL_CTX_use_certificate_chain_file"); + functions.fpSSL_CTX_use_RSAPrivateKey_file = LoadSslMethod("SSL_CTX_use_RSAPrivateKey_file"); + functions.fpSSL_CTX_set_cipher_list = LoadSslMethod("SSL_CTX_set_cipher_list"); + + functions.fpSSL_get_verify_result = LoadSslMethod("SSL_get_verify_result"); + functions.fpSSL_library_init = LoadSslMethod("SSL_library_init"); + functions.fpSSL_load_error_strings = LoadSslMethod("SSL_load_error_strings"); + functions.fpSSL_get_peer_certificate = LoadSslMethod("SSL_get_peer_certificate"); + functions.fpSSL_ctrl = LoadSslMethod("SSL_ctrl"); + functions.fpSSL_CTX_ctrl = LoadSslMethod("SSL_CTX_ctrl"); + + functions.fpSSLv23_method = LoadSslMethod("SSLv23_method"); + functions.fpBIO_new_ssl_connect = LoadSslMethod("BIO_new_ssl_connect"); + + functions.fpOPENSSL_config = LoadSslMethod("OPENSSL_config"); + functions.fpX509_free = LoadSslMethod("X509_free"); + + functions.fpBIO_write = LoadSslMethod("BIO_write"); + functions.fpBIO_read = LoadSslMethod("BIO_read"); + functions.fpBIO_free_all = LoadSslMethod("BIO_free_all"); + functions.fpBIO_test_flags = LoadSslMethod("BIO_test_flags"); + functions.fpBIO_ctrl = LoadSslMethod("BIO_ctrl"); bool allLoaded = functions.fpSSL_CTX_new != 0 && @@ -169,6 +182,7 @@ namespace ignite { libeay32.Unload(); ssleay32.Unload(); + libssl.Unload(); } inited = allLoaded; @@ -176,9 +190,15 @@ namespace ignite return inited; } - void* SslGateway::LoadSslMethod(common::dynamic::Module mod, const char* name) + void* SslGateway::LoadSslMethod(const char* name) { - void* fp = mod.FindSymbol(name); + void* fp = libeay32.FindSymbol(name); + + if (!fp) + fp = ssleay32.FindSymbol(name); + + if (!fp) + fp = libssl.FindSymbol(name); if (!fp) LOG_MSG("Can not load function " << name); From cf4c716749b5b7b0f6d20bc48b0992a6233fbe3d Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Fri, 12 Jan 2018 12:08:33 +0300 Subject: [PATCH 14/89] IGNITE-6810: Merge-related fixes --- .../processors/odbc/ClientListenerProcessor.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java index 81136e145c201..4797591980963 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java @@ -115,22 +115,10 @@ public ClientListenerProcessor(GridKernalContext ctx) { GridNioFilter[] filters = makeFilters(); int maxOpenCursors = cliConnCfg.getMaxOpenCursorsPerConnection(); + long idleTimeout = cliConnCfg.getIdleTimeout(); for (int port = cliConnCfg.getPort(); port <= portTo && port <= 65535; port++) { try { - GridNioFilter[] filters = new GridNioFilter[] { - new GridNioAsyncNotifyFilter(ctx.igniteInstanceName(), execSvc, log) { - @Override public void onSessionOpened(GridNioSession ses) - throws IgniteCheckedException { - proceedSessionOpened(ses); - } - }, - new GridNioCodecFilter(new ClientListenerBufferedParser(), log, false) - }; - - int maxOpenCursors = cliConnCfg.getMaxOpenCursorsPerConnection(); - long idleTimeout = cliConnCfg.getIdleTimeout(); - GridNioServer srv0 = GridNioServer.builder() .address(hostAddr) .port(port) From a5aec9b62aedf24434d9ea12c9259ef04db74ed9 Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Tue, 16 Jan 2018 18:46:38 +0300 Subject: [PATCH 15/89] IGNITE-6810: Improved Server-side --- .../ClientConnectorConfiguration.java | 116 ++++++++++++++++++ .../odbc/ClientListenerBufferedParser.java | 6 +- .../odbc/ClientListenerNioListener.java | 8 ++ .../odbc/ClientListenerNioServerBuffer.java | 12 +- .../odbc/ClientListenerProcessor.java | 49 +++++--- .../cpp/odbc-test/config/queries-ssl-32.xml | 25 ++-- .../cpp/odbc-test/config/queries-ssl.xml | 27 ++-- .../cpp/odbc-test/include/odbc_test_suite.h | 3 - .../cpp/odbc-test/src/api_robustness_test.cpp | 3 +- .../cpp/odbc-test/src/odbc_test_suite.cpp | 13 +- .../include/ignite/odbc/ssl/ssl_bindings.h | 3 + .../cpp/odbc/src/ssl/secure_socket_client.cpp | 19 ++- 12 files changed, 227 insertions(+), 57 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/ClientConnectorConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/ClientConnectorConfiguration.java index d2520d2373459..397d2596cbe78 100644 --- a/modules/core/src/main/java/org/apache/ignite/configuration/ClientConnectorConfiguration.java +++ b/modules/core/src/main/java/org/apache/ignite/configuration/ClientConnectorConfiguration.java @@ -17,7 +17,10 @@ package org.apache.ignite.configuration; +import javax.cache.configuration.Factory; +import javax.net.ssl.SSLContext; import org.apache.ignite.internal.util.typedef.internal.S; +import org.apache.ignite.ssl.SslContextFactory; import org.jetbrains.annotations.Nullable; /** @@ -45,6 +48,9 @@ public class ClientConnectorConfiguration { /** Default idle timeout. */ public static final int DFLT_IDLE_TIMEOUT = 0; + /** Default value of whether to use Ignite SSL context factory. */ + public static final boolean DFLT_USE_IGNITE_SSL_CTX_FACTORY = true; + /** Host. */ private String host; @@ -72,6 +78,18 @@ public class ClientConnectorConfiguration { /** Idle timeout. */ private long idleTimeout = DFLT_IDLE_TIMEOUT; + /** SSL enable flag, default is disabled. */ + private boolean sslEnabled; + + /** If to use SSL context factory from Ignite configuration. */ + private boolean useIgniteSslCtxFactory = DFLT_USE_IGNITE_SSL_CTX_FACTORY; + + /** SSL need client auth flag. */ + private boolean sslClientAuth; + + /** SSL connection factory. */ + private Factory sslCtxFactory; + /** * Creates SQL connector configuration with all default values. */ @@ -96,6 +114,10 @@ public ClientConnectorConfiguration(ClientConnectorConfiguration cfg) { tcpNoDelay = cfg.isTcpNoDelay(); threadPoolSize = cfg.getThreadPoolSize(); idleTimeout = cfg.getIdleTimeout(); + sslEnabled = cfg.isSslEnabled(); + sslClientAuth = cfg.isSslClientAuth(); + useIgniteSslCtxFactory = cfg.isUseIgniteSslContextFactory(); + sslCtxFactory = cfg.getSslContextFactory(); } /** @@ -301,6 +323,100 @@ public ClientConnectorConfiguration setIdleTimeout(long idleTimeout) { return this; } + /** + * Whether secure socket layer should be enabled on client connector. + *

+ * Note that if this flag is set to {@code true}, an instance of {@code Factory<SSLContext>} + * should be provided, otherwise client connector will fail to start. + * + * @return {@code True} if SSL should be enabled. + */ + public boolean isSslEnabled() { + return sslEnabled; + } + + /** + * Sets whether Secure Socket Layer should be enabled for client connector. + *

+ * Note that if this flag is set to {@code true}, then a valid instance of {@code Factory<SSLContext>} + * should be provided in {@link IgniteConfiguration}. Otherwise, TCP binary protocol will fail to start. + * + * @param sslEnabled {@code True} if SSL should be enabled. + * @return {@code this} for chaining. + */ + public ClientConnectorConfiguration setSslEnabled(boolean sslEnabled) { + this.sslEnabled = sslEnabled; + + return this; + } + + /** + * Gets whether to use Ignite SSL context factory configured through + * {@link IgniteConfiguration#getSslContextFactory()} if {@link #getSslContextFactory()} is not set. + * + * @return {@code True} if Ignite SSL context factory can be used. + */ + public boolean isUseIgniteSslContextFactory() { + return useIgniteSslCtxFactory; + } + + /** + * Sets whether to use Ignite SSL context factory. See {@link #isUseIgniteSslContextFactory()} for more information. + * + * @param useIgniteSslCtxFactory Whether to use Ignite SSL context factory + * @return {@code this} for chaining. + */ + public ClientConnectorConfiguration setUseIgniteSslContextFactory(boolean useIgniteSslCtxFactory) { + this.useIgniteSslCtxFactory = useIgniteSslCtxFactory; + + return this; + } + + /** + * Gets a flag indicating whether or not remote clients will be required to have a valid SSL certificate which + * validity will be verified with trust manager. + * + * @return Whether or not client authentication is required. + */ + public boolean isSslClientAuth() { + return sslClientAuth; + } + + /** + * Sets flag indicating whether or not SSL client authentication is required. + * + * @param sslClientAuth Whether or not client authentication is required. + * @return {@code this} for chaining. + */ + public ClientConnectorConfiguration setSslClientAuth(boolean sslClientAuth) { + this.sslClientAuth = sslClientAuth; + + return this; + } + + /** + * Sets SSL context factory that will be used for creating a secure socket layer. + * + * @param sslCtxFactory Ssl context factory. + * @see SslContextFactory + * @return {@code this} for chaining. + */ + public ClientConnectorConfiguration setSslContextFactory(Factory sslCtxFactory) { + this.sslCtxFactory = sslCtxFactory; + + return this; + } + + /** + * Returns SSL context factory that will be used for creating a secure socket layer. + * + * @return SSL connection factory. + * @see SslContextFactory + */ + public Factory getSslContextFactory() { + return sslCtxFactory; + } + /** {@inheritDoc} */ @Override public String toString() { return S.toString(ClientConnectorConfiguration.class, this); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerBufferedParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerBufferedParser.java index eb7bfe87b7fa4..8dd26b674302b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerBufferedParser.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerBufferedParser.java @@ -55,7 +55,9 @@ public class ClientListenerBufferedParser implements GridNioParser { assert old == null; } - return nioBuf.read(buf); + boolean checkHandshake = ses.meta(ClientListenerNioListener.CONN_CTX_HANDSHAKE_PASSED) == null; + + return nioBuf.read(buf, checkHandshake); } /** {@inheritDoc} */ @@ -78,4 +80,4 @@ public class ClientListenerBufferedParser implements GridNioParser { @Override public String toString() { return ClientListenerBufferedParser.class.getSimpleName(); } -} \ No newline at end of file +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java index b41e2401b4f82..ce25ad08e274b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java @@ -47,6 +47,12 @@ public class ClientListenerNioListener extends GridNioServerListenerAdapter 0 && (msgSize > ClientListenerNioListener.MAX_HANDSHAKE_MSG_SIZE + || data[0] != ClientListenerRequest.HANDSHAKE)) + throw new IgniteCheckedException("Invalid handshake message"); + return null; + } } -} \ No newline at end of file +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java index 4797591980963..6316ff8d7f132 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java @@ -21,6 +21,8 @@ import java.nio.ByteOrder; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; +import javax.cache.configuration.Factory; +import javax.net.ssl.SSLContext; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.configuration.ClientConnectorConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; @@ -112,7 +114,7 @@ public ClientListenerProcessor(GridKernalContext ctx) { if (portTo <= 0) // Handle int overflow. portTo = Integer.MAX_VALUE; - GridNioFilter[] filters = makeFilters(); + GridNioFilter[] filters = makeFilters(cliConnCfg); int maxOpenCursors = cliConnCfg.getMaxOpenCursorsPerConnection(); long idleTimeout = cliConnCfg.getIdleTimeout(); @@ -168,34 +170,50 @@ public ClientListenerProcessor(GridKernalContext ctx) { } } - @NotNull private GridNioFilter[] makeFilters() { - GridNioFilter asyncNotifyFilter = new GridNioAsyncNotifyFilter(ctx.igniteInstanceName(), execSvc, log) { + /** + * Make NIO server filters. + * @param cliConnCfg Client configuration. + * @return Array of filters, suitable for the configuration. + * @throws IgniteCheckedException if provided SslContextFactory is null. + */ + @NotNull private GridNioFilter[] makeFilters(@NotNull ClientConnectorConfiguration cliConnCfg) + throws IgniteCheckedException { + GridNioFilter openSesFilter = new GridNioAsyncNotifyFilter(ctx.igniteInstanceName(), execSvc, log) { @Override public void onSessionOpened(GridNioSession ses) throws IgniteCheckedException { proceedSessionOpened(ses); } }; - GridNioFilter bufferParser = new GridNioCodecFilter(new ClientListenerBufferedParser(), log, false); + GridNioFilter codecFilter = new GridNioCodecFilter(new ClientListenerBufferedParser(), log, false); + + if (cliConnCfg.isSslEnabled()) { + Factory sslCtxFactory = cliConnCfg.isUseIgniteSslContextFactory() ? + ctx.config().getSslContextFactory() : cliConnCfg.getSslContextFactory(); - if (isSslEnabled()) { - GridNioSslFilter sslFilter = new GridNioSslFilter(ctx.config().getSslContextFactory().create(), + if (sslCtxFactory == null) + throw new IgniteCheckedException("Failed to create client listener " + + "(SSL is enabled but factory is null). Check the ClientConnectorConfiguration"); + + GridNioSslFilter sslFilter = new GridNioSslFilter(sslCtxFactory.create(), true, ByteOrder.nativeOrder(), log); sslFilter.directMode(false); - sslFilter.wantClientAuth(true); - sslFilter.needClientAuth(true); + boolean auth = cliConnCfg.isSslClientAuth(); + + sslFilter.wantClientAuth(auth); + sslFilter.needClientAuth(auth); return new GridNioFilter[] { - asyncNotifyFilter, - bufferParser, + openSesFilter, + codecFilter, sslFilter }; } else { return new GridNioFilter[] { - asyncNotifyFilter, - bufferParser + openSesFilter, + codecFilter }; } } @@ -344,11 +362,4 @@ private HostAndPortRange parseOdbcEndpoint(OdbcConfiguration odbcCfg) throws Ign private static boolean isNotDefault(ClientConnectorConfiguration cliConnCfg) { return cliConnCfg != null && !(cliConnCfg instanceof ClientConnectorConfigurationEx); } - - /** - * @return {@code True} if ssl enabled. - */ - private boolean isSslEnabled() { - return ctx.config().getSslContextFactory() != null; - } } diff --git a/modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml b/modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml index 209f1330027e2..3f6d6f0775a9f 100644 --- a/modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml +++ b/modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml @@ -27,13 +27,24 @@ - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/modules/platforms/cpp/odbc-test/config/queries-ssl.xml b/modules/platforms/cpp/odbc-test/config/queries-ssl.xml index 24bb6d4ad725a..8e25b4c14b469 100644 --- a/modules/platforms/cpp/odbc-test/config/queries-ssl.xml +++ b/modules/platforms/cpp/odbc-test/config/queries-ssl.xml @@ -33,15 +33,26 @@ - + - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h b/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h index a82dab291176d..c5356792bd52f 100644 --- a/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h +++ b/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h @@ -29,9 +29,6 @@ #include "ignite/ignite.h" -#include "test_type.h" -#include "complex_type.h" - namespace ignite { namespace odbc diff --git a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp index 1438e167a67ee..293d8bcef63a2 100644 --- a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp @@ -63,9 +63,10 @@ struct ApiRobustnessTestSuiteFixture : public odbc::OdbcTestSuite * Constructor. */ ApiRobustnessTestSuiteFixture() : + grid(), testCache(0) { - grid = StartNode("queries-test.xml", "NodeMain"); + grid = StartAdditionalNode("NodeMain"); testCache = grid.GetCache("cache"); } diff --git a/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp b/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp index 6d0edc9212404..7304b2aea48b6 100644 --- a/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp +++ b/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp @@ -90,16 +90,23 @@ namespace ignite { // Releasing statement handle. SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = NULL; + } + if (dbc) + { // Disconneting from the server. SQLDisconnect(dbc); // Releasing allocated handles. SQLFreeHandle(SQL_HANDLE_DBC, dbc); - SQLFreeHandle(SQL_HANDLE_ENV, env); - - stmt = NULL; dbc = NULL; + } + + if (env) + { + // Releasing allocated handles. + SQLFreeHandle(SQL_HANDLE_ENV, env); env = NULL; } } diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h index 97996f9cd2b84..b269f636a5106 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h @@ -29,6 +29,9 @@ namespace ignite { namespace ssl { + // Declaring constant used by OpenSSL for readability. + enum { OPERATION_SUCCESS = 1 }; + inline SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) { typedef SSL_CTX*(FuncType)(const SSL_METHOD*); diff --git a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp index 68cbced529537..60db96333cc49 100644 --- a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp +++ b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp @@ -23,9 +23,6 @@ #include "ignite/odbc/ssl/secure_socket_client.h" #include "ignite/odbc/ssl/ssl_bindings.h" -// Declaring constant used by OpenSSL for readability. -enum { SSL_OPERATION_SUCCESS = 1 }; - namespace ignite { namespace odbc @@ -82,7 +79,7 @@ namespace ignite std::string address = stream.str(); long res = ssl::BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, const_cast(address.c_str())); - if (res != SSL_OPERATION_SUCCESS) + if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set SSL connection hostname."); @@ -104,7 +101,7 @@ namespace ignite res = ssl::SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, const_cast(hostname)); - if (res != SSL_OPERATION_SUCCESS) + if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set host name for secure connection"); @@ -114,7 +111,7 @@ namespace ignite } res = ssl::BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL); - if (res != SSL_OPERATION_SUCCESS) + if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "Failed to establish secure connection with the host."); @@ -125,7 +122,7 @@ namespace ignite } res = ssl::BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL); - if (res != SSL_OPERATION_SUCCESS) + if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "SSL handshake failed."); @@ -276,7 +273,7 @@ namespace ignite const char* cCaPath = caPath.empty() ? 0 : caPath.c_str(); long res = ssl::SSL_CTX_load_verify_locations(ctx, cCaPath, 0); - if (res != SSL_OPERATION_SUCCESS) + if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set Certificate Authority path for secure connection."); @@ -287,7 +284,7 @@ namespace ignite } res = ssl::SSL_CTX_use_certificate_chain_file(ctx, certPath.c_str()); - if (res != SSL_OPERATION_SUCCESS) + if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set client certificate file for secure connection."); @@ -298,7 +295,7 @@ namespace ignite } res = ssl::SSL_CTX_use_RSAPrivateKey_file(ctx, keyPath.c_str(), SSL_FILETYPE_PEM); - if (res != SSL_OPERATION_SUCCESS) + if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set private key file for secure connection."); @@ -310,7 +307,7 @@ namespace ignite const char* const PREFERRED_CIPHERS = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4"; res = ssl::SSL_CTX_set_cipher_list(ctx, PREFERRED_CIPHERS); - if (res != SSL_OPERATION_SUCCESS) + if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set ciphers list for secure connection."); From 09fe00532faa75e0148eafd67696efda73dca6ba Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Thu, 18 Jan 2018 15:43:28 +0300 Subject: [PATCH 16/89] IGNITE-6810: Implemented timeouts for SSL connections --- .../cpp/odbc-test/src/queries_ssl_test.cpp | 147 ++++++++++++++++-- .../ignite/odbc/ssl/secure_socket_client.h | 27 +++- .../include/ignite/odbc/ssl/ssl_bindings.h | 48 ++++++ modules/platforms/cpp/odbc/src/connection.cpp | 7 +- .../cpp/odbc/src/ssl/secure_socket_client.cpp | 98 ++++++++++-- 5 files changed, 295 insertions(+), 32 deletions(-) diff --git a/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp index c51a5c735e2cb..995f8e9db271c 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp @@ -89,6 +89,28 @@ struct SslQueriesTestSuiteFixture : odbc::OdbcTestSuite // No-op. } + /** + * Create default connection string. + * @return Default connection string. + */ + std::string MakeDefaultConnectionString() + { + std::string cfgDirPath = GetTestConfigDir(); + + std::stringstream connectString; + + connectString << + "DRIVER={Apache Ignite};" + "ADDRESS=127.0.0.1:11110;" + "SCHEMA=cache;" + "SSL_MODE=require;" + "SSL_KEY_FILE=" << cfgDirPath << Fs << "ssl" << Fs << "client_full.pem;" + "SSL_CERT_FILE=" << cfgDirPath << Fs << "ssl" << Fs << "client_full.pem;" + "SSL_CA_FILE=" << cfgDirPath << Fs << "ssl" << Fs << "ca.pem;"; + + return connectString.str(); + } + /** Node started during the test. */ Ignite grid; @@ -103,23 +125,124 @@ BOOST_FIXTURE_TEST_SUITE(SslQueriesTestSuite, SslQueriesTestSuiteFixture) BOOST_AUTO_TEST_CASE(TestConnectionSsl) { - std::string cfgDirPath = GetTestConfigDir(); + Connect(MakeDefaultConnectionString()); - std::stringstream connectString; + InsertTestStrings(10, false); + InsertTestBatch(11, 2000, 1989); +} + +BOOST_AUTO_TEST_CASE(TestConnectionTimeoutQuery) +{ + Connect(MakeDefaultConnectionString()); - connectString << - "DRIVER={Apache Ignite};" - "ADDRESS=127.0.0.1:11110;" - "SCHEMA=cache;" - "SSL_MODE=require;" - "SSL_KEY_FILE=" << cfgDirPath << Fs << "ssl" << Fs << "client_full.pem;" - "SSL_CERT_FILE=" << cfgDirPath << Fs << "ssl" << Fs << "client_full.pem;" - "SSL_CA_FILE=" << cfgDirPath << Fs << "ssl" << Fs << "ca.pem;"; + SQLRETURN ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast(5), 0); - Connect(connectString.str()); + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc); InsertTestStrings(10, false); - InsertTestBatch(11, 2000, 1989); +} + +BOOST_AUTO_TEST_CASE(TestConnectionTimeoutBatch) +{ + Connect(MakeDefaultConnectionString()); + + SQLRETURN ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast(5), 0); + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc); + + InsertTestBatch(11, 20, 9); +} + +BOOST_AUTO_TEST_CASE(TestConnectionTimeoutBoth) +{ + Connect(MakeDefaultConnectionString()); + + SQLRETURN ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast(5), 0); + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc); + + InsertTestStrings(10, false); + InsertTestBatch(11, 20, 9); +} + +BOOST_AUTO_TEST_CASE(TestQueryTimeoutQuery) +{ + Connect(MakeDefaultConnectionString()); + + SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast(5), 0); + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt); + + InsertTestStrings(10, false); +} + +BOOST_AUTO_TEST_CASE(TestQueryTimeoutBatch) +{ + Connect(MakeDefaultConnectionString()); + + SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast(5), 0); + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt); + + InsertTestBatch(11, 20, 9); +} + +BOOST_AUTO_TEST_CASE(TestQueryTimeoutBoth) +{ + Connect(MakeDefaultConnectionString()); + + SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast(5), 0); + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt); + + InsertTestStrings(10, false); + InsertTestBatch(11, 20, 9); +} + +BOOST_AUTO_TEST_CASE(TestQueryAndConnectionTimeoutQuery) +{ + Connect(MakeDefaultConnectionString()); + + SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast(5), 0); + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt); + + ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast(3), 0); + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc); + + InsertTestStrings(10, false); +} + +BOOST_AUTO_TEST_CASE(TestQueryAndConnectionTimeoutBatch) +{ + Connect(MakeDefaultConnectionString()); + + SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast(5), 0); + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt); + + ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast(3), 0); + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc); + + InsertTestBatch(11, 20, 9); +} + +BOOST_AUTO_TEST_CASE(TestQueryAndConnectionTimeoutBoth) +{ + Connect(MakeDefaultConnectionString()); + + SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast(5), 0); + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt); + + ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast(3), 0); + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc); + + InsertTestStrings(10, false); + InsertTestBatch(11, 20, 9); } BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h index 9fb82167cb8a9..5383f3c00bce0 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h @@ -93,6 +93,24 @@ namespace ignite virtual bool IsBlocking() const; private: + /** + * Close the connection. + * Internal call. + */ + void CloseInteral(); + + /** + * Wait on the socket for any event for specified time. + * This function uses poll to achive timeout functionality + * for every separate socket operation. + * + * @param timeout Timeout. + * @param rd Wait for read if @c true, or for write if @c false. + * @return -errno on error, WaitResult::TIMEOUT on timeout and + * WaitResult::SUCCESS on success. + */ + int WaitOnSocket(int32_t timeout, bool rd); + /** * Make new context instance. * @@ -105,12 +123,6 @@ namespace ignite static void* MakeContext(const std::string& certPath, const std::string& keyPath, const std::string& caPath, diagnostic::Diagnosable& diag); - /** - * Close the connection. - * Internal call. - */ - void CloseInteral(); - /** Certificate file path. */ std::string certPath; @@ -125,6 +137,9 @@ namespace ignite /** OpenSSL I/O stream abstraction */ void* sslBio; + + /** Blocking flag. */ + bool blocking; }; } } diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h index b269f636a5106..b23533a9062a0 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_bindings.h @@ -167,6 +167,14 @@ namespace ignite return fp(s, cmd, larg ,parg); } + inline long SSL_set_tlsext_host_name_(SSL *s, const char *name) + { + return ssl::SSL_ctrl(s, SSL_CTRL_SET_TLSEXT_HOSTNAME, + TLSEXT_NAMETYPE_host_name, const_cast(name)); + } + + + inline const SSL_METHOD *SSLv23_method() { typedef const SSL_METHOD*(FuncType)(); @@ -240,6 +248,11 @@ namespace ignite return fp(b, flags); } + inline int BIO_should_retry_(const BIO *b) + { + return ssl::BIO_test_flags(b, BIO_FLAGS_SHOULD_RETRY); + } + inline long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg) { typedef long(FuncType)(BIO*, int, long, void*); @@ -248,6 +261,41 @@ namespace ignite return fp(bp, cmd, larg, parg); } + + inline long BIO_get_fd_(BIO *bp, int *fd) + { + return ssl::BIO_ctrl(bp, BIO_C_GET_FD, 0, reinterpret_cast(fd)); + } + + inline long BIO_do_handshake_(BIO *bp) + { + return ssl::BIO_ctrl(bp, BIO_C_DO_STATE_MACHINE, 0, NULL); + } + + inline long BIO_do_connect_(BIO *bp) + { + return ssl::BIO_do_handshake_(bp); + } + + inline long BIO_get_ssl_(BIO *bp, SSL** ssl) + { + return ssl::BIO_ctrl(bp, BIO_C_GET_SSL, 0, reinterpret_cast(ssl)); + } + + inline long BIO_set_nbio_(BIO *bp, long n) + { + return ssl::BIO_ctrl(bp, BIO_C_SET_NBIO, n, NULL); + } + + inline long BIO_set_conn_hostname_(BIO *bp, const char *name) + { + return ssl::BIO_ctrl(bp, BIO_C_SET_CONNECT, 0, const_cast(name)); + } + + inline long BIO_pending_(BIO *bp) + { + return ssl::BIO_ctrl(bp, BIO_CTRL_PENDING, 0, NULL); + } } } } diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp index 68be8bf244a20..fe3bf3eee1eaa 100644 --- a/modules/platforms/cpp/odbc/src/connection.cpp +++ b/modules/platforms/cpp/odbc/src/connection.cpp @@ -193,9 +193,12 @@ namespace ignite void Connection::Close() { - socket->Close(); + if (socket.get() != 0) + { + socket->Close(); - socket.reset(); + socket.reset(); + } } Statement* Connection::CreateStatement() diff --git a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp index 60db96333cc49..1b40338305582 100644 --- a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp +++ b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp @@ -23,6 +23,7 @@ #include "ignite/odbc/ssl/secure_socket_client.h" #include "ignite/odbc/ssl/ssl_bindings.h" + namespace ignite { namespace odbc @@ -35,7 +36,8 @@ namespace ignite keyPath(keyPath), caPath(caPath), context(0), - sslBio(0) + sslBio(0), + blocking(true) { // No-op. } @@ -73,12 +75,22 @@ namespace ignite return false; } + blocking = false; + long res = ssl::BIO_set_nbio_(bio, 1); + if (res != OPERATION_SUCCESS) + { + blocking = true; + + diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, + "Can not set up non-blocking mode. Timeouts are not available."); + } + std::stringstream stream; stream << hostname << ":" << port; std::string address = stream.str(); - long res = ssl::BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, const_cast(address.c_str())); + res = ssl::BIO_set_conn_hostname_(bio, address.c_str()); if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set SSL connection hostname."); @@ -89,7 +101,7 @@ namespace ignite } SSL* ssl = 0; - ssl::BIO_ctrl(bio, BIO_C_GET_SSL, 0, reinterpret_cast(&ssl)); + ssl::BIO_get_ssl_(bio, &ssl); if (!ssl) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not get SSL instance from BIO."); @@ -99,8 +111,7 @@ namespace ignite return false; } - res = ssl::SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, - TLSEXT_NAMETYPE_host_name, const_cast(hostname)); + res = ssl::SSL_set_tlsext_host_name_(ssl, hostname); if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not set host name for secure connection"); @@ -110,7 +121,11 @@ namespace ignite return false; } - res = ssl::BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL); + do + { + res = ssl::BIO_do_connect_(bio); + } while (ssl::BIO_should_retry_(bio)); + if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, @@ -121,7 +136,11 @@ namespace ignite return false; } - res = ssl::BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL); + do + { + res = ssl::BIO_do_handshake_(bio); + } while (ssl::BIO_should_retry_(bio)); + if (res != OPERATION_SUCCESS) { diag.AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "SSL handshake failed."); @@ -177,7 +196,6 @@ namespace ignite return -1; } - (void)timeout; BIO* sslBio0 = reinterpret_cast(sslBio); int res = 0; @@ -186,7 +204,7 @@ namespace ignite { res = ssl::BIO_write(sslBio0, data, static_cast(size)); } - while (ssl::BIO_test_flags(sslBio0, BIO_FLAGS_SHOULD_RETRY)); + while (ssl::BIO_should_retry_(sslBio0)); return res; } @@ -202,23 +220,30 @@ namespace ignite return -1; } - (void)timeout; BIO* sslBio0 = reinterpret_cast(sslBio); int res = 0; + if (!blocking && BIO_pending_(sslBio0) == 0) + { + res = WaitOnSocket(timeout, true); + + if (res < 0 || res == WaitResult::TIMEOUT) + return res; + } + do { res = ssl::BIO_read(sslBio0, buffer, static_cast(size)); } - while (ssl::BIO_test_flags(sslBio0, BIO_FLAGS_SHOULD_RETRY)); + while (ssl::BIO_should_retry_(sslBio0)); return res; } bool SecureSocketClient::IsBlocking() const { - return true; + return blocking; } void* SecureSocketClient::MakeContext(const std::string& certPath, const std::string& keyPath, @@ -331,6 +356,55 @@ namespace ignite sslBio = 0; } } + + int SecureSocketClient::WaitOnSocket(int32_t timeout, bool rd) + { + int ready = 0; + int lastError = 0; + int fdSocket = 0; + BIO* sslBio0 = reinterpret_cast(sslBio); + + fd_set fds; + + long res = ssl::BIO_get_fd_(sslBio0, &fdSocket); + + if (res < 0) + { + LOG_MSG("Can not get file descriptor from the SSL socket: " << res); + + return res; + } + + do { + struct timeval tv = { 0 }; + tv.tv_sec = timeout; + + FD_ZERO(&fds); + FD_SET(static_cast(fdSocket), &fds); + + fd_set* readFds = 0; + fd_set* writeFds = 0; + + if (rd) + readFds = &fds; + else + writeFds = &fds; + + ready = select(fdSocket + 1, readFds, writeFds, NULL, (timeout == 0 ? NULL : &tv)); + + if (ready == SOCKET_ERROR) + lastError = WSAGetLastError(); + + } while (ready == SOCKET_ERROR && lastError == WSAEINTR); + + if (ready == SOCKET_ERROR) + return -lastError; + + if (ready == 0) + return WaitResult::TIMEOUT; + + return WaitResult::SUCCESS; + } } } } From db770a8537b28922f74b3984eef88285fe53508f Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Thu, 18 Jan 2018 18:11:02 +0300 Subject: [PATCH 17/89] IGNITE-6810: Fix for linux --- .../include/ignite/odbc/system/tcp_socket_client.h | 11 +++++++++++ .../odbc/os/linux/src/system/tcp_socket_client.cpp | 14 ++++++++++++-- .../odbc/os/win/src/system/tcp_socket_client.cpp | 14 ++++++++++++-- .../cpp/odbc/src/ssl/secure_socket_client.cpp | 14 ++++++++++++-- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h index ac3db7be849d4..0eb3495c24e67 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h @@ -100,6 +100,17 @@ namespace ignite */ virtual bool IsBlocking() const; + /** + * Get socket error. + * @return Last socket error. + */ + static int GetLastSocketError(); + + /** + * Check whether socket operation was interupted. + * @return @c true if the socket operation was interupted. + */ + static bool IsSocketOperationInterrupted(int errorCode); private: /** * Tries set socket options. diff --git a/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp b/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp index 6845ae02bc5cd..6f70a0d93d7cb 100644 --- a/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp +++ b/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp @@ -341,9 +341,9 @@ namespace ignite readFds, writeFds, NULL, (timeout == 0 ? NULL : &tv)); if (ready == SOCKET_ERROR) - lastError = errno; + lastError = GetLastSocketError(); - } while (ready == SOCKET_ERROR && lastError == EINTR); + } while (ready == SOCKET_ERROR && IsSocketOperationInterrupted(lastError)); if (ready == SOCKET_ERROR) return -lastError; @@ -359,6 +359,16 @@ namespace ignite return WaitResult::SUCCESS; } + + int TcpSocketClient::GetLastSocketError() + { + return errno; + } + + bool TcpSocketClient::IsSocketOperationInterrupted(int errorCode) + { + return errorCode == EINTR; + } } } } diff --git a/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp b/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp index b51895cf9a428..6de92a30267d2 100644 --- a/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp +++ b/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp @@ -425,9 +425,9 @@ namespace ignite readFds, writeFds, NULL, (timeout == 0 ? NULL : &tv)); if (ready == SOCKET_ERROR) - lastError = WSAGetLastError(); + lastError = GetLastSocketError(); - } while (ready == SOCKET_ERROR && lastError == WSAEINTR); + } while (ready == SOCKET_ERROR && IsSocketOperationInterrupted(lastError)); if (ready == SOCKET_ERROR) return -lastError; @@ -437,6 +437,16 @@ namespace ignite return WaitResult::SUCCESS; } + + int TcpSocketClient::GetLastSocketError() + { + return WSAGetLastError(); + } + + bool TcpSocketClient::IsSocketOperationInterrupted(int errorCode) + { + return errorCode == WSAEINTR; + } } } } diff --git a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp index 1b40338305582..650213f661f6e 100644 --- a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp +++ b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp @@ -20,9 +20,13 @@ #include "ignite/odbc/log.h" #include "ignite/common/concurrent.h" +#include "ignite/odbc/system/tcp_socket_client.h" #include "ignite/odbc/ssl/secure_socket_client.h" #include "ignite/odbc/ssl/ssl_bindings.h" +#ifndef SOCKET_ERROR +# define SOCKET_ERROR (-1) +#endif // SOCKET_ERROR namespace ignite { @@ -393,13 +397,19 @@ namespace ignite ready = select(fdSocket + 1, readFds, writeFds, NULL, (timeout == 0 ? NULL : &tv)); if (ready == SOCKET_ERROR) - lastError = WSAGetLastError(); + lastError = system::TcpSocketClient::GetLastSocketError(); - } while (ready == SOCKET_ERROR && lastError == WSAEINTR); + } while (ready == SOCKET_ERROR && system::TcpSocketClient::IsSocketOperationInterrupted(lastError)); if (ready == SOCKET_ERROR) return -lastError; + int size = sizeof(lastError); + res = getsockopt(fdSocket, SOL_SOCKET, SO_ERROR, reinterpret_cast(&lastError), &size); + + if (res != SOCKET_ERROR && lastError != 0) + return -lastError; + if (ready == 0) return WaitResult::TIMEOUT; From 471d49cf33a8008dc100c33c9ac107f199f19f17 Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Thu, 18 Jan 2018 18:49:03 +0300 Subject: [PATCH 18/89] IGNITE-6810: Fixes for linux --- .../odbc/include/ignite/odbc/system/tcp_socket_client.h | 7 +++++++ .../cpp/odbc/os/linux/src/system/tcp_socket_client.cpp | 9 +++++++++ .../cpp/odbc/os/win/src/system/tcp_socket_client.cpp | 9 +++++++++ .../platforms/cpp/odbc/src/ssl/secure_socket_client.cpp | 5 ++--- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h index 0eb3495c24e67..f489d56d7c917 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h @@ -106,6 +106,13 @@ namespace ignite */ static int GetLastSocketError(); + /** + * Get socket error. + * @param handle Socket handle. + * @return Last socket error. + */ + static int GetLastSocketError(int handle); + /** * Check whether socket operation was interupted. * @return @c true if the socket operation was interupted. diff --git a/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp b/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp index 6f70a0d93d7cb..043f61bf0619e 100644 --- a/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp +++ b/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp @@ -365,6 +365,15 @@ namespace ignite return errno; } + int TcpSocketClient::GetLastSocketError(int handle) + { + int lastError = 0; + int size = sizeof(lastError); + int res = getsockopt(handle, SOL_SOCKET, SO_ERROR, reinterpret_cast(&lastError), &size); + + return res == SOCKET_ERROR ? 0 : lastError; + } + bool TcpSocketClient::IsSocketOperationInterrupted(int errorCode) { return errorCode == EINTR; diff --git a/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp b/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp index 6de92a30267d2..2bc44229d2adc 100644 --- a/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp +++ b/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp @@ -443,6 +443,15 @@ namespace ignite return WSAGetLastError(); } + int TcpSocketClient::GetLastSocketError(int handle) + { + int lastError = 0; + int size = sizeof(lastError); + int res = getsockopt(handle, SOL_SOCKET, SO_ERROR, reinterpret_cast(&lastError), &size); + + return res == SOCKET_ERROR ? 0 : lastError; + } + bool TcpSocketClient::IsSocketOperationInterrupted(int errorCode) { return errorCode == WSAEINTR; diff --git a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp index 650213f661f6e..c305b87395be3 100644 --- a/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp +++ b/modules/platforms/cpp/odbc/src/ssl/secure_socket_client.cpp @@ -404,10 +404,9 @@ namespace ignite if (ready == SOCKET_ERROR) return -lastError; - int size = sizeof(lastError); - res = getsockopt(fdSocket, SOL_SOCKET, SO_ERROR, reinterpret_cast(&lastError), &size); + lastError = system::TcpSocketClient::GetLastSocketError(fdSocket); - if (res != SOCKET_ERROR && lastError != 0) + if (lastError != 0) return -lastError; if (ready == 0) From 77eb83cb2d249faea4c36050653ab9d1de24272b Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Thu, 18 Jan 2018 19:10:43 +0300 Subject: [PATCH 19/89] IGNITE-6810: Fixed linux errors --- .../cpp/odbc/os/linux/src/system/tcp_socket_client.cpp | 2 +- .../platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp b/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp index 043f61bf0619e..f145361c0528a 100644 --- a/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp +++ b/modules/platforms/cpp/odbc/os/linux/src/system/tcp_socket_client.cpp @@ -368,7 +368,7 @@ namespace ignite int TcpSocketClient::GetLastSocketError(int handle) { int lastError = 0; - int size = sizeof(lastError); + socklen_t size = sizeof(lastError); int res = getsockopt(handle, SOL_SOCKET, SO_ERROR, reinterpret_cast(&lastError), &size); return res == SOCKET_ERROR ? 0 : lastError; diff --git a/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp b/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp index 2bc44229d2adc..1459a17953869 100644 --- a/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp +++ b/modules/platforms/cpp/odbc/os/win/src/system/tcp_socket_client.cpp @@ -446,7 +446,7 @@ namespace ignite int TcpSocketClient::GetLastSocketError(int handle) { int lastError = 0; - int size = sizeof(lastError); + socklen_t size = sizeof(lastError); int res = getsockopt(handle, SOL_SOCKET, SO_ERROR, reinterpret_cast(&lastError), &size); return res == SOCKET_ERROR ? 0 : lastError; From 97b1c80b078bbf984d4137f17f9ad6ddf6b3e1fc Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Tue, 23 Jan 2018 19:43:25 +0300 Subject: [PATCH 20/89] IGNITE-6810: Fix for x86 --- .../internal/processors/odbc/odbc/OdbcRequestHandler.java | 1 - modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml | 8 ++++++++ .../platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java index bfc8d9e77f445..43af98042e99a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java @@ -42,7 +42,6 @@ import org.apache.ignite.internal.processors.odbc.ClientListenerRequestHandler; import org.apache.ignite.internal.processors.odbc.ClientListenerResponse; import org.apache.ignite.internal.processors.odbc.odbc.escape.OdbcEscapeUtils; -import org.apache.ignite.internal.processors.query.GridQueryIndexing; import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor; import org.apache.ignite.internal.util.GridSpinBusyLock; import org.apache.ignite.internal.util.typedef.F; diff --git a/modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml b/modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml index 3f6d6f0775a9f..3fa26597c0f8b 100644 --- a/modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml +++ b/modules/platforms/cpp/odbc-test/config/queries-ssl-32.xml @@ -25,6 +25,14 @@ http://www.springframework.org/schema/beans/spring-beans.xsd"> + + + + + + diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj index 7cf1675a133de..b1074b222840b 100644 --- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj +++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj @@ -94,6 +94,7 @@ $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(ProjectDir)\..\..\..\common\include;$(ProjectDir)\..\..\..\common\os\win\include;$(ProjectDir)\..\..\..\jni\include;$(ProjectDir)\..\..\..\jni\os\win\include;$(ProjectDir)\..\..\..\binary\include;$(ProjectDir)\..\..\..\binary\os\win\include;$(ProjectDir)\..\..\..\core\include;$(ProjectDir)\..\..\..\odbc\include;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\os\win;$(ProjectDir)\..\..\src;$(BOOST_HOME);$(OPENSSL_HOME)\include _CRT_SECURE_NO_WARNINGS;BOOST_DATE_TIME_NO_LIB;BOOST_REGEX_NO_LIB;IGNITE_IMPL;IGNITE_FRIEND;IGNITE_TESTS_32;%(PreprocessorDefinitions) Async + false true @@ -226,4 +227,4 @@ - + \ No newline at end of file From 79b5be4fe5c078c0d2fa28f9c9adbb29dadce491 Mon Sep 17 00:00:00 2001 From: Igor Sapego Date: Tue, 23 Jan 2018 19:44:59 +0300 Subject: [PATCH 21/89] IGNITE-6810: Typo fixed --- modules/platforms/cpp/odbc/include/ignite/odbc/socket_client.h | 2 +- .../cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h | 2 +- .../cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/socket_client.h index 349f0475805dc..2df035b9f5919 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/socket_client.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/socket_client.h @@ -92,7 +92,7 @@ namespace ignite * @param buffer Pointer to data buffer. * @param size Size of the buffer in bytes. * @param timeout Timeout. - * @return Number of bytes that have been sent on success, + * @return Number of bytes that have been received on success, * WaitResult::TIMEOUT on timeout and -errno on failure. */ virtual int Receive(int8_t* buffer, size_t size, int32_t timeout) = 0; diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h index 5383f3c00bce0..4cd58444ed906 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/secure_socket_client.h @@ -81,7 +81,7 @@ namespace ignite * @param buffer Pointer to data buffer. * @param size Size of the buffer in bytes. * @param timeout Timeout. - * @return Number of bytes that have been sent on success, + * @return Number of bytes that have been received on success, * WaitResult::TIMEOUT on timeout and -errno on failure. */ virtual int Receive(int8_t* buffer, size_t size, int32_t timeout); diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h index f489d56d7c917..a3c9c30af7751 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/system/tcp_socket_client.h @@ -89,7 +89,7 @@ namespace ignite * @param buffer Pointer to data buffer. * @param size Size of the buffer in bytes. * @param timeout Timeout. - * @return Number of bytes that have been sent on success, + * @return Number of bytes that have been received on success, * WaitResult::TIMEOUT on timeout and -errno on failure. */ virtual int Receive(int8_t* buffer, size_t size, int32_t timeout); From 18bf93161008cdf02b6e35d536a37baaf58753ec Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 11:29:36 +0300 Subject: [PATCH 22/89] IGNITE-7329 .NET: Thin client: SSL --- .../Apache.Ignite.Core.Tests.csproj | 1 + .../Client/RawSecureSocketTest.cs | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj index ab16bf1eaf5ec..76f1c19387cdd 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj @@ -139,6 +139,7 @@ + diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs new file mode 100644 index 0000000000000..e8315af2cf42a --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Client +{ + using NUnit.Framework; + + ///

+ /// Tests the thin client mode with a raw secure socket. + /// + public class RawSecureSocketTest + { + // TODO: See queries_ssl_test.cpp, queries-ssl.xml + + + [Test] + public void Test() + { + + } + } +} From 78f22353add53bee60b341756dee41c5aed738a9 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 15:16:34 +0300 Subject: [PATCH 23/89] wip raw tests --- .../Client/RawSecureSocketTest.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index e8315af2cf42a..e2da390d69671 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -17,6 +17,7 @@ namespace Apache.Ignite.Core.Tests.Client { + using Apache.Ignite.Core.Client; using NUnit.Framework; /// @@ -28,9 +29,21 @@ public class RawSecureSocketTest [Test] - public void Test() + public void TestSslOnServer() { - + using (var ignite = Ignition.Start( + @"S:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\queries-ssl.xml")) + { + var cfg = new IgniteClientConfiguration + { + Host = "127.0.0.1", + Port = 11110 + }; + using (var client = Ignition.StartClient(cfg)) + { + client.GetCacheNames(); + } + } } } } From 80b399895a13686a231872fabb0f07a672219c85 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 15:21:54 +0300 Subject: [PATCH 24/89] wip --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index e2da390d69671..7522307177681 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -17,6 +17,7 @@ namespace Apache.Ignite.Core.Tests.Client { + using System; using Apache.Ignite.Core.Client; using NUnit.Framework; @@ -31,6 +32,12 @@ public class RawSecureSocketTest [Test] public void TestSslOnServer() { + // S:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\ssl\server.jks + // IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH + + Environment.SetEnvironmentVariable("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH", + @"S:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config"); + using (var ignite = Ignition.Start( @"S:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\queries-ssl.xml")) { From 2b723d494f12c97989f1f24338d056e308a3b01f Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 15:30:19 +0300 Subject: [PATCH 25/89] wip test --- .../Client/RawSecureSocketTest.cs | 63 ++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 7522307177681..3d3222c55035c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -18,6 +18,12 @@ namespace Apache.Ignite.Core.Tests.Client { using System; + using System.Collections; + using System.Net.Security; + using System.Net.Sockets; + using System.Security.Authentication; + using System.Security.Cryptography.X509Certificates; + using System.Text; using Apache.Ignite.Core.Client; using NUnit.Framework; @@ -46,11 +52,64 @@ public void TestSslOnServer() Host = "127.0.0.1", Port = 11110 }; - using (var client = Ignition.StartClient(cfg)) + //using (var client = Ignition.StartClient(cfg)) + //{ + // client.GetCacheNames(); + //} + + RunClient(cfg.Host, cfg.Host, cfg.Port); + } + } + + + // The following method is invoked by the RemoteCertificateValidationDelegate. + public static bool ValidateServerCertificate( + object sender, + X509Certificate certificate, + X509Chain chain, + SslPolicyErrors sslPolicyErrors) + { + if (sslPolicyErrors == SslPolicyErrors.None) + return true; + + Console.WriteLine("Certificate error: {0}", sslPolicyErrors); + + // Do not allow this client to communicate with unauthenticated servers. + return false; + } + + public static void RunClient(string machineName, string serverName, int port) + { + // Create a TCP/IP client socket. + // machineName is the host running the server application. + var client = new TcpClient(machineName, 443); + Console.WriteLine("Client connected."); + + // Create an SSL stream that will close the client's stream. + var sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null); + + // The server name must match the name on the server certificate. + try + { + sslStream.AuthenticateAsClient(serverName); + } + catch (AuthenticationException e) + { + Console.WriteLine("Exception: {0}", e.Message); + if (e.InnerException != null) { - client.GetCacheNames(); + Console.WriteLine("Inner exception: {0}", e.InnerException.Message); } + Console.WriteLine("Authentication failed - closing the connection."); + client.Close(); + return; } + + // TODO: Handhsake. + sslStream.WriteByte(1); + + client.Close(); + Console.WriteLine("Client closed."); } } } From 7b64da68e243839e0508365b4486cec49adab54f Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 15:37:14 +0300 Subject: [PATCH 26/89] wip tests --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 3d3222c55035c..1ae54b61c4093 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -82,16 +82,19 @@ public static void RunClient(string machineName, string serverName, int port) { // Create a TCP/IP client socket. // machineName is the host running the server application. - var client = new TcpClient(machineName, 443); + var client = new TcpClient(machineName, port); Console.WriteLine("Client connected."); // Create an SSL stream that will close the client's stream. var sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null); // The server name must match the name on the server certificate. + var certificate = new X509Certificate2(@"d:\mySrvKeystore.p12", "123456"); + var certsCollection = new X509CertificateCollection(new X509Certificate[] { certificate }); + try { - sslStream.AuthenticateAsClient(serverName); + sslStream.AuthenticateAsClient(serverName, certsCollection, SslProtocols.Default, false); } catch (AuthenticationException e) { From 449253909a11b3490c22f9c3230ee8e31093f2a5 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 15:45:15 +0300 Subject: [PATCH 27/89] wip tests --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 1ae54b61c4093..0577a20460105 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -89,7 +89,7 @@ public static void RunClient(string machineName, string serverName, int port) var sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null); // The server name must match the name on the server certificate. - var certificate = new X509Certificate2(@"d:\mySrvKeystore.p12", "123456"); + var certificate = new X509Certificate2(@"S:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\ssl\client_full.pem"); var certsCollection = new X509CertificateCollection(new X509Certificate[] { certificate }); try From 1d3ef776b287e54f813d46d77c8fcf737b56076e Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 18:02:15 +0300 Subject: [PATCH 28/89] wip --- .../Client/RawSecureSocketTest.cs | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 0577a20460105..5b832a161d8d8 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -63,7 +63,7 @@ public void TestSslOnServer() // The following method is invoked by the RemoteCertificateValidationDelegate. - public static bool ValidateServerCertificate( + private static bool ValidateServerCertificate( object sender, X509Certificate certificate, X509Chain chain, @@ -78,7 +78,7 @@ public void TestSslOnServer() return false; } - public static void RunClient(string machineName, string serverName, int port) + private static void RunClient(string machineName, string serverName, int port) { // Create a TCP/IP client socket. // machineName is the host running the server application. @@ -89,7 +89,8 @@ public static void RunClient(string machineName, string serverName, int port) var sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null); // The server name must match the name on the server certificate. - var certificate = new X509Certificate2(@"S:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\ssl\client_full.pem"); + var certificate = LoadCertificateFile( + @"S:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\ssl\client_full.pem"); var certsCollection = new X509CertificateCollection(new X509Certificate[] { certificate }); try @@ -114,5 +115,32 @@ public static void RunClient(string machineName, string serverName, int port) client.Close(); Console.WriteLine("Client closed."); } + + static byte[] GetPem(string type, byte[] data) + { + string pem = Encoding.UTF8.GetString(data); + string header = String.Format("-----BEGIN {0}-----", type); + string footer = String.Format("-----END {0}-----", type); + int start = pem.IndexOf(header) + header.Length; + int end = pem.IndexOf(footer, start); + string base64 = pem.Substring(start, (end - start)).Trim(); + return Convert.FromBase64String(base64); + } + + static X509Certificate2 LoadCertificateFile(string filename) + { + using (System.IO.FileStream fs = System.IO.File.OpenRead(filename)) + { + byte[] data = new byte[fs.Length]; + byte[] res = null; + fs.Read(data, 0, data.Length); + if (data[0] != 0x30) + { + res = GetPem("RSA PRIVATE KEY", data); + } + X509Certificate2 x509 = new X509Certificate2(res); //Exception hit here + return x509; + } + } } } From a0664d7d6740623f87ef3700b7d6f01022587489 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 18:14:21 +0300 Subject: [PATCH 29/89] It works!! --- .../cpp/odbc-test/config/ssl/cert.pfx | Bin 0 -> 4549 bytes .../Client/RawSecureSocketTest.cs | 34 +++++------------- 2 files changed, 8 insertions(+), 26 deletions(-) create mode 100644 modules/platforms/cpp/odbc-test/config/ssl/cert.pfx diff --git a/modules/platforms/cpp/odbc-test/config/ssl/cert.pfx b/modules/platforms/cpp/odbc-test/config/ssl/cert.pfx new file mode 100644 index 0000000000000000000000000000000000000000..2f5c12ee44676a4932ff0bb538eeb8a6a0111844 GIT binary patch literal 4549 zcmV;$5jyTLf)T+20Ru3C5r+l|Duzgg_YDCD0ic2rcm#qGbTEPua4>=lCk6>BhDe6@ z4FLxRpn?n-FoFye0s#Opf(#7?2`Yw2hW8Bt2LUh~1_~;MNQUg zsH)aCq|HpeN_y=gLq~hSNQWaGuVwG`Ct(R-Yx;x*-rJhS@kE_F(}TXxDLAv+8u;KD zC!XFe>vZ>k9M*cFRu7yRKqFN8p}+32=z<9)s@GY|z*p8GvbV6=hX3#V6XSdMXmcL- zN`W35Vdi9dW3`nR=EFu#-bMcH6?f48AA{PwmXX#fldsdQTQZvoz3+IK6?cMafoh!V zgqL=2oKz6vf*^3Ax6D7@J)hItOA6RWd>X?gIDTA(~SvosTxXdSRdGu_e zI)kt7ZFCx|rSsi*z7caEQjkT#jRy|Joy{+)_(pBWmndiySCm+qpECC9BsfDzezdud8hP`Y_Q}Hvzjkff-8q>0h z6lt86<{*DLAgkq#SuPrrzvjxJhH<5FJkxH&jmD{Zh!;W0ayt2ZWSwjj+f9f-9$o&% zXGK(!KH#JlRG8@UeE|707a-MaTMFY3Pv!>y?Y)Lim3Ksfj}^@|t?TGrtKTmZ>Fjoq zT<_oL$zwkIy!Rz`7uU)@ErMd1Y(Ze4iEcq3@1^xs6+0xGpErvqto`1e6%lC4?kiq? zA~9>j5}}9IXC%;IgRX4tWPY}Eo{|m(mrm4zK>?bTpjtu{?@+iq_vQkLjm#!c@Gg?7 zbjykGXHBl3+qyb|mrHbDE}Xw8F5V~FnNU0g1$9$Ym!1NskuHCo`52JyKl4X@j1fW= zNOdXQy*D&w8iC@&i4Y?(SFSV`MM&PCYY#e9>u!1yuo3-T#Un2u$|o%jvs2iq@{@H;wvvznRoI{HgO}O<*nhCz^OT#M;&rgu z`u`_3!-;$4318p?_aR=1VOn%^1FYP^T=cDqZoDRqBG<@*oeDcCiwL->$^^(ORG{VF zbnP;v3L~$6T0EG}+3aPAnnOIVqcdeZz(Lx}m;|ZiLw44VCO!t8bw0#O`&y5cs~28S zh)RDWEa9^wpSGs51p?+n(#fK;!vSbSI{J6h2T{*nL7NokmllG{Aut(mjyi%1-f?SN zt?b8^ld_raJVUkk9J|4k1y}9(JF1D2hs&1;nAh#yMiFS~d8QJDvn(vl`?0TIRc$JAeP{`OVfQ@$3ZM>Kej5R% znB!&7k#KmrVUcWv40UH3LJ^&j@p_?#`%;$Y<@x}~IR=K}pOTR6JE3Ago`L*vJhm1O zp>=S?!E}ACf)8~U6>4ss5ax~ZLw>}1?Gz#597{#C0=t`wbz?cx6oFjw`yEzX3FusM z?U#y;XGFB>?I2arKo~OL@mR;*I4zAF~MZv{1U8kh8Y$Li;q zmI#=q2Zg}D4URZF&vy&L%hkQz@(U%U8U&5Xf6)k7%C%u^Q%*^1ygJPi4jbRJH&Au0 z9BKq985p*tQfOuhim-3e>le0a_X#t$fftb8ycsyq1FruPVHT1AT<`z}Prmd{s}RI> zIt+Dq^R+0J4ByH%#Kb@Cf#X?)gKXv+Q;} zHP-N}rP~Jt%TkGa_QpyYeAWNVY}cN3@C&W9y)g8eyU8o1aGKI^lUs32W}GTi<*POO zJ82y=-`qMEC5V9N8d!VBqr+14oVF$Yxq_U&gfvmwP{Te7Kv^{TsnoYoQ}+$`+0p7! zJ`4MthFzjd}Gl^1tQr5Xty}gqocPLvFf%E zB|1NJC6}tu=XOyJR;CvJ&DGo$jp)AtI6f)eg^M~c^gEDd z7S5eCi81K)L9Up)jZPq&7hWVfj;M*P|7LeVw1wPN8QR88rHlif-%J13xhRm%+}Xar=Asylf>7>O zPgWyW8N2F{_zJ>5kM6Xq6q{F#|uI}cMRriXoD|LFRhO%_^dJaO$NmnLrxJ zIh%0rqDCbI8K?+`%M{TDZ8C-k6qih9L>~lK6RBkp(qU#t9p%%|dknMC&=7NU``!8= z^=$HTLE+oc+)@kfF3Ho$9W{*WRIxAjG_opiL@oW|0Q#Cld=@exieOv1U#mJCe#Mxm zsA{J@panhuI)%~k3Qzz&Gm5ZH>P&L9B|w+c<-~*47e!u=LiV)m+08GKJ(fks1Ay-# zzd8W$kS`n(2Qvn~t8brpFHpGm{(ct+i$c?46u`zB6yM6;#-F_2aaFV~mq}|B3-?SO zLfG8;(3j&yY%l+ss{lgY`TZllQtd^xBjO$|42B-w;XMz<$Be@(@j zTnI|Kg?{N1rT0z%=^(FF38=UdAm(Ml) zS#C8Ui7I0%1aq{~H^+rZ-!pLW+r)$|tS6#{gz0zoh1``o;EPSB2v~+4LVRes)&YHK zN%SnTkApW6>VZLl@I=zL*1DfjDY=-T@{A91j_&M-mp+*=(kaT>8%GOeu{#a$?Xl!Z zbpGYf&B#P`Jp~&_tR)aiafnmRqOTXMpLef7_i@Y2V%l^iMuJQ8DT1-g|HpQtD%T6?gmyi!|K5vHXG{n%3x7mpNmFUX?m+xpFoFd^1_>&LNQUF;*8LxBcb<#xlueo<9y_LVs+5>Q zAJa!9a(l(Uqd)oM&n&?j5v)Yah}$O%IVvVpKbn$ISu)QNX;WWYz^kR=~%!z=4~Li>Zr=&h%Q5&KxDIPh*B zq?KwJ*+Uxdcs!9%Ru;@UsR0ZW58*kZA67P(1zU3>QFQ}u3nJ1SA(p5>S7N}vdPm&m zOdJDpDGS07ubVx7Ozg-!XAh<4+Vjhp3qgp(I68L4`RbOyASEJ?=I2nW6HjqxC8RJlt}jh)(p{7{>^A{nW|SZcbp((p^K8x5l!(M zvl=fqL<-TT9b|q(m-U#DWE^ypMmyrTkz|aOh_%w*f??+_T|BA+leEFGEsIqI#(>?p zV$r^^d7Z`g(*Qexp+7Ha(M&DypAjWm@Qk#in{4|li0f{=Fzfr2IomIDml~h9ro+X{ z=J5Adz>L?~>BREFY$>Do9*nOCa&0S6MFYtH1@ZE&t%pq#G(hzN*ZTerujY4+SG@oY z`T={uY%71qS%c4O%*|02V)qV9&(rF2Zv(0D8J>I?dES6#s>*gvi47@B%P7HQ{rYVu zB8+^9l{I;n{EoY?5xn%3cu55Vi&E{N&WeS;Bq4N!#B^@D?qpyWhm?S{exBz5Jxtyk zc>Jd}GC;|)R4m+}*_OA%I9qqrZo4cPO25Y;Krp-61~Y=pX}6T3`T8i{x1OjoWfyC2 zf}_}>jSzUGra6ZWFz$X?Ph!V|Vf)yauZM`f=JmD{u|_$FVUGzHPM8FR%^YkFSWbqc z@$McFlpw6GX@g|M@<-**D;)~1m;Vo8o=hKL2`vt2DVGW_APu1GQ635%Huc%c)6oU4 z1=q0nmj`!xw)os?(MA6_BQmY!;zU6&ITZmvh_5ysMUTnx1qOrh0ZyoAp!QTnuo?a5 z;B?GeRjqAu6%0g}Z^GQ#a!q$|Q?G*k4YrI!-_w)g)L!m+m%{wc|M zHDRbTIRjr_C$jhS&vM5@f6zv~@j~*H!&0wI$TfHfnEjEmJ4`-4REy#$m~&$q&qYj2 z$4+P1UGge(&Iyd7Z<5%k;Y{Asf-^7H0Dqd_a%)NGhMyIL(+9{%sIzuK5%rZs)n@(k z9ro5W%{dQgesj1!t(QHBJpya+g+T041${K4wP{RRFy6DT3)hmY?Sz~tn@I)EjAMEB zEB5A!yPu|NvAnNFzjko-cemsun?iS^@{?AKf}E1=EIctKFe3&D zDuzgg_YDCF6)_eB6vhx?M6mFdtpF&pGptc{Pp-?4d@wOEAutIB1uG5%0vZJX1QcPU jhV>3T Date: Wed, 24 Jan 2018 18:14:51 +0300 Subject: [PATCH 30/89] wip --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index c0f724f513382..5169a37cb524f 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -120,8 +120,10 @@ private static void RunClient(string machineName, string serverName, int port) Console.WriteLine("Client closed."); } - static X509Certificate2 LoadCertificateFile() + public static X509Certificate2 LoadCertificateFile() { + // File has been created with the command: + // openssl pkcs12 -export -out cert.pfx -in client_full.pem -certfile ca.pem return new X509Certificate2(@"s:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\ssl\cert.pfx", "123456"); } } From c8aaa5ecd158f7643c713cc2f433c14c1b4a288a Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 18:20:11 +0300 Subject: [PATCH 31/89] it does not actually work --- .../Client/RawSecureSocketTest.cs | 51 ++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 5169a37cb524f..f13aab709bae0 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -30,6 +30,7 @@ namespace Apache.Ignite.Core.Tests.Client using System.Security.Principal; using System.Text; using Apache.Ignite.Core.Client; + using Apache.Ignite.Core.Impl.Binary.IO; using NUnit.Framework; /// @@ -101,18 +102,17 @@ private static void RunClient(string machineName, string serverName, int port) { sslStream.AuthenticateAsClient(serverName, certsCollection, SslProtocols.Default, false); } - catch (AuthenticationException e) + catch (AuthenticationException) { - Console.WriteLine("Exception: {0}", e.Message); - if (e.InnerException != null) - { - Console.WriteLine("Inner exception: {0}", e.InnerException.Message); - } Console.WriteLine("Authentication failed - closing the connection."); client.Close(); - return; + throw; } + Assert.IsTrue(sslStream.IsAuthenticated); + Assert.IsTrue(sslStream.IsMutuallyAuthenticated); + Assert.IsTrue(sslStream.IsEncrypted); + // TODO: Handhsake. sslStream.WriteByte(1); @@ -120,11 +120,46 @@ private static void RunClient(string machineName, string serverName, int port) Console.WriteLine("Client closed."); } - public static X509Certificate2 LoadCertificateFile() + private static X509Certificate2 LoadCertificateFile() { // File has been created with the command: // openssl pkcs12 -export -out cert.pfx -in client_full.pem -certfile ca.pem return new X509Certificate2(@"s:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\ssl\cert.pfx", "123456"); } + + /// + /// Receives the message. + /// + private static byte[] ReceiveMessage(Socket sock) + { + var buf = new byte[4]; + sock.Receive(buf); + + using (var stream = new BinaryHeapStream(buf)) + { + var size = stream.ReadInt(); + buf = new byte[size]; + sock.Receive(buf); + return buf; + } + } + + /// + /// Sends the request. + /// + private static int SendRequest(Socket sock, Action writeAction) + { + using (var stream = new BinaryHeapStream(128)) + { + stream.WriteInt(0); // Reserve message size. + + writeAction(stream); + + stream.WriteInt(0, stream.Position - 4); // Write message size. + + return sock.Send(stream.GetArray(), stream.Position, SocketFlags.None); + } + } + } } From 031f28352de29094849a65cbcc0b800ad7d16167 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 18:26:59 +0300 Subject: [PATCH 32/89] Handshake works. --- .../Client/RawSecureSocketTest.cs | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index f13aab709bae0..84404ea40f8ae 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -75,13 +75,15 @@ public void TestSslOnServer() X509Chain chain, SslPolicyErrors sslPolicyErrors) { + return true; + /** if (sslPolicyErrors == SslPolicyErrors.None) return true; Console.WriteLine("Certificate error: {0}", sslPolicyErrors); // Do not allow this client to communicate with unauthenticated servers. - return false; + return false;*/ } private static void RunClient(string machineName, string serverName, int port) @@ -113,8 +115,7 @@ private static void RunClient(string machineName, string serverName, int port) Assert.IsTrue(sslStream.IsMutuallyAuthenticated); Assert.IsTrue(sslStream.IsEncrypted); - // TODO: Handhsake. - sslStream.WriteByte(1); + DoHandshake(sslStream); client.Close(); Console.WriteLine("Client closed."); @@ -127,19 +128,47 @@ private static X509Certificate2 LoadCertificateFile() return new X509Certificate2(@"s:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\ssl\cert.pfx", "123456"); } + /// + /// Does the handshake. + /// + /// The sock. + private static void DoHandshake(Stream sock) + { + SendRequest(sock, stream => + { + // Handshake. + stream.WriteByte(1); + + // Protocol version. + stream.WriteShort(1); + stream.WriteShort(0); + stream.WriteShort(0); + + // Client type: platform. + stream.WriteByte(2); + }); + + // ACK. + var ack = ReceiveMessage(sock); + + Assert.AreEqual(1, ack.Length); + Assert.AreEqual(1, ack[0]); + } + + /// /// Receives the message. /// - private static byte[] ReceiveMessage(Socket sock) + private static byte[] ReceiveMessage(Stream sock) { var buf = new byte[4]; - sock.Receive(buf); + sock.Read(buf, 0, 4); using (var stream = new BinaryHeapStream(buf)) { var size = stream.ReadInt(); buf = new byte[size]; - sock.Receive(buf); + sock.Read(buf, 0, size); return buf; } } @@ -147,7 +176,7 @@ private static byte[] ReceiveMessage(Socket sock) /// /// Sends the request. /// - private static int SendRequest(Socket sock, Action writeAction) + private static void SendRequest(Stream sock, Action writeAction) { using (var stream = new BinaryHeapStream(128)) { @@ -157,7 +186,7 @@ private static int SendRequest(Socket sock, Action writeAction stream.WriteInt(0, stream.Position - 4); // Write message size. - return sock.Send(stream.GetArray(), stream.Position, SocketFlags.None); + sock.Write(stream.GetArray(), 0, stream.Position); } } From 2b3df0f1f2f8c01dd08b529225cd57d274c310df Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 18:28:52 +0300 Subject: [PATCH 33/89] wip --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 84404ea40f8ae..66a92c29b275f 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -125,6 +125,9 @@ private static X509Certificate2 LoadCertificateFile() { // File has been created with the command: // openssl pkcs12 -export -out cert.pfx -in client_full.pem -certfile ca.pem + + // Instead we can convert from JKS directly with + // keytool -importkeystore -srckeystore thekeystore.jks -srcstoretype JKS -destkeystore thekeystore.pfx -deststoretype PKCS12 return new X509Certificate2(@"s:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\ssl\cert.pfx", "123456"); } From d539ba4763450d56f0396e531bfdc321cb235e1c Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 19:00:27 +0300 Subject: [PATCH 34/89] wip --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 66a92c29b275f..f7841db665e7a 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -128,6 +128,12 @@ private static X509Certificate2 LoadCertificateFile() // Instead we can convert from JKS directly with // keytool -importkeystore -srckeystore thekeystore.jks -srcstoretype JKS -destkeystore thekeystore.pfx -deststoretype PKCS12 + + // TODO: What is the use case? Ask Igor. + // 1) User generates some certificates for server and client ? + // 2) Certificates are applied in Java style on server, pfx on .NET client? + // What do we add to IgniteClientConfiguration? + return new X509Certificate2(@"s:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\ssl\cert.pfx", "123456"); } From 61305b956b964500035a3277b56f62a0d1c50fb7 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 19:29:10 +0300 Subject: [PATCH 35/89] IClientSocket introduced --- .../Apache.Ignite.Core.csproj | 2 + .../Client/ISslStreamFactory.cs | 34 +++++++++++++++ .../Client/IgniteClientConfiguration.cs | 7 ++++ .../Impl/Binary/BinaryProcessorClient.cs | 4 +- .../Impl/Client/ClientSocket.cs | 2 +- .../Impl/Client/IClientSocket.cs | 42 +++++++++++++++++++ .../Impl/Client/IgniteClient.cs | 4 +- 7 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs create mode 100644 modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IClientSocket.cs diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj index adae2b10c249a..71525bf7aec12 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj @@ -56,6 +56,7 @@ + @@ -92,6 +93,7 @@ + diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs new file mode 100644 index 0000000000000..8475f079a3528 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +namespace Apache.Ignite.Core.Client +{ + using System.IO; + using System.Net.Security; + + /// + /// SSL Stream Factory defines how SSL connection is established. + /// + public interface ISslStreamFactory + { + /// + /// Creates the SSL stream. + /// + SslStream Create(Stream innerStream); + } +} diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientConfiguration.cs index e20666f29baac..ff94b3ca9b74c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientConfiguration.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientConfiguration.cs @@ -137,6 +137,13 @@ public IgniteClientConfiguration(IgniteClientConfiguration cfg) : this() /// public BinaryConfiguration BinaryConfiguration { get; set; } + /// + /// Gets or sets the SSL stream factory. + /// + /// When not null, secure socket connection will be established. + /// + public ISslStreamFactory SslStreamFactory { get; set; } + /// /// Gets or sets custom binary processor. Internal property for tests. /// diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs index febecd456e48a..d68f66ea6da8e 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs @@ -32,7 +32,7 @@ internal class BinaryProcessorClient : IBinaryProcessor private const byte DotNetPlatformId = 1; /** Socket. */ - private readonly ClientSocket _socket; + private readonly IClientSocket _socket; /** Marshaller. */ private readonly Marshaller _marsh = BinaryUtils.Marshaller; @@ -41,7 +41,7 @@ internal class BinaryProcessorClient : IBinaryProcessor /// Initializes a new instance of the class. /// /// The socket. - public BinaryProcessorClient(ClientSocket socket) + public BinaryProcessorClient(IClientSocket socket) { Debug.Assert(socket != null); diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs index f9e77fcbdc23c..e29f8f8f97b90 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs @@ -35,7 +35,7 @@ namespace Apache.Ignite.Core.Impl.Client /// /// Wrapper over framework socket for Ignite thin client operations. /// - internal sealed class ClientSocket : IDisposable + internal sealed class ClientSocket : IClientSocket { /** Current version. */ private static readonly ClientProtocolVersion CurrentProtocolVersion = new ClientProtocolVersion(1, 0, 0); diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IClientSocket.cs new file mode 100644 index 0000000000000..badf38708da25 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IClientSocket.cs @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Impl.Client +{ + using System; + using System.Threading.Tasks; + using Apache.Ignite.Core.Client; + using Apache.Ignite.Core.Impl.Binary.IO; + + /// + /// Client socket interface. + /// + internal interface IClientSocket : IDisposable + { + /// + /// Performs a send-receive operation. + /// + T DoOutInOp(ClientOp opId, Action writeAction, + Func readFunc, Func errorFunc = null); + + /// + /// Performs a send-receive operation asynchronously. + /// + Task DoOutInOpAsync(ClientOp opId, Action writeAction, + Func readFunc, Func errorFunc = null); + } +} \ No newline at end of file diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs index 1b1aa6f82b7b5..aad7d15fc35e1 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs @@ -39,7 +39,7 @@ namespace Apache.Ignite.Core.Impl.Client internal class IgniteClient : IIgniteInternal, IIgniteClient { /** Socket. */ - private readonly ClientSocket _socket; + private readonly IClientSocket _socket; /** Marshaller. */ private readonly Marshaller _marsh; @@ -78,7 +78,7 @@ public IgniteClient(IgniteClientConfiguration clientConfiguration) /// /// Gets the socket. /// - public ClientSocket Socket + public IClientSocket Socket { get { return _socket; } } From 1c88ce07d082a9eb4ead8fe5926bd37e08a54c9b Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 19:31:57 +0300 Subject: [PATCH 36/89] wip --- .../Apache.Ignite.Core.csproj | 1 + .../Impl/Client/ClientSecureSocket.cs | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj index 71525bf7aec12..1ff65a16bda03 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj @@ -93,6 +93,7 @@ + diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs new file mode 100644 index 0000000000000..1bfbcfaad5370 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Impl.Client +{ + using System; + using System.Threading.Tasks; + using Apache.Ignite.Core.Client; + using Apache.Ignite.Core.Impl.Binary.IO; + + /// + /// Wrapper over framework socket for Ignite thin client operations, with SSL. + /// + internal class ClientSecureSocket : IClientSocket + { + /** */ + public T DoOutInOp(ClientOp opId, Action writeAction, Func readFunc, Func errorFunc = null) + { + throw new NotImplementedException(); + } + + /** */ + public Task DoOutInOpAsync(ClientOp opId, Action writeAction, Func readFunc, Func errorFunc = null) + { + throw new NotImplementedException(); + } + + /** */ + public void Dispose() + { + throw new NotImplementedException(); + } + } +} From f6403548d880d1675d46a56b1c52c74888b79757 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 19:45:39 +0300 Subject: [PATCH 37/89] wip --- .../Impl/Client/ClientSecureSocket.cs | 34 +++++++++++++++++-- .../Impl/Client/ClientSocket.cs | 2 +- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs index 1bfbcfaad5370..01630999199f0 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs @@ -18,6 +18,9 @@ namespace Apache.Ignite.Core.Impl.Client { using System; + using System.Diagnostics; + using System.Net.Security; + using System.Net.Sockets; using System.Threading.Tasks; using Apache.Ignite.Core.Client; using Apache.Ignite.Core.Impl.Binary.IO; @@ -27,14 +30,41 @@ namespace Apache.Ignite.Core.Impl.Client /// internal class ClientSecureSocket : IClientSocket { + /** Stream. */ + private readonly SslStream _stream; + + /// + /// Initializes a new instance of the class. + /// + /// The client configuration. + public ClientSecureSocket(IgniteClientConfiguration clientConfiguration) + { + Debug.Assert(clientConfiguration != null); + Debug.Assert(clientConfiguration.SslStreamFactory != null); + + _stream = Connect(clientConfiguration); + } + + /// + /// Connects the SSL stream. + /// + private static SslStream Connect(IgniteClientConfiguration cfg) + { + var sock = ClientSocket.Connect(cfg); + + return cfg.SslStreamFactory.Create(new NetworkStream(sock)); + } + /** */ - public T DoOutInOp(ClientOp opId, Action writeAction, Func readFunc, Func errorFunc = null) + public T DoOutInOp(ClientOp opId, Action writeAction, Func readFunc, + Func errorFunc = null) { throw new NotImplementedException(); } /** */ - public Task DoOutInOpAsync(ClientOp opId, Action writeAction, Func readFunc, Func errorFunc = null) + public Task DoOutInOpAsync(ClientOp opId, Action writeAction, + Func readFunc, Func errorFunc = null) { throw new NotImplementedException(); } diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs index e29f8f8f97b90..3bf9c1a0b3868 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs @@ -415,7 +415,7 @@ private RequestMessage WriteMessage(Action writeAction, ClientOp /// [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Socket is returned from this method.")] - private static Socket Connect(IgniteClientConfiguration cfg) + public static Socket Connect(IgniteClientConfiguration cfg) { List errors = null; From 71e041a925963ebecebfaf53036848accacba8c1 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 19:47:51 +0300 Subject: [PATCH 38/89] wip --- .../Apache.Ignite.Core/Client/IgniteClientConfiguration.cs | 1 + .../dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientConfiguration.cs index ff94b3ca9b74c..8730f39340965 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientConfiguration.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientConfiguration.cs @@ -89,6 +89,7 @@ public IgniteClientConfiguration(IgniteClientConfiguration cfg) : this() } BinaryProcessor = cfg.BinaryProcessor; + SslStreamFactory = cfg.SslStreamFactory; } /// diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs index aad7d15fc35e1..8167ff86303d5 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs @@ -63,7 +63,9 @@ public IgniteClient(IgniteClientConfiguration clientConfiguration) _configuration = new IgniteClientConfiguration(clientConfiguration); - _socket = new ClientSocket(_configuration); + _socket = _configuration.SslStreamFactory != null + ? (IClientSocket) new ClientSecureSocket(_configuration) + : new ClientSocket(_configuration); _marsh = new Marshaller(_configuration.BinaryConfiguration) { From b07b3996d44d6f5d1557d0a960c385518aaac695 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 19:58:29 +0300 Subject: [PATCH 39/89] wip --- .../Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs index 01630999199f0..53045558eb988 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs @@ -66,13 +66,18 @@ private static SslStream Connect(IgniteClientConfiguration cfg) public Task DoOutInOpAsync(ClientOp opId, Action writeAction, Func readFunc, Func errorFunc = null) { - throw new NotImplementedException(); + // TODO: Proper async. + var tcs = new TaskCompletionSource(); + + tcs.SetResult(DoOutInOp(opId, writeAction, readFunc, errorFunc)); + + return tcs.Task; } /** */ public void Dispose() { - throw new NotImplementedException(); + _stream.Dispose(); } } } From 4ea45e3dec54d24fec561fe71e78106618cc5f0d Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 24 Jan 2018 20:07:13 +0300 Subject: [PATCH 40/89] wip --- .../dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs index 53045558eb988..324ca4c73bb35 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs @@ -43,6 +43,8 @@ public ClientSecureSocket(IgniteClientConfiguration clientConfiguration) Debug.Assert(clientConfiguration.SslStreamFactory != null); _stream = Connect(clientConfiguration); + + // TODO: Refactor ClientSocket to use NetworkStream? Need to check performance. } /// From 69011bbd800a4df58d58ba91d71138a58e867b6d Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Thu, 25 Jan 2018 12:20:16 +0300 Subject: [PATCH 41/89] wip --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index f7841db665e7a..7ec23fbf05dc5 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -39,8 +39,9 @@ namespace Apache.Ignite.Core.Tests.Client public class RawSecureSocketTest { // TODO: See queries_ssl_test.cpp, queries-ssl.xml - - + // https://ggsystems.atlassian.net/wiki/spaces/GG/pages/4219735/Set+up+SSL+connection+between+nodes + + [Test] public void TestSslOnServer() { From caec742336d24fac68f9da9aad42a43fd558d37e Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Thu, 25 Jan 2018 12:31:03 +0300 Subject: [PATCH 42/89] Refactor existing code to NetworkStream --- .../Impl/Client/ClientSecureSocket.cs | 2 +- .../Impl/Client/ClientSocket.cs | 23 +++++++++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs index 324ca4c73bb35..fd9b11b672a73 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs @@ -54,7 +54,7 @@ private static SslStream Connect(IgniteClientConfiguration cfg) { var sock = ClientSocket.Connect(cfg); - return cfg.SslStreamFactory.Create(new NetworkStream(sock)); + return cfg.SslStreamFactory.Create(sock); } /** */ diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs index 3bf9c1a0b3868..38bf7a2ce00f0 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs @@ -47,7 +47,7 @@ internal sealed class ClientSocket : IClientSocket private const byte ClientType = 2; /** Underlying socket. */ - private readonly Socket _socket; + private readonly NetworkStream _socket; /** Operation timeout. */ private readonly TimeSpan _timeout; @@ -242,8 +242,7 @@ private void Handshake(ClientProtocolVersion version) Debug.Assert(messageLen == 12); - var sent = _socket.Send(buf, messageLen, SocketFlags.None); - Debug.Assert(sent == messageLen); + _socket.Write(buf, 0, messageLen); // Decode response. var res = ReceiveMessage(); @@ -288,11 +287,11 @@ private byte[] ReceiveBytes(int size) // Socket.Receive can return any number of bytes, even 1. // We should repeat Receive calls until required amount of data has been received. var buf = new byte[size]; - var received = _socket.Receive(buf); + var received = _socket.Read(buf,0, size); - while (received < size) + while (received < size) // TODO: ?? { - var res = _socket.Receive(buf, received, size - received, SocketFlags.None); + var res = _socket.Read(buf, received, size - received); if (res == 0) { @@ -326,7 +325,7 @@ private BinaryHeapStream SendRequest(ref RequestMessage reqMsg) if (_requests.IsEmpty) { - _socket.Send(reqMsg.Buffer, 0, reqMsg.Length, SocketFlags.None); + _socket.Write(reqMsg.Buffer, 0, reqMsg.Length); var respMsg = ReceiveMessage(); var response = new BinaryHeapStream(respMsg); @@ -368,7 +367,7 @@ private Task SendRequestAsync(ref RequestMessage reqMsg) Debug.Assert(added); // Send. - _socket.Send(reqMsg.Buffer, 0, reqMsg.Length, SocketFlags.None); + _socket.Write(reqMsg.Buffer, 0, reqMsg.Length); _listenerEvent.Set(); return req.CompletionSource.Task; } @@ -415,7 +414,7 @@ private RequestMessage WriteMessage(Action writeAction, ClientOp /// [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Socket is returned from this method.")] - public static Socket Connect(IgniteClientConfiguration cfg) + public static NetworkStream Connect(IgniteClientConfiguration cfg) { List errors = null; @@ -443,7 +442,11 @@ public static Socket Connect(IgniteClientConfiguration cfg) socket.Connect(ipEndPoint); - return socket; + return new NetworkStream(socket) + { + ReadTimeout = (int) cfg.SocketTimeout.TotalMilliseconds, + WriteTimeout = (int) cfg.SocketTimeout.TotalMilliseconds + }; } catch (SocketException e) { From fda3996e51188afc62a795a1cc49b0cff8e1a3b8 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Thu, 25 Jan 2018 13:04:52 +0300 Subject: [PATCH 43/89] Remove IClientSocket stuff --- .../Apache.Ignite.Core.csproj | 2 - .../Impl/Binary/BinaryProcessorClient.cs | 4 +- .../Impl/Client/ClientSecureSocket.cs | 85 ------------------- .../Impl/Client/ClientSocket.cs | 2 +- .../Impl/Client/IClientSocket.cs | 42 --------- .../Impl/Client/IgniteClient.cs | 8 +- 6 files changed, 6 insertions(+), 137 deletions(-) delete mode 100644 modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs delete mode 100644 modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IClientSocket.cs diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj index 1ff65a16bda03..e1aa994b4d722 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj @@ -93,8 +93,6 @@ - - diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs index d68f66ea6da8e..febecd456e48a 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessorClient.cs @@ -32,7 +32,7 @@ internal class BinaryProcessorClient : IBinaryProcessor private const byte DotNetPlatformId = 1; /** Socket. */ - private readonly IClientSocket _socket; + private readonly ClientSocket _socket; /** Marshaller. */ private readonly Marshaller _marsh = BinaryUtils.Marshaller; @@ -41,7 +41,7 @@ internal class BinaryProcessorClient : IBinaryProcessor /// Initializes a new instance of the class. /// /// The socket. - public BinaryProcessorClient(IClientSocket socket) + public BinaryProcessorClient(ClientSocket socket) { Debug.Assert(socket != null); diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs deleted file mode 100644 index fd9b11b672a73..0000000000000 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSecureSocket.cs +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace Apache.Ignite.Core.Impl.Client -{ - using System; - using System.Diagnostics; - using System.Net.Security; - using System.Net.Sockets; - using System.Threading.Tasks; - using Apache.Ignite.Core.Client; - using Apache.Ignite.Core.Impl.Binary.IO; - - /// - /// Wrapper over framework socket for Ignite thin client operations, with SSL. - /// - internal class ClientSecureSocket : IClientSocket - { - /** Stream. */ - private readonly SslStream _stream; - - /// - /// Initializes a new instance of the class. - /// - /// The client configuration. - public ClientSecureSocket(IgniteClientConfiguration clientConfiguration) - { - Debug.Assert(clientConfiguration != null); - Debug.Assert(clientConfiguration.SslStreamFactory != null); - - _stream = Connect(clientConfiguration); - - // TODO: Refactor ClientSocket to use NetworkStream? Need to check performance. - } - - /// - /// Connects the SSL stream. - /// - private static SslStream Connect(IgniteClientConfiguration cfg) - { - var sock = ClientSocket.Connect(cfg); - - return cfg.SslStreamFactory.Create(sock); - } - - /** */ - public T DoOutInOp(ClientOp opId, Action writeAction, Func readFunc, - Func errorFunc = null) - { - throw new NotImplementedException(); - } - - /** */ - public Task DoOutInOpAsync(ClientOp opId, Action writeAction, - Func readFunc, Func errorFunc = null) - { - // TODO: Proper async. - var tcs = new TaskCompletionSource(); - - tcs.SetResult(DoOutInOp(opId, writeAction, readFunc, errorFunc)); - - return tcs.Task; - } - - /** */ - public void Dispose() - { - _stream.Dispose(); - } - } -} diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs index 38bf7a2ce00f0..7de61f4154d2b 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs @@ -35,7 +35,7 @@ namespace Apache.Ignite.Core.Impl.Client /// /// Wrapper over framework socket for Ignite thin client operations. /// - internal sealed class ClientSocket : IClientSocket + internal sealed class ClientSocket : IDisposable { /** Current version. */ private static readonly ClientProtocolVersion CurrentProtocolVersion = new ClientProtocolVersion(1, 0, 0); diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IClientSocket.cs deleted file mode 100644 index badf38708da25..0000000000000 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IClientSocket.cs +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace Apache.Ignite.Core.Impl.Client -{ - using System; - using System.Threading.Tasks; - using Apache.Ignite.Core.Client; - using Apache.Ignite.Core.Impl.Binary.IO; - - /// - /// Client socket interface. - /// - internal interface IClientSocket : IDisposable - { - /// - /// Performs a send-receive operation. - /// - T DoOutInOp(ClientOp opId, Action writeAction, - Func readFunc, Func errorFunc = null); - - /// - /// Performs a send-receive operation asynchronously. - /// - Task DoOutInOpAsync(ClientOp opId, Action writeAction, - Func readFunc, Func errorFunc = null); - } -} \ No newline at end of file diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs index 8167ff86303d5..1b1aa6f82b7b5 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs @@ -39,7 +39,7 @@ namespace Apache.Ignite.Core.Impl.Client internal class IgniteClient : IIgniteInternal, IIgniteClient { /** Socket. */ - private readonly IClientSocket _socket; + private readonly ClientSocket _socket; /** Marshaller. */ private readonly Marshaller _marsh; @@ -63,9 +63,7 @@ public IgniteClient(IgniteClientConfiguration clientConfiguration) _configuration = new IgniteClientConfiguration(clientConfiguration); - _socket = _configuration.SslStreamFactory != null - ? (IClientSocket) new ClientSecureSocket(_configuration) - : new ClientSocket(_configuration); + _socket = new ClientSocket(_configuration); _marsh = new Marshaller(_configuration.BinaryConfiguration) { @@ -80,7 +78,7 @@ public IgniteClient(IgniteClientConfiguration clientConfiguration) /// /// Gets the socket. /// - public IClientSocket Socket + public ClientSocket Socket { get { return _socket; } } From 32d080e1459b87b455738c018936c1d301d3a4e7 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Thu, 25 Jan 2018 13:07:23 +0300 Subject: [PATCH 44/89] ClientSocket SSL refactoring done --- .../Impl/Client/ClientSocket.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs index 7de61f4154d2b..7c897e5a5a998 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs @@ -22,6 +22,7 @@ namespace Apache.Ignite.Core.Impl.Client using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; + using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; @@ -47,7 +48,7 @@ internal sealed class ClientSocket : IDisposable private const byte ClientType = 2; /** Underlying socket. */ - private readonly NetworkStream _socket; + private readonly Stream _socket; /** Operation timeout. */ private readonly TimeSpan _timeout; @@ -289,7 +290,7 @@ private byte[] ReceiveBytes(int size) var buf = new byte[size]; var received = _socket.Read(buf,0, size); - while (received < size) // TODO: ?? + while (received < size) { var res = _socket.Read(buf, received, size - received); @@ -414,7 +415,7 @@ private RequestMessage WriteMessage(Action writeAction, ClientOp /// [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Socket is returned from this method.")] - public static NetworkStream Connect(IgniteClientConfiguration cfg) + public static Stream Connect(IgniteClientConfiguration cfg) { List errors = null; @@ -442,11 +443,18 @@ public static NetworkStream Connect(IgniteClientConfiguration cfg) socket.Connect(ipEndPoint); - return new NetworkStream(socket) + var stream = new NetworkStream(socket) { ReadTimeout = (int) cfg.SocketTimeout.TotalMilliseconds, WriteTimeout = (int) cfg.SocketTimeout.TotalMilliseconds }; + + if (cfg.SslStreamFactory == null) + { + return stream; + } + + return cfg.SslStreamFactory.Create(stream); } catch (SocketException e) { From 529d40385a4de362e35cf8a337e40ffefba6185b Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Thu, 25 Jan 2018 13:17:47 +0300 Subject: [PATCH 45/89] Fix dispose --- .../Impl/Client/ClientSocket.cs | 51 ++++++++++++------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs index 7c897e5a5a998..830c75234cc33 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs @@ -48,7 +48,10 @@ internal sealed class ClientSocket : IDisposable private const byte ClientType = 2; /** Underlying socket. */ - private readonly Stream _socket; + private readonly Socket _socket; + + /** Underlying socket stream. */ + private readonly Stream _stream; /** Operation timeout. */ private readonly TimeSpan _timeout; @@ -94,6 +97,7 @@ public ClientSocket(IgniteClientConfiguration clientConfiguration, ClientProtoco _timeout = clientConfiguration.SocketTimeout; _socket = Connect(clientConfiguration); + _stream = GetSocketStream(_socket, clientConfiguration); Handshake(version ?? CurrentProtocolVersion); @@ -243,7 +247,7 @@ private void Handshake(ClientProtocolVersion version) Debug.Assert(messageLen == 12); - _socket.Write(buf, 0, messageLen); + _stream.Write(buf, 0, messageLen); // Decode response. var res = ReceiveMessage(); @@ -288,11 +292,11 @@ private byte[] ReceiveBytes(int size) // Socket.Receive can return any number of bytes, even 1. // We should repeat Receive calls until required amount of data has been received. var buf = new byte[size]; - var received = _socket.Read(buf,0, size); + var received = _stream.Read(buf,0, size); while (received < size) { - var res = _socket.Read(buf, received, size - received); + var res = _stream.Read(buf, received, size - received); if (res == 0) { @@ -326,7 +330,7 @@ private BinaryHeapStream SendRequest(ref RequestMessage reqMsg) if (_requests.IsEmpty) { - _socket.Write(reqMsg.Buffer, 0, reqMsg.Length); + _stream.Write(reqMsg.Buffer, 0, reqMsg.Length); var respMsg = ReceiveMessage(); var response = new BinaryHeapStream(respMsg); @@ -368,7 +372,7 @@ private Task SendRequestAsync(ref RequestMessage reqMsg) Debug.Assert(added); // Send. - _socket.Write(reqMsg.Buffer, 0, reqMsg.Length); + _stream.Write(reqMsg.Buffer, 0, reqMsg.Length); _listenerEvent.Set(); return req.CompletionSource.Task; } @@ -415,7 +419,7 @@ private RequestMessage WriteMessage(Action writeAction, ClientOp /// [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Socket is returned from this method.")] - public static Stream Connect(IgniteClientConfiguration cfg) + private static Socket Connect(IgniteClientConfiguration cfg) { List errors = null; @@ -443,18 +447,7 @@ public static Stream Connect(IgniteClientConfiguration cfg) socket.Connect(ipEndPoint); - var stream = new NetworkStream(socket) - { - ReadTimeout = (int) cfg.SocketTimeout.TotalMilliseconds, - WriteTimeout = (int) cfg.SocketTimeout.TotalMilliseconds - }; - - if (cfg.SslStreamFactory == null) - { - return stream; - } - - return cfg.SslStreamFactory.Create(stream); + return socket; } catch (SocketException e) { @@ -476,6 +469,25 @@ public static Stream Connect(IgniteClientConfiguration cfg) "examine inner exceptions for details.", errors); } + /// + /// Gets the socket stream. + /// + private static Stream GetSocketStream(Socket socket, IgniteClientConfiguration cfg) + { + var stream = new NetworkStream(socket) + { + ReadTimeout = (int) cfg.SocketTimeout.TotalMilliseconds, + WriteTimeout = (int) cfg.SocketTimeout.TotalMilliseconds + }; + + if (cfg.SslStreamFactory == null) + { + return stream; + } + + return cfg.SslStreamFactory.Create(stream); + } + /// /// Gets the endpoints: all combinations of IP addresses and ports according to configuration. /// @@ -598,6 +610,7 @@ public void Dispose() _exception = _exception ?? new ObjectDisposedException(typeof(ClientSocket).FullName); EndRequestsWithError(); + _stream.Dispose(); _socket.Dispose(); _listenerEvent.Set(); _listenerEvent.Dispose(); From 2a25d16459e9aa9c11d2f734f0f46ba580dacc5a Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Thu, 25 Jan 2018 19:27:52 +0300 Subject: [PATCH 46/89] Adding predefined SslStreamFactory --- .../Apache.Ignite.Core.csproj | 1 + .../Client/ISslStreamFactory.cs | 1 - .../Client/SslStreamFactory.cs | 42 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj index e1aa994b4d722..039aecf1af822 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj @@ -57,6 +57,7 @@ + diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs index 8475f079a3528..fccf7efef0d8b 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs @@ -15,7 +15,6 @@ * limitations under the License. */ - namespace Apache.Ignite.Core.Client { using System.IO; diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs new file mode 100644 index 0000000000000..525fdce9d5658 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Client +{ + using System; + using System.IO; + using System.Net.Security; + + /// + /// Predefined SSL stream factory, loads certificate from specified file. + /// + public class SslStreamFactory : ISslStreamFactory + { + /** */ + public SslStream Create(Stream innerStream) + { + throw new NotImplementedException(); + } + + /// + /// Gets or sets a value indicating whether to ignore invalid certificates. + /// This undermines security (because anyone can join the cluster), + /// but may be useful for testing with self-signed certificates. + /// + public bool IgnoreInvalidCertificates { get; set; } + } +} From 0277f16e6f9cdd8420dc56ffcf779121034e0701 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Thu, 25 Jan 2018 19:31:59 +0300 Subject: [PATCH 47/89] wip --- .../Client/RawSecureSocketTest.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 7ec23fbf05dc5..d0365340202c7 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -49,10 +49,14 @@ public void TestSslOnServer() // IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH Environment.SetEnvironmentVariable("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH", - @"S:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config"); + @"c:\w\incubator-ignite\modules\platforms\cpp\odbc-test\config"); - using (var ignite = Ignition.Start( - @"S:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\queries-ssl.xml")) + var icfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) + { + SpringConfigUrl = @"c:\w\incubator-ignite\modules\platforms\cpp\odbc-test\config\queries-ssl.xml" + }; + + using (var ignite = Ignition.Start(icfg)) { var cfg = new IgniteClientConfiguration { From f7290a114421aa9485a7f7a2c0ca5c6e08420e24 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Thu, 25 Jan 2018 19:42:49 +0300 Subject: [PATCH 48/89] SslStreamFactory implemented --- .../Client/ISslStreamFactory.cs | 7 ++- .../Client/SslStreamFactory.cs | 51 +++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs index fccf7efef0d8b..d4c2347ecb695 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/ISslStreamFactory.cs @@ -28,6 +28,11 @@ public interface ISslStreamFactory /// /// Creates the SSL stream. /// - SslStream Create(Stream innerStream); + /// The underlying raw stream. + /// Target host. + /// + /// SSL stream. + /// + SslStream Create(Stream stream, string targetHost); } } diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs index 525fdce9d5658..ccdd25168871c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs @@ -17,9 +17,11 @@ namespace Apache.Ignite.Core.Client { - using System; using System.IO; using System.Net.Security; + using System.Security.Authentication; + using System.Security.Cryptography.X509Certificates; + using Apache.Ignite.Core.Impl.Common; /// /// Predefined SSL stream factory, loads certificate from specified file. @@ -27,16 +29,59 @@ namespace Apache.Ignite.Core.Client public class SslStreamFactory : ISslStreamFactory { /** */ - public SslStream Create(Stream innerStream) + public SslStream Create(Stream stream, string targetHost) { - throw new NotImplementedException(); + IgniteArgumentCheck.NotNull(stream, "stream"); + + var sslStream = new SslStream(stream, false, ValidateServerCertificate, null); + + var cert = new X509Certificate2(CertificatePath, CertificatePassword); + var certs = new X509CertificateCollection(new X509Certificate[] { cert }); + + sslStream.AuthenticateAsClient(targetHost, certs, SslProtocols.Default, CheckCertificateRevocation); + + return sslStream; + } + + /// + /// Validates the server certificate. + /// + private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, + SslPolicyErrors sslPolicyErrors) + { + if (IgnoreInvalidCertificates) + { + return true; + } + + if (sslPolicyErrors == SslPolicyErrors.None) + { + return true; + } + + return false; } + /// + /// Gets or sets the certificate file (pfx) path. + /// + public string CertificatePath { get; set; } + + /// + /// Gets or sets the certificate file password. + /// + public string CertificatePassword { get; set; } + /// /// Gets or sets a value indicating whether to ignore invalid certificates. /// This undermines security (because anyone can join the cluster), /// but may be useful for testing with self-signed certificates. /// public bool IgnoreInvalidCertificates { get; set; } + + /// + /// Gets or sets a value indicating whether the certificate revocation list is checked during authentication. + /// + public bool CheckCertificateRevocation { get; set; } } } From 02183ff84682f2379571dd172c393b4b8101d7b9 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Thu, 25 Jan 2018 19:45:37 +0300 Subject: [PATCH 49/89] wip --- .../dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs index 830c75234cc33..99cc53e855d87 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs @@ -485,7 +485,8 @@ private static Stream GetSocketStream(Socket socket, IgniteClientConfiguration c return stream; } - return cfg.SslStreamFactory.Create(stream); + // TODO: Host name. + return cfg.SslStreamFactory.Create(stream, null); } /// From 36d07342d9a100e1c0999e2a9a120fb881cc0b49 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Fri, 26 Jan 2018 11:56:38 +0300 Subject: [PATCH 50/89] wip --- .../Impl/Client/ClientSocket.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs index 99cc53e855d87..981bd0398ff3a 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs @@ -694,5 +694,30 @@ public RequestMessage(long id, byte[] buffer, int length) Buffer = buffer; } } + + /// + /// Represents a socket connection. + /// + private struct Connection + { + /** */ + public readonly Socket Socket; + + /** */ + public readonly Stream Stream; + + /** */ + public readonly string Host; + + /// + /// Initializes a new instance of the struct. + /// + public Connection(Socket socket, Stream stream, string host) + { + Socket = socket; + Stream = stream; + Host = host; + } + } } } From cb5524f9c8651c01d47349b0c4055906c8974bad Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Fri, 26 Jan 2018 12:22:56 +0300 Subject: [PATCH 51/89] fix host --- .../Impl/Client/ClientSocket.cs | 28 +------------------ 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs index 981bd0398ff3a..301000443789b 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs @@ -485,8 +485,7 @@ private static Stream GetSocketStream(Socket socket, IgniteClientConfiguration c return stream; } - // TODO: Host name. - return cfg.SslStreamFactory.Create(stream, null); + return cfg.SslStreamFactory.Create(stream, cfg.Host); } /// @@ -694,30 +693,5 @@ public RequestMessage(long id, byte[] buffer, int length) Buffer = buffer; } } - - /// - /// Represents a socket connection. - /// - private struct Connection - { - /** */ - public readonly Socket Socket; - - /** */ - public readonly Stream Stream; - - /** */ - public readonly string Host; - - /// - /// Initializes a new instance of the struct. - /// - public Connection(Socket socket, Stream stream, string host) - { - Socket = socket; - Stream = stream; - Host = host; - } - } } } From 8016cf6dbc2cfa6935f7c4f232123ee0744160f1 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Fri, 26 Jan 2018 12:43:48 +0300 Subject: [PATCH 52/89] wip --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index d0365340202c7..5559fb2cbd3af 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -18,17 +18,11 @@ namespace Apache.Ignite.Core.Tests.Client { using System; - using System.Collections; using System.IO; using System.Net.Security; using System.Net.Sockets; - using System.Security; - using System.Security.AccessControl; using System.Security.Authentication; - using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; - using System.Security.Principal; - using System.Text; using Apache.Ignite.Core.Client; using Apache.Ignite.Core.Impl.Binary.IO; using NUnit.Framework; From 577b90ec0afbbf61570aa06c3dcb76a2958d57f9 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Fri, 26 Jan 2018 15:03:11 +0300 Subject: [PATCH 53/89] wip tests --- .../Apache.Ignite.Core.Tests.csproj | 1 + .../Client/RawSecureSocketTest.cs | 2 +- .../Config/thin-client-cert.pfx} | Bin 3 files changed, 2 insertions(+), 1 deletion(-) rename modules/platforms/{cpp/odbc-test/config/ssl/cert.pfx => dotnet/Apache.Ignite.Core.Tests/Config/thin-client-cert.pfx} (100%) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj index 76f1c19387cdd..6a7e3e3ccdd11 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj @@ -474,6 +474,7 @@ + PreserveNewest diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 5559fb2cbd3af..3b9b9c56acac3 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -133,7 +133,7 @@ private static X509Certificate2 LoadCertificateFile() // 2) Certificates are applied in Java style on server, pfx on .NET client? // What do we add to IgniteClientConfiguration? - return new X509Certificate2(@"s:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\ssl\cert.pfx", "123456"); + return new X509Certificate2(@"Config\thin-client-cert.pfx", "123456"); } /// diff --git a/modules/platforms/cpp/odbc-test/config/ssl/cert.pfx b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/thin-client-cert.pfx similarity index 100% rename from modules/platforms/cpp/odbc-test/config/ssl/cert.pfx rename to modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/thin-client-cert.pfx From 116c044abca0721bc5f6565d57763cb06b8b228a Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Fri, 26 Jan 2018 15:53:15 +0300 Subject: [PATCH 54/89] wip --- .../Apache.Ignite.Core.Tests.csproj | 4 +++- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 7 ++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj index 6a7e3e3ccdd11..d32bbad929d19 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj @@ -474,7 +474,9 @@ - + + PreserveNewest + PreserveNewest diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 3b9b9c56acac3..db00943b2b712 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -128,11 +128,8 @@ private static X509Certificate2 LoadCertificateFile() // Instead we can convert from JKS directly with // keytool -importkeystore -srckeystore thekeystore.jks -srcstoretype JKS -destkeystore thekeystore.pfx -deststoretype PKCS12 - // TODO: What is the use case? Ask Igor. - // 1) User generates some certificates for server and client ? - // 2) Certificates are applied in Java style on server, pfx on .NET client? - // What do we add to IgniteClientConfiguration? - + // TODO: In C++ there is some key store with root cert, server and client certs are signed with root cert. + // How do we check certs against some trusted store? return new X509Certificate2(@"Config\thin-client-cert.pfx", "123456"); } From 711c6639792625e8c7c89273f5b6cfe844a5b5b7 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Fri, 26 Jan 2018 16:52:32 +0300 Subject: [PATCH 55/89] CacheTestSsl added --- .../Apache.Ignite.Core.Tests.csproj | 1 + .../Client/Cache/CacheTest.cs | 16 +++++++++ .../Client/Cache/CacheTestSsl.cs | 36 +++++++++++++++++++ .../Client/ClientTestBase.cs | 15 ++++++-- 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj index d32bbad929d19..58311aeace386 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj @@ -127,6 +127,7 @@ + diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs index 4c51d721e4ec8..dc27efda60b52 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs @@ -32,6 +32,22 @@ namespace Apache.Ignite.Core.Tests.Client.Cache /// public class CacheTest : ClientTestBase { + /// + /// Initializes a new instance of the class. + /// + public CacheTest() + { + // No-op. + } + + /// + /// Initializes a new instance of the class. + /// + public CacheTest(int gridCount, bool ssl) : base(gridCount, ssl) + { + // No-op. + } + /// /// Tests the cache put / get with primitive data types. /// diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs new file mode 100644 index 0000000000000..87307f39fd94f --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Client.Cache +{ + using NUnit.Framework; + + /// + /// Async cache test. + /// + [TestFixture] + public sealed class CacheTestSsl : CacheTest + { + /// + /// Initializes a new instance of the class. + /// + public CacheTestSsl() : base(1, true) + { + // No-op. + } + } +} diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs index 71e4a6fb11f0a..c7953f07941fb 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs @@ -38,6 +38,9 @@ public class ClientTestBase /** Grid count. */ private readonly int _gridCount = 1; + /** Whether SSL should be enabled. */ + private readonly bool _ssl; + /// /// Initializes a new instance of the class. /// @@ -49,9 +52,10 @@ public ClientTestBase() /// /// Initializes a new instance of the class. /// - public ClientTestBase(int gridCount) + public ClientTestBase(int gridCount, bool ssl) { _gridCount = gridCount; + _ssl = ssl; } /// @@ -140,7 +144,14 @@ protected IgniteClientConfiguration GetClientConfiguration() { return new IgniteClientConfiguration { - Host = IPAddress.Loopback.ToString() + Host = IPAddress.Loopback.ToString(), + SslStreamFactory = _ssl + ? new SslStreamFactory + { + CertificatePath = @"Config\thin-client-cert.pfx", + CertificatePassword = "123456" + } + : null }; } From f33894c25c1cc5f3cda807de3ce924ff5e11ba00 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Fri, 26 Jan 2018 16:53:55 +0300 Subject: [PATCH 56/89] wip --- .../dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs index c7953f07941fb..e320a7122989f 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs @@ -52,7 +52,7 @@ public ClientTestBase() /// /// Initializes a new instance of the class. /// - public ClientTestBase(int gridCount, bool ssl) + public ClientTestBase(int gridCount, bool ssl = false) { _gridCount = gridCount; _ssl = ssl; From 266bc90afa5d97ed842e4710aef2beda60b9550b Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 13:15:25 +0300 Subject: [PATCH 57/89] wip --- .../Client/Cache/CacheTestSsl.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs index 87307f39fd94f..067795d56d934 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs @@ -32,5 +32,14 @@ public CacheTestSsl() : base(1, true) { // No-op. } + + /// + /// Gets the Ignite configuration. + /// + protected override IgniteConfiguration GetIgniteConfiguration() + { + // TODO: Enable SSL. Add our own configs (copy from CPP or whatever). + return base.GetIgniteConfiguration(); + } } } From eb9865ef2acae09ae93f4f41713693e8c9ba6b66 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 13:16:58 +0300 Subject: [PATCH 58/89] wip --- .../Client/Cache/CacheTestSsl.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs index 067795d56d934..f59c2df32ddc2 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs @@ -17,6 +17,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache { + using System; using NUnit.Framework; /// @@ -39,7 +40,14 @@ public CacheTestSsl() : base(1, true) protected override IgniteConfiguration GetIgniteConfiguration() { // TODO: Enable SSL. Add our own configs (copy from CPP or whatever). - return base.GetIgniteConfiguration(); + var cfg = base.GetIgniteConfiguration(); + + Environment.SetEnvironmentVariable("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH", + @"c:\w\incubator-ignite\modules\platforms\cpp\odbc-test\config"); + + cfg.SpringConfigUrl = @"c:\w\incubator-ignite\modules\platforms\cpp\odbc-test\config\queries-ssl.xml"; + + return cfg; } } } From 98a47aef9bd2a55bf6d8d53a334e262038298959 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 13:26:12 +0300 Subject: [PATCH 59/89] wip --- .../Client/Cache/CacheTestSsl.cs | 21 ++++++++++++++----- .../Client/ClientTestBase.cs | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs index f59c2df32ddc2..87b94ed7f6a11 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs @@ -18,6 +18,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache { using System; + using Apache.Ignite.Core.Client; using NUnit.Framework; /// @@ -39,15 +40,25 @@ public CacheTestSsl() : base(1, true) /// protected override IgniteConfiguration GetIgniteConfiguration() { - // TODO: Enable SSL. Add our own configs (copy from CPP or whatever). - var cfg = base.GetIgniteConfiguration(); - + // TODO: Add our own configs. Environment.SetEnvironmentVariable("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH", @"c:\w\incubator-ignite\modules\platforms\cpp\odbc-test\config"); - cfg.SpringConfigUrl = @"c:\w\incubator-ignite\modules\platforms\cpp\odbc-test\config\queries-ssl.xml"; + return new IgniteConfiguration(base.GetIgniteConfiguration()) + { + SpringConfigUrl = @"c:\w\incubator-ignite\modules\platforms\cpp\odbc-test\config\queries-ssl.xml" + }; + } - return cfg; + /// + /// Gets the client configuration. + /// + protected override IgniteClientConfiguration GetClientConfiguration() + { + return new IgniteClientConfiguration(base.GetClientConfiguration()) + { + Port = 11110 + }; } } } diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs index e320a7122989f..9f6e48df6e7f0 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs @@ -140,7 +140,7 @@ protected IIgniteClient GetClient() /// /// Gets the client configuration. /// - protected IgniteClientConfiguration GetClientConfiguration() + protected virtual IgniteClientConfiguration GetClientConfiguration() { return new IgniteClientConfiguration { From 723ebc5185ce077752884c0c436e4b5edf45dd09 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 13:29:24 +0300 Subject: [PATCH 60/89] wip tests --- .../Client/Cache/CacheTest.cs | 16 ---------------- .../Client/Cache/CacheTestSsl.cs | 15 ++++++--------- .../Client/ClientTestBase.cs | 15 ++------------- 3 files changed, 8 insertions(+), 38 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs index dc27efda60b52..4c51d721e4ec8 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs @@ -32,22 +32,6 @@ namespace Apache.Ignite.Core.Tests.Client.Cache /// public class CacheTest : ClientTestBase { - /// - /// Initializes a new instance of the class. - /// - public CacheTest() - { - // No-op. - } - - /// - /// Initializes a new instance of the class. - /// - public CacheTest(int gridCount, bool ssl) : base(gridCount, ssl) - { - // No-op. - } - /// /// Tests the cache put / get with primitive data types. /// diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs index 87b94ed7f6a11..eee63cafb697c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs @@ -27,14 +27,6 @@ namespace Apache.Ignite.Core.Tests.Client.Cache [TestFixture] public sealed class CacheTestSsl : CacheTest { - /// - /// Initializes a new instance of the class. - /// - public CacheTestSsl() : base(1, true) - { - // No-op. - } - /// /// Gets the Ignite configuration. /// @@ -57,7 +49,12 @@ protected override IgniteClientConfiguration GetClientConfiguration() { return new IgniteClientConfiguration(base.GetClientConfiguration()) { - Port = 11110 + Port = 11110, + SslStreamFactory = new SslStreamFactory + { + CertificatePath = @"Config\thin-client-cert.pfx", + CertificatePassword = "123456" + } }; } } diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs index 9f6e48df6e7f0..db5e621729dab 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs @@ -38,9 +38,6 @@ public class ClientTestBase /** Grid count. */ private readonly int _gridCount = 1; - /** Whether SSL should be enabled. */ - private readonly bool _ssl; - /// /// Initializes a new instance of the class. /// @@ -52,10 +49,9 @@ public ClientTestBase() /// /// Initializes a new instance of the class. /// - public ClientTestBase(int gridCount, bool ssl = false) + public ClientTestBase(int gridCount) { _gridCount = gridCount; - _ssl = ssl; } /// @@ -144,14 +140,7 @@ protected virtual IgniteClientConfiguration GetClientConfiguration() { return new IgniteClientConfiguration { - Host = IPAddress.Loopback.ToString(), - SslStreamFactory = _ssl - ? new SslStreamFactory - { - CertificatePath = @"Config\thin-client-cert.pfx", - CertificatePassword = "123456" - } - : null + Host = IPAddress.Loopback.ToString() }; } From a0cc2a01335c0f6ddb02dd502a8dc962ae9b8a5e Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 13:31:25 +0300 Subject: [PATCH 61/89] wip --- .../Client/Cache/CacheTestSsl.cs | 3 ++- .../dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs | 9 ++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs index eee63cafb697c..e95d809de47d8 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs @@ -53,7 +53,8 @@ protected override IgniteClientConfiguration GetClientConfiguration() SslStreamFactory = new SslStreamFactory { CertificatePath = @"Config\thin-client-cert.pfx", - CertificatePassword = "123456" + CertificatePassword = "123456", + SkipServerCertificateValidation = true } }; } diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs index ccdd25168871c..5edafa7a47e2e 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs @@ -49,7 +49,7 @@ public SslStream Create(Stream stream, string targetHost) private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { - if (IgnoreInvalidCertificates) + if (SkipServerCertificateValidation) { return true; } @@ -73,11 +73,10 @@ public SslStream Create(Stream stream, string targetHost) public string CertificatePassword { get; set; } /// - /// Gets or sets a value indicating whether to ignore invalid certificates. - /// This undermines security (because anyone can join the cluster), - /// but may be useful for testing with self-signed certificates. + /// Gets or sets a value indicating whether to ignore invalid remote (server) certificates. + /// This may be useful for testing with self-signed certificates. /// - public bool IgnoreInvalidCertificates { get; set; } + public bool SkipServerCertificateValidation { get; set; } /// /// Gets or sets a value indicating whether the certificate revocation list is checked during authentication. From 15f3692e721f10071821c6aa7c2dc75482520bf0 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 13:34:47 +0300 Subject: [PATCH 62/89] wip --- .../dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs index 301000443789b..8814bc56e4176 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs @@ -322,6 +322,9 @@ private BinaryHeapStream SendRequest(ref RequestMessage reqMsg) // If there are no pending async requests, we can execute this operation synchronously, // which is more efficient. + + // TODO: SSL: The Write method cannot be called when another write operation is pending. + // We may have to force sync mode in SSL, or at least write in sync mode. if (_sendRequestLock.TryEnterWriteLock(0)) { try From e1e12914958a847eb51bdf1f8dcb79b200874baa Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 14:31:56 +0300 Subject: [PATCH 63/89] Adding test certs --- .../Apache.Ignite.Core.Tests.csproj | 7 ++- .../Client/Cache/CacheTestSsl.cs | 9 +-- .../Config/Client/server-with-ssl.xml | 53 ++++++++++++++++++ .../Config/Client/server.jks | Bin 0 -> 4256 bytes .../Config/{ => Client}/thin-client-cert.pfx | Bin .../Config/Client/trust.jks | Bin 0 -> 1089 bytes 6 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml create mode 100644 modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server.jks rename modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/{ => Client}/thin-client-cert.pfx (100%) create mode 100644 modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/trust.jks diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj index 58311aeace386..6ab873a00e3f7 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj @@ -388,6 +388,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -475,9 +478,11 @@ - + + PreserveNewest + PreserveNewest diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs index e95d809de47d8..e81a89922e891 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs @@ -17,7 +17,6 @@ namespace Apache.Ignite.Core.Tests.Client.Cache { - using System; using Apache.Ignite.Core.Client; using NUnit.Framework; @@ -32,13 +31,9 @@ public sealed class CacheTestSsl : CacheTest /// protected override IgniteConfiguration GetIgniteConfiguration() { - // TODO: Add our own configs. - Environment.SetEnvironmentVariable("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH", - @"c:\w\incubator-ignite\modules\platforms\cpp\odbc-test\config"); - return new IgniteConfiguration(base.GetIgniteConfiguration()) { - SpringConfigUrl = @"c:\w\incubator-ignite\modules\platforms\cpp\odbc-test\config\queries-ssl.xml" + SpringConfigUrl = @"Config\Client\server-with-ssl.xml" }; } @@ -52,7 +47,7 @@ protected override IgniteClientConfiguration GetClientConfiguration() Port = 11110, SslStreamFactory = new SslStreamFactory { - CertificatePath = @"Config\thin-client-cert.pfx", + CertificatePath = @"Config\Client\thin-client-cert.pfx", CertificatePassword = "123456", SkipServerCertificateValidation = true } diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml new file mode 100644 index 0000000000000..4e909a6b65bf4 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server.jks b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server.jks new file mode 100644 index 0000000000000000000000000000000000000000..2632662c175974e8c31fdaf377fd4b9393854e83 GIT binary patch literal 4256 zcmeH~cU03^7RU2TNF*3~wbF|~LINZd1wjOXrARL_KxmPcgoKWO1jItI&_NI>Dlj0$ z&=CTPG#vzW03m>=bQqA1z@j_jnLWE_|KHvDYU~?}n0-6>R;01Dv`(}90u5=V=ETg8Sr ztWCzdUUV0+Aba=+;VJGSdZYlN8{XfOM8pW7`MxWN5#ir)8d?ee4)amjRzKmT}L^pT=-RB&>EdxmK7?Ft;i`7EqgWAm89=W zgy&UBBOA3XiU-og%XcGd?2~nHvXqHP{SKRa1M3rRd_}nx+Zlz`x_XA!5k_I-nF&A) zS6^O4kN0+<=;0&=*{)1_RRI|g7jFEsBSO>00DoF(0(%SM+g9!K4Q=$#Nlt02YVca-$4X9 zBK+32@L-4dl%}yGCpx9)&l5VQ+@yA5hpB5`7wYg_w5|y0kpk+dU1M|QBQnHb4#mVP z%k-410415yG(=OEhpm?}zm?mbqxJ_m;+$4xJv3CkwLpiVDJs~TYv$@8@B9`h^o*~* zy)0+vfe2rIYy{*q_C;}0-uO!-C z(C#f~xiQo7r+^fJv7$HAvw<05`ZAqwO!v|{uGBa1cjh! zEPH4U7@HgnU;$*o+`xWHvCvp%d&XPLqU4Zp8diS-+3Mr+FnSZyIIAlhnWQnhn(2HR z!?YFB>iuPoE`2HQ-TUs!;#Z?h#!EG@O2gMAI&GWpzWHTmqy*C>!kH$?xdN)Ir+)GE zon-P7Q&tydAGF_&==F$O2lwl{5O*`~ND9r`d*1VeafW)DYA(A5l`+ak#);sm8;ZOe z8rN~V%=k1@1Oz*BSDGiW{KAB`^a$2BQ8?X1)j<-bx)>w;G>!O7hTPg%&+o_Ke@RBO zY6S>yG)_Sr_BZq7rgwOK;vQmr9u@QY{1y^U0Z zU1$9ZrAS0nT>tXzwu(i1d!w=I@dX>V`Cf{*V;t&3?44_-9)oVTyxXZoA}2S{t7oKx z&vDz-1sPAt9Wr_?Ln!WIyn3>-1mNVGJCYB)=SO~iaEfv-;pPh@uJcu~r`AdF$U{wW zVUo>@D{V`jzAw|0_$|EK+cN3-wgu@rb@l2y;eD0~5nA09_VIZwo3yTrXK@Yj(h9ho z;&@F+Q+vi9{nL!#Gqrl&_YGjXc|Avm%i73(^$kn>>k6FQ2jTU1r9Z#a?x5kwHoD`6&A(Yoa&8J+COZ-yJbW@Xp?+GHQKWQ@c-6ARh35!E-F^Plo-*{; z;ktLuwy3e_b7|?w32%+pCc}y`O81nQINefbuf>&*Pfs&H2SN@ZLZyO83WeUjmah(% zWs7=tM#g64juMp-N{-h}&-&nqIIUiIks?4qg$# zNmft4n0jhEE(-5V91NWe2)c{t$}0Wjqd{gGD$4nc-3@3M=(iz&rgqYEJg|;yq$%hb z?%L3@Rr{7|xWMqn-fqjPRd6vl-UjyN7~4XGa)sUW;ToP%w+|tzoHJGP2_d1*FG4aD z9{Yr}``xOl?GQm7@#-CKbxDUW^wxOnqJzzws=j2ivi3R6ByOM6jDB>8MZP%`|3pl? z{g)bH*Oe9gTKtyo=Af&gsk@adf>_#3q9zZ&+Qoi)%5EI%lyZ3rj|k_@HHCBt5#uQX z*6Ujyj}`*I)-tHdd-t=NJ8DNZT?xsx2gveeIQ@}ck;aY4xW6IGnq$_#W;oJ_O6S!i zUvL?{6)!HE)~VjoSfc$j7?j(&(jfNp&q_8F?9g*?l^a2Lu1~kwE`P zs7MW?gjQ0*{y{}5ze}{h58&ecGjQ#b#eXJ_rod7u4%R$aN9`F`N6*You^qh7%-LSE z3q^5vco&_92hW);o6C5dkn^#2mb!Ahj=?f1r<~{E{dR)8mQ*WjYCki>gK|tP$ySu8 z2IoKnjath4p$*vjq1?JHryB~-@#}>r%qQ8r@&(%yjPoTd06*1SmB+2mnq=$fGFN&b zd{$uKjE}9g3$K{bw!tcF_cVM$#CT*`40qI+i~cTg@S62%!KM3&**7Z?8uNjjHwYKw zUw$wiZm%{hY4>VR9TLLzNo#h>GfUH%ajCP9n!8&p7Rc^bD^dP2IwwnaMh05d+Q3Q6 zCrygu5`Hw{ukodPn7S(fgK2o<__zAIRRZCOmK70LhUxfko%eLBXqo%0UBGOpW70Jf!_-)NI z3w`93t|w_h$FE!v&rLR*=1^{XT~MfHkT7a_PFHSifs$Knjh%gF_{++HNtZ>wt*(r$ zsmn=N=`Q1$Y2G1QLh;j&^fha03Cl}6H#XWNIM@nd3TO%(oe+!TQ)@CmESuq&;toAC zDmI&!c=5UPz58m)JV)EaS?-i@;~wnjnZ2b&n@9VFh2xR1=kw~j!bYXcifY&=JXBBB z-2Njf_EnpP$&wXQX^4NDIn;i-|Ms>~HS@uE>$|@ij=vg?zZ#DJ+lIpf^ESbNu+xpu P>lk0NnWR0ZSn~WGo?zNW literal 0 HcmV?d00001 diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/thin-client-cert.pfx b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/thin-client-cert.pfx similarity index 100% rename from modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/thin-client-cert.pfx rename to modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/thin-client-cert.pfx diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/trust.jks b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/trust.jks new file mode 100644 index 0000000000000000000000000000000000000000..a0f3bcfc30787fbe400e3c794f039dbbdd3161e3 GIT binary patch literal 1089 zcmezO_TO6u1_mY|W(3nB$*DypnQ58Hi6yCtr6n2pMVTd)K*_C*_cCF*o2va zLJcJi#6cVm9)aM*%)AoafYg%IqT-~|qI8%PI~FNr14WQ7E*>ezg2d#ERE6Mzw370~ zqErR9{L;LX#FEVXJVP-95s)Ho9$u&-&-A>^l2k(x10j$&GY_|CdVY~YaAHAfdcL8e zfjr!$oQz^ZnZ;mnheWUidih1^26E!OhUSKbMiz$V#)gJwQR2KtAg&pdJEZ;A#HfTE zRgA0*%uS5^3NNJ01V`@{=Phk7nAj{dcb0_nx)cUuDVa zKS>i*?(cNqf4e?&`tmHQ6IKk8{yx zb=^IV!K-e}P~PybetXmuXEUv$$Mqg3!WVmnX{Ly*T(I%?%%$60-Ml(^e5xPL>Sb&Z zxU{J5O!n_GMXAXL3nJI4zZTyeQe7Q7Nm`?mr_nN5Wh-}%Pa&uDWw|NyVm|*=IQ8>* zh}%xJ^<3}R_~P4VZM{{zOILrlmO|j^FB7NxCU1SYT*i{~g5sqMvm}14l5LrN=Et?? zQTe7uiky8O|CY_>JSos#+;eA|4!`);HowNxOw5c7jL0DbOw7O#Vr1}Naj;26ne&Rt z%`I%R8N@R-ZnY#CZwB||mw*l!VU!|2W4-+IeprHtk}qvO2WH`JkPm z_=N?5$uT+!R~eUP_H3K@Njox)r}oo&AI5omE;R}UPMy5TwtB%^LG3@aKB7}*Z=P6x z!#3nf@x2`3r&r$YT6Jl4bECjTSZQGZMl^5!}TpUkd{^R;@Z>Dg|rIgZnTC+W8RCLz& aPIr=dbfVr#$@Hq`rNH^hlc!vtsRsa3Nt9gx literal 0 HcmV?d00001 From 128e69504ecdb6e8c58997e87ae4205070f53ce8 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 14:34:45 +0300 Subject: [PATCH 64/89] wip --- .../Apache.Ignite.Core.Tests.csproj | 8 ++++++-- .../Config/Client/server-with-ssl.xml | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj index 6ab873a00e3f7..1d6084d0fed70 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj @@ -478,11 +478,15 @@ - + + PreserveNewest + PreserveNewest - + + PreserveNewest + PreserveNewest diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml index 4e909a6b65bf4..03acc6aa2c577 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml @@ -41,9 +41,9 @@ - + - + From 4a9f77b8e3117b94d8e6ae1f5093bcd621eaf1bc Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 14:50:20 +0300 Subject: [PATCH 65/89] wip tests cleanup --- .../Client/RawSecureSocketTest.cs | 102 ++++++------------ 1 file changed, 31 insertions(+), 71 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index db00943b2b712..f441e03db2af2 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -32,105 +32,65 @@ namespace Apache.Ignite.Core.Tests.Client /// public class RawSecureSocketTest { - // TODO: See queries_ssl_test.cpp, queries-ssl.xml - // https://ggsystems.atlassian.net/wiki/spaces/GG/pages/4219735/Set+up+SSL+connection+between+nodes - - + /// + /// Tests the SSL on server. + /// [Test] public void TestSslOnServer() { - // S:\W\incubator-ignite\modules\platforms\cpp\odbc-test\config\ssl\server.jks - // IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH - - Environment.SetEnvironmentVariable("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH", - @"c:\w\incubator-ignite\modules\platforms\cpp\odbc-test\config"); - var icfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) { - SpringConfigUrl = @"c:\w\incubator-ignite\modules\platforms\cpp\odbc-test\config\queries-ssl.xml" + SpringConfigUrl = @"Config\Client\server-with-ssl.xml" }; - using (var ignite = Ignition.Start(icfg)) + using (Ignition.Start(icfg)) { var cfg = new IgniteClientConfiguration { Host = "127.0.0.1", Port = 11110 }; - //using (var client = Ignition.StartClient(cfg)) - //{ - // client.GetCacheNames(); - //} - RunClient(cfg.Host, cfg.Host, cfg.Port); + using (var client = new TcpClient(cfg.Host, cfg.Port)) + using (var sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null)) + { + var certsCollection = new X509CertificateCollection(new X509Certificate[] {LoadCertificateFile()}); + + sslStream.AuthenticateAsClient(cfg.Host, certsCollection, SslProtocols.Default, false); + + Assert.IsTrue(sslStream.IsAuthenticated); + Assert.IsTrue(sslStream.IsMutuallyAuthenticated); + Assert.IsTrue(sslStream.IsEncrypted); + + DoHandshake(sslStream); + } } } - - // The following method is invoked by the RemoteCertificateValidationDelegate. + /// + /// Validates the server certificate. + /// private static bool ValidateServerCertificate( object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { - return true; - /** - if (sslPolicyErrors == SslPolicyErrors.None) - return true; - - Console.WriteLine("Certificate error: {0}", sslPolicyErrors); - - // Do not allow this client to communicate with unauthenticated servers. - return false;*/ - } - - private static void RunClient(string machineName, string serverName, int port) - { - // Create a TCP/IP client socket. - // machineName is the host running the server application. - var client = new TcpClient(machineName, port); - Console.WriteLine("Client connected."); - - // Create an SSL stream that will close the client's stream. - var sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null); - - // The server name must match the name on the server certificate. - var certificate = LoadCertificateFile(); - var certsCollection = new X509CertificateCollection(new X509Certificate[] { certificate }); - - try - { - sslStream.AuthenticateAsClient(serverName, certsCollection, SslProtocols.Default, false); - } - catch (AuthenticationException) - { - Console.WriteLine("Authentication failed - closing the connection."); - client.Close(); - throw; - } + Console.WriteLine("Validating certificate: " + certificate); + Console.WriteLine("Certificate errors: " + sslPolicyErrors); - Assert.IsTrue(sslStream.IsAuthenticated); - Assert.IsTrue(sslStream.IsMutuallyAuthenticated); - Assert.IsTrue(sslStream.IsEncrypted); - - DoHandshake(sslStream); - - client.Close(); - Console.WriteLine("Client closed."); + return true; } + /// + /// Loads the certificate file. + /// private static X509Certificate2 LoadCertificateFile() { - // File has been created with the command: - // openssl pkcs12 -export -out cert.pfx -in client_full.pem -certfile ca.pem - - // Instead we can convert from JKS directly with - // keytool -importkeystore -srckeystore thekeystore.jks -srcstoretype JKS -destkeystore thekeystore.pfx -deststoretype PKCS12 - - // TODO: In C++ there is some key store with root cert, server and client certs are signed with root cert. - // How do we check certs against some trusted store? - return new X509Certificate2(@"Config\thin-client-cert.pfx", "123456"); + // Conveting from JKS to PFX: + // keytool -importkeystore -srckeystore thekeystore.jks -srcstoretype JKS + // -destkeystore thekeystore.pfx -deststoretype PKCS12 + return new X509Certificate2(@"Config\Client\thin-client-cert.pfx", "123456"); } /// From f4586aa09ce1e8e56bffa620c221ef47ec9b377d Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 14:51:39 +0300 Subject: [PATCH 66/89] wip --- .../dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs index 5edafa7a47e2e..f028e211ac04b 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs @@ -64,6 +64,10 @@ public SslStream Create(Stream stream, string targetHost) /// /// Gets or sets the certificate file (pfx) path. + /// + /// Java certificates can be converted with keytool: + /// keytool -importkeystore -srckeystore thekeystore.jks -srcstoretype JKS + /// -destkeystore thekeystore.pfx -deststoretype PKCS12 /// public string CertificatePath { get; set; } From de98fc2650a52bab344854c9fafd66d8c01a8e14 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 15:10:33 +0300 Subject: [PATCH 67/89] wip --- .../Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs index e81a89922e891..d3049d40f14c8 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs @@ -49,7 +49,8 @@ protected override IgniteClientConfiguration GetClientConfiguration() { CertificatePath = @"Config\Client\thin-client-cert.pfx", CertificatePassword = "123456", - SkipServerCertificateValidation = true + SkipServerCertificateValidation = true, + CheckCertificateRevocation = true } }; } From e5bcd476c80bc2a26528550b6ac7da4e828846ee Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 15:11:24 +0300 Subject: [PATCH 68/89] wip --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index f441e03db2af2..f0b9e5693bf8c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -36,7 +36,7 @@ public class RawSecureSocketTest /// Tests the SSL on server. /// [Test] - public void TestSslOnServer() + public void TestHandshake() { var icfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) { From ac521aec9b0ccd3f82aec923d3cc718510b78c0b Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 15:12:39 +0300 Subject: [PATCH 69/89] raw test done --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index f0b9e5693bf8c..3818da4878dea 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -28,12 +28,12 @@ namespace Apache.Ignite.Core.Tests.Client using NUnit.Framework; /// - /// Tests the thin client mode with a raw secure socket. + /// Tests the thin client mode with a raw secure socket stream. /// public class RawSecureSocketTest { /// - /// Tests the SSL on server. + /// Tests that we can do handshake over SSL without using Ignite.NET APIs. /// [Test] public void TestHandshake() From d7ed074cd7b89e077c11eb2bbfd202b8cbfd3058 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 15:22:55 +0300 Subject: [PATCH 70/89] wip config stuff --- .../Client/IgniteClientConfiguration.xml | Bin 2482 -> 3134 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/IgniteClientConfiguration.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/IgniteClientConfiguration.xml index 18026b4cfc13acf8c39223e3a273c4a415f81630..c943ec792657706d13aedc5ca9a6ab66c5193f3f 100644 GIT binary patch delta 496 zcmZuuI|{;35S&gFthBHcdlmnU3L*%0V!%oZiJAm8ipDR9hsZ_519&!P_aP|^kG#B{ z-JRLbJM+oC?#X8!=A@C*R~tv34J-sWV2L@l81S}f?}*$O74Y8E*Fgb2zQpU&E@21< zK0HQ<)z=L3+7MmR7ZA51g)G58iSU-FI5s^8hI?4?vl%6%BmKK7E%d&69ZV?}NlY2* zGRsGinGr6QVJ)%j6|N|Rk3_NcL;tm87#D40p_&y`Q9~UKG)->Lv~FX~3gRjr6Frl` xbl_>tGB_FUi9W4hc4WTCnk?lw>mAQG;RK|kg-#-dj|(cJi{C=I-td&{d;y0HUYh^_ delta 11 Scmdldu}OGC73X9&9t!{(h6Ahs From f28dc1e999c799b0df111a9d5fc3b30a456afeda Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 15:34:01 +0300 Subject: [PATCH 71/89] Update config xsd schema --- .../IgniteClientConfigurationSection.xsd | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteClientConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteClientConfigurationSection.xsd index f71ce0bae76dc..17b12c76f5178 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteClientConfigurationSection.xsd +++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteClientConfigurationSection.xsd @@ -172,6 +172,35 @@ + + + + + Assembly-qualified type name. + + + + + Path to the certificate file (pfx). + + + + + Certificate file password. + + + + + Whether to check certificate revocation. + + + + + Whether to skip server certificate validation. + + + + From 1c0a7b52d0ab577752024645b3ed7e5ad230ae3f Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 15:35:30 +0300 Subject: [PATCH 72/89] wip tests --- .../Client/IgniteClientConfigurationTest.cs | 7 +++++++ .../Client/IgniteClientConfiguration.xml | Bin 3134 -> 3062 bytes 2 files changed, 7 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs index 1857520063c86..4d55dbb2da507 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs @@ -75,6 +75,13 @@ public void TestFromXml() CompactFooter = false, KeepDeserialized = false, Types = new[] {"foo", "bar"} + }, + SslStreamFactory = new SslStreamFactory + { + CertificatePath = "abc.pfx", + CertificatePassword = "foo", + CheckCertificateRevocation = true, + SkipServerCertificateValidation = true } }; diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/IgniteClientConfiguration.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/IgniteClientConfiguration.xml index c943ec792657706d13aedc5ca9a6ab66c5193f3f..6b3569bb95d7c4a79eafaa8a112d5cbd0a1773fd 100644 GIT binary patch delta 37 rcmdld@lAX~0vBr{LlQ&s}d@7K&UiXkV}8E1^1!JY&;eK+2;y@ delta 119 zcmew+zE5I90+*{ZLq0 Date: Mon, 29 Jan 2018 15:50:50 +0300 Subject: [PATCH 73/89] Refactor sendRequest synchronization --- .../Impl/Client/ClientSocket.cs | 37 ++++++------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs index 8814bc56e4176..fca5dab55062b 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientSocket.cs @@ -73,8 +73,7 @@ internal sealed class ClientSocket : IDisposable private volatile Exception _exception; /** Locker. */ - private readonly ReaderWriterLockSlim _sendRequestLock = - new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); + private readonly object _sendRequestSyncRoot = new object(); /** Background socket receiver trigger. */ private readonly ManualResetEventSlim _listenerEvent = new ManualResetEventSlim(); @@ -322,12 +321,11 @@ private BinaryHeapStream SendRequest(ref RequestMessage reqMsg) // If there are no pending async requests, we can execute this operation synchronously, // which is more efficient. - - // TODO: SSL: The Write method cannot be called when another write operation is pending. - // We may have to force sync mode in SSL, or at least write in sync mode. - if (_sendRequestLock.TryEnterWriteLock(0)) + var lockTaken = false; + try { - try + Monitor.TryEnter(_sendRequestSyncRoot, 0, ref lockTaken); + if (lockTaken) { CheckException(); @@ -343,12 +341,12 @@ private BinaryHeapStream SendRequest(ref RequestMessage reqMsg) return response; } } - finally + } + finally + { + if (lockTaken) { - if (_sendRequestLock.IsWriteLockHeld) - { - _sendRequestLock.ExitWriteLock(); - } + Monitor.Exit(_sendRequestSyncRoot); } } @@ -364,8 +362,7 @@ private Task SendRequestAsync(ref RequestMessage reqMsg) // Do not enter lock when disposed. CheckException(); - _sendRequestLock.EnterReadLock(); - try + lock (_sendRequestSyncRoot) { CheckException(); @@ -379,10 +376,6 @@ private Task SendRequestAsync(ref RequestMessage reqMsg) _listenerEvent.Set(); return req.CompletionSource.Task; } - finally - { - _sendRequestLock.ExitReadLock(); - } } /// @@ -623,14 +616,6 @@ public void Dispose() _timeoutCheckTimer.Dispose(); } - // Wait for lock to be released and dispose. - if (!_sendRequestLock.IsWriteLockHeld) - { - _sendRequestLock.EnterWriteLock(); - } - _sendRequestLock.ExitWriteLock(); - _sendRequestLock.Dispose(); - _isDisposed = true; } } From 8e2c3f8cdd61d35dd16438733365550a53dfd054 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 16:03:23 +0300 Subject: [PATCH 74/89] Fix tests --- .../Client/ClientConnectionTest.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs index 57eb97cee6836..02f88e2b2093e 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs @@ -19,6 +19,7 @@ namespace Apache.Ignite.Core.Tests.Client { using System; using System.Collections.Generic; + using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; @@ -238,15 +239,19 @@ public void TestOperationTimeout() var task = cache.PutAllAsync(data); Assert.IsFalse(task.IsCompleted); var aex = Assert.Throws(() => task.Wait()); - Assert.AreEqual(SocketError.TimedOut, ((SocketException) aex.GetBaseException()).SocketErrorCode); + var socketEx = (SocketException) aex.GetBaseException().InnerException; + Assert.IsNotNull(socketEx); + Assert.AreEqual(SocketError.TimedOut, socketEx.SocketErrorCode); // Sync (reconnect for clean state). Ignition.StopAll(true); Ignition.Start(TestUtils.GetTestConfiguration()); client = Ignition.StartClient(cfg); cache = client.CreateCache("s"); - var ex = Assert.Throws(() => cache.PutAll(data)); - Assert.AreEqual(SocketError.TimedOut, ex.SocketErrorCode); + var ex = Assert.Throws(() => cache.PutAll(data)); + socketEx = (SocketException)ex.InnerException; + Assert.IsNotNull(socketEx); + Assert.AreEqual(SocketError.TimedOut, socketEx.SocketErrorCode); } /// @@ -315,8 +320,10 @@ public void TestIdleTimeout() // Idle check frequency is 2 seconds. Thread.Sleep(4000); - var ex = Assert.Throws(() => cache.Get(1)); - Assert.AreEqual(SocketError.ConnectionAborted, ex.SocketErrorCode); + var ex = Assert.Throws(() => cache.Get(1)); + var socketEx = (SocketException) ex.InnerException; + Assert.IsNotNull(socketEx); + Assert.AreEqual(SocketError.ConnectionAborted, socketEx.SocketErrorCode); } } From 03fcc9f6377abbd3433dbbe173829ea0aaedea1f Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 16:04:12 +0300 Subject: [PATCH 75/89] wip --- .../ApiParity/CacheConfigurationParityTest.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheConfigurationParityTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheConfigurationParityTest.cs index 0022e963ed5a6..4269695204879 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheConfigurationParityTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheConfigurationParityTest.cs @@ -57,8 +57,11 @@ public class CacheConfigurationParityTest private static readonly string[] MissingProperties = { "NodeFilter", // IGNITE-2890 - "EvictionPolicyFactory", // IGNITE-6649, - "isSqlOnheapCacheEnabled" // IGNITE-7379 + "EvictionPolicyFactory", // IGNITE-6649 + "isSqlOnheapCacheEnabled", // IGNITE-7379 + + // IGNITE-7228 + "isSslEnabled", "isUseIgniteSslContextFactory", "isSslClientAuth", "SslContextFactory" }; /// From 9bde5855ea0a30e90d029b2307e219947829f898 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 16:06:06 +0300 Subject: [PATCH 76/89] wip --- .../ApiParity/CacheConfigurationParityTest.cs | 7 ++----- .../ClientConnectorConfigurationParityTest.cs | 11 +++++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheConfigurationParityTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheConfigurationParityTest.cs index 4269695204879..0022e963ed5a6 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheConfigurationParityTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheConfigurationParityTest.cs @@ -57,11 +57,8 @@ public class CacheConfigurationParityTest private static readonly string[] MissingProperties = { "NodeFilter", // IGNITE-2890 - "EvictionPolicyFactory", // IGNITE-6649 - "isSqlOnheapCacheEnabled", // IGNITE-7379 - - // IGNITE-7228 - "isSslEnabled", "isUseIgniteSslContextFactory", "isSslClientAuth", "SslContextFactory" + "EvictionPolicyFactory", // IGNITE-6649, + "isSqlOnheapCacheEnabled" // IGNITE-7379 }; /// diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClientConnectorConfigurationParityTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClientConnectorConfigurationParityTest.cs index f735557af833c..a79c3d68d9c3c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClientConnectorConfigurationParityTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClientConnectorConfigurationParityTest.cs @@ -25,6 +25,13 @@ namespace Apache.Ignite.Core.Tests.ApiParity /// public class ClientConnectorConfigurationParityTest { + /** Properties that are missing on .NET side. */ + private static readonly string[] MissingProperties = + { + // IGNITE-7228 + "isSslEnabled", "isUseIgniteSslContextFactory", "isSslClientAuth", "SslContextFactory" + }; + /// /// Tests the ignite configuration parity. /// @@ -32,8 +39,8 @@ public class ClientConnectorConfigurationParityTest public void TestConnectorConfiguration() { ParityTest.CheckConfigurationParity( - @"modules\core\src\main\java\org\apache\ignite\configuration\ClientConnectorConfiguration.java", - typeof(ClientConnectorConfiguration)); + @"modules\core\src\main\java\org\apache\ignite\configuration\ClientConnectorConfiguration.java", + typeof(ClientConnectorConfiguration), knownMissingProperties: MissingProperties); } } } \ No newline at end of file From c0372511e5fdff49044b8263e9bc5be4e95258ac Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 16:13:38 +0300 Subject: [PATCH 77/89] Add new tests to .NET Core project --- .../Apache.Ignite.Core.Tests.DotNetCore.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj index 67ece471ed823..dc642fd46cc69 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj @@ -97,6 +97,7 @@ + @@ -107,6 +108,7 @@ + From d92095a83101776643f4a29880cf6481229695a1 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 16:25:32 +0300 Subject: [PATCH 78/89] Fix config paths --- .../Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs | 5 +++-- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs index d3049d40f14c8..3f371ff382a08 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs @@ -17,6 +17,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache { + using System.IO; using Apache.Ignite.Core.Client; using NUnit.Framework; @@ -33,7 +34,7 @@ protected override IgniteConfiguration GetIgniteConfiguration() { return new IgniteConfiguration(base.GetIgniteConfiguration()) { - SpringConfigUrl = @"Config\Client\server-with-ssl.xml" + SpringConfigUrl = Path.Combine("Config", "Client", "server-with-ssl.xml") }; } @@ -47,7 +48,7 @@ protected override IgniteClientConfiguration GetClientConfiguration() Port = 11110, SslStreamFactory = new SslStreamFactory { - CertificatePath = @"Config\Client\thin-client-cert.pfx", + CertificatePath = Path.Combine("Config", "Client", "thin-client-cert.pfx"), CertificatePassword = "123456", SkipServerCertificateValidation = true, CheckCertificateRevocation = true diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 3818da4878dea..2704f579d9024 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -40,7 +40,7 @@ public void TestHandshake() { var icfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) { - SpringConfigUrl = @"Config\Client\server-with-ssl.xml" + SpringConfigUrl = Path.Combine("Config", "Client", "server-with-ssl.xml") }; using (Ignition.Start(icfg)) @@ -90,7 +90,7 @@ private static X509Certificate2 LoadCertificateFile() // Conveting from JKS to PFX: // keytool -importkeystore -srckeystore thekeystore.jks -srcstoretype JKS // -destkeystore thekeystore.pfx -deststoretype PKCS12 - return new X509Certificate2(@"Config\Client\thin-client-cert.pfx", "123456"); + return new X509Certificate2(Path.Combine("Config", "Client", "thin-client-cert.pfx"), "123456"); } /// From 9a223763d4c5e1ab43f5e75d7925d46d0917fe17 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 16:28:24 +0300 Subject: [PATCH 79/89] fixing .NET core tests --- .../Apache.Ignite.Core.Tests.DotNetCore.csproj | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj index dc642fd46cc69..b1bdb75bbce6b 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/Apache.Ignite.Core.Tests.DotNetCore.csproj @@ -147,6 +147,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -191,6 +194,15 @@ + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest From fe404195a92f4eed5d7f0e879ee9e8978f542e96 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 16:34:29 +0300 Subject: [PATCH 80/89] wip --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 3 +-- .../dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 2704f579d9024..1868e38e1b850 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -21,7 +21,6 @@ namespace Apache.Ignite.Core.Tests.Client using System.IO; using System.Net.Security; using System.Net.Sockets; - using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using Apache.Ignite.Core.Client; using Apache.Ignite.Core.Impl.Binary.IO; @@ -56,7 +55,7 @@ public void TestHandshake() { var certsCollection = new X509CertificateCollection(new X509Certificate[] {LoadCertificateFile()}); - sslStream.AuthenticateAsClient(cfg.Host, certsCollection, SslProtocols.Default, false); + sslStream.AuthenticateAsClient(cfg.Host, certsCollection, false); Assert.IsTrue(sslStream.IsAuthenticated); Assert.IsTrue(sslStream.IsMutuallyAuthenticated); diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs index f028e211ac04b..45ade109e4726 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs @@ -19,7 +19,6 @@ namespace Apache.Ignite.Core.Client { using System.IO; using System.Net.Security; - using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using Apache.Ignite.Core.Impl.Common; @@ -38,7 +37,7 @@ public SslStream Create(Stream stream, string targetHost) var cert = new X509Certificate2(CertificatePath, CertificatePassword); var certs = new X509CertificateCollection(new X509Certificate[] { cert }); - sslStream.AuthenticateAsClient(targetHost, certs, SslProtocols.Default, CheckCertificateRevocation); + sslStream.AuthenticateAsClient(targetHost, certs, CheckCertificateRevocation); return sslStream; } From b4f79030c42423a9409178fdc68e9d94ab97604c Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 16:45:25 +0300 Subject: [PATCH 81/89] wip fixing ssl protocols --- .../Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs | 3 ++- .../dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs index 1868e38e1b850..11b4e86598d86 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/RawSecureSocketTest.cs @@ -21,6 +21,7 @@ namespace Apache.Ignite.Core.Tests.Client using System.IO; using System.Net.Security; using System.Net.Sockets; + using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using Apache.Ignite.Core.Client; using Apache.Ignite.Core.Impl.Binary.IO; @@ -55,7 +56,7 @@ public void TestHandshake() { var certsCollection = new X509CertificateCollection(new X509Certificate[] {LoadCertificateFile()}); - sslStream.AuthenticateAsClient(cfg.Host, certsCollection, false); + sslStream.AuthenticateAsClient(cfg.Host, certsCollection, SslProtocols.Tls, false); Assert.IsTrue(sslStream.IsAuthenticated); Assert.IsTrue(sslStream.IsMutuallyAuthenticated); diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs index 45ade109e4726..1b5e9ab08abf4 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs @@ -19,6 +19,7 @@ namespace Apache.Ignite.Core.Client { using System.IO; using System.Net.Security; + using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using Apache.Ignite.Core.Impl.Common; @@ -37,7 +38,7 @@ public SslStream Create(Stream stream, string targetHost) var cert = new X509Certificate2(CertificatePath, CertificatePassword); var certs = new X509CertificateCollection(new X509Certificate[] { cert }); - sslStream.AuthenticateAsClient(targetHost, certs, CheckCertificateRevocation); + sslStream.AuthenticateAsClient(targetHost, certs, SslProtocols.Tls, CheckCertificateRevocation); return sslStream; } From 432804e6d6b6ea037cc7a46dcadc0476024be265 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 16:48:47 +0300 Subject: [PATCH 82/89] Adding configurable SSL protocols --- .../Client/SslStreamFactory.cs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs index 1b5e9ab08abf4..7edf08e8114d2 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/SslStreamFactory.cs @@ -17,6 +17,7 @@ namespace Apache.Ignite.Core.Client { + using System.ComponentModel; using System.IO; using System.Net.Security; using System.Security.Authentication; @@ -28,6 +29,19 @@ namespace Apache.Ignite.Core.Client /// public class SslStreamFactory : ISslStreamFactory { + /// + /// Default SSL protocols. + /// + public const SslProtocols DefaultSslProtocols = SslProtocols.Tls; + + /// + /// Initializes a new instance of the class. + /// + public SslStreamFactory() + { + SslProtocols = DefaultSslProtocols; + } + /** */ public SslStream Create(Stream stream, string targetHost) { @@ -38,7 +52,7 @@ public SslStream Create(Stream stream, string targetHost) var cert = new X509Certificate2(CertificatePath, CertificatePassword); var certs = new X509CertificateCollection(new X509Certificate[] { cert }); - sslStream.AuthenticateAsClient(targetHost, certs, SslProtocols.Tls, CheckCertificateRevocation); + sslStream.AuthenticateAsClient(targetHost, certs, SslProtocols, CheckCertificateRevocation); return sslStream; } @@ -86,5 +100,11 @@ public SslStream Create(Stream stream, string targetHost) /// Gets or sets a value indicating whether the certificate revocation list is checked during authentication. /// public bool CheckCertificateRevocation { get; set; } + + /// + /// Gets or sets the SSL protocols. + /// + [DefaultValue(DefaultSslProtocols)] + public SslProtocols SslProtocols { get; set; } } } From 3a2f2b1b7a3534ea8bfdf32b22d5931044565bfb Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 16:50:14 +0300 Subject: [PATCH 83/89] wip --- .../Client/IgniteClientConfigurationTest.cs | 4 +++- .../Client/IgniteClientConfiguration.xml | Bin 3062 -> 3144 bytes .../IgniteClientConfigurationSection.xsd | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs index 4d55dbb2da507..09decc659f542 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/IgniteClientConfigurationTest.cs @@ -20,6 +20,7 @@ namespace Apache.Ignite.Core.Tests.Client using System; using System.Configuration; using System.IO; + using System.Security.Authentication; using System.Text; using System.Xml; using Apache.Ignite.Core.Binary; @@ -81,7 +82,8 @@ public void TestFromXml() CertificatePath = "abc.pfx", CertificatePassword = "foo", CheckCertificateRevocation = true, - SkipServerCertificateValidation = true + SkipServerCertificateValidation = true, + SslProtocols = SslProtocols.None } }; diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/IgniteClientConfiguration.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/IgniteClientConfiguration.xml index 6b3569bb95d7c4a79eafaa8a112d5cbd0a1773fd..8d8d9bf0fec7c58d6eaff3c42ee4a26dd79cea38 100644 GIT binary patch delta 47 ycmew+enMiy7VgP5+h@lAZg7VgPxJWc=}=mbOn diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteClientConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteClientConfigurationSection.xsd index 17b12c76f5178..569ee6fd2d5bd 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteClientConfigurationSection.xsd +++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteClientConfigurationSection.xsd @@ -199,6 +199,11 @@ Whether to skip server certificate validation. + + + SSL protocols to use. + + From 258464784b627ec34acb4372b592ed2f8cd630ed Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 16:57:26 +0300 Subject: [PATCH 84/89] wip ssl/tls --- .../Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs index 3f371ff382a08..95d45afa07944 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestSsl.cs @@ -18,6 +18,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache { using System.IO; + using System.Security.Authentication; using Apache.Ignite.Core.Client; using NUnit.Framework; @@ -51,7 +52,12 @@ protected override IgniteClientConfiguration GetClientConfiguration() CertificatePath = Path.Combine("Config", "Client", "thin-client-cert.pfx"), CertificatePassword = "123456", SkipServerCertificateValidation = true, - CheckCertificateRevocation = true + CheckCertificateRevocation = true, +#if !NETCOREAPP2_0 + SslProtocols = SslProtocols.Tls +#else + SslProtocols = SslProtocols.Tls12 +#endif } }; } From 478a5c2f2e3884cb550684c62a9c960b711bc803 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Mon, 29 Jan 2018 07:26:43 -0800 Subject: [PATCH 85/89] Fix client connection tests on Linux --- .../Client/ClientConnectionTest.cs | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs index 02f88e2b2093e..2169edcea3503 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs @@ -19,7 +19,6 @@ namespace Apache.Ignite.Core.Tests.Client { using System; using System.Collections.Generic; - using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; @@ -238,20 +237,16 @@ public void TestOperationTimeout() // Async. var task = cache.PutAllAsync(data); Assert.IsFalse(task.IsCompleted); - var aex = Assert.Throws(() => task.Wait()); - var socketEx = (SocketException) aex.GetBaseException().InnerException; - Assert.IsNotNull(socketEx); - Assert.AreEqual(SocketError.TimedOut, socketEx.SocketErrorCode); + var ex = Assert.Catch(() => task.Wait()); + Assert.AreEqual(SocketError.TimedOut, GetSocketException(ex).SocketErrorCode); // Sync (reconnect for clean state). Ignition.StopAll(true); Ignition.Start(TestUtils.GetTestConfiguration()); client = Ignition.StartClient(cfg); cache = client.CreateCache("s"); - var ex = Assert.Throws(() => cache.PutAll(data)); - socketEx = (SocketException)ex.InnerException; - Assert.IsNotNull(socketEx); - Assert.AreEqual(SocketError.TimedOut, socketEx.SocketErrorCode); + ex = Assert.Catch(() => cache.PutAll(data)); + Assert.AreEqual(SocketError.TimedOut, GetSocketException(ex).SocketErrorCode); } /// @@ -320,10 +315,8 @@ public void TestIdleTimeout() // Idle check frequency is 2 seconds. Thread.Sleep(4000); - var ex = Assert.Throws(() => cache.Get(1)); - var socketEx = (SocketException) ex.InnerException; - Assert.IsNotNull(socketEx); - Assert.AreEqual(SocketError.ConnectionAborted, socketEx.SocketErrorCode); + var ex = Assert.Catch(() => cache.Get(1)); + Assert.AreEqual(SocketError.ConnectionAborted, GetSocketException(ex).SocketErrorCode); } } @@ -357,5 +350,28 @@ private static IgniteClientConfiguration GetClientConfiguration() { return new IgniteClientConfiguration { Host = IPAddress.Loopback.ToString() }; } + + /// + /// Finds SocketException in the hierarchy. + /// + private static SocketException GetSocketException(Exception ex) + { + Assert.IsNotNull(ex); + var origEx = ex; + + while (ex != null) + { + var socketEx = ex as SocketException; + + if (socketEx != null) + { + return socketEx; + } + + ex = ex.InnerException; + } + + throw new Exception("SocketException not found.", origEx); + } } } From b34525b002bf7622a35bbe315a10d6722a26cf7b Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 31 Jan 2018 18:06:46 +0300 Subject: [PATCH 86/89] Add missing file --- .../Config/Client/server-with-ssl.xml | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml new file mode 100644 index 0000000000000..17e92d8bda8de --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 127.0.0.1:47500 + + + + + + + + + \ No newline at end of file From 0fbfe809dcdfcd4aa3b7e77f75799f2eac6f2cf5 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Wed, 31 Jan 2018 18:09:05 +0300 Subject: [PATCH 87/89] Fix jks paths --- .../Config/Client/server-with-ssl.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml index 17e92d8bda8de..7ef8e17d7911a 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Client/server-with-ssl.xml @@ -39,9 +39,9 @@ - + - + From 4dad862846e0282c35fb9628641cdb590a3c3883 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsyn Date: Fri, 2 Feb 2018 14:17:29 +0300 Subject: [PATCH 88/89] attempt to fix TestGetMultithreadedMultiClient failure on TC --- .../dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs index 4c51d721e4ec8..c2620a6113430 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs @@ -789,8 +789,7 @@ public void TestGetMultithreadedMultiClient() var clientCache = client.GetCache(CacheName); Assert.AreEqual("foo", clientCache.Get(1)); - }, - Environment.ProcessorCount, 5); + }, 4, 5); clients.ToList().ForEach(x => x.Value.Dispose()); } From 048982925632d4e1a0f95dd7a46185abd242a9d1 Mon Sep 17 00:00:00 2001 From: Pavel Tupitsin Date: Mon, 26 Feb 2018 17:02:43 +0300 Subject: [PATCH 89/89] Merge branch 'master' into ignite-7329 # Conflicts: # modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj --- .../Apache.Ignite.Core.Tests.csproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj index 1e5cbee178973..8cd64cc9d6c61 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj @@ -473,6 +473,12 @@ + + PreserveNewest + + + PreserveNewest + PreserveNewest