summaryrefslogtreecommitdiff
path: root/librabbitmq
diff options
context:
space:
mode:
authorHan Mai <cafe2310@gmail.com>2019-04-29 11:43:46 +0700
committerAlan Antonuk <alan.antonuk@gmail.com>2020-06-25 22:52:56 -0700
commitf182c13765e2a653da3bd9c3b49cac92e8dbd9fa (patch)
treec76bb0b945d16f959e6e6388c1653535fc6ffc52 /librabbitmq
parent91759021f5d938dbef0c358e2194377c406ce418 (diff)
downloadrabbitmq-c-f182c13765e2a653da3bd9c3b49cac92e8dbd9fa.tar.gz
Support openssl engine setting
Diffstat (limited to 'librabbitmq')
-rw-r--r--librabbitmq/amqp.h3
-rw-r--r--librabbitmq/amqp_api.c6
-rw-r--r--librabbitmq/amqp_openssl.c71
-rw-r--r--librabbitmq/amqp_ssl_socket.h34
4 files changed, 111 insertions, 3 deletions
diff --git a/librabbitmq/amqp.h b/librabbitmq/amqp.h
index d2c458d..d8a8b2e 100644
--- a/librabbitmq/amqp.h
+++ b/librabbitmq/amqp.h
@@ -770,7 +770,8 @@ typedef enum amqp_status_enum_ {
AMQP_STATUS_SSL_PEER_VERIFY_FAILED = -0x0202, /**< SSL validation of peer
certificate failed. */
AMQP_STATUS_SSL_CONNECTION_FAILED = -0x0203, /**< SSL handshake failed. */
- _AMQP_STATUS_SSL_NEXT_VALUE = -0x0204 /**< Internal value */
+ AMQP_STATUS_SSL_SET_ENGINE_FAILED = -0x0204, /**< SSL setting engine failed */
+ _AMQP_STATUS_SSL_NEXT_VALUE = -0x0205 /**< Internal value */
} amqp_status_enum;
/**
diff --git a/librabbitmq/amqp_api.c b/librabbitmq/amqp_api.c
index e29b177..abf60d5 100644
--- a/librabbitmq/amqp_api.c
+++ b/librabbitmq/amqp_api.c
@@ -108,14 +108,16 @@ static const char *tcp_error_strings[] = {
"socket library initialization failed"};
static const char *ssl_error_strings[] = {
- /* AMQP_STATUS_SSL_ERRO R -0x0200 */
+ /* AMQP_STATUS_SSL_ERROR -0x0200 */
"a SSL error occurred",
/* AMQP_STATUS_SSL_HOSTNAME_VERIFY_FAILED -0x0201 */
"SSL hostname verification failed",
/* AMQP_STATUS_SSL_PEER_VERIFY_FAILED -0x0202 */
"SSL peer cert verification failed",
/* AMQP_STATUS_SSL_CONNECTION_FAILED -0x0203 */
- "SSL handshake failed"};
+ "SSL handshake failed",
+ /* AMQP_STATUS_SSL_SET_ENGINE_FAILED -0x0204 */
+ "SSL setting engine failed"};
static const char *unknown_error_string = "(unknown error)";
diff --git a/librabbitmq/amqp_openssl.c b/librabbitmq/amqp_openssl.c
index 9bb73d2..0a37fe0 100644
--- a/librabbitmq/amqp_openssl.c
+++ b/librabbitmq/amqp_openssl.c
@@ -63,6 +63,7 @@ static amqp_boolean_t do_initialize_openssl = 1;
static amqp_boolean_t openssl_initialized = 0;
static amqp_boolean_t openssl_bio_initialized = 0;
static int openssl_connections = 0;
+static ENGINE *openssl_engine = NULL;
#define CHECK_SUCCESS(condition) \
do { \
@@ -412,6 +413,34 @@ int amqp_ssl_socket_set_key(amqp_socket_t *base, const char *cert,
return AMQP_STATUS_OK;
}
+int amqp_ssl_socket_set_key_engine(amqp_socket_t *base, const char *cert,
+ const char *key) {
+ int status;
+ struct amqp_ssl_socket_t *self;
+ EVP_PKEY *pkey = NULL;
+ 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;
+ status = SSL_CTX_use_certificate_chain_file(self->ctx, cert);
+ if (1 != status) {
+ return AMQP_STATUS_SSL_ERROR;
+ }
+
+ pkey = ENGINE_load_private_key(openssl_engine, key, NULL, NULL);
+ if (pkey == NULL) {
+ return AMQP_STATUS_SSL_ERROR;
+ }
+
+ status = SSL_CTX_use_PrivateKey(self->ctx, pkey);
+ EVP_PKEY_free(pkey);
+
+ if (1 != status) {
+ return AMQP_STATUS_SSL_ERROR;
+ }
+ return AMQP_STATUS_OK;
+}
+
static int password_cb(AMQP_UNUSED char *buffer, AMQP_UNUSED int length,
AMQP_UNUSED int rwflag, AMQP_UNUSED void *user_data) {
amqp_abort("rabbitmq-c does not support password protected keys");
@@ -633,6 +662,43 @@ out:
return status;
}
+int amqp_set_ssl_engine(const char *engine) {
+ int status = AMQP_STATUS_OK;
+ CHECK_SUCCESS(pthread_mutex_lock(&openssl_init_mutex));
+
+ if (!openssl_initialized) {
+ status = AMQP_STATUS_SSL_ERROR;
+ goto out;
+ }
+
+ if (openssl_engine != NULL) {
+ ENGINE_free(openssl_engine);
+ openssl_engine = NULL;
+ }
+
+ if (engine == NULL) {
+ goto out;
+ }
+
+ ENGINE_load_builtin_engines();
+ openssl_engine = ENGINE_by_id(engine);
+ if (openssl_engine == NULL) {
+ status = AMQP_STATUS_SSL_SET_ENGINE_FAILED;
+ goto out;
+ }
+
+ if (ENGINE_set_default(openssl_engine, ENGINE_METHOD_ALL) == 0) {
+ ENGINE_free(openssl_engine);
+ openssl_engine = NULL;
+ status = AMQP_STATUS_SSL_SET_ENGINE_FAILED;
+ goto out;
+ }
+
+out:
+ CHECK_SUCCESS(pthread_mutex_unlock(&openssl_init_mutex));
+ return status;
+}
+
static int initialize_ssl_and_increment_connections() {
int status;
CHECK_SUCCESS(pthread_mutex_lock(&openssl_init_mutex));
@@ -701,6 +767,11 @@ int amqp_uninitialize_ssl_library(void) {
free(amqp_openssl_lockarray);
}
+ if (openssl_engine != NULL) {
+ ENGINE_free(openssl_engine);
+ openssl_engine = NULL;
+ }
+
ENGINE_cleanup();
CONF_modules_free();
EVP_cleanup();
diff --git a/librabbitmq/amqp_ssl_socket.h b/librabbitmq/amqp_ssl_socket.h
index 70d1a56..5aab8bf 100644
--- a/librabbitmq/amqp_ssl_socket.h
+++ b/librabbitmq/amqp_ssl_socket.h
@@ -102,6 +102,24 @@ int AMQP_CALL amqp_ssl_socket_set_key(amqp_socket_t *self, const char *cert,
const char *key);
/**
+ * Set the client key use the engine.
+ *
+ * This function requires amqp_set_ssl_engine() has been called.
+ *
+ * \param [in,out] self An SSL/TLS socket object.
+ * \param [in] cert Path to the client certificate in PEM foramt.
+ * \param [in] the key ID.
+ *
+ * \return \ref AMQP_STATUS_OK on success an \ref amqp_status_enum value on
+ * failure.
+ *
+ * \since v0.9.1
+ */
+AMQP_PUBLIC_FUNCTION
+int AMQP_CALL amqp_ssl_socket_set_key_engine(amqp_socket_t *self,
+ const char *cert, const char *key);
+
+/**
* Set the client key from a buffer.
*
* \param [in,out] self An SSL/TLS socket object.
@@ -238,6 +256,22 @@ AMQP_PUBLIC_FUNCTION
int AMQP_CALL amqp_initialize_ssl_library(void);
/**
+ * Set the engine for underlying SSL/TLS library.
+ *
+ * This function is thread-safe, and may be called more than once.
+ *
+ * This function requires amqp_initialize_ssl_library() or amqp_ssl_socket_new()
+ * has been called.
+ *
+ * \param [in] engine the engine ID
+ * \return AMQP_STATUS_OK on success.
+ *
+ * \since v0.9.1
+ */
+AMQP_PUBLIC_FUNCTION
+int amqp_set_ssl_engine(const char *engine);
+
+/**
* Uninitialize the underlying SSL/TLS library.
*
* \return AMQP_STATUS_OK on success.