fix build system and add test and cleanup code

This commit is contained in:
okhowang(王沛文) 2020-05-28 17:14:46 +08:00 committed by Azat Khuzhin
parent 8218777d44
commit 028385f685
20 changed files with 1081 additions and 736 deletions

View File

@ -991,7 +991,9 @@ endif()
if (NOT EVENT__DISABLE_MBEDTLS)
add_event_library(event_mbedtls
LIBRARIES event_core_shared ${MBEDTLS_LIBRARIES}
INNER_LIBRARIES event_core
OUTER_INCLUDES ${MBEDTLS_INCLUDE_DIR}
LIBRARIES ${MBEDTLS_LIBRARIES}
SOURCES ${SRC_MBEDTLS})
endif()
@ -1038,8 +1040,8 @@ macro(add_sample_prog ssl name)
${LIB_APPS}
${LIB_PLATFORM})
if (${ssl})
target_link_libraries(${name} event_openssl)
if (TARGET ${ssl})
target_link_libraries(${name} ${ssl})
if(WIN32)
target_link_libraries(${name} crypt32)
endif()
@ -1062,13 +1064,18 @@ if (NOT EVENT__DISABLE_SAMPLES)
endif()
if (NOT EVENT__DISABLE_OPENSSL)
add_sample_prog(ON https-client
add_sample_prog(event_openssl https-client
sample/https-client.c
sample/openssl_hostname_validation.c
sample/hostcheck.c)
add_sample_prog(ON le-proxy
add_sample_prog(event_openssl le-proxy
sample/le-proxy.c)
add_sample_prog(ON becat sample/becat.c ${WIN32_GETOPT})
add_sample_prog(event_openssl becat sample/becat.c ${WIN32_GETOPT})
endif()
if (NOT EVENT__DISABLE_MBEDTLS)
add_sample_prog(event_mbedtls ssl-client-mbedtls
sample/ssl-client-mbedtls.c)
endif()
set(SAMPLES_WOPT
@ -1180,7 +1187,11 @@ if (NOT EVENT__DISABLE_TESTS)
endif()
if (NOT EVENT__DISABLE_OPENSSL)
list(APPEND SRC_REGRESS test/regress_ssl.c)
list(APPEND SRC_REGRESS test/regress_openssl.c)
endif()
if (NOT EVENT__DISABLE_MBEDTLS)
list(APPEND SRC_REGRESS test/regress_mbedtls.c)
endif()
add_executable(regress ${SRC_REGRESS})
@ -1193,6 +1204,9 @@ if (NOT EVENT__DISABLE_TESTS)
if (NOT EVENT__DISABLE_OPENSSL)
target_link_libraries(regress event_openssl)
endif()
if (NOT EVENT__DISABLE_MBEDTLS)
target_link_libraries(regress event_mbedtls)
endif()
if (CMAKE_USE_PTHREADS_INIT)
target_link_libraries(regress event_pthreads)
endif()

View File

@ -101,7 +101,8 @@ LIBEVENT_PKGCONFIG=libevent.pc libevent_core.pc libevent_extra.pc
# included from other files.
PLATFORM_DEPENDENT_SRC = \
arc4random.c \
epoll_sub.c
epoll_sub.c \
test/regress_ssl.c
CMAKE_FILES = \
cmake/AddCompilerFlags.cmake \
@ -116,6 +117,7 @@ CMAKE_FILES = \
cmake/CodeCoverage.cmake \
cmake/COPYING-CMAKE-SCRIPTS \
cmake/Copyright.txt \
cmake/FindMbedTLS.cmake \
cmake/LibeventConfig.cmake.in \
cmake/LibeventConfigVersion.cmake.in \
cmake/Macros.cmake \

View File

@ -70,39 +70,13 @@
#define SSL_ERROR_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE
#define SSL mbedtls_ssl_context
/*
* Define an OpenSSL bio that targets a bufferevent.
*/
/* --------------------
A BIO is an OpenSSL abstraction that handles reading and writing data. The
library will happily speak SSL over anything that implements a BIO
interface.
Here we define a BIO implementation that directs its output to a
bufferevent. We'll want to use this only when none of OpenSSL's built-in
IO mechanisms work for us.
-------------------- */
/* every BIO type needs its own integer type value. */
#define BIO_TYPE_LIBEVENT 57
/* ???? Arguably, we should set BIO_TYPE_FILTER or BIO_TYPE_SOURCE_SINK on
* this. */
#if 0
static void
print_err(int val)
{
int err;
printf("Error was %d\n", val);
while ((err = ERR_get_error())) {
const char *msg = (const char*)ERR_reason_error_string(err);
const char *lib = (const char*)ERR_lib_error_string(err);
const char *func = (const char*)ERR_func_error_string(err);
printf("%s in %s %s\n", msg, lib, func);
}
char buf[1024];
mbedtls_strerror(val, buf, sizeof(buf));
printf("Error was %d:%s\n", val, buf);
}
#else
#define print_err(v) ((void)0)
@ -117,10 +91,6 @@ bio_bufferevent_read(void *ctx, unsigned char *out, size_t outlen)
int r = 0;
struct evbuffer *input;
//BIO_clear_retry_flags(b);
fprintf(stdout, "bio prepare write:\n");
fwrite(out, 1, outlen, stdout);
if (!out)
return 0;
if (!bufev)
@ -129,17 +99,15 @@ bio_bufferevent_read(void *ctx, unsigned char *out, size_t outlen)
input = bufferevent_get_input(bufev);
if (evbuffer_get_length(input) == 0) {
/* If there's no data to read, say so. */
//BIO_set_retry_read(b);
return MBEDTLS_ERR_SSL_WANT_READ;
} else {
r = evbuffer_remove(input, out, outlen);
}
fprintf(stderr, "bio read %d bytes\n", r);
return r;
}
/* Called to write data info the BIO */
/* Called to write data into the BIO */
static int
bio_bufferevent_write(void *ctx, const unsigned char *in, size_t inlen)
{
@ -147,8 +115,6 @@ bio_bufferevent_write(void *ctx, const unsigned char *in, size_t inlen)
struct evbuffer *output;
size_t outlen;
//BIO_clear_retry_flags(b);
if (!bufev)
return MBEDTLS_ERR_NET_INVALID_CONTEXT;
@ -160,7 +126,6 @@ bio_bufferevent_write(void *ctx, const unsigned char *in, size_t inlen)
if (bufev->wm_write.high && bufev->wm_write.high <= (outlen+inlen)) {
if (bufev->wm_write.high <= outlen) {
/* If no data can fit, we'll need to retry later. */
//BIO_set_retry_write(b);
return MBEDTLS_ERR_SSL_WANT_WRITE;
}
inlen = bufev->wm_write.high - outlen;
@ -168,22 +133,15 @@ bio_bufferevent_write(void *ctx, const unsigned char *in, size_t inlen)
EVUTIL_ASSERT(inlen > 0);
evbuffer_add(output, in, inlen);
fprintf(stderr, "bio write %d bytes\n", inlen);
return inlen;
}
/* --------------------
Now, here's the OpenSSL-based implementation of bufferevent.
Now, here's the mbedTLS-based implementation of bufferevent.
The implementation comes in two flavors: one that connects its SSL object
to an underlying bufferevent using a BIO_bufferevent, and one that has the
SSL object connect to a socket directly. The latter should generally be
faster, except on Windows, where your best bet is using a
bufferevent_async.
(OpenSSL supports many other BIO types, too. But we can't use any unless
we have a good way to get notified when they become readable/writable.)
The implementation comes in only one flavors, that has the
SSL object connect to a socket directly.
-------------------- */
struct bio_data_counts {
@ -201,8 +159,8 @@ struct bufferevent_mbedtls {
/* An underlying bufferevent that we're directing our output to.
If it's NULL, then we're connected to an fd, not an evbuffer. */
struct bufferevent *underlying;
/* net fd */
mbedtls_net_context net_ctx;
/* net fd */
mbedtls_net_context net_ctx;
/* The SSL object doing our encryption. */
SSL *ssl;
@ -248,7 +206,7 @@ static int be_mbedtls_flush(struct bufferevent *bufev,
static int be_mbedtls_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
const struct bufferevent_ops bufferevent_ops_mbedtls = {
"ssl",
"mbedtls",
evutil_offsetof(struct bufferevent_mbedtls, bev.bev),
be_mbedtls_enable,
be_mbedtls_disable,
@ -407,10 +365,7 @@ conn_closed(struct bufferevent_mbedtls *bev_ssl, int when, int errcode, int ret)
{
int event = BEV_EVENT_ERROR;
//int dirty_shutdown = 0;
unsigned long err;
char buf[100] = {};
fprintf(stderr, "when %d error code %d", when, errcode);
char buf[100];
if (when & BEV_EVENT_READING && ret == 0)
{
@ -443,33 +398,6 @@ conn_closed(struct bufferevent_mbedtls *bev_ssl, int when, int errcode, int ret)
bufferevent_run_eventcb_(&bev_ssl->bev.bev, when | event, 0);
}
/*static void
init_bio_counts(struct bufferevent_mbedtls *bev_ssl)
{
BIO *rbio, *wbio;
wbio = SSL_get_wbio(bev_ssl->ssl);
bev_ssl->counts.n_written = wbio ? BIO_number_written(wbio) : 0;
rbio = SSL_get_rbio(bev_ssl->ssl);
bev_ssl->counts.n_read = rbio ? BIO_number_read(rbio) : 0;
}
static inline void
decrement_buckets(struct bufferevent_mbedtls *bev_ssl)
{
unsigned long num_w = BIO_number_written(SSL_get_wbio(bev_ssl->ssl));
unsigned long num_r = BIO_number_read(SSL_get_rbio(bev_ssl->ssl));
/* These next two subtractions can wrap around. That's okay. * /
unsigned long w = num_w - bev_ssl->counts.n_written;
unsigned long r = num_r - bev_ssl->counts.n_read;
if (w)
bufferevent_decrement_write_buckets_(&bev_ssl->bev, w);
if (r)
bufferevent_decrement_read_buckets_(&bev_ssl->bev, r);
bev_ssl->counts.n_written = num_w;
bev_ssl->counts.n_read = num_r;
}*/
#define OP_MADE_PROGRESS 1
#define OP_BLOCKED 2
#define OP_ERR 4
@ -507,7 +435,6 @@ do_read(struct bufferevent_mbedtls *bev_ssl, int n_to_read) {
return OP_ERR | result;
++n_used;
space[i].iov_len = r;
//decrement_buckets(bev_ssl);
} else {
int err = r;
print_err(err);
@ -584,7 +511,6 @@ do_write(struct bufferevent_mbedtls *bev_ssl, int atmost)
return OP_ERR | result;
n_written += r;
bev_ssl->last_write = -1;
//decrement_buckets(bev_ssl);
} else {
int err = r;
print_err(err);
@ -924,7 +850,6 @@ do_handshake(struct bufferevent_mbedtls *bev_ssl)
r = mbedtls_ssl_handshake(bev_ssl->ssl);
break;
}
//decrement_buckets(bev_ssl);
if (r==0) {
evutil_socket_t fd = event_get_fd(&bev_ssl->bev.bev.ev_read);
@ -1010,7 +935,7 @@ set_handshake_callbacks(struct bufferevent_mbedtls *bev_ssl, evutil_socket_t fd)
}
int
bufferevent_ssl_renegotiate(struct bufferevent *bev)
bufferevent_mbedtls_renegotiate(struct bufferevent *bev)
{
struct bufferevent_mbedtls *bev_ssl = upcast(bev);
if (!bev_ssl)
@ -1103,7 +1028,9 @@ be_mbedtls_unlink(struct bufferevent *bev)
} else {
mbedtls_ssl_set_bio(bev_ssl->ssl, NULL, NULL, NULL, NULL);
bufferevent_free(bev_ssl->underlying);
bev_ssl->underlying = NULL;
/* We still have a reference to it, via our
* BIO. So we don't drop this. */
// bev_ssl->underlying = NULL;
}
}
} else {
@ -1169,14 +1096,12 @@ be_mbedtls_set_fd(struct bufferevent_mbedtls *bev_ssl,
case BUFFEREVENT_SSL_ACCEPTING:
if (bev_ssl->ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER)
return -1;
//SSL_set_accept_state(bev_ssl->ssl);
if (set_handshake_callbacks(bev_ssl, fd) < 0)
return -1;
break;
case BUFFEREVENT_SSL_CONNECTING:
if (bev_ssl->ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT)
return -1;
//SSL_set_connect_state(bev_ssl->ssl);
if (set_handshake_callbacks(bev_ssl, fd) < 0)
return -1;
break;
@ -1256,10 +1181,6 @@ bufferevent_mbedtls_new_impl(struct event_base *base,
&bufferevent_ops_mbedtls, tmp_options) < 0)
goto err;
/* Don't explode if we decide to realloc a chunk we're writing from in
* the output buffer. */
//SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
bev_ssl->underlying = underlying;
bev_ssl->ssl = ssl;
@ -1277,8 +1198,6 @@ bufferevent_mbedtls_new_impl(struct event_base *base,
bev_ssl->old_state = state;
bev_ssl->last_write = -1;
//init_bio_counts(bev_ssl);
fd = be_mbedtls_auto_fd(bev_ssl, fd);
if (be_mbedtls_set_fd(bev_ssl, state, fd))
goto err;
@ -1340,10 +1259,6 @@ bufferevent_mbedtls_socket_new(struct event_base *base,
return bufferevent_mbedtls_new_impl(
base, NULL, fd, ssl, state, options);
err:
if (options & BEV_OPT_CLOSE_ON_FREE)
mbedtls_ssl_free(ssl);
return NULL;
}
int

View File

@ -124,7 +124,7 @@ endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(mbedTLS
find_package_handle_standard_args(MbedTLS
FOUND_VAR MBEDTLS_FOUND
REQUIRED_VARS
MBEDTLS_INCLUDE_DIR

View File

@ -60,6 +60,9 @@ AC_ARG_ENABLE(malloc-replacement,
AC_ARG_ENABLE(openssl,
AS_HELP_STRING(--disable-openssl, disable support for openssl encryption),
[], [enable_openssl=yes])
AC_ARG_ENABLE(mbedtls,
AS_HELP_STRING(--disable-mbedtls, disable support for mbedtls encryption),
[], [enable_mbedtls=yes])
AC_ARG_ENABLE(debug-mode,
AS_HELP_STRING(--disable-debug-mode, disable support for running in debug mode),
[], [enable_debug_mode=yes])
@ -179,6 +182,7 @@ AC_SUBST(OPENSSL_LIBADD)
AC_SYS_LARGEFILE
LIBEVENT_OPENSSL
LIBEVENT_MBEDTLS
dnl Checks for header files.
AC_CHECK_HEADERS([ \
@ -804,7 +808,7 @@ if test x$enable_debug_mode = xno; then
[Define if libevent should build without support for a debug mode])
fi
dnl check if we should enable verbose debugging
dnl check if we should enable verbose debugging
if test x$enable_verbose_debug = xyes; then
CFLAGS="$CFLAGS -DUSE_DEBUG"
fi
@ -812,6 +816,9 @@ fi
dnl check if we have and should use OpenSSL
AM_CONDITIONAL(OPENSSL, [test "$enable_openssl" != "no" && test "$have_openssl" = "yes"])
# check if we have and should use mbedtls
AM_CONDITIONAL(MBEDTLS, [test "$enable_mbedtls" != "no" && test "$have_mbedtls" = "yes"])
dnl enable some warnings by default
AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"],[],[-Werror])
@ -961,5 +968,5 @@ DX_INIT_DOXYGEN([libevent], [${top_srcdir}/Doxyfile], [doxygen])
AM_CONDITIONAL([ENABLE_DOXYGEN], [test "$DX_FLAG_doc" = "1"])
AM_CONDITIONAL([ENABLE_DOXYGEN_MAN], [test "$DX_FLAG_man" = "1"])
AC_CONFIG_FILES( [libevent.pc libevent_openssl.pc libevent_pthreads.pc libevent_core.pc libevent_extra.pc] )
AC_CONFIG_FILES( [libevent.pc libevent_mbedtls.pc libevent_openssl.pc libevent_pthreads.pc libevent_core.pc libevent_extra.pc] )
AC_OUTPUT(Makefile)

View File

@ -214,6 +214,9 @@
/* Define if the system has openssl */
#cmakedefine EVENT__HAVE_OPENSSL 1
/* Define if the system has mbedtls */
#cmakedefine EVENT__HAVE_MBEDTLS 1
/* Define to 1 if you have the `pipe' function. */
#cmakedefine EVENT__HAVE_PIPE 1

View File

@ -194,7 +194,7 @@ bufferevent_mbedtls_get_ssl(struct bufferevent *bufev);
/** Tells a bufferevent to begin SSL renegotiation. */
EVENT2_EXPORT_SYMBOL
int bufferevent_ssl_renegotiate(struct bufferevent *bev);
int bufferevent_mbedtls_renegotiate(struct bufferevent *bev);
/** Return the most recent OpenSSL error reported on an SSL bufferevent. */
EVENT2_EXPORT_SYMBOL

View File

@ -33,7 +33,8 @@
defined(event_extra_shared_EXPORTS) || \
defined(event_core_shared_EXPORTS) || \
defined(event_pthreads_shared_EXPORTS) || \
defined(event_openssl_shared_EXPORTS)
defined(event_openssl_shared_EXPORTS) || \
defined(event_mbedtls_shared_EXPORTS)
# if defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
# define EVENT2_EXPORT_SYMBOL __global

View File

@ -11,18 +11,15 @@ case "$enable_mbedtls" in
save_LIBS="$LIBS"
LIBS=""
MBEDTLS_LIBS=""
for lib in mbedtls ; do
# clear cache
unset ac_cv_search_mbedtls_ssl_init
AC_SEARCH_LIBS([mbedtls_ssl_init], [mbedtls ],
[have_mbedtls=yes
MBEDTLS_LIBS="$LIBS -l$lib -lmbedcrypto -lmbedx509 $EV_LIB_GDI $EV_LIB_WS32 $MBEDTLS_LIBADD"],
[have_mbedtls=no],
[-l$lib $EV_LIB_GDI $EV_LIB_WS32 $MBEDTLS_LIBADD])
LIBS="$save_LIBS"
test "$have_mbedtls" = "yes" && break
done
;;
# clear cache
unset ac_cv_search_mbedtls_ssl_init
AC_SEARCH_LIBS([mbedtls_ssl_init], [mbedtls],
[have_mbedtls=yes
MBEDTLS_LIBS="$LIBS -lmbedtls -lmbedcrypto -lmbedx509 $EV_LIB_GDI $EV_LIB_WS32"],
[have_mbedtls=no],
[-lmbedtls -lmbedcrypto -lmbedx509 $EV_LIB_GDI $EV_LIB_WS32])
LIBS="$save_LIBS"
test "$have_mbedtls" = "yes" && break
esac
CPPFLAGS_SAVE=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $MBEDTLS_INCS"

View File

@ -40,6 +40,13 @@ noinst_HEADERS += \
sample/openssl_hostname_validation.h
endif
if MBEDTLS
SAMPLES += sample/ssl-client-mbedtls
sample_ssl_client_mbedtls_SOURCES = sample/ssl-client-mbedtls.c
sample_ssl_client_mbedtls_LDADD = libevent.la libevent_mbedtls.la $(MBEDTLS_LIBS) $(MBEDTLS_LIBADD)
sample_ssl_client_mbedtls_CPPFLAGS = $(AM_CPPFLAGS) $(MBEDTLS_INCS)
endif
if BUILD_SAMPLES
noinst_PROGRAMS += $(SAMPLES)
endif

264
sample/ssl-client-mbedtls.c Normal file
View File

@ -0,0 +1,264 @@
/*
* SSL client demonstration program
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#include "mbedtls/config.h"
#include "mbedtls/platform.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "mbedtls/certs.h"
#include <string.h>
#include <event2/event.h>
#include <event2/dns.h>
#include <event2/bufferevent.h>
#include <event2/bufferevent_ssl.h>
#include <event2/util.h>
#define SERVER_PORT "443"
#define SERVER_NAME "amazon.com"
#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
#define DEBUG_LEVEL 1
static void
my_debug(void *ctx, int level, const char *file, int line, const char *str)
{
((void)level);
mbedtls_fprintf((FILE *)ctx, "%s:%04d: %s", file, line, str);
fflush((FILE *)ctx);
}
static void
writecb(struct bufferevent *bev, void *arg)
{
fprintf(stderr, "writecb\n");
}
static void
readcb(struct bufferevent *bev, void *arg)
{
char buf[1000];
size_t r = 0;
int i;
for (i = 0; i < 10; ++i) {
r = bufferevent_read(bev, buf, 800);
fprintf(stderr, "readcb %zu\n\n", r);
if (r > 1) {
fwrite(buf, 1, r, stdout);
fwrite("\n", 1, r, stdout);
fflush(stdout);
}
}
}
static void
eventcb(struct bufferevent *bev, short what, void *arg)
{
fprintf(stderr, "\n---------------eventcb %d\n", what);
if (what & BEV_EVENT_CONNECTED) {
const char headers[] = "GET / HTTP/1.1\r\n"
"HOST: " SERVER_NAME "\r\n"
"User-Agent: curl/7.65.1\r\n"
"Connection: Keep-Alive\r\n"
"\r\n";
bufferevent_write(
bev, headers, sizeof(headers) - 1); // without ending '\0'
// bufferevent_disable(bev, EV_WRITE);
fprintf(stderr, "write request completely\n");
} else if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
fprintf(stderr, "closed\n");
bufferevent_free(bev);
}
}
int
main(void)
{
int ret;
mbedtls_net_context server_fd;
const char *pers = "ssl_client1";
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt cacert;
struct event_base *evbase;
struct evdns_base *evdns;
struct bufferevent *bev;
struct bufferevent *bevf;
#ifdef WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
#endif
#if defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold(DEBUG_LEVEL);
#endif
/*
* 0. Initialize the RNG and the session data
*/
mbedtls_net_init(&server_fd);
mbedtls_ssl_init(&ssl);
mbedtls_ssl_config_init(&conf);
mbedtls_x509_crt_init(&cacert);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_printf("\n . Seeding the random number generator...");
fflush(stdout);
mbedtls_entropy_init(&entropy);
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *)pers, strlen(pers))) != 0) {
mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret);
goto exit;
}
mbedtls_printf(" ok\n");
/*
* 0. Initialize certificates
*/
mbedtls_printf(" . Loading the CA root certificate ...");
fflush(stdout);
ret = mbedtls_x509_crt_parse(&cacert,
(const unsigned char *)mbedtls_test_cas_pem, mbedtls_test_cas_pem_len);
if (ret < 0) {
mbedtls_printf(
" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret);
goto exit;
}
mbedtls_printf(" ok (%d skipped)\n", ret);
/*
* 1. Start the connection
*/
mbedtls_printf(" . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT);
fflush(stdout);
if ((ret = mbedtls_net_connect(&server_fd, SERVER_NAME, SERVER_PORT,
MBEDTLS_NET_PROTO_TCP)) != 0) {
mbedtls_printf(" failed\n ! mbedtls_net_connect returned %d\n\n", ret);
goto exit;
}
mbedtls_printf(" ok\n");
/*
* 2. Setup stuff
*/
mbedtls_printf(" . Setting up the SSL/TLS structure...");
fflush(stdout);
if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
mbedtls_printf(
" failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
goto exit;
}
mbedtls_printf(" ok\n");
/* OPTIONAL is not optimal for security,
* but makes interop easier in this simplified example */
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE);
mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
mbedtls_printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret);
goto exit;
}
if ((ret = mbedtls_ssl_set_hostname(&ssl, SERVER_NAME)) != 0) {
mbedtls_printf(
" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
goto exit;
}
fflush(stdout);
event_enable_debug_mode();
evbase = event_base_new();
evdns = evdns_base_new(evbase, 1);
evdns_base_set_option(evdns, "randomize-case:", "0");
evutil_make_socket_nonblocking(server_fd.fd);
bev = bufferevent_socket_new(evbase, server_fd.fd, BEV_OPT_CLOSE_ON_FREE);
bevf = bufferevent_mbedtls_filter_new(
evbase, bev, &ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE);
bev = bevf;
bufferevent_setcb(bev, readcb, writecb, eventcb, NULL);
bufferevent_enable(bev, EV_READ);
event_base_loop(evbase, 0);
event_base_free(evbase);
exit:
#ifdef MBEDTLS_ERROR_C
if (ret != 0) {
char error_buf[100];
mbedtls_strerror(ret, error_buf, 100);
mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf);
}
#endif
mbedtls_net_free(&server_fd);
mbedtls_x509_crt_free(&cacert);
mbedtls_ssl_free(&ssl);
mbedtls_ssl_config_free(&conf);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
#if defined(_WIN32)
mbedtls_printf(" + Press Enter to exit this program.\n");
fflush(stdout);
getchar();
#endif
return (ret);
}

View File

@ -1,315 +0,0 @@
/*
* SSL client demonstration program
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_time time
#define mbedtls_time_t time_t
#define mbedtls_fprintf fprintf
#define mbedtls_printf printf
#endif
#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \
!defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
!defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_CERTS_C) || !defined(MBEDTLS_PEM_PARSE_C) || \
!defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_X509_CRT_PARSE_C)
int main( void )
{
mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
"MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
"MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
"MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C "
"not defined.\n");
return( 0 );
}
#else
#include "mbedtls/net_sockets.h"
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "mbedtls/certs.h"
#include <string.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/bufferevent_ssl.h>
#include <event2/util.h>
#define SERVER_PORT "443"
#define SERVER_NAME "amazon.com"
#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
#define DEBUG_LEVEL 1
static void my_debug( void *ctx, int level,
const char *file, int line,
const char *str )
{
((void) level);
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
fflush( (FILE *) ctx );
}
void writecb(struct bufferevent *bev, void *arg)
{
fprintf(stderr, "writecb\n");
}
void readcb(struct bufferevent *bev, void *arg)
{
char buf[1000] = {};
size_t r = 0;
int i;
for (i=0; i<10; ++i)
{
r = bufferevent_read(bev, buf, 800);
fprintf(stderr, "readcb %d\n\n", r);
if (r > 1) {
fwrite(buf, 1, r, stdout);
fwrite("\n", 1, r, stdout);
fflush(stdout);
}
}
}
void eventcb(struct bufferevent *bev, short what, void *arg)
{
fprintf(stderr, "\n---------------eventcb %d\n", what);
if (what & BEV_EVENT_CONNECTED) {
const char headers[] =
"GET / HTTP/1.1\r\n"
"HOST: " SERVER_NAME "\r\n"
"User-Agent: curl/7.65.1\r\n"
"Connection: Keep-Alive\r\n"
"\r\n";
bufferevent_write(bev, headers, sizeof(headers) - 1); // without ending '\0'
//bufferevent_disable(bev, EV_WRITE);
fprintf(stderr, "write request completely\n");
} else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
fprintf(stderr, "closed\n");
bufferevent_free(bev);
}
}
int main( void )
{
int ret, len;
mbedtls_net_context server_fd;
uint32_t flags;
unsigned char buf[1024];
const char *pers = "ssl_client1";
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt cacert;
struct event *ev_sigterm;
struct event_base *evbase;
struct evdns_base *evdns;
#ifdef WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
#endif
#if defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold( DEBUG_LEVEL );
#endif
/*
* 0. Initialize the RNG and the session data
*/
mbedtls_net_init( &server_fd );
mbedtls_ssl_init( &ssl );
mbedtls_ssl_config_init( &conf );
mbedtls_x509_crt_init( &cacert );
mbedtls_ctr_drbg_init( &ctr_drbg );
mbedtls_printf( "\n . Seeding the random number generator..." );
fflush( stdout );
mbedtls_entropy_init( &entropy );
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers,
strlen( pers ) ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 0. Initialize certificates
*/
mbedtls_printf( " . Loading the CA root certificate ..." );
fflush( stdout );
ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem,
mbedtls_test_cas_pem_len );
if( ret < 0 )
{
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
goto exit;
}
mbedtls_printf( " ok (%d skipped)\n", ret );
/*
* 1. Start the connection
*/
mbedtls_printf( " . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT );
fflush( stdout );
if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME,
SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 2. Setup stuff
*/
mbedtls_printf( " . Setting up the SSL/TLS structure..." );
fflush( stdout );
if( ( ret = mbedtls_ssl_config_defaults( &conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/* OPTIONAL is not optimal for security,
* but makes interop easier in this simplified example */
mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_NONE );
mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret );
goto exit;
}
if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret );
goto exit;
}
fflush( stdout );
//mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
event_enable_debug_mode();
evbase = event_base_new();
evdns = evdns_base_new(evbase, 1);
evdns_base_set_option(evdns, "randomize-case:", "0");
evutil_make_socket_nonblocking(server_fd.fd);
#if 1
struct bufferevent *bev = bufferevent_socket_new(evbase, server_fd.fd, BEV_OPT_CLOSE_ON_FREE);
struct bufferevent *bevf = bufferevent_mbedtls_filter_new(
evbase, bev, &ssl,
BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE);
bev = bevf;
#else
struct bufferevent *bev = bufferevent_mbedtls_socket_new(
evbase, server_fd.fd, &ssl,
BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE);
#endif
bufferevent_setcb(bev, readcb, NULL, eventcb, NULL);
bufferevent_enable(bev, EV_READ);
event_base_loop(evbase, 0);
event_base_free(evbase);
exit:
#ifdef MBEDTLS_ERROR_C
if( ret != 0 )
{
char error_buf[100];
mbedtls_strerror( ret, error_buf, 100 );
mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf );
}
#endif
mbedtls_net_free( &server_fd );
mbedtls_x509_crt_free( &cacert );
mbedtls_ssl_free( &ssl );
mbedtls_ssl_config_free( &conf );
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
#if defined(_WIN32)
mbedtls_printf( " + Press Enter to exit this program.\n" );
fflush( stdout ); getchar();
#endif
return( ret );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
MBEDTLS_CERTS_C && MBEDTLS_PEM_PARSE_C && MBEDTLS_CTR_DRBG_C &&
MBEDTLS_X509_CRT_PARSE_C */

View File

@ -9,6 +9,9 @@
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <event2/bufferevent_ssl.h>
#elif defined(EVENT_EXPORT_TEST_COMPONENT_MBEDTLS)
#include <mbedtls/ssl.h>
#include <event2/bufferevent_ssl.h>
#endif
#if defined(EVENT_EXPORT_TEST_COMPONENT_EXTRA)
@ -90,6 +93,54 @@ error:
SSL_free(ssl);
return r;
}
#elif defined(EVENT_EXPORT_TEST_COMPONENT_MBEDTLS)
static int
test()
{
struct event_base *base = NULL;
mbedtls_ssl_config *conf = NULL;
mbedtls_ssl_context *ssl = NULL;
struct bufferevent *bev;
int r = 1;
base = event_base_new();
if (!base) {
goto error;
}
conf = malloc(sizeof(*conf));
if (!conf) {
goto error;
}
mbedtls_ssl_config_init(conf);
ssl = malloc(sizeof(*ssl));
if (!ssl) {
goto error;
}
mbedtls_ssl_init(ssl);
mbedtls_ssl_setup(ssl, conf);
bev = bufferevent_mbedtls_socket_new(base, -1, ssl,
BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
if (bev == NULL) {
goto error;
}
r = 0;
error:
if (base)
event_base_free(base);
if (ssl) {
mbedtls_ssl_free(ssl);
free(ssl);
}
if (conf) {
mbedtls_ssl_config_free(conf);
free(conf);
}
return r;
}
#else
static int
test()

View File

@ -88,13 +88,18 @@ def test_group():
testcase("core", "core", 0)
testcase("extra", "extra", 0)
testcase("openssl", "openssl", 0)
testcase("mbedtls", "mbedtls", 0)
testcase("", "", 0)
testcase("extra", "core", 0)
testcase("openssl", "core", 0)
testcase("mbedtls", "core", 0)
testcase("core", "extra", 1)
testcase("core", "openssl", 1)
testcase("extra", "openssl", 1)
testcase("openssl", "extra", 1)
testcase("core", "mbedtls", 1)
testcase("extra", "mbedtls", 1)
testcase("mbedtls", "extra", 1)
if platform.system() != "Windows":
testcase("pthreads", "pthreads", 0)
testcase("pthreads", "core", 0)
@ -103,6 +108,8 @@ def test_group():
testcase("pthreads", "extra", 1)
testcase("pthreads", "openssl", 1)
testcase("openssl", "pthreads", 1)
testcase("pthreads", "mbedtls", 1)
testcase("mbedtls", "pthreads", 1)
def config_restore():

View File

@ -149,11 +149,17 @@ test_regress_CPPFLAGS = $(AM_CPPFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS) -Itest
test_regress_LDFLAGS = $(PTHREAD_CFLAGS)
if OPENSSL
test_regress_SOURCES += test/regress_ssl.c
test_regress_SOURCES += test/regress_openssl.c
test_regress_CPPFLAGS += $(OPENSSL_INCS)
test_regress_LDADD += libevent_openssl.la $(OPENSSL_LIBS) ${OPENSSL_LIBADD}
endif
if MBEDTLS
test_regress_SOURCES += test/regress_mbedtls.c
test_regress_CPPFLAGS += $(MBEDTLS_INCS)
test_regress_LDADD += libevent_mbedtls.la $(MBEDTLS_LIBS)
endif
test_bench_SOURCES = test/bench.c
test_bench_LDADD = $(LIBEVENT_GC_SECTIONS) libevent.la
test_bench_cascade_SOURCES = test/bench_cascade.c

View File

@ -50,6 +50,7 @@ extern struct testcase_t edgetriggered_testcases[];
extern struct testcase_t minheap_testcases[];
extern struct testcase_t iocp_testcases[];
extern struct testcase_t ssl_testcases[];
extern struct testcase_t mbedtls_testcases[];
extern struct testcase_t listener_testcases[];
extern struct testcase_t listener_iocp_testcases[];
extern struct testcase_t thread_testcases[];

View File

@ -452,6 +452,9 @@ struct testgroup_t testgroups[] = {
#endif
#ifdef EVENT__HAVE_OPENSSL
{ "ssl/", ssl_testcases },
#endif
#ifdef EVENT__HAVE_MBEDTLS
{ "mbedtls/", mbedtls_testcases },
#endif
END_OF_GROUPS
};

335
test/regress_mbedtls.c Normal file
View File

@ -0,0 +1,335 @@
/*
* Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** For event_debug() usage/coverage */
#define EVENT_VISIBILITY_WANT_DLLIMPORT
#include "event2/util.h"
#include <mbedtls/ssl.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/debug.h>
#include "regress.h"
#include "tinytest.h"
#define TESTCASES_NAME mbedtls_testcases
#ifdef OPENSSL_VERSION_NUMBER
#undef OPENSSL_VERSION_NUMBER
#endif
#define OPENSSL_VERSION_NUMBER 0
#define SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT
#define SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER
#define get_ssl_ctx get_mbedtls_config
#define SSL_renegotiate mbedtls_ssl_renegotiate
#define SSL_get_peer_certificate mbedtls_ssl_get_peer_cert
#define SSL_new mbedtls_ssl_new
#define SSL_use_certificate(a, b) \
do { \
} while (0);
#define SSL_use_PrivateKey(a, b) \
do { \
} while (0);
#define X509_free(x) \
do { \
} while (0);
#define X509 const mbedtls_x509_crt
#define SSL mbedtls_ssl_context
#define bufferevent_ssl_get_ssl bufferevent_mbedtls_get_ssl
#define bufferevent_ssl_set_allow_dirty_shutdown \
bufferevent_mbedtls_set_allow_dirty_shutdown
#define bufferevent_ssl_socket_new bufferevent_mbedtls_socket_new
#define bufferevent_ssl_filter_new bufferevent_mbedtls_filter_new
struct rwcount;
static void BIO_setup(SSL *ssl, struct rwcount *rw);
static mbedtls_ssl_config *get_mbedtls_config(int endpoint);
static mbedtls_ssl_context *mbedtls_ssl_new(mbedtls_ssl_config *config);
static void *mbedtls_test_setup(const struct testcase_t *testcase);
static int mbedtls_test_cleanup(const struct testcase_t *testcase, void *ptr);
static const struct testcase_setup_t ssl_setup = {
mbedtls_test_setup, mbedtls_test_cleanup};
#include "regress_ssl.c"
static mbedtls_ssl_config *the_mbedtls_conf[2] = {NULL, NULL};
static mbedtls_ssl_context *the_mbedtls_ctx[1024] = {NULL};
static int the_mbedtls_ctx_count = 0;
static mbedtls_entropy_context entropy;
static mbedtls_ctr_drbg_context ctr_drbg;
static mbedtls_x509_crt *the_cert;
static mbedtls_pk_context *the_key;
static void
mbedtls_debug(
void *userdata, int level, const char *file, int line, const char *str)
{
int loglen = strlen(str);
if (str[loglen - 1] == '\n')
loglen--;
event_debug(("[mbedtls][%s][%d][%s][%d]%.*s", (char *)userdata, level, file,
line, loglen, str));
}
static mbedtls_pk_context *
mbedtls_getkey(void)
{
int ret = 0;
mbedtls_pk_context *pk = malloc(sizeof(mbedtls_pk_context));
tt_assert(pk);
mbedtls_pk_init(pk);
ret = mbedtls_pk_parse_key(
pk, (const unsigned char *)KEY, sizeof(KEY), NULL, 0);
tt_assert(ret == 0);
return pk;
end:
if (pk) {
mbedtls_pk_free(pk);
free(pk);
}
return NULL;
}
static void
create_tm_from_unix_epoch(struct tm *cur_p, const time_t t)
{
#ifdef _WIN32
struct tm *tmp = gmtime(&t);
if (!tmp) {
fprintf(stderr, "gmtime: %s (%i)", strerror(errno), (int)t);
exit(1);
}
*cur_p = *tmp;
#else
gmtime_r(&t, cur_p);
#endif
}
static mbedtls_x509_crt *
mbedtls_getcert(mbedtls_pk_context *pk)
{
const char *name = "commonName=example.com";
time_t now = time(NULL);
char now_string[32] = "";
char not_before[32] = "";
char not_after[32] = "";
unsigned char certbuf[8192];
struct tm tm;
mbedtls_x509_crt *crt = NULL;
int ret = 0;
mbedtls_mpi serial;
mbedtls_x509write_cert write_cert;
snprintf(now_string, sizeof(now_string), "%lld", (long long)now);
create_tm_from_unix_epoch(&tm, now);
strftime(not_before, sizeof(not_before), "%Y%m%d%H%M%S", &tm);
now += 3600;
create_tm_from_unix_epoch(&tm, now);
strftime(not_after, sizeof(not_after), "%Y%m%d%H%M%S", &tm);
mbedtls_x509write_crt_init(&write_cert);
mbedtls_x509write_crt_set_version(&write_cert, 2);
mbedtls_mpi_init(&serial);
ret = mbedtls_mpi_read_string(&serial, 10, now_string);
tt_assert(ret == 0);
ret = mbedtls_x509write_crt_set_serial(&write_cert, &serial);
tt_assert(ret == 0);
mbedtls_mpi_free(&serial);
ret = mbedtls_x509write_crt_set_subject_name(&write_cert, name);
tt_assert(ret == 0);
ret = mbedtls_x509write_crt_set_issuer_name(&write_cert, name);
tt_assert(ret == 0);
mbedtls_x509write_crt_set_md_alg(&write_cert, MBEDTLS_MD_SHA256);
ret =
mbedtls_x509write_crt_set_validity(&write_cert, not_before, not_after);
tt_assert(ret == 0);
mbedtls_x509write_crt_set_issuer_key(&write_cert, pk);
mbedtls_x509write_crt_set_subject_key(&write_cert, pk);
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *)name, strlen(name));
tt_assert(ret == 0);
ret = mbedtls_x509write_crt_pem(&write_cert, certbuf, sizeof(certbuf),
mbedtls_ctr_drbg_random, &ctr_drbg);
tt_assert(ret == 0);
mbedtls_x509write_crt_free(&write_cert);
crt = malloc(sizeof(mbedtls_x509_crt));
tt_assert(crt);
mbedtls_x509_crt_init(crt);
ret = mbedtls_x509_crt_parse(crt, certbuf, strlen((char *)certbuf) + 1);
tt_assert(ret == 0);
return crt;
end:
if (crt) {
mbedtls_x509_crt_free(crt);
free(crt);
}
return NULL;
}
static mbedtls_ssl_config *
get_mbedtls_config(int endpoint)
{
if (the_mbedtls_conf[endpoint])
return the_mbedtls_conf[endpoint];
the_mbedtls_conf[endpoint] = malloc(sizeof(mbedtls_ssl_config));
if (!the_mbedtls_conf[endpoint])
return NULL;
mbedtls_ssl_config_init(the_mbedtls_conf[endpoint]);
mbedtls_ssl_conf_renegotiation(
the_mbedtls_conf[endpoint], MBEDTLS_SSL_RENEGOTIATION_ENABLED);
mbedtls_ssl_conf_dbg(the_mbedtls_conf[endpoint], mbedtls_debug,
(void *)(endpoint == MBEDTLS_SSL_IS_SERVER ? "server" : "client"));
mbedtls_ssl_config_defaults(the_mbedtls_conf[endpoint], endpoint,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
mbedtls_ssl_conf_rng(
the_mbedtls_conf[endpoint], mbedtls_ctr_drbg_random, &ctr_drbg);
if (disable_tls_11_and_12) {
mbedtls_ssl_conf_max_version(the_mbedtls_conf[endpoint],
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1);
}
if (endpoint == MBEDTLS_SSL_IS_SERVER) {
mbedtls_ssl_conf_own_cert(
the_mbedtls_conf[endpoint], the_cert, the_key);
} else { /* MBEDTLS_SSL_IS_CLIENT */
mbedtls_ssl_conf_ca_chain(the_mbedtls_conf[endpoint], the_cert, NULL);
}
return the_mbedtls_conf[endpoint];
}
static void
init_mbedtls(void)
{
mbedtls_debug_set_threshold(5);
}
static void *
mbedtls_test_setup(const struct testcase_t *testcase)
{
init_mbedtls();
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *)"libevent", sizeof("libevent"));
the_key = mbedtls_getkey();
EVUTIL_ASSERT(the_key);
the_cert = mbedtls_getcert(the_key);
EVUTIL_ASSERT(the_cert);
disable_tls_11_and_12 = 0;
return basic_test_setup(testcase);
}
static int
mbedtls_test_cleanup(const struct testcase_t *testcase, void *ptr)
{
int i;
int ret = basic_test_cleanup(testcase, ptr);
if (!ret) {
return ret;
}
test_is_done = 0;
n_connected = 0;
got_close = 0;
got_error = 0;
got_timeout = 0;
renegotiate_at = -1;
stop_when_connected = 0;
pending_connect_events = 0;
exit_base = NULL;
mbedtls_x509_crt_free(the_cert);
free(the_cert);
mbedtls_pk_free(the_key);
free(the_key);
for (i = 0; i < the_mbedtls_ctx_count; i++) {
mbedtls_ssl_free(the_mbedtls_ctx[i]);
}
if (the_mbedtls_conf[0]) {
mbedtls_ssl_config_free(the_mbedtls_conf[0]);
free(the_mbedtls_conf[0]);
the_mbedtls_conf[0] = NULL;
}
if (the_mbedtls_conf[1]) {
mbedtls_ssl_config_free(the_mbedtls_conf[1]);
free(the_mbedtls_conf[1]);
the_mbedtls_conf[1] = NULL;
}
return 1;
}
static mbedtls_ssl_context *
mbedtls_ssl_new(mbedtls_ssl_config *config)
{
mbedtls_ssl_context *ssl = malloc(sizeof(*ssl));
mbedtls_ssl_init(ssl);
mbedtls_ssl_setup(ssl, config);
the_mbedtls_ctx[the_mbedtls_ctx_count++] = ssl;
return ssl;
}
static int
bio_rwcount_read(void *ctx, unsigned char *out, size_t outlen)
{
struct rwcount *rw = ctx;
ev_ssize_t ret = recv(rw->fd, out, outlen, 0);
++rw->read;
if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
return ret;
}
static int
bio_rwcount_write(void *ctx, const unsigned char *in, size_t inlen)
{
struct rwcount *rw = ctx;
ev_ssize_t ret = send(rw->fd, in, inlen, 0);
++rw->write;
if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
return MBEDTLS_ERR_SSL_WANT_WRITE;
}
return ret;
}
static void
BIO_setup(SSL *ssl, struct rwcount *rw)
{
mbedtls_ssl_set_bio(ssl, rw, bio_rwcount_write, bio_rwcount_read,
NULL);
}

