From 667ee721a72d52799c2f443fa13d4f00003d36f8 Mon Sep 17 00:00:00 2001 From: Alan Antonuk Date: Tue, 20 Oct 2015 23:02:31 -0700 Subject: Lib: add amqp_ssl_socket_set_versions fn Add amqp_ssl_socket_versions function which allows a user to specify the acceptable range of TLS versions they want to connect to the broker with. --- librabbitmq/amqp.h | 4 ++- librabbitmq/amqp_api.c | 3 ++- librabbitmq/amqp_openssl.c | 60 +++++++++++++++++++++++++++++++++++++++++++ librabbitmq/amqp_ssl_socket.h | 30 ++++++++++++++++++++++ 4 files changed, 95 insertions(+), 2 deletions(-) diff --git a/librabbitmq/amqp.h b/librabbitmq/amqp.h index 5121097..ed5f35a 100644 --- a/librabbitmq/amqp.h +++ b/librabbitmq/amqp.h @@ -726,7 +726,9 @@ typedef enum amqp_status_enum_ AMQP_STATUS_BROKER_UNSUPPORTED_SASL_METHOD = -0x0013, /**< Broker does not support the requested SASL mechanism */ - _AMQP_STATUS_NEXT_VALUE = -0x0014, /**< Internal value */ + AMQP_STATUS_UNSUPPORTED = -0x0014, /**< Parameter is unsupported + in this version */ + _AMQP_STATUS_NEXT_VALUE = -0x0015, /**< Internal value */ AMQP_STATUS_TCP_ERROR = -0x0100, /**< A generic TCP error occurred */ diff --git a/librabbitmq/amqp_api.c b/librabbitmq/amqp_api.c index f0c805e..9556ec5 100644 --- a/librabbitmq/amqp_api.c +++ b/librabbitmq/amqp_api.c @@ -82,7 +82,8 @@ static const char *base_error_strings[] = { "unexpected protocol state", /* AMQP_STATUS_UNEXPECTED STATE -0x0010 */ "socket is closed", /* AMQP_STATUS_SOCKET_CLOSED -0x0011 */ "socket already open", /* AMQP_STATUS_SOCKET_INUSE -0x0012 */ - "unsupported sasl method requested" /* AMQP_STATUS_BROKER_UNSUPPORTED_SASL_METHOD -0x0013 */ + "unsupported sasl method requested", /* AMQP_STATUS_BROKER_UNSUPPORTED_SASL_METHOD -0x0013 */ + "parameter value is unsupported" /* AMQP_STATUS_UNSUPPORTED -0x0014 */ }; static const char *tcp_error_strings[] = { diff --git a/librabbitmq/amqp_openssl.c b/librabbitmq/amqp_openssl.c index f385bfd..bbb16e8 100644 --- a/librabbitmq/amqp_openssl.c +++ b/librabbitmq/amqp_openssl.c @@ -585,6 +585,66 @@ void amqp_ssl_socket_set_verify_hostname(amqp_socket_t *base, self->verify_hostname = verify; } +int amqp_ssl_socket_set_ssl_versions(amqp_socket_t *base, + amqp_tls_version_t min, + amqp_tls_version_t max) { + struct amqp_ssl_socket_t *self; + if (base->klass != &amqp_ssl_socket_class) { + amqp_abort("<%p> is not of type amqp_ssl_socket_t", base); + } + self = (struct amqp_ssl_socket_t *)base; + + { + long clear_options; + long set_options = 0; +#if defined(SSL_OP_NO_TLSv1_2) + amqp_tls_version_t max_supported = AMQP_TLSv1_2; + clear_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2; +#elif defined(SSL_OP_NO_TLSv1_1) + amqp_tls_version_t max_supported = AMQP_TLSv1_1; + clear_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1; +#elif defined(SSL_OP_NO_TLSv1) + amqp_tls_version_t max_supported = AMQP_TLSv1; + clear_options = SSL_OP_NO_TLSv1; +#else +# error "Need a version of OpenSSL that can support TLSv1 or greater." +#endif + + if (AMQP_TLSvLATEST == max) { + max = max_supported; + } + if (AMQP_TLSvLATEST == min) { + min = max_supported; + } + + if (min > max) { + return AMQP_STATUS_INVALID_PARAMETER; + } + + if (max > max_supported || min > max_supported) { + return AMQP_STATUS_UNSUPPORTED; + } + + if (min > AMQP_TLSv1) { + set_options |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 + if (min > AMQP_TLSv1_1 || max < AMQP_TLSv1_1) { + set_options |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 + if (max < AMQP_TLSv1_2) { + set_options |= SSL_OP_NO_TLSv1_2; + } +#endif + SSL_CTX_clear_options(self->ctx, clear_options); + SSL_CTX_set_options(self->ctx, set_options); + } + + return AMQP_STATUS_OK; +} + void amqp_set_initialize_ssl_library(amqp_boolean_t do_initialize) { diff --git a/librabbitmq/amqp_ssl_socket.h b/librabbitmq/amqp_ssl_socket.h index 47b5ad1..45dcf5b 100644 --- a/librabbitmq/amqp_ssl_socket.h +++ b/librabbitmq/amqp_ssl_socket.h @@ -168,6 +168,36 @@ void AMQP_CALL amqp_ssl_socket_set_verify_hostname(amqp_socket_t *self, amqp_boolean_t verify); +typedef enum { + AMQP_TLSv1 = 1, + AMQP_TLSv1_1 = 2, + AMQP_TLSv1_2 = 3, + AMQP_TLSvLATEST = 0xFFFF +} amqp_tls_version_t; + +/** + * Set min and max TLS versions. + * + * Set the oldest and newest acceptable TLS versions that are acceptable when + * connecting to the broker. Set min == max to restrict to just that + * version. + * + * \param [in,out] self An SSL/TLS socket object. + * \param [in] min the minimum acceptable TLS version + * \param [in] max the maxmium acceptable TLS version + * \returns AMQP_STATUS_OK on success, AMQP_STATUS_UNSUPPORTED if OpenSSL does + * not support the requested TLS version, AMQP_STATUS_INVALID_PARAMETER if an + * invalid combination of parameters is passed. + * + * \since v0.8.0 + */ +AMQP_PUBLIC_FUNCTION +int +AMQP_CALL +amqp_ssl_socket_set_ssl_versions(amqp_socket_t *self, + amqp_tls_version_t min, + amqp_tls_version_t max); + /** * Sets whether rabbitmq-c initializes the underlying SSL library. * -- cgit v1.2.1