Skip to content

Commit

Permalink
Make it build using OpenSSL 1.1.0
Browse files Browse the repository at this point in the history
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: libevent#397 (cherry-picked)
  • Loading branch information
kroeckx authored and azat committed Oct 16, 2016
1 parent 6702da1 commit 3e9e0a0
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 63 deletions.
62 changes: 30 additions & 32 deletions bufferevent_openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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;
}

Expand Down
33 changes: 33 additions & 0 deletions openssl-compat.h
Original file line number Diff line number Diff line change
@@ -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 */
4 changes: 4 additions & 0 deletions sample/https-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -474,6 +476,7 @@ main(int argc, char **argv)
SSL_CTX_free(ssl_ctx);
if (type == HTTP && ssl)
SSL_free(ssl);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_cleanup();
ERR_free_strings();

Expand All @@ -485,6 +488,7 @@ main(int argc, char **argv)
CRYPTO_cleanup_all_ex_data();

sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
#endif /*OPENSSL_VERSION_NUMBER < 0x10100000L */

#ifdef _WIN32
WSACleanup();
Expand Down
10 changes: 7 additions & 3 deletions sample/openssl_hostname_validation.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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);
Expand All @@ -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)) {
Expand Down Expand Up @@ -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)) {
Expand Down
56 changes: 28 additions & 28 deletions test/regress_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -551,28 +552,25 @@ 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
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())) {
Expand All @@ -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())) {
Expand All @@ -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;
Expand All @@ -622,31 +620,33 @@ 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)
{
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;
}

Expand Down Expand Up @@ -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");
Expand Down

0 comments on commit 3e9e0a0

Please sign in to comment.