311
test/regress_openssl.c Normal file
View File

@ -0,0 +1,311 @@
/*
* Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "event2/util.h"
#include <openssl/err.h>
#include <openssl/pem.h>
#include "openssl-compat.h"
#include "regress.h"
#include "tinytest.h"
#define TESTCASES_NAME ssl_testcases
static void *ssl_test_setup(const struct testcase_t *testcase);
static int ssl_test_cleanup(const struct testcase_t *testcase, void *ptr);
static const struct testcase_setup_t ssl_setup = {
ssl_test_setup, ssl_test_cleanup};
static X509 *the_cert;
EVP_PKEY *the_key;
#define SSL_IS_CLIENT
#define SSL_IS_SERVER
#define bufferevent_ssl_get_ssl bufferevent_openssl_get_ssl
#define bufferevent_ssl_set_allow_dirty_shutdown \
bufferevent_openssl_set_allow_dirty_shutdown
#define bufferevent_ssl_socket_new bufferevent_openssl_socket_new
#define bufferevent_ssl_filter_new bufferevent_openssl_filter_new
struct rwcount;
static void BIO_setup(SSL *ssl, struct rwcount *rw);
#include "regress_ssl.c"
EVP_PKEY *
ssl_getkey(void)
{
EVP_PKEY *key;
BIO *bio;
/* new read-only BIO backed by KEY. */
bio = BIO_new_mem_buf((char *)KEY, -1);
tt_assert(bio);
key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
BIO_free(bio);
tt_assert(key);
return key;
end:
return NULL;
}
X509 *
ssl_getcert(EVP_PKEY *key)
{
/* Dummy code to make a quick-and-dirty valid certificate with
OpenSSL. Don't copy this code into your own program! It does a
number of things in a stupid and insecure way. */
X509 *x509 = NULL;
X509_NAME *name = NULL;
int nid;
time_t now = time(NULL);
tt_assert(key);
x509 = X509_new();
tt_assert(x509);
tt_assert(0 != X509_set_version(x509, 2));
tt_assert(0 != ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)now));
name = X509_NAME_new();
tt_assert(name);
nid = OBJ_txt2nid("commonName");
tt_assert(NID_undef != nid);
tt_assert(0 != X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
(unsigned char *)"example.com", -1, -1, 0));
X509_set_subject_name(x509, name);
X509_set_issuer_name(x509, name);
X509_NAME_free(name);
X509_time_adj(X509_getm_notBefore(x509), 0, &now);
now += 3600;
X509_time_adj(X509_getm_notAfter(x509), 0, &now);
X509_set_pubkey(x509, key);
tt_assert(0 != X509_sign(x509, key, EVP_sha1()));
return x509;
end:
X509_free(x509);
X509_NAME_free(name);
return NULL;
}
static SSL_CTX *the_ssl_ctx = NULL;
SSL_CTX *
get_ssl_ctx(void)
{
if (the_ssl_ctx)
return the_ssl_ctx;
the_ssl_ctx = SSL_CTX_new(SSLv23_method());
if (!the_ssl_ctx)
return NULL;
if (disable_tls_11_and_12) {
#ifdef SSL_OP_NO_TLSv1_2
SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_2);
#endif
#ifdef SSL_OP_NO_TLSv1_1
SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_1);
#endif
}
return the_ssl_ctx;
}
void
init_ssl(void)
{
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && \
LIBRESSL_VERSION_NUMBER < 0x20700000L)
SSL_library_init();
ERR_load_crypto_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
if (SSLeay() != OPENSSL_VERSION_NUMBER) {
TT_DECLARE("WARN", ("Version mismatch for openssl: compiled with %lx "
"but running with %lx",
(unsigned long)OPENSSL_VERSION_NUMBER,
(unsigned long)SSLeay()));
}
#endif
}
static void *
ssl_test_setup(const struct testcase_t *testcase)
{
init_ssl();
the_key = ssl_getkey();
EVUTIL_ASSERT(the_key);
the_cert = ssl_getcert(the_key);
EVUTIL_ASSERT(the_cert);
disable_tls_11_and_12 = 0;
return basic_test_setup(testcase);
}
static int
ssl_test_cleanup(const struct testcase_t *testcase, void *ptr)
{
int ret = basic_test_cleanup(testcase, ptr);
if (!ret) {
return ret;
}
test_is_done = 0;
n_connected = 0;
got_close = 0;
got_error = 0;
got_timeout = 0;
renegotiate_at = -1;
stop_when_connected = 0;
pending_connect_events = 0;
exit_base = NULL;
X509_free(the_cert);
EVP_PKEY_free(the_key);
SSL_CTX_free(the_ssl_ctx);
the_ssl_ctx = NULL;
return 1;
}
static int
bio_rwcount_new(BIO *b)
{
BIO_set_init(b, 0);
BIO_set_data(b, NULL);
return 1;
}
static int
bio_rwcount_free(BIO *b)
{
TT_BLATHER(("bio_rwcount_free: %p", b));
if (!b)
return 0;
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 = 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())) {
BIO_set_retry_read(b);
}
return ret;
}
static int
bio_rwcount_write(BIO *b, const char *in, int inlen)
{
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())) {
BIO_set_retry_write(b);
}
return ret;
}
static long
bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr)
{
struct rwcount *rw = BIO_get_data(b);
long ret = 0;
switch (cmd) {
case BIO_C_GET_FD:
ret = rw->fd;
break;
case BIO_CTRL_GET_CLOSE:
ret = BIO_get_shutdown(b);
break;
case BIO_CTRL_SET_CLOSE:
BIO_set_shutdown(b, (int)num);
break;
case BIO_CTRL_PENDING:
ret = 0;
break;
case BIO_CTRL_WPENDING:
ret = 0;
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
ret = 1;
break;
}
return ret;
}
static int
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;
static BIO_METHOD *
BIO_s_rwcount(void)
{
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;
BIO_set_init(result, 1);
BIO_set_data(result, NULL);
BIO_set_shutdown(result, !!close_flag);
return result;
}
static void
BIO_setup(SSL *ssl, struct rwcount *rw)
{
BIO *bio;
bio = BIO_new_rwcount(0);
tt_assert(bio);
BIO_set_data(bio, rw);
SSL_set_bio(ssl, bio, bio);
end:
return;
}

View File

@ -42,21 +42,15 @@
#include <netinet/in.h>
#endif
#include "event2/util.h"
#include "event2/event.h"
#include "event2/bufferevent_ssl.h"
#include "event2/bufferevent_struct.h"
#include "event2/buffer.h"
#include "event2/listener.h"
#include "regress.h"
#include "tinytest.h"
#include "tinytest_macros.h"
#include <openssl/err.h>
#include <openssl/pem.h>
#include "openssl-compat.h"
#include <string.h>
#ifdef _WIN32
#include <io.h>
@ -98,91 +92,7 @@ static const char KEY[] =
"lhdEOj7mAgHwGwwVZWOgs9Lq6vfztnSuhqjha1daESY6kDscPIQ=\n"
"-----END RSA PRIVATE KEY-----\n";
EVP_PKEY *
ssl_getkey(void)
{
EVP_PKEY *key;
BIO *bio;
/* new read-only BIO backed by KEY. */
bio = BIO_new_mem_buf((char*)KEY, -1);
tt_assert(bio);
key = PEM_read_bio_PrivateKey(bio,NULL,NULL,NULL);
BIO_free(bio);
tt_assert(key);
return key;
end:
return NULL;
}
X509 *
ssl_getcert(EVP_PKEY *key)
{
/* Dummy code to make a quick-and-dirty valid certificate with
OpenSSL. Don't copy this code into your own program! It does a
number of things in a stupid and insecure way. */
X509 *x509 = NULL;
X509_NAME *name = NULL;
int nid;
time_t now = time(NULL);
tt_assert(key);
x509 = X509_new();
tt_assert(x509);
tt_assert(0 != X509_set_version(x509, 2));
tt_assert(0 != ASN1_INTEGER_set(X509_get_serialNumber(x509),
(long)now));
name = X509_NAME_new();
tt_assert(name);
nid = OBJ_txt2nid("commonName");
tt_assert(NID_undef != nid);
tt_assert(0 != X509_NAME_add_entry_by_NID(
name, nid, MBSTRING_ASC, (unsigned char*)"example.com",
-1, -1, 0));
X509_set_subject_name(x509, name);
X509_set_issuer_name(x509, name);
X509_NAME_free(name);
X509_time_adj(X509_getm_notBefore(x509), 0, &now);
now += 3600;
X509_time_adj(X509_getm_notAfter(x509), 0, &now);
X509_set_pubkey(x509, key);
tt_assert(0 != X509_sign(x509, key, EVP_sha1()));
return x509;
end:
X509_free(x509);
X509_NAME_free(name);
return NULL;
}
static int disable_tls_11_and_12 = 0;
static SSL_CTX *the_ssl_ctx = NULL;
SSL_CTX *
get_ssl_ctx(void)
{
if (the_ssl_ctx)
return the_ssl_ctx;
the_ssl_ctx = SSL_CTX_new(SSLv23_method());
if (!the_ssl_ctx)
return NULL;
if (disable_tls_11_and_12) {
#ifdef SSL_OP_NO_TLSv1_2
SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_2);
#endif
#ifdef SSL_OP_NO_TLSv1_1
SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_1);
#endif
}
return the_ssl_ctx;
}
static int test_is_done;
static int n_connected;
static int got_close;
@ -192,70 +102,6 @@ static int renegotiate_at = -1;
static int stop_when_connected;
static int pending_connect_events;
static struct event_base *exit_base;
static X509 *the_cert;
EVP_PKEY *the_key;
void
init_ssl(void)
{
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
SSL_library_init();
ERR_load_crypto_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
if (SSLeay() != OPENSSL_VERSION_NUMBER) {
TT_DECLARE("WARN",
("Version mismatch for openssl: compiled with %lx but running with %lx",
(unsigned long)OPENSSL_VERSION_NUMBER, (unsigned long)SSLeay()));
}
#endif
}
static void *
ssl_test_setup(const struct testcase_t *testcase)
{
init_ssl();
the_key = ssl_getkey();
EVUTIL_ASSERT(the_key);
the_cert = ssl_getcert(the_key);
EVUTIL_ASSERT(the_cert);
disable_tls_11_and_12 = 0;
return basic_test_setup(testcase);
}
static int
ssl_test_cleanup(const struct testcase_t *testcase, void *ptr)
{
int ret = basic_test_cleanup(testcase, ptr);
if (!ret) {
return ret;
}
test_is_done = 0;
n_connected = 0;
got_close = 0;
got_error = 0;
got_timeout = 0;
renegotiate_at = -1;
stop_when_connected = 0;
pending_connect_events = 0;
exit_base = NULL;
X509_free(the_cert);
EVP_PKEY_free(the_key);
SSL_CTX_free(the_ssl_ctx);
the_ssl_ctx = NULL;
return 1;
}
const struct testcase_setup_t ssl_setup = {
ssl_test_setup, ssl_test_cleanup
};
/* ====================
@ -285,7 +131,7 @@ enum regress_openssl_type
};
static void
bufferevent_openssl_check_fd(struct bufferevent *bev, int filter)
bufferevent_ssl_check_fd(struct bufferevent *bev, int filter)
{
tt_fd_op(bufferevent_getfd(bev), !=, EVUTIL_INVALID_SOCKET);
tt_fd_op(bufferevent_setfd(bev, EVUTIL_INVALID_SOCKET), ==, 0);
@ -299,7 +145,7 @@ end:
;
}
static void
bufferevent_openssl_check_freed(struct bufferevent *bev)
bufferevent_ssl_check_freed(struct bufferevent *bev)
{
tt_int_op(event_pending(&bev->ev_read, EVLIST_ALL, NULL), ==, 0);
tt_int_op(event_pending(&bev->ev_write, EVLIST_ALL, NULL), ==, 0);
@ -339,14 +185,15 @@ respond_to_number(struct bufferevent *bev, void *ctx)
return;
}
if ((type & REGRESS_OPENSSL_CLIENT) && n == renegotiate_at) {
SSL_renegotiate(bufferevent_openssl_get_ssl(bev));
SSL_renegotiate(bufferevent_ssl_get_ssl(bev));
}
++n;
evbuffer_add_printf(bufferevent_get_output(bev),
"%d\n", n);
TT_BLATHER(("Done reading; now writing."));
bufferevent_enable(bev, EV_WRITE);
bufferevent_disable(bev, EV_READ);
// we shouldn't disable EV_READ here, otherwise we wouldn't got close cb
// bufferevent_disable(bev, EV_READ);
}
static void
@ -372,7 +219,7 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
if (what & BEV_EVENT_CONNECTED) {
SSL *ssl;
++n_connected;
ssl = bufferevent_openssl_get_ssl(bev);
ssl = bufferevent_ssl_get_ssl(bev);
tt_assert(ssl);
peer_cert = SSL_get_peer_certificate(ssl);
if (type & REGRESS_OPENSSL_SERVER) {
@ -391,30 +238,30 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
TT_BLATHER(("Got a good EOF"));
++got_close;
if (type & REGRESS_OPENSSL_FD) {
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
bufferevent_ssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
}
if (type & REGRESS_OPENSSL_FREED) {
bufferevent_openssl_check_freed(bev);
bufferevent_ssl_check_freed(bev);
}
bufferevent_free(bev);
} else if (what & BEV_EVENT_ERROR) {
TT_BLATHER(("Got an error."));
++got_error;
if (type & REGRESS_OPENSSL_FD) {
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
bufferevent_ssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
}
if (type & REGRESS_OPENSSL_FREED) {
bufferevent_openssl_check_freed(bev);
bufferevent_ssl_check_freed(bev);
}
bufferevent_free(bev);
} else if (what & BEV_EVENT_TIMEOUT) {
TT_BLATHER(("Got timeout."));
++got_timeout;
if (type & REGRESS_OPENSSL_FD) {
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
bufferevent_ssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
}
if (type & REGRESS_OPENSSL_FREED) {
bufferevent_openssl_check_freed(bev);
bufferevent_ssl_check_freed(bev);
}
bufferevent_free(bev);
}
@ -434,14 +281,14 @@ open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
int state2 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_ACCEPTING;
int dirty_shutdown = type & REGRESS_OPENSSL_DIRTY_SHUTDOWN;
if (fd_pair) {
*bev1_out = bufferevent_openssl_socket_new(
*bev1_out = bufferevent_ssl_socket_new(
base, fd_pair[0], ssl1, state1, flags);
*bev2_out = bufferevent_openssl_socket_new(
*bev2_out = bufferevent_ssl_socket_new(
base, fd_pair[1], ssl2, state2, flags);
} else {
*bev1_out = bufferevent_openssl_filter_new(
*bev1_out = bufferevent_ssl_filter_new(
base, underlying_pair[0], ssl1, state1, flags);
*bev2_out = bufferevent_openssl_filter_new(
*bev2_out = bufferevent_ssl_filter_new(
base, underlying_pair[1], ssl2, state2, flags);
}
@ -450,8 +297,8 @@ open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
bufferevent_setcb(*bev2_out, respond_to_number, done_writing_cb,
eventcb, (void*)(REGRESS_OPENSSL_SERVER | (long)type));
bufferevent_openssl_set_allow_dirty_shutdown(*bev1_out, dirty_shutdown);
bufferevent_openssl_set_allow_dirty_shutdown(*bev2_out, dirty_shutdown);
bufferevent_ssl_set_allow_dirty_shutdown(*bev1_out, dirty_shutdown);
bufferevent_ssl_set_allow_dirty_shutdown(*bev2_out, dirty_shutdown);
}
static void
@ -478,8 +325,8 @@ regress_bufferevent_openssl(void *arg)
renegotiate_at = 600;
}
ssl1 = SSL_new(get_ssl_ctx());
ssl2 = SSL_new(get_ssl_ctx());
ssl1 = SSL_new(get_ssl_ctx(SSL_IS_CLIENT));
ssl2 = SSL_new(get_ssl_ctx(SSL_IS_SERVER));
SSL_use_certificate(ssl2, the_cert);
SSL_use_PrivateKey(ssl2, the_key);
@ -581,14 +428,14 @@ acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
struct basic_test_data *data = arg;
struct bufferevent *bev;
enum regress_openssl_type type;
SSL *ssl = SSL_new(get_ssl_ctx());
SSL *ssl = SSL_new(get_ssl_ctx(SSL_IS_SERVER));
type = (enum regress_openssl_type)data->setup_data;
SSL_use_certificate(ssl, the_cert);
SSL_use_PrivateKey(ssl, the_key);
bev = bufferevent_openssl_socket_new(
bev = bufferevent_ssl_socket_new(
data->base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
tt_assert(bev);
@ -618,110 +465,6 @@ struct rwcount
size_t read;
size_t write;
};
static int
bio_rwcount_new(BIO *b)
{
BIO_set_init(b, 0);
BIO_set_data(b, NULL);
return 1;
}
static int
bio_rwcount_free(BIO *b)
{
TT_BLATHER(("bio_rwcount_free: %p", b));
if (!b)
return 0;
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 = 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())) {
BIO_set_retry_read(b);
}
return ret;
}
static int
bio_rwcount_write(BIO *b, const char *in, int inlen)
{
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())) {
BIO_set_retry_write(b);
}
return ret;
}
static long
bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr)
{
struct rwcount *rw = BIO_get_data(b);
long ret = 0;
switch (cmd) {
case BIO_C_GET_FD:
ret = rw->fd;
break;
case BIO_CTRL_GET_CLOSE:
ret = BIO_get_shutdown(b);
break;
case BIO_CTRL_SET_CLOSE:
BIO_set_shutdown(b, (int)num);
break;
case BIO_CTRL_PENDING:
ret = 0;
break;
case BIO_CTRL_WPENDING:
ret = 0;
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
ret = 1;
break;
}
return ret;
}
static int
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;
static BIO_METHOD *
BIO_s_rwcount(void)
{
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;
BIO_set_init(result, 1);
BIO_set_data(result, NULL);
BIO_set_shutdown(result, !!close_flag);
return result;
}
static void
regress_bufferevent_openssl_connect(void *arg)
@ -755,10 +498,10 @@ regress_bufferevent_openssl_connect(void *arg)
tt_assert(listener);
tt_assert(evconnlistener_get_fd(listener) >= 0);
ssl = SSL_new(get_ssl_ctx());
ssl = SSL_new(get_ssl_ctx(SSL_IS_CLIENT));
tt_assert(ssl);
bev = bufferevent_openssl_socket_new(
bev = bufferevent_ssl_socket_new(
data->base, -1, ssl,
BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
@ -777,13 +520,8 @@ regress_bufferevent_openssl_connect(void *arg)
/* Possible only when we have fd, since be_openssl can and will overwrite
* bio otherwise before */
if (type & REGRESS_OPENSSL_SLEEP) {
BIO *bio;
rw.fd = bufferevent_getfd(bev);
bio = BIO_new_rwcount(0);
tt_assert(bio);
BIO_set_data(bio, &rw);
SSL_set_bio(ssl, bio, bio);
BIO_setup(ssl, &rw);
}
evbuffer_add_printf(bufferevent_get_output(bev), "1\n");
bufferevent_enable(bev, EV_READ|EV_WRITE);
@ -859,12 +597,12 @@ wm_acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
struct wm_context *ctx = arg;
struct bufferevent *bev;
struct event_base *base = evconnlistener_get_base(listener);
SSL *ssl = SSL_new(get_ssl_ctx());
SSL *ssl = SSL_new(get_ssl_ctx(SSL_IS_SERVER));
SSL_use_certificate(ssl, the_cert);
SSL_use_PrivateKey(ssl, the_key);
bev = bufferevent_openssl_socket_new(
bev = bufferevent_ssl_socket_new(
base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, ctx->flags);
TT_BLATHER(("wm_transfer-%s(%p): accept",
@ -940,16 +678,16 @@ regress_bufferevent_openssl_wm(void *arg)
tt_assert(listener);
tt_assert(evconnlistener_get_fd(listener) >= 0);
ssl = SSL_new(get_ssl_ctx());
ssl = SSL_new(get_ssl_ctx(SSL_IS_CLIENT));
tt_assert(ssl);
if (type & REGRESS_OPENSSL_FILTER) {
bev = bufferevent_socket_new(data->base, -1, client.flags);
tt_assert(bev);
bev = bufferevent_openssl_filter_new(
bev = bufferevent_ssl_filter_new(
base, bev, ssl, BUFFEREVENT_SSL_CONNECTING, client.flags);
} else {
bev = bufferevent_openssl_socket_new(
bev = bufferevent_ssl_socket_new(
data->base, -1, ssl,
BUFFEREVENT_SSL_CONNECTING,
client.flags);
@ -988,7 +726,7 @@ end:
event_base_loop(base, EVLOOP_ONCE);
}
struct testcase_t ssl_testcases[] = {
struct testcase_t TESTCASES_NAME[] = {
#define T(a) ((void *)(a))
{ "bufferevent_socketpair", regress_bufferevent_openssl,
TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
@ -1057,12 +795,10 @@ struct testcase_t ssl_testcases[] = {
{ "bufferevent_socketpair_timeout_freed_fd", regress_bufferevent_openssl,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
{ "bufferevent_connect", regress_bufferevent_openssl_connect,
TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
{ "bufferevent_connect_sleep", regress_bufferevent_openssl_connect,
TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_SLEEP) },
{ "bufferevent_wm", regress_bufferevent_openssl_wm,
TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
{ "bufferevent_wm_filter", regress_bufferevent_openssl_wm,