diff --git a/include/amqpcpp/linux_tcp/tcpconnection.h b/include/amqpcpp/linux_tcp/tcpconnection.h index a8dae17..95e3f4d 100644 --- a/include/amqpcpp/linux_tcp/tcpconnection.h +++ b/include/amqpcpp/linux_tcp/tcpconnection.h @@ -5,7 +5,7 @@ * IO between the client application and the RabbitMQ server. * * @author Emiel Bruijntjes - * @copyright 2015 - 2018 Copernica BV + * @copyright 2015 - 2021 Copernica BV */ /** @@ -126,6 +126,18 @@ private: // pass on to the handler if (_handler) _handler->onConnected(this); } + + /** + * Method that is called when right before connection is being secured + * @param state + * @param ssl + * @return bool + */ + virtual bool onSecuring(TcpState *state, SSL *ssl) override + { + // pass on to user-space + return _handler && _handler->onSecuring(this, ssl); + } /** * Method that is called when the connection is secured diff --git a/include/amqpcpp/linux_tcp/tcphandler.h b/include/amqpcpp/linux_tcp/tcphandler.h index 1b64fe9..2322a02 100644 --- a/include/amqpcpp/linux_tcp/tcphandler.h +++ b/include/amqpcpp/linux_tcp/tcphandler.h @@ -6,7 +6,7 @@ * class. * * @author Emiel Bruijntjes - * @copyright 2015 - 2018 Copernica BV + * @copyright 2015 - 2021 Copernica BV */ /** @@ -59,6 +59,25 @@ public: (void) connection; } + /** + * Method that is called after a TCP connection has been set up, and right before + * the SSL handshake is going to be performed to secure the connection (only for + * amqps:// connections). This method can be overridden in user space to load + * client side certificates. + * @param connection The connection for which TLS was just started + * @param ssl Pointer to the SSL structure that can be modified + * @return bool True to proceed / accept the connection, false to break up + */ + virtual bool onSecuring(TcpConnection *connection, SSL *ssl) + { + // make sure compilers dont complain about unused parameters + (void) connection; + (void) ssl; + + // default implementation: do not do anything, just allow the connection + return true; + } + /** * Method that is called after a TCP connection has been set up and the initial * TLS handshake is finished too, but right before the AMQP login handshake is diff --git a/include/amqpcpp/linux_tcp/tcpparent.h b/include/amqpcpp/linux_tcp/tcpparent.h index eded2b8..ee92c49 100644 --- a/include/amqpcpp/linux_tcp/tcpparent.h +++ b/include/amqpcpp/linux_tcp/tcpparent.h @@ -5,7 +5,7 @@ * an _internal_ interface that is not relevant for user-space applications. * * @author Emiel Bruijntjes - * @copyright 2018 Copernica BV + * @copyright 2018 - 2021 Copernica BV */ /** @@ -46,6 +46,14 @@ public: * @param state */ virtual void onConnected(TcpState *state) = 0; + + /** + * Method that is called right before a connection is secured and that allows userspac to change SSL + * @param state + * @param ssl + * @return bool + */ + virtual bool onSecuring(TcpState *state, SSL *ssl) = 0; /** * Method that is called when the connection is secured diff --git a/src/linux_tcp/sslhandshake.h b/src/linux_tcp/sslhandshake.h index 44a5fcd..33092b1 100644 --- a/src/linux_tcp/sslhandshake.h +++ b/src/linux_tcp/sslhandshake.h @@ -4,7 +4,7 @@ * Implementation of the TCP state that is responsible for setting * up the STARTTLS handshake. * - * @copyright 2018 Copernica BV + * @copyright 2018 - 2021 Copernica BV */ /** @@ -135,6 +135,9 @@ public: // associate the ssl context with the socket filedescriptor if (OpenSSL::SSL_set_fd(_ssl, _socket) == 0) throw std::runtime_error("failed to associate filedescriptor with ssl socket"); + // we allow userspace to make changes to the SSL structure + if (!_parent->onSecuring(this, _ssl)) throw std::runtime_error("failed to initialize SSL structure in user space"); + // we are going to wait until the socket becomes writable before we start the handshake _parent->onIdle(this, _socket, writable); }