Merge pull request #194 from CopernicaMarketingSoftware/openssl_auth

Openssl auth
This commit is contained in:
Emiel Bruijntjes 2018-03-06 17:24:34 +01:00 committed by GitHub
commit 963d06c1e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 410 additions and 2 deletions

View File

@ -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/");

176
src/linux_tcp/function.h Normal file
View File

@ -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<int(int)> magic_open(library, "my_function");
*
* // call the function
* int result = func(123);
*
* @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
* @copyright 2018 Copernica BV
*/
/**
* Include guard
*/
#pragma once
/**
* Dependencies
*/
#include <cstddef>
#include <functional>
/**
* Namespace
*/
namespace AMQP {
/**
* Make the Function class a templated class
*/
template <class T> class Function {};
/**
* So that we can write a partial specialisation
* using a function prototype, indicating the
* prototype usable for the given callback
*/
template <class T, class ...Arguments>
class Function<T(Arguments...)>
{
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<Arguments>(parameters)...);
}
};
/**
* End of namespace
*/
}

228
src/linux_tcp/openssl.cpp Normal file
View File

@ -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 <iostream>
/**
* 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<decltype(::SSL_library_init)> 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<decltype(::SSL_CTX_new)> 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<decltype(::SSL_read)> 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<decltype(::SSL_write)> 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<decltype(::SSL_set_fd)> 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<decltype(::SSL_free)> 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<decltype(::SSL_new)> 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<decltype(::SSL_up_ref)> 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<decltype(::SSL_shutdown)> 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<decltype(::SSL_set_connect_state)> 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<decltype(::SSL_do_handshake)> 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<decltype(::SSL_get_error)> func(library(), "SSL_get_error");
// call the openssl function
return func(ssl, ret);
}
/**
* End of namespace
*/
}}

View File

@ -12,6 +12,11 @@
*/
#pragma once
/**
* Dependencies
*/
#include <openssl/ssl.h>
/**
* Beginnig of namespace
*/

View File

@ -19,7 +19,6 @@
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <openssl/ssl.h>
/**
* FIONREAD on Solaris is defined elsewhere
*/