http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/src/impl/ssl/secure_socket_client.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/src/impl/ssl/secure_socket_client.h b/modules/platforms/cpp/thin-client/src/impl/ssl/secure_socket_client.h new file mode 100644 index 0000000..9649135 --- /dev/null +++ b/modules/platforms/cpp/thin-client/src/impl/ssl/secure_socket_client.h @@ -0,0 +1,187 @@ +/* + * 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_IMPL_THIN_SSL_SECURE_SOCKET_CLIENT +#define _IGNITE_IMPL_THIN_SSL_SECURE_SOCKET_CLIENT + +#include <stdint.h> +#include <string> + +#include "impl/socket_client.h" + +namespace ignite +{ + namespace impl + { + namespace thin + { + namespace ssl + { + /** + * Secure socket client. + */ + class SecureSocketClient : public SocketClient + { + public: + /** + * Constructor. + * + * @param certPath Certificate file path. + * @param keyPath Private key file path. + * @param caPath Certificate authority file path. + */ + SecureSocketClient(const std::string& certPath, const std::string& keyPath, const std::string& caPath); + + /** + * Destructor. + */ + virtual ~SecureSocketClient(); + + /** + * Establish connection with the host. + * + * @param hostname Host name or address. + * @param port TCP port. + * @param timeout Timeout in seconds. + * @return @c true on success and @c false on fail. + */ + virtual bool Connect(const char* hostname, uint16_t port, int32_t timeout); + + /** + * Close the connection. + */ + virtual void Close(); + + /** + * Send data using connection. + * @param data Data to send. + * @param size Number of bytes to send. + * @param timeout Timeout in seconds. + * @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); + + /** + * Receive data from established connection. + * + * @param buffer Pointer to data buffer. + * @param size Size of the buffer in bytes. + * @param timeout Timeout in seconds. + * @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); + + /** + * Check if the socket is blocking or not. + * @return @c true if the socket is blocking and false otherwise. + */ + 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 ssl SSL instance. + * @param timeout Timeout in seconds. + * @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. + */ + static int WaitOnSocket(void* ssl, int32_t timeout, bool rd); + + /** + * Make new context instance. + * + * @param certPath Certificate file path. + * @param keyPath Private key file path. + * @param caPath Certificate authority file path. + * @return New context instance on success and null-pointer on fail. + */ + static void* MakeContext(const std::string& certPath, const std::string& keyPath, + const std::string& caPath); + + /** + * Make new SSL instance. + * + * @param context SSL context. + * @param hostname Host name or address. + * @param port TCP port. + * @param blocking Indicates if the resulted SSL is blocking or not. + * @return New SSL instance on success and null-pointer on fail. + */ + static void* MakeSsl(void* context, const char* hostname, uint16_t port, bool& blocking); + + /** + * Complete async connect. + * + * @param ssl SSL instance. + * @param timeout Timeout in seconds. + * @return @c true on success. + */ + static bool CompleteConnectInternal(void* ssl, int timeout); + + /** + * Get SSL error. + * + * @param ssl SSL instance. + * @param ret Return value of the pervious operation. + * @return Error string. + */ + static std::string GetSslError(void* ssl, int ret); + + /** + * Check if a actual error occured. + * + * @param err SSL error code. + * @return @true if a actual error occured + */ + static bool IsActualError(int err); + + /** Certificate file path. */ + std::string certPath; + + /** Private key file path. */ + std::string keyPath; + + /** Certificate authority file path. */ + std::string caPath; + + /** SSL context. */ + void* context; + + /** OpenSSL instance */ + void* ssl; + + /** Blocking flag. */ + bool blocking; + }; + } + } + } +} + +#endif //_IGNITE_IMPL_THIN_SSL_SECURE_SOCKET_CLIENT
http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_bindings.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_bindings.h b/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_bindings.h new file mode 100644 index 0000000..05ad00d --- /dev/null +++ b/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_bindings.h @@ -0,0 +1,360 @@ +/* + * 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_IMPL_THIN_SSL_SSL_BINDINGS +#define _IGNITE_IMPL_THIN_SSL_SSL_BINDINGS + +#include <openssl/ssl.h> +#include <openssl/conf.h> +#include <openssl/err.h> + +#include "impl/ssl/ssl_gateway.h" + +namespace ignite +{ + namespace impl + { + namespace thin + { + 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*); + + FuncType* fp = reinterpret_cast<FuncType*>(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<FuncType*>(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<FuncType*>( + 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<FuncType*>( + 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<FuncType*>( + 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<FuncType*>( + 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<FuncType*>( + 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<FuncType*>( + 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<FuncType*>(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<FuncType*>( + SslGateway::GetInstance().GetFunctions().fpSSL_get_verify_result); + + return fp(s); + } + + inline int SSL_library_init() + { + typedef int(FuncType)(); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpSSL_library_init); + + return fp(); + } + + inline void SSL_load_error_strings() + { + typedef void(FuncType)(); + + FuncType* fp = reinterpret_cast<FuncType*>( + 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<FuncType*>( + 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<FuncType*>(SslGateway::GetInstance().GetFunctions().fpSSL_ctrl); + + 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<char*>(name)); + } + + inline void SSL_set_connect_state_(SSL* s) + { + typedef void(FuncType)(SSL*); + + FuncType* fp = reinterpret_cast<FuncType*>( + SslGateway::GetInstance().GetFunctions().fpSSL_set_connect_state); + + return fp(s); + } + + inline int SSL_connect_(SSL* s) + { + typedef int(FuncType)(SSL*); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpSSL_connect); + + return fp(s); + } + + inline int SSL_get_error_(const SSL *s, int ret) + { + typedef int(FuncType)(const SSL*, int); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpSSL_get_error); + + return fp(s, ret); + } + + inline int SSL_want_(const SSL *s) + { + typedef int(FuncType)(const SSL*); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpSSL_want); + + return fp(s); + } + + inline int SSL_write_(SSL *s, const void *buf, int num) + { + typedef int(FuncType)(SSL*, const void*, int); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpSSL_write); + + return fp(s, buf, num); + } + + inline int SSL_read_(SSL *s, void *buf, int num) + { + typedef int(FuncType)(SSL*, void*, int); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpSSL_read); + + return fp(s, buf, num); + } + + inline int SSL_pending_(const SSL *ssl) + { + typedef int(FuncType)(const SSL*); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpSSL_pending); + + return fp(ssl); + } + + inline int SSL_get_fd_(const SSL *ssl) + { + typedef int(FuncType)(const SSL*); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpSSL_get_fd); + + return fp(ssl); + } + + inline void SSL_free_(SSL *ssl) + { + typedef void(FuncType)(SSL*); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpSSL_free); + + fp(ssl); + } + + inline const SSL_METHOD *SSLv23_client_method_() + { + typedef const SSL_METHOD*(FuncType)(); + + FuncType* fp = reinterpret_cast<FuncType*>( + SslGateway::GetInstance().GetFunctions().fpSSLv23_client_method); + + return fp(); + } + + inline void OPENSSL_config(const char *configName) + { + typedef void(FuncType)(const char*); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpOPENSSL_config); + + fp(configName); + } + + inline void X509_free(X509 *a) + { + typedef void(FuncType)(X509*); + + FuncType* fp = reinterpret_cast<FuncType*>(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<FuncType*>( + SslGateway::GetInstance().GetFunctions().fpBIO_new_ssl_connect); + + return fp(ctx); + } + + inline void BIO_free_all(BIO *a) + { + typedef void(FuncType)(BIO*); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpBIO_free_all); + + fp(a); + } + + inline long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg) + { + typedef long(FuncType)(BIO*, int, long, void*); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpBIO_ctrl); + + 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<void*>(fd)); + } + + inline long BIO_get_ssl_(BIO *bp, SSL** ssl) + { + return ssl::BIO_ctrl(bp, BIO_C_GET_SSL, 0, reinterpret_cast<void*>(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<char*>(name)); + } + + inline unsigned long ERR_get_error_() + { + typedef unsigned long(FuncType)(); + + FuncType* fp = reinterpret_cast<FuncType*>(SslGateway::GetInstance().GetFunctions().fpERR_get_error); + + return fp(); + } + + inline void ERR_error_string_n_(unsigned long e, char *buf, size_t len) + { + typedef void(FuncType)(unsigned long, char*, size_t); + + FuncType* fp = reinterpret_cast<FuncType*>( + SslGateway::GetInstance().GetFunctions().fpERR_error_string_n); + + fp(e, buf, len); + } + } + } + } +} + +#endif //_IGNITE_IMPL_THIN_SSL_SSL_BINDINGS \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_gateway.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_gateway.cpp b/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_gateway.cpp new file mode 100644 index 0000000..380fe0f --- /dev/null +++ b/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_gateway.cpp @@ -0,0 +1,237 @@ +/* + * 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 <sstream> + +#include <ignite/ignite_error.h> +#include <ignite/common/utils.h> + +#include "impl/ssl/ssl_gateway.h" + +#ifndef ADDITIONAL_OPENSSL_HOME_ENV +# define ADDITIONAL_OPENSSL_HOME_ENV "OPEN_SSL_HOME" +#endif // ADDITIONAL_OPENSSL_HOME_ENV + +namespace ignite +{ + namespace impl + { + namespace thin + { + namespace ssl + { + 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(ADDITIONAL_OPENSSL_HOME_ENV); + + 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); + } + + void SslGateway::LoadSslLibraries() + { + libeay32 = LoadSslLibrary("libeay32"); + ssleay32 = LoadSslLibrary("ssleay32"); + libssl = LoadSslLibrary("libssl"); + + if (!libssl.IsLoaded() && (!libeay32.IsLoaded() || !ssleay32.IsLoaded())) + { + if (!libssl.IsLoaded()) + throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, + "Can not load neccessary OpenSSL library: libssl"); + + std::stringstream ss; + + ss << "Can not load neccessary OpenSSL libraries: "; + + if (!libeay32.IsLoaded()) + ss << "libeay32"; + + if (!ssleay32.IsLoaded()) + ss << " ssleay32"; + + libeay32.Unload(); + ssleay32.Unload(); + libssl.Unload(); + + std::string res = ss.str(); + + throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, res.c_str()); + } + } + + SslGateway& SslGateway::GetInstance() + { + static SslGateway self; + + return self; + } + + void SslGateway::LoadAll() + { + using namespace common::dynamic; + + if (inited) + return; + + common::concurrent::CsLockGuard lock(initCs); + + if (inited) + return; + + LoadSslLibraries(); + + 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_client_method = LoadSslMethod("SSLv23_client_method"); + functions.fpSSL_set_connect_state = LoadSslMethod("SSL_set_connect_state"); + functions.fpSSL_connect = LoadSslMethod("SSL_connect"); + functions.fpSSL_get_error = LoadSslMethod("SSL_get_error"); + functions.fpSSL_want = LoadSslMethod("SSL_want"); + functions.fpSSL_write = LoadSslMethod("SSL_write"); + functions.fpSSL_read = LoadSslMethod("SSL_read"); + functions.fpSSL_pending = LoadSslMethod("SSL_pending"); + functions.fpSSL_get_fd = LoadSslMethod("SSL_get_fd"); + functions.fpSSL_free = LoadSslMethod("SSL_free"); + functions.fpBIO_new_ssl_connect = LoadSslMethod("BIO_new_ssl_connect"); + + functions.fpOPENSSL_config = LoadSslMethod("OPENSSL_config"); + functions.fpX509_free = LoadSslMethod("X509_free"); + + functions.fpBIO_free_all = LoadSslMethod("BIO_free_all"); + functions.fpBIO_ctrl = LoadSslMethod("BIO_ctrl"); + + functions.fpERR_get_error = LoadSslMethod("ERR_get_error"); + functions.fpERR_error_string_n = LoadSslMethod("ERR_error_string_n"); + + 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_client_method != 0 && + functions.fpSSL_set_connect_state != 0 && + functions.fpSSL_connect != 0 && + functions.fpSSL_get_error != 0 && + functions.fpSSL_want != 0 && + functions.fpSSL_write != 0 && + functions.fpSSL_read != 0 && + functions.fpSSL_pending != 0 && + functions.fpSSL_get_fd != 0 && + functions.fpSSL_free != 0 && + functions.fpBIO_new_ssl_connect != 0 && + functions.fpOPENSSL_config != 0 && + functions.fpX509_free != 0 && + functions.fpBIO_free_all != 0 && + functions.fpBIO_ctrl != 0 && + functions.fpERR_get_error != 0 && + functions.fpERR_error_string_n != 0; + + if (!allLoaded) + { + libeay32.Unload(); + ssleay32.Unload(); + libssl.Unload(); + } + + inited = allLoaded; + } + + void* SslGateway::LoadSslMethod(const char* name) + { + void* fp = libeay32.FindSymbol(name); + + if (!fp) + fp = ssleay32.FindSymbol(name); + + if (!fp) + fp = libssl.FindSymbol(name); + + if (!fp) + { + std::stringstream ss; + + ss << "Can not load function " << name; + + std::string res = ss.str(); + + throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, res.c_str()); + } + + return fp; + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_gateway.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_gateway.h b/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_gateway.h new file mode 100644 index 0000000..440aaa8 --- /dev/null +++ b/modules/platforms/cpp/thin-client/src/impl/ssl/ssl_gateway.h @@ -0,0 +1,161 @@ +/* + * 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_IMPL_THIN_SSL_SSL_LIBRARY +#define _IGNITE_IMPL_THIN_SSL_SSL_LIBRARY + +#include <ignite/common/concurrent.h> +#include <ignite/common/dynamic_load_os.h> + +namespace ignite +{ + namespace impl + { + namespace thin + { + 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_client_method; + void *fpSSL_set_connect_state; + void *fpSSL_connect; + void *fpSSL_get_error; + void *fpSSL_want; + void *fpSSL_write; + void *fpSSL_read; + void *fpSSL_pending; + void *fpSSL_get_fd; + void *fpSSL_free; + void *fpOPENSSL_config; + void *fpX509_free; + void *fpBIO_new_ssl_connect; + void *fpBIO_free_all; + void *fpBIO_ctrl; + void *fpERR_get_error; + void *fpERR_error_string_n; + }; + + /** + * 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. + */ + void LoadAll(); + + /** + * Get functions. + * @return Functions structure. + */ + SslFunctions& GetFunctions() + { + return functions; + } + + /** + * Check whether the libraries are loaded. + * @return @c true if loaded. + */ + bool Loaded() const + { + return inited; + } + + private: + /** + * Constructor. + */ + SslGateway(); + + /** + * Destructor. + */ + ~SslGateway(); + + /** + * Load SSL library. + * @param name Name. + * @return Module. + */ + common::dynamic::Module LoadSslLibrary(const char* name); + + /** + * Load all SSL libraries. + */ + void LoadSslLibraries(); + + /** + * Load SSL method. + * @param name Name. + * @return Method pointer. + */ + void* LoadSslMethod(const char* name); + + /** 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; + + /** libssl module. */ + common::dynamic::Module libssl; + + /** Functions. */ + SslFunctions functions; + }; + } + } + + } +} + +#endif //_IGNITE_IMPL_THIN_SSL_SSL_LIBRARY \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/src/impl/utility.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/src/impl/utility.cpp b/modules/platforms/cpp/thin-client/src/impl/utility.cpp new file mode 100644 index 0000000..7aa7d03 --- /dev/null +++ b/modules/platforms/cpp/thin-client/src/impl/utility.cpp @@ -0,0 +1,181 @@ +/* + * 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 <cctype> +#include <algorithm> +#include <sstream> + +#include <ignite/binary/binary.h> + +#include <ignite/common/utils.h> + +#include "impl/utility.h" + +namespace ignite +{ + namespace impl + { + namespace thin + { + namespace utility + { + bool ParseSingleAddress(const std::string& value, net::TcpRange& tcpRange, uint16_t dfltPort) + { + int64_t colonNum = std::count(value.begin(), value.end(), ':'); + + if (colonNum == 0) + { + tcpRange.host = value; + tcpRange.port = dfltPort; + tcpRange.range = 0; + + return true; + } + + if (colonNum != 1) + return false; + + size_t colonPos = value.find(':'); + + tcpRange.host = value.substr(0, colonPos); + + if (colonPos == value.size() - 1) + return false; + + std::string portRange = value.substr(colonPos + 1); + + return ParsePortRange(portRange, tcpRange.port, tcpRange.range); + } + + void ParseAddress(const std::string& value, std::vector<net::TcpRange>& endPoints, uint16_t dfltPort) + { + size_t addrNum = std::count(value.begin(), value.end(), ',') + 1; + + endPoints.reserve(endPoints.size() + addrNum); + + std::string parsedAddr(value); + + while (!parsedAddr.empty()) + { + size_t addrBeginPos = parsedAddr.rfind(','); + + if (addrBeginPos == std::string::npos) + addrBeginPos = 0; + else + ++addrBeginPos; + + const char* addrBegin = parsedAddr.data() + addrBeginPos; + const char* addrEnd = parsedAddr.data() + parsedAddr.size(); + + std::string addr = common::StripSurroundingWhitespaces(addrBegin, addrEnd); + + if (!addr.empty()) + { + net::TcpRange tcpRange; + + bool success = ParseSingleAddress(addr, tcpRange, dfltPort); + + if (success) + endPoints.push_back(tcpRange); + } + + if (!addrBeginPos) + break; + + parsedAddr.erase(addrBeginPos - 1); + } + } + + bool ParsePortRange(const std::string& value, uint16_t& port, uint16_t& range) + { + size_t sepPos = value.find('.'); + + if (sepPos == std::string::npos) + { + range = 0; + port = ParsePort(value); + + return port != 0; + } + + if (sepPos + 2 > value.size() || value[sepPos + 1] != '.') + return false; + + uint16_t rangeBegin = ParsePort(value.substr(0, sepPos)); + + if (!rangeBegin) + return false; + + uint16_t rangeEnd = ParsePort(value.substr(sepPos + 2)); + + if (!rangeEnd) + return false; + + if (rangeEnd < rangeBegin) + return false; + + port = rangeBegin; + range = rangeEnd - rangeBegin; + + return true; + } + + uint16_t ParsePort(const std::string& value) + { + std::string port = common::StripSurroundingWhitespaces(value.begin(), value.end()); + + if (!common::AllOf(port.begin(), port.end(), &isdigit)) + return 0; + + if (port.size() >= sizeof("65535")) + return 0; + + int32_t intPort = 0; + std::stringstream conv; + + conv << port; + conv >> intPort; + + if (intPort <= 0 || intPort > 0xFFFF) + return 0; + + return static_cast<uint16_t>(intPort); + } + + int32_t GetCacheId(const char* cacheName) + { + if (!cacheName) + return 0; + + int32_t hash = 0; + + int i = 0; + + while (cacheName[i]) + { + hash = 31 * hash + cacheName[i]; + + ++i; + } + + return hash; + } + } + } + } +} + http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/src/impl/utility.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/src/impl/utility.h b/modules/platforms/cpp/thin-client/src/impl/utility.h new file mode 100644 index 0000000..7945960 --- /dev/null +++ b/modules/platforms/cpp/thin-client/src/impl/utility.h @@ -0,0 +1,82 @@ +/* + * 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_IMPL_THIN_UTILITY +#define _IGNITE_IMPL_THIN_UTILITY + +#include <vector> + +#include "impl/net/tcp_range.h" + +namespace ignite +{ + namespace impl + { + namespace thin + { + namespace utility + { + /** + * Parse address. + * + * @param value String value to parse. + * @param endPoints End ponts list. + * @param dfltPort Default port. + */ + void ParseAddress(const std::string& value, std::vector<net::TcpRange>& endPoints, uint16_t dfltPort); + + /** + * Parse single address. + * + * @param value String value to parse. + * @param tcpRange TCP range. + * @param dfltPort Default port. + * @return @c true, if parsed successfully, and @c false otherwise. + */ + bool ParseSingleAddress(const std::string& value, net::TcpRange& tcpRange, uint16_t dfltPort); + + /** + * Parse single network port. + * + * @param value String value to parse. + * @param port Port range begin. + * @param range Number of ports in range. + * @return @c Port value on success and zero on failure. + */ + bool ParsePortRange(const std::string& value, uint16_t& port, uint16_t& range); + + /** + * Parse single network port. + * + * @param value String value to parse. + * @return @c Port value on success and zero on failure. + */ + uint16_t ParsePort(const std::string& value); + + /** + * Get cache ID for the name. + * + * @param cacheName Cache name. + * @return Cache ID. + */ + int32_t GetCacheId(const char* cacheName); + } + } + } +} + +#endif //_IGNITE_IMPL_THIN_UTILITY