diff options
author | Yevhen Kyriukha <kirgene@gmail.com> | 2014-12-30 05:36:53 +0200 |
---|---|---|
committer | Alan Antonuk <alan.antonuk@gmail.com> | 2015-01-06 21:29:55 -0800 |
commit | 513ad4afeaabff2a9be90f940381569194909227 (patch) | |
tree | e9865b467974c48f6de64e6184cf44bb7dc771a8 /librabbitmq | |
parent | 656f833016ec2dae1f51425ea667c6a6f644a9ae (diff) | |
download | rabbitmq-c-513ad4afeaabff2a9be90f940381569194909227.tar.gz |
Enable SSL verification of hostname using certificates with Subject Alternate Names DNS entries.
Additional check for entries in SSL certificate.
Signed-off-by: Yevhen Kyriukha <kirgene@gmail.com>
Diffstat (limited to 'librabbitmq')
-rw-r--r-- | librabbitmq/amqp_openssl.c | 104 |
1 files changed, 75 insertions, 29 deletions
diff --git a/librabbitmq/amqp_openssl.c b/librabbitmq/amqp_openssl.c index c1b5515..57589d8 100644 --- a/librabbitmq/amqp_openssl.c +++ b/librabbitmq/amqp_openssl.c @@ -39,6 +39,7 @@ #include <openssl/conf.h> #include <openssl/err.h> #include <openssl/ssl.h> +#include <openssl/x509v3.h> #include <stdlib.h> #include <string.h> @@ -178,36 +179,10 @@ amqp_ssl_socket_recv(void *base, return received; } -static int -amqp_ssl_socket_verify_hostname(void *base, const char *host) +static int match(ASN1_STRING *entry_string, const char *string) { - struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base; unsigned char *utf8_value = NULL, *cp, ch; - int pos, utf8_length, status = 0; - ASN1_STRING *entry_string; - X509_NAME_ENTRY *entry; - X509_NAME *name; - X509 *peer; - peer = SSL_get_peer_certificate(self->ssl); - if (!peer) { - goto error; - } - name = X509_get_subject_name(peer); - if (!name) { - goto error; - } - pos = X509_NAME_get_index_by_NID(name, NID_commonName, -1); - if (0 > pos) { - goto error; - } - entry = X509_NAME_get_entry(name, pos); - if (!entry) { - goto error; - } - entry_string = X509_NAME_ENTRY_get_data(entry); - if (!entry_string) { - goto error; - } + int utf8_length, status = 1; utf8_length = ASN1_STRING_to_UTF8(&utf8_value, entry_string); if (0 > utf8_length) { goto error; @@ -226,13 +201,84 @@ amqp_ssl_socket_verify_hostname(void *base, const char *host) goto error; } } - if (!amqp_hostcheck((char *)utf8_value, host)) { + if (!amqp_hostcheck((char *)utf8_value, string)) { goto error; } exit: OPENSSL_free(utf8_value); return status; error: + status = 0; + goto exit; +} + +/* Does this hostname match an entry in the subjectAltName extension? + * returns: 0 if no, 1 if yes, -1 if no subjectAltName entries were found. + */ +static int hostname_matches_subject_alt_name(const char *hostname, X509 *cert) +{ + int found_any_entries = 0; + int found_match; + GENERAL_NAME *namePart = NULL; + STACK_OF(GENERAL_NAME) *san = + (STACK_OF(GENERAL_NAME)*) X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); + + while (sk_GENERAL_NAME_num(san) > 0) + { + namePart = sk_GENERAL_NAME_pop(san); + + if (namePart->type == GEN_DNS) { + found_any_entries = 1; + found_match = match(namePart->d.uniformResourceIdentifier, hostname); + if (found_match) + return 1; + } + } + + return (found_any_entries ? 0 : -1); +} + +static int hostname_matches_subject_common_name(const char *hostname, X509 *cert) +{ + X509_NAME *name; + X509_NAME_ENTRY *name_entry; + int position; + ASN1_STRING *entry_string; + + name = X509_get_subject_name(cert); + position = -1; + for (;;) { + position = X509_NAME_get_index_by_NID(name, NID_commonName, position); + if (position == -1) + break; + name_entry = X509_NAME_get_entry(name, position); + entry_string = X509_NAME_ENTRY_get_data(name_entry); + if (match(entry_string, hostname)) + return 1; + } + return 0; +} + +static int +amqp_ssl_socket_verify_hostname(void *base, const char *host) +{ + struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base; + int status = 0; + X509 *cert; + int res; + cert = SSL_get_peer_certificate(self->ssl); + if (!cert) { + goto error; + } + res = hostname_matches_subject_alt_name(host, cert); + if (res != 1) { + res = hostname_matches_subject_common_name(host, cert); + if (!res) + goto error; + } +exit: + return status; +error: status = -1; goto exit; } |