]> granicus.if.org Git - libevent/commitdiff
Make it build using OpenSSL 1.1.0
authorKurt Roeckx <kurt@roeckx.be>
Mon, 19 Sep 2016 20:05:15 +0000 (22:05 +0200)
committerAzat Khuzhin <a3at.mail@gmail.com>
Sun, 16 Oct 2016 16:05:24 +0000 (19:05 +0300)
Rebased (azat):
- tabs instead of whitespaces
- make openssl-compat.h safe for complex expressions
- do not call sk_SSL_COMP_free() in 1.1 (fixes double free)

TODO:
- clean methods_bufferevent

Closes: #397 (cherry-picked)
bufferevent_openssl.c
openssl-compat.h [new file with mode: 0644]
sample/https-client.c
sample/openssl_hostname_validation.c
test/regress_ssl.c

index 4e93ad5310c8fcaf1fcef1e86ebccad70c26a154..2703d7044ce1c93d209b3162fa441db5cea66117 100644 (file)
@@ -66,6 +66,7 @@
 #include <openssl/bio.h>
 #include <openssl/ssl.h>
 #include <openssl/err.h>
+#include "openssl-compat.h"
 
 /*
  * Define an OpenSSL bio that targets a bufferevent.
@@ -109,10 +110,8 @@ print_err(int val)
 static int
 bio_bufferevent_new(BIO *b)
 {
-       b->init = 0;
-       b->num = -1;
-       b->ptr = NULL; /* We'll be putting the bufferevent in this field.*/
-       b->flags = 0;
+       BIO_set_init(b, 0);
+       BIO_set_data(b, NULL); /* We'll be putting the bufferevent in this field.*/
        return 1;
 }
 
@@ -122,12 +121,10 @@ bio_bufferevent_free(BIO *b)
 {
        if (!b)
                return 0;
-       if (b->shutdown) {
-               if (b->init && b->ptr)
-                       bufferevent_free(b->ptr);
-               b->init = 0;
-               b->flags = 0;
-               b->ptr = NULL;
+       if (BIO_get_shutdown(b)) {
+               if (BIO_get_init(b) && BIO_get_data(b))
+                       bufferevent_free(BIO_get_data(b));
+               BIO_free(b);
        }
        return 1;
 }
@@ -143,10 +140,10 @@ bio_bufferevent_read(BIO *b, char *out, int outlen)
 
        if (!out)
                return 0;
-       if (!b->ptr)
+       if (!BIO_get_data(b))
                return -1;
 
-       input = bufferevent_get_input(b->ptr);
+       input = bufferevent_get_input(BIO_get_data(b));
        if (evbuffer_get_length(input) == 0) {
                /* If there's no data to read, say so. */
                BIO_set_retry_read(b);
@@ -162,13 +159,13 @@ bio_bufferevent_read(BIO *b, char *out, int outlen)
 static int
 bio_bufferevent_write(BIO *b, const char *in, int inlen)
 {
-       struct bufferevent *bufev = b->ptr;
+       struct bufferevent *bufev = BIO_get_data(b);
        struct evbuffer *output;
        size_t outlen;
 
        BIO_clear_retry_flags(b);
 
-       if (!b->ptr)
+       if (!BIO_get_data(b))
                return -1;
 
        output = bufferevent_get_output(bufev);
@@ -194,15 +191,15 @@ bio_bufferevent_write(BIO *b, const char *in, int inlen)
 static long
 bio_bufferevent_ctrl(BIO *b, int cmd, long num, void *ptr)
 {
-       struct bufferevent *bufev = b->ptr;
+       struct bufferevent *bufev = BIO_get_data(b);
        long ret = 1;
 
        switch (cmd) {
        case BIO_CTRL_GET_CLOSE:
-               ret = b->shutdown;
+               ret = BIO_get_shutdown(b);
                break;
        case BIO_CTRL_SET_CLOSE:
-               b->shutdown = (int)num;
+               BIO_set_shutdown(b, (int)num);
                break;
        case BIO_CTRL_PENDING:
                ret = evbuffer_get_length(bufferevent_get_input(bufev)) != 0;
@@ -231,23 +228,24 @@ bio_bufferevent_puts(BIO *b, const char *s)
 }
 
 /* Method table for the bufferevent BIO */
-static BIO_METHOD methods_bufferevent = {
-       BIO_TYPE_LIBEVENT, "bufferevent",
-       bio_bufferevent_write,
-       bio_bufferevent_read,
-       bio_bufferevent_puts,
-       NULL /* bio_bufferevent_gets */,
-       bio_bufferevent_ctrl,
-       bio_bufferevent_new,
-       bio_bufferevent_free,
-       NULL /* callback_ctrl */,
-};
+static BIO_METHOD *methods_bufferevent;
 
 /* Return the method table for the bufferevents BIO */
 static BIO_METHOD *
 BIO_s_bufferevent(void)
 {
-       return &methods_bufferevent;
+       if (methods_bufferevent == NULL) {
+               methods_bufferevent = BIO_meth_new(BIO_TYPE_LIBEVENT, "bufferevent");
+               if (methods_bufferevent == NULL)
+                       return NULL;
+               BIO_meth_set_write(methods_bufferevent, bio_bufferevent_write);
+               BIO_meth_set_read(methods_bufferevent, bio_bufferevent_read);
+               BIO_meth_set_puts(methods_bufferevent, bio_bufferevent_puts);
+               BIO_meth_set_ctrl(methods_bufferevent, bio_bufferevent_ctrl);
+               BIO_meth_set_create(methods_bufferevent, bio_bufferevent_new);
+               BIO_meth_set_destroy(methods_bufferevent, bio_bufferevent_free);
+       }
+       return methods_bufferevent;
 }
 
 /* Create a new BIO to wrap communication around a bufferevent.  If close_flag
@@ -260,9 +258,9 @@ BIO_new_bufferevent(struct bufferevent *bufferevent, int close_flag)
                return NULL;
        if (!(result = BIO_new(BIO_s_bufferevent())))
                return NULL;
-       result->init = 1;
-       result->ptr = bufferevent;
-       result->shutdown = close_flag ? 1 : 0;
+       BIO_set_init(result, 1);
+       BIO_set_data(result, bufferevent);
+       BIO_set_shutdown(result, close_flag ? 1 : 0);
        return result;
 }
 
diff --git a/openssl-compat.h b/openssl-compat.h
new file mode 100644 (file)
index 0000000..628f566
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef OPENSSL_COMPAT_H
+#define OPENSSL_COMPAT_H
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
+static BIO_METHOD *BIO_meth_new(int type, const char *name)
+{
+       BIO_METHOD *biom = calloc(1, sizeof(BIO_METHOD));
+
+       if (biom != NULL) {
+               biom->type = type;
+               biom->name = name;
+       }
+       return biom;
+}
+
+#define BIO_meth_set_write(b, f) (b)->bwrite = (f)
+#define BIO_meth_set_read(b, f) (b)->bread = (f)
+#define BIO_meth_set_puts(b, f) (b)->bputs = (f)
+#define BIO_meth_set_ctrl(b, f) (b)->ctrl = (f)
+#define BIO_meth_set_create(b, f) (b)->create = (f)
+#define BIO_meth_set_destroy(b, f) (b)->destroy = (f)
+
+#define BIO_set_init(b, val) (b)->init = (val)
+#define BIO_set_data(b, val) (b)->ptr = (val)
+#define BIO_set_shutdown(b, val) (b)->shutdown = (val)
+#define BIO_get_init(b) (b)->init
+#define BIO_get_data(b) (b)->ptr
+#define BIO_get_shutdown(b) (b)->shutdown
+
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+
+#endif /* OPENSSL_COMPAT_H */
index 029cd19c753fafc048fa6c7c75112257f66539af..d9bf19087c3159bdb9ae1adc09161ab7d7e22f00 100644 (file)
@@ -310,11 +310,13 @@ main(int argc, char **argv)
        }
        uri[sizeof(uri) - 1] = '\0';
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
        // Initialize OpenSSL
        SSL_library_init();
        ERR_load_crypto_strings();
        SSL_load_error_strings();
        OpenSSL_add_all_algorithms();
+#endif
 
        /* This isn't strictly necessary... OpenSSL performs RAND_poll
         * automatically on first use of random number generator. */
@@ -474,6 +476,7 @@ cleanup:
                SSL_CTX_free(ssl_ctx);
        if (type == HTTP && ssl)
                SSL_free(ssl);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
        EVP_cleanup();
        ERR_free_strings();
 
@@ -485,6 +488,7 @@ cleanup:
        CRYPTO_cleanup_all_ex_data();
 
        sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
+#endif /*OPENSSL_VERSION_NUMBER < 0x10100000L */
 
 #ifdef _WIN32
        WSACleanup();
index 00e63d1e15e20298530756437562291cbb4e991c..40312f2e96132cbdb73aca15a545a4a407528f22 100644 (file)
@@ -48,6 +48,10 @@ SOFTWARE.
 
 #define HOSTNAME_MAX_SIZE 255
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#define ASN1_STRING_get0_data ASN1_STRING_data
+#endif
+
 /**
 * Tries to find a match for hostname in the certificate's Common Name field.
 *
@@ -60,7 +64,7 @@ static HostnameValidationResult matches_common_name(const char *hostname, const
         int common_name_loc = -1;
         X509_NAME_ENTRY *common_name_entry = NULL;
         ASN1_STRING *common_name_asn1 = NULL;
-        char *common_name_str = NULL;
+        const char *common_name_str = NULL;
 
         // Find the position of the CN field in the Subject field of the certificate
         common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name((X509 *) server_cert), NID_commonName, -1);
@@ -79,7 +83,7 @@ static HostnameValidationResult matches_common_name(const char *hostname, const
         if (common_name_asn1 == NULL) {
                 return Error;
         }
-        common_name_str = (char *) ASN1_STRING_data(common_name_asn1);
+        common_name_str = (char *) ASN1_STRING_get0_data(common_name_asn1);
 
         // Make sure there isn't an embedded NUL character in the CN
         if ((size_t)ASN1_STRING_length(common_name_asn1) != strlen(common_name_str)) {
@@ -123,7 +127,7 @@ static HostnameValidationResult matches_subject_alternative_name(const char *hos
 
                 if (current_name->type == GEN_DNS) {
                         // Current name is a DNS name, let's check it
-                        char *dns_name = (char *) ASN1_STRING_data(current_name->d.dNSName);
+                        const char *dns_name = (char *) ASN1_STRING_get0_data(current_name->d.dNSName);
 
                         // Make sure there isn't an embedded NUL character in the DNS name
                         if ((size_t)ASN1_STRING_length(current_name->d.dNSName) != strlen(dns_name)) {
index 230e721d93711aae6822eb5fafd45e56cd4bf1f9..6452d2705c45a053b5e2833cc0b5af0fd49a7cc1 100644 (file)
@@ -55,6 +55,7 @@
 #include <openssl/bio.h>
 #include <openssl/err.h>
 #include <openssl/pem.h>
+#include "openssl-compat.h"
 
 #include <string.h>
 #ifdef _WIN32
@@ -551,10 +552,8 @@ struct rwcount
 static int
 bio_rwcount_new(BIO *b)
 {
-       b->init = 0;
-       b->num = -1;
-       b->ptr = NULL;
-       b->flags = 0;
+       BIO_set_init(b, 0);
+       BIO_set_data(b, NULL);
        return 1;
 }
 static int
@@ -562,17 +561,16 @@ bio_rwcount_free(BIO *b)
 {
        if (!b)
                return 0;
-       if (b->shutdown) {
-               b->init = 0;
-               b->flags = 0;
-               b->ptr = NULL;
+       if (BIO_get_shutdown(b)) {
+               BIO_set_init(b, 0);
+               BIO_set_data(b, NULL);
        }
        return 1;
 }
 static int
 bio_rwcount_read(BIO *b, char *out, int outlen)
 {
-       struct rwcount *rw = b->ptr;
+       struct rwcount *rw = BIO_get_data(b);
        ev_ssize_t ret = recv(rw->fd, out, outlen, 0);
        ++rw->read;
        if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
@@ -584,7 +582,7 @@ static int
 bio_rwcount_write(BIO *b, const char *in, int inlen)
 {
 
-       struct rwcount *rw = b->ptr;
+       struct rwcount *rw = BIO_get_data(b);
        ev_ssize_t ret = send(rw->fd, in, inlen, 0);
        ++rw->write;
        if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
@@ -598,10 +596,10 @@ bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr)
        long ret = 0;
        switch (cmd) {
        case BIO_CTRL_GET_CLOSE:
-               ret = b->shutdown;
+               ret = BIO_get_shutdown(b);
                break;
        case BIO_CTRL_SET_CLOSE:
-               b->shutdown = (int)num;
+               BIO_set_shutdown(b, (int)num);
                break;
        case BIO_CTRL_PENDING:
                ret = 0;
@@ -622,21 +620,23 @@ bio_rwcount_puts(BIO *b, const char *s)
        return bio_rwcount_write(b, s, strlen(s));
 }
 #define BIO_TYPE_LIBEVENT_RWCOUNT 0xff1
-static BIO_METHOD methods_rwcount = {
-       BIO_TYPE_LIBEVENT_RWCOUNT, "rwcount",
-       bio_rwcount_write,
-       bio_rwcount_read,
-       bio_rwcount_puts,
-       NULL /* bio_rwcount_gets */,
-       bio_rwcount_ctrl,
-       bio_rwcount_new,
-       bio_rwcount_free,
-       NULL /* callback_ctrl */,
-};
+static BIO_METHOD *methods_rwcount;
+
 static BIO_METHOD *
 BIO_s_rwcount(void)
 {
-       return &methods_rwcount;
+       if (methods_rwcount == NULL) {
+               methods_rwcount = BIO_meth_new(BIO_TYPE_LIBEVENT_RWCOUNT, "rwcount");
+               if (methods_rwcount == NULL)
+                       return NULL;
+               BIO_meth_set_write(methods_rwcount, bio_rwcount_write);
+               BIO_meth_set_read(methods_rwcount, bio_rwcount_read);
+               BIO_meth_set_puts(methods_rwcount, bio_rwcount_puts);
+               BIO_meth_set_ctrl(methods_rwcount, bio_rwcount_ctrl);
+               BIO_meth_set_create(methods_rwcount, bio_rwcount_new);
+               BIO_meth_set_destroy(methods_rwcount, bio_rwcount_free);
+       }
+       return methods_rwcount;
 }
 static BIO *
 BIO_new_rwcount(int close_flag)
@@ -644,9 +644,9 @@ BIO_new_rwcount(int close_flag)
        BIO *result;
        if (!(result = BIO_new(BIO_s_rwcount())))
                return NULL;
-       result->init = 1;
-       result->ptr = NULL;
-       result->shutdown = !!close_flag;
+       BIO_set_init(result, 1);
+       BIO_set_data(result,  NULL);
+       BIO_set_shutdown(result, !!close_flag);
        return result;
 }
 
@@ -710,7 +710,7 @@ regress_bufferevent_openssl_connect(void *arg)
                rw.fd = bufferevent_getfd(bev);
                bio = BIO_new_rwcount(0);
                tt_assert(bio);
-               bio->ptr = &rw;
+               BIO_set_data(bio, &rw);
                SSL_set_bio(ssl, bio, bio);
        }
        evbuffer_add_printf(bufferevent_get_output(bev), "1\n");