mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
fix build system and add test and cleanup code
This commit is contained in:
parent
8218777d44
commit
028385f685
@ -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()
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
11
configure.ac
11
configure.ac
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
264
sample/ssl-client-mbedtls.c
Normal 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);
|
||||
}
|
@ -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 */
|
@ -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()
|
||||
|
@ -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():
|
||||
|
@ -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
|
||||
|
@ -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[];
|
||||
|
@ -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
335
test/regress_mbedtls.c
Normal 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
311
test/regress_openssl.c
Normal 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;
|
||||
}
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user