summaryrefslogtreecommitdiff
path: root/librabbitmq/amqp_openssl.c
diff options
context:
space:
mode:
authorAlan Antonuk <alan.antonuk@gmail.com>2013-06-10 11:43:51 -0700
committerAlan Antonuk <alan.antonuk@gmail.com>2013-06-13 15:54:55 -0700
commit7231d921b3db2f7d62e716976c31abdbf8e0edc5 (patch)
tree6927abe6bfcf667abbe3e22a98b0c95cd719e967 /librabbitmq/amqp_openssl.c
parent0ae534a671804d5a7b68fa0825494000f31b1536 (diff)
downloadrabbitmq-c-7231d921b3db2f7d62e716976c31abdbf8e0edc5.tar.gz
Add more specific SSL connection error codes
Add the following error codes: - hostname verify failure: e.g., provided hostname doesn't match peer certificate - peer verification failed - connection handshake failed
Diffstat (limited to 'librabbitmq/amqp_openssl.c')
-rw-r--r--librabbitmq/amqp_openssl.c82
1 files changed, 54 insertions, 28 deletions
diff --git a/librabbitmq/amqp_openssl.c b/librabbitmq/amqp_openssl.c
index b210e31..a42b109 100644
--- a/librabbitmq/amqp_openssl.c
+++ b/librabbitmq/amqp_openssl.c
@@ -65,7 +65,7 @@ struct amqp_ssl_socket_t {
char *buffer;
size_t length;
amqp_boolean_t verify;
- int last_error;
+ int internal_error;
};
static ssize_t
@@ -152,7 +152,7 @@ amqp_ssl_socket_recv(void *base,
}
static int
-amqp_ssl_socket_verify(void *base, const char *host)
+amqp_ssl_socket_verify_hostname(void *base, const char *host)
{
struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
unsigned char *utf8_value = NULL, *cp, ch;
@@ -222,41 +222,67 @@ amqp_ssl_socket_open(void *base, const char *host, int port)
struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
long result;
int status;
- self->last_error = 0;
+ ERR_clear_error();
+
self->ssl = SSL_new(self->ctx);
if (!self->ssl) {
- self->last_error = AMQP_STATUS_SSL_ERROR;
- return -1;
+ self->internal_error = ERR_peek_error();
+ status = AMQP_STATUS_SSL_ERROR;
+ goto exit;
}
+
SSL_set_mode(self->ssl, SSL_MODE_AUTO_RETRY);
self->sockfd = amqp_open_socket(host, port);
if (0 > self->sockfd) {
- self->last_error = -self->sockfd;
- return -1;
+ status = self->sockfd;
+ self->internal_error = amqp_os_socket_error();
+ self->sockfd = -1;
+ goto error_out1;
}
+
status = SSL_set_fd(self->ssl, self->sockfd);
if (!status) {
- self->last_error = AMQP_STATUS_SSL_ERROR;
- return -1;
+ self->internal_error = SSL_get_error(self->ssl, status);
+ status = AMQP_STATUS_SSL_ERROR;
+ goto error_out2;
}
+
status = SSL_connect(self->ssl);
if (!status) {
- self->last_error = AMQP_STATUS_SSL_ERROR;
- return -1;
+ self->internal_error = SSL_get_error(self->ssl, status);
+ status = AMQP_STATUS_SSL_CONNECTION_FAILED;
+ goto error_out2;
}
+
result = SSL_get_verify_result(self->ssl);
if (X509_V_OK != result) {
- self->last_error = AMQP_STATUS_SSL_ERROR;
- return -1;
+ self->internal_error = result;
+ status = AMQP_STATUS_SSL_PEER_VERIFY_FAILED;
+ goto error_out3;
}
if (self->verify) {
- int status = amqp_ssl_socket_verify(self, host);
+ int status = amqp_ssl_socket_verify_hostname(self, host);
if (status) {
- self->last_error = AMQP_STATUS_SSL_ERROR;
- return -1;
+ self->internal_error = 0;
+ status = AMQP_STATUS_SSL_HOSTNAME_VERIFY_FAILED;
+ goto error_out3;
}
}
- return 0;
+
+ self->internal_error = 0;
+ status = AMQP_STATUS_OK;
+
+exit:
+ return status;
+
+error_out3:
+ SSL_shutdown(self->ssl);
+error_out2:
+ amqp_os_socket_close(self->sockfd);
+ self->sockfd = -1;
+error_out1:
+ SSL_free(self->ssl);
+ goto exit;
}
static int
@@ -278,7 +304,7 @@ static int
amqp_ssl_socket_error(void *base)
{
struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
- return self->last_error;
+ return self->internal_error;
}
char *
@@ -340,9 +366,9 @@ amqp_ssl_socket_set_cacert(amqp_socket_t *base,
self = (struct amqp_ssl_socket_t *)base;
status = SSL_CTX_load_verify_locations(self->ctx, cacert, NULL);
if (1 != status) {
- return -1;
+ return AMQP_STATUS_SSL_ERROR;
}
- return 0;
+ return AMQP_STATUS_OK;
}
int
@@ -358,14 +384,14 @@ amqp_ssl_socket_set_key(amqp_socket_t *base,
self = (struct amqp_ssl_socket_t *)base;
status = SSL_CTX_use_certificate_chain_file(self->ctx, cert);
if (1 != status) {
- return -1;
+ return AMQP_STATUS_SSL_ERROR;
}
status = SSL_CTX_use_PrivateKey_file(self->ctx, key,
SSL_FILETYPE_PEM);
if (1 != status) {
- return -1;
+ return AMQP_STATUS_SSL_ERROR;
}
- return 0;
+ return AMQP_STATUS_OK;
}
static int
@@ -384,7 +410,7 @@ amqp_ssl_socket_set_key_buffer(amqp_socket_t *base,
const void *key,
size_t n)
{
- int status = 0;
+ int status = AMQP_STATUS_OK;
BIO *buf = NULL;
RSA *rsa = NULL;
struct amqp_ssl_socket_t *self;
@@ -394,7 +420,7 @@ amqp_ssl_socket_set_key_buffer(amqp_socket_t *base,
self = (struct amqp_ssl_socket_t *)base;
status = SSL_CTX_use_certificate_chain_file(self->ctx, cert);
if (1 != status) {
- return -1;
+ return AMQP_STATUS_SSL_ERROR;
}
buf = BIO_new_mem_buf((void *)key, n);
if (!buf) {
@@ -413,7 +439,7 @@ exit:
RSA_free(rsa);
return status;
error:
- status = -1;
+ status = AMQP_STATUS_SSL_ERROR;
goto exit;
}
@@ -429,9 +455,9 @@ amqp_ssl_socket_set_cert(amqp_socket_t *base,
self = (struct amqp_ssl_socket_t *)base;
status = SSL_CTX_use_certificate_chain_file(self->ctx, cert);
if (1 != status) {
- return -1;
+ return AMQP_STATUS_SSL_ERROR;
}
- return 0;
+ return AMQP_STATUS_OK;
}
void