summaryrefslogtreecommitdiff
path: root/librabbitmq/amqp_gnutls.c
diff options
context:
space:
mode:
Diffstat (limited to 'librabbitmq/amqp_gnutls.c')
-rw-r--r--librabbitmq/amqp_gnutls.c362
1 files changed, 0 insertions, 362 deletions
diff --git a/librabbitmq/amqp_gnutls.c b/librabbitmq/amqp_gnutls.c
deleted file mode 100644
index f18d427..0000000
--- a/librabbitmq/amqp_gnutls.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/* vim:set ft=c ts=2 sw=2 sts=2 et cindent: */
-/*
- * Copyright 2012-2013 Michael Steinert
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "amqp_ssl_socket.h"
-#include "amqp_private.h"
-#include <gnutls/gnutls.h>
-#include <gnutls/x509.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef AMQP_USE_UNTESTED_SSL_BACKEND
-# error This SSL backend is alpha quality and likely contains errors.\
- -DAMQP_USE_UNTESTED_SSL_BACKEND to use this backend
-#endif
-
-struct amqp_ssl_socket_t {
- const struct amqp_socket_class_t *klass;
- gnutls_session_t session;
- gnutls_certificate_credentials_t credentials;
- int sockfd;
- char *host;
- char *buffer;
- size_t length;
- int last_error;
-};
-
-static ssize_t
-amqp_ssl_socket_send(void *base,
- const void *buf,
- size_t len,
- AMQP_UNUSED int flags)
-{
- ssize_t status;
- struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
-
- self->last_error = 0;
- status = gnutls_record_send(self->session, buf, len);
- if (status < 0) {
- self->last_error = AMQP_STATUS_SSL_ERROR;
- }
- return status;
-}
-
-static ssize_t
-amqp_ssl_socket_writev(void *base,
- const struct iovec *iov,
- int iovcnt)
-{
- struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
- ssize_t written = -1;
- char *bufferp;
- size_t bytes;
- int i;
- self->last_error = 0;
- bytes = 0;
- for (i = 0; i < iovcnt; ++i) {
- bytes += iov[i].iov_len;
- }
- if (self->length < bytes) {
- free(self->buffer);
- self->buffer = malloc(bytes);
- if (!self->buffer) {
- self->length = 0;
- self->last_error = AMQP_STATUS_NO_MEMORY;
- goto exit;
- }
- self->length = 0;
- }
- bufferp = self->buffer;
- for (i = 0; i < iovcnt; ++i) {
- memcpy(bufferp, iov[i].iov_base, iov[i].iov_len);
- bufferp += iov[i].iov_len;
- }
- written = amqp_ssl_socket_send(self, self->buffer, bytes, 0);
-exit:
- return written;
-}
-
-static ssize_t
-amqp_ssl_socket_recv(void *base,
- void *buf,
- size_t len,
- AMQP_UNUSED int flags)
-{
- ssize_t status;
- struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
-
- self->last_error = 0;
- status = gnutls_record_recv(self->session, buf, len);
- if (status < 0) {
- self->last_error = AMQP_STATUS_SSL_ERROR;
- }
-
- return status;
-}
-
-static int
-amqp_ssl_socket_open(void *base, const char *host, int port, struct timeval *timeout)
-{
- struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
- int status;
- self->last_error = 0;
-
- free(self->host);
- self->host = strdup(host);
- if (NULL == self->host) {
- self->last_error = AMQP_STATUS_NO_MEMORY;
- return -1;
- }
-
- self->sockfd = amqp_open_socket_noblock(host, port, timeout);
- if (0 > self->sockfd) {
- self->last_error = -self->sockfd;
- return -1;
- }
- gnutls_transport_set_ptr(self->session,
- (gnutls_transport_ptr_t)self->sockfd);
- do {
- status = gnutls_handshake(self->session);
- } while (status < 0 && !gnutls_error_is_fatal(status));
-
- if (gnutls_error_is_fatal(status)) {
- self->last_error = AMQP_STATUS_SSL_ERROR;
- }
-
- return status;
-}
-
-static int
-amqp_ssl_socket_close(void *base)
-{
- int status = -1;
- struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
- if (self->sockfd >= 0) {
- status = amqp_os_socket_close(self->sockfd);
- }
- if (self) {
- gnutls_deinit(self->session);
- gnutls_certificate_free_credentials(self->credentials);
- free(self->host);
- free(self->buffer);
- free(self);
- }
- return status;
-}
-
-static int
-amqp_ssl_socket_error(void *base)
-{
- struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
- return self->last_error;
-}
-
-char *
-amqp_ssl_error_string(AMQP_UNUSED int err)
-{
- return strdup("A SSL error occurred");
-}
-
-static int
-amqp_ssl_socket_get_sockfd(void *base)
-{
- struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
- return self->sockfd;
-}
-
-static int
-amqp_ssl_verify(gnutls_session_t session)
-{
- int ret;
- unsigned int status, size;
- const gnutls_datum_t *list;
- gnutls_x509_crt_t cert = NULL;
- struct amqp_ssl_socket_t *self = gnutls_session_get_ptr(session);
- ret = gnutls_certificate_verify_peers2(session, &status);
- if (0 > ret) {
- goto error;
- }
- if (status & GNUTLS_CERT_INVALID) {
- goto error;
- }
- if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
- goto error;
- }
- if (status & GNUTLS_CERT_REVOKED) {
- goto error;
- }
- if (status & GNUTLS_CERT_EXPIRED) {
- goto error;
- }
- if (status & GNUTLS_CERT_NOT_ACTIVATED) {
- goto error;
- }
- if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) {
- goto error;
- }
- if (gnutls_x509_crt_init(&cert) < 0) {
- goto error;
- }
- list = gnutls_certificate_get_peers(session, &size);
- if (!list) {
- goto error;
- }
- ret = gnutls_x509_crt_import(cert, &list[0], GNUTLS_X509_FMT_DER);
- if (0 > ret) {
- goto error;
- }
- if (!gnutls_x509_crt_check_hostname(cert, self->host)) {
- goto error;
- }
- gnutls_x509_crt_deinit(cert);
- return 0;
-error:
- if (cert) {
- gnutls_x509_crt_deinit (cert);
- }
- return GNUTLS_E_CERTIFICATE_ERROR;
-}
-
-static const struct amqp_socket_class_t amqp_ssl_socket_class = {
- amqp_ssl_socket_writev, /* writev */
- amqp_ssl_socket_send, /* send */
- amqp_ssl_socket_recv, /* recv */
- amqp_ssl_socket_open, /* open */
- amqp_ssl_socket_close, /* close */
- amqp_ssl_socket_error, /* error */
- amqp_ssl_socket_get_sockfd /* get_sockfd */
-};
-
-amqp_socket_t *
-amqp_ssl_socket_new(void)
-{
- struct amqp_ssl_socket_t *self = calloc(1, sizeof(*self));
- const char *error;
- int status;
- if (!self) {
- goto error;
- }
- gnutls_global_init();
- status = gnutls_init(&self->session, GNUTLS_CLIENT);
- if (GNUTLS_E_SUCCESS != status) {
- goto error;
- }
- status = gnutls_certificate_allocate_credentials(&self->credentials);
- if (GNUTLS_E_SUCCESS != status) {
- goto error;
- }
- gnutls_certificate_set_verify_function(self->credentials,
- amqp_ssl_verify);
- status = gnutls_credentials_set(self->session, GNUTLS_CRD_CERTIFICATE,
- self->credentials);
- if (GNUTLS_E_SUCCESS != status) {
- goto error;
- }
- gnutls_session_set_ptr(self->session, self);
- status = gnutls_priority_set_direct(self->session, "NORMAL", &error);
- if (GNUTLS_E_SUCCESS != status) {
- goto error;
- }
- self->klass = &amqp_ssl_socket_class;
- return (amqp_socket_t *)self;
-error:
- amqp_socket_close((amqp_socket_t *)self);
- return NULL;
-}
-
-int
-amqp_ssl_socket_set_cacert(amqp_socket_t *base,
- const char *cacert)
-{
- int status;
- 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;
- status = gnutls_certificate_set_x509_trust_file(self->credentials,
- cacert,
- GNUTLS_X509_FMT_PEM);
- if (0 > status) {
- return -1;
- }
- return 0;
-}
-
-int
-amqp_ssl_socket_set_key(amqp_socket_t *base,
- const char *cert,
- const char *key)
-{
- int status;
- 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;
- status = gnutls_certificate_set_x509_key_file(self->credentials,
- cert,
- key,
- GNUTLS_X509_FMT_PEM);
- if (0 > status) {
- return -1;
- }
- return 0;
-}
-
-int
-amqp_ssl_socket_set_key_buffer(AMQP_UNUSED amqp_socket_t *base,
- AMQP_UNUSED const char *cert,
- AMQP_UNUSED const void *key,
- AMQP_UNUSED size_t n)
-{
- amqp_abort("%s is not implemented for GnuTLS", __func__);
- return -1;
-}
-
-void
-amqp_ssl_socket_set_verify(amqp_socket_t *base,
- amqp_boolean_t verify)
-{
- 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;
- if (verify) {
- gnutls_certificate_set_verify_function(self->credentials,
- amqp_ssl_verify);
- } else {
- gnutls_certificate_set_verify_function(self->credentials,
- NULL);
- }
-}
-
-void
-amqp_set_initialize_ssl_library(AMQP_UNUSED amqp_boolean_t do_initialize)
-{
-}