From 3bb7714f3bb3a04d3ca627e0fdb776a711f65360 Mon Sep 17 00:00:00 2001 From: Tamas Elekes Date: Tue, 6 Mar 2018 14:39:36 +0100 Subject: [PATCH 1/2] dynamically loading openssl funtions during runtime work in progress --- examples/libev.cpp | 2 +- src/linux_tcp/tcpinbuffer.h | 5 +++++ src/linux_tcp/tcpoutbuffer.h | 1 - 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/libev.cpp b/examples/libev.cpp index 0600d92..43cad39 100644 --- a/examples/libev.cpp +++ b/examples/libev.cpp @@ -65,7 +65,7 @@ int main() MyHandler handler(loop); // init the SSL library -// SSL_library_init(); + SSL_library_init(); // make a connection AMQP::Address address("amqps://guest:guest@localhost/"); diff --git a/src/linux_tcp/tcpinbuffer.h b/src/linux_tcp/tcpinbuffer.h index e535067..bd020e3 100644 --- a/src/linux_tcp/tcpinbuffer.h +++ b/src/linux_tcp/tcpinbuffer.h @@ -12,6 +12,11 @@ */ #pragma once +/** + * Dependencies + */ + #include + /** * Beginnig of namespace */ diff --git a/src/linux_tcp/tcpoutbuffer.h b/src/linux_tcp/tcpoutbuffer.h index a619620..8d18526 100644 --- a/src/linux_tcp/tcpoutbuffer.h +++ b/src/linux_tcp/tcpoutbuffer.h @@ -19,7 +19,6 @@ #include #include #include - /** * FIONREAD on Solaris is defined elsewhere */ From 8ba8ed17271145fb563ddf59c28d5e72fe62086c Mon Sep 17 00:00:00 2001 From: Tamas Elekes Date: Tue, 6 Mar 2018 14:40:46 +0100 Subject: [PATCH 2/2] dynamically loading openssl funtions during runtime work in progress --- src/linux_tcp/function.h | 176 +++++++++++++++++++++++++++++ src/linux_tcp/openssl.cpp | 228 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 404 insertions(+) create mode 100644 src/linux_tcp/function.h create mode 100644 src/linux_tcp/openssl.cpp diff --git a/src/linux_tcp/function.h b/src/linux_tcp/function.h new file mode 100644 index 0000000..586163f --- /dev/null +++ b/src/linux_tcp/function.h @@ -0,0 +1,176 @@ +/** + * Function.h + * + * When you want to retrieve a function from a dynamicallly loaded + * library, you normally use the dlsym() function for that. The + * Function object is a little more convenient: + * + * // open the library + * void *lib = dlopen("library.so"); + * + * // get the function object + * Function func magic_open(library, "my_function"); + * + * // call the function + * int result = func(123); + * + * @author Emiel Bruijntjes + * @copyright 2018 Copernica BV + */ + + +/** + * Include guard + */ +#pragma once + +/** + * Dependencies + */ +#include +#include + +/** + * Namespace + */ +namespace AMQP { + +/** + * Make the Function class a templated class + */ +template class Function {}; + +/** + * So that we can write a partial specialisation + * using a function prototype, indicating the + * prototype usable for the given callback + */ +template +class Function +{ +private: + /** + * Store pointer to the actual dynamically loaded + * function. This is done in a union because the + * result from a dlsym call is a void pointer which + * cannot be legally cast into a function pointer. + * + * We therefore always set the first type (which is + * void* making it legal) and, because all members + * in a union share the same address, we can then + * read the second type and actually call it. + * + * @var Callable + */ + union Callable { + + /** + * Property for getting and setting the return + * value from dlsym. This is always a void* + * @var void + */ + void *ptr; + + /** + * Property for executing the mapped function + * + * @param mixed,... function parameters + * @return mixed + * + * @var function + */ + T (*func)(Arguments...); + + + /** + * Constructor + */ + Callable() : ptr(nullptr) {} + + /** + * We may be moved + * + * @param callable the callable we are moving + */ + Callable(Callable&& callable) : + ptr(callable.ptr) + { + // the other callable no longer has a handle + callable.ptr = nullptr; + } + + /** + * Copy construtor + * @param callable the callable we are moving + */ + Callable(const Callable &callable) : + ptr(callable.ptr) {} + + /** + * Constructor + * + * @param function the mapped function + */ + Callable(void *function) : ptr(function) {} + + } _method; + +public: + /** + * Constructor + * @param library The library to load the function from + * @param name Name of the function + */ + Function(void *library, const char *name) : + _method(dlsym(library, name)) {} + + /** + * Destructor + */ + virtual ~Function() {} + + /** + * Is this a valid function or not? + * @return bool + */ + bool valid() const + { + return _method.ptr != nullptr; + } + + /** + * The library object can also be used as in a boolean context, + * for that there is an implementation of a casting operator, and + * the negate operator + * @return bool + */ + operator bool () const { return valid(); } + bool operator ! () const { return !valid(); } + + /** + * Test whether we are a valid object + * @param nullptr test if we are null + */ + bool operator==(std::nullptr_t /* nullptr */) const { return !valid(); } + bool operator!=(std::nullptr_t /* nullptr */) const { return valid(); } + + /** + * Invoke the function + * + * @param mixed,... + */ + T operator()(Arguments... parameters) const + { + // check whether we have a valid function + if (!valid()) throw std::bad_function_call(); + + // execute the method given all the parameters + return _method.func(std::forward(parameters)...); + } +}; + +/** + * End of namespace + */ +} + diff --git a/src/linux_tcp/openssl.cpp b/src/linux_tcp/openssl.cpp new file mode 100644 index 0000000..f885730 --- /dev/null +++ b/src/linux_tcp/openssl.cpp @@ -0,0 +1,228 @@ +/** + * OpenSSL.cpp + * + * Implementation file for the openssl.h header file + * + * @copyright 2018 Copernica BV + */ + +/** + * Dependencies + */ +// #include "includes.h" +#include "amqpcpp/linux_tcp/openssl.h" + +#include "function.h" +#include + +/** + * Begin of namespace + */ +namespace AMQP { namespace OpenSSL { + +/** + * Get the library handle + * @return void * + */ +static void *library() +{ + // stored pointer + static void *ptr = nullptr; + + // is it already opened? + if (ptr != nullptr) return ptr; + + // open ourselves + ptr = dlopen("libssl.so", RTLD_NOW); + if (!ptr) + { + std::cout << "Cannot load library: " << dlerror() << std::endl; + + // reset errors + dlerror(); + + return nullptr; + } + + return ptr; +} + +/** + * Initialize SSL library by registering algorithnms + */ + //~int SSL_library_init() + //~{ + //~// create function + //~static Function func(library(), "SSL_libarary_init"); + + //~// call the openssl function + //~func(); + //~} + +/** + * Create new SSL context + * @param SSL_METHOD can be of the following types: TLS_method(), TLS_server_method(), TLS_client_method() + * @return nullptr if failed pointer to object otherwise + */ +SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) +{ + // create a function + static Function func(library(), "SSL_CTX_new"); + + // call the openssl function + return func(method); +} + +/** + * Read data from an ssl socket + * @param ssl + * @param buf + * @param num + * @return int number of bytes read + */ +int SSL_read(SSL *ssl, void *buf, int num) +{ + // create a function + static Function func(library(), "SSL_read"); + + // call the openssl function + return func(ssl, buf, num); +} + +/** + * Read data from an ssl socket + * @param ssl + * @param buf + * @param num + * @return int number of bytes written + */ +int SSL_write(SSL *ssl, const void *buf, int num) +{ + // create a function + static Function func(library(), "SSL_write"); + + // call the openssl function + return func(ssl, buf, num); +} + +/** + * Connect the SSL object with a file descriptor + * @param ssl SSL object + * @param fd file descriptor + * @return int wether the operation succeeded or not + */ +int SSL_set_fd(SSL *ssl, int fd) +{ + // create a function + static Function func(library(), "SSL_set_fd"); + + // call the openssl function + return func(ssl, fd); +} + + +/** + * Free an allocated SSL structure + * @param ssl SSL object to be freed + * @return int wether the operation succeeded or not + */ +void SSL_free(SSL *ssl) +{ + // create a function + static Function func(library(), "SSL_free"); + + // call the openssl function + return func(ssl); + +} + +/** + * Create a new SSL structure for a connection + * @param ctx SSL context object + * @return SSL the created SSL oject based on th context + */ +SSL *SSL_new(SSL_CTX *ctx) +{ + // create a function + static Function func(library(), "SSL_new"); + + // call the openssl function + return func(ctx); +} + +/** + * Create a new SSL structure for a connection + * @param ctx SSL context object + * @return SSL the created SSL oject based on th context + */ +int SSL_up_ref(SSL *ssl) +{ + // create a function + static Function func(library(), "SSL_up_ref"); + + // call the openssl function + return func(ssl); +} + +/** + * Shut down a TLS/SSL shut down + * @param ssl SSL object to terminate + * @return int returns diagnostic values + */ +int SSL_shutdown(SSL *ssl) +{ + // create a function + static Function func(library(), "SSL_shutdown"); + + // call the openssl function + return func(ssl); +} + +/** + * Prepare SSL object to work in client or server mode + * @param ssl SSL object to set connect state on + */ +void SSL_set_connect_state(SSL *ssl) +{ + // create a function + static Function func(library(), "SSL_set_connect_state"); + + // call the openssl function + func(ssl); + +} + +/** + * Perform a TLS/SSL handshake + * @param ssl SSL object + * @return int returns diagnostic values + */ +int SSL_do_handshake(SSL *ssl) +{ + // create a function + static Function func(library(), "SSL_do_handshake"); + + // call the openssl function + return func(ssl); +} + +/** + * Obtain result code for TLS/SSL I/O operation + * @param ssl SSL object + * @param ret the returned diagnostic value of SSL calls + * @return int returns error values + */ +int SSL_get_error(const SSL *ssl, int ret) +{ + // create a function + static Function func(library(), "SSL_get_error"); + + // call the openssl function + return func(ssl, ret); +} + +/** + * End of namespace + */ +}} +