mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-09 20:41:27 -04:00
Merge branch 'openssl-filter-fixes-v4'
* openssl-filter-fixes-v4: be: fix with filtered bufferevents and connect() without EAGAIN test/ssl: fix bufferevent_getfd() for bufferevent_openssl_filter_new() be_openssl: Fix writing into filted openssl bufferevent after connected test/https: separate cases for https client with filtered openssl bufferevent test/ssl: cover case when we writing to be_openssl after connecting Fixes: #428
This commit is contained in:
commit
83e0f43b03
@ -404,7 +404,10 @@ start_writing(struct bufferevent_openssl *bev_ssl)
|
|||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
if (bev_ssl->underlying) {
|
if (bev_ssl->underlying) {
|
||||||
;
|
if (bev_ssl->write_blocked_on_read) {
|
||||||
|
bufferevent_unsuspend_read_(bev_ssl->underlying,
|
||||||
|
BEV_SUSPEND_FILT_READ);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
struct bufferevent *bev = &bev_ssl->bev.bev;
|
struct bufferevent *bev = &bev_ssl->bev.bev;
|
||||||
r = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
|
r = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
|
||||||
@ -435,7 +438,8 @@ stop_writing(struct bufferevent_openssl *bev_ssl)
|
|||||||
if (bev_ssl->read_blocked_on_write)
|
if (bev_ssl->read_blocked_on_write)
|
||||||
return;
|
return;
|
||||||
if (bev_ssl->underlying) {
|
if (bev_ssl->underlying) {
|
||||||
;
|
bufferevent_unsuspend_read_(bev_ssl->underlying,
|
||||||
|
BEV_SUSPEND_FILT_READ);
|
||||||
} else {
|
} else {
|
||||||
struct bufferevent *bev = &bev_ssl->bev.bev;
|
struct bufferevent *bev = &bev_ssl->bev.bev;
|
||||||
event_del(&bev->ev_write);
|
event_del(&bev->ev_write);
|
||||||
@ -716,7 +720,7 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost)
|
|||||||
if (bev_ssl->underlying)
|
if (bev_ssl->underlying)
|
||||||
BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
|
BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
|
||||||
|
|
||||||
bufferevent_trigger_nolock_(bev, EV_WRITE, 0);
|
bufferevent_trigger_nolock_(bev, EV_WRITE, BEV_OPT_DEFER_CALLBACKS);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1040,17 +1044,11 @@ do_handshake(struct bufferevent_openssl *bev_ssl)
|
|||||||
print_err(err);
|
print_err(err);
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
if (!bev_ssl->underlying) {
|
stop_reading(bev_ssl);
|
||||||
stop_reading(bev_ssl);
|
return start_writing(bev_ssl);
|
||||||
return start_writing(bev_ssl);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
if (!bev_ssl->underlying) {
|
stop_writing(bev_ssl);
|
||||||
stop_writing(bev_ssl);
|
return start_reading(bev_ssl);
|
||||||
return start_reading(bev_ssl);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
default:
|
default:
|
||||||
conn_closed(bev_ssl, BEV_EVENT_READING, err, r);
|
conn_closed(bev_ssl, BEV_EVENT_READING, err, r);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1086,6 +1084,13 @@ set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
|||||||
be_openssl_handshakecb, be_openssl_handshakecb,
|
be_openssl_handshakecb, be_openssl_handshakecb,
|
||||||
be_openssl_eventcb,
|
be_openssl_eventcb,
|
||||||
bev_ssl);
|
bev_ssl);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (bufferevent_setfd(bev_ssl->underlying, fd))
|
||||||
|
return 1;
|
||||||
|
|
||||||
return do_handshake(bev_ssl);
|
return do_handshake(bev_ssl);
|
||||||
} else {
|
} else {
|
||||||
struct bufferevent *bev = &bev_ssl->bev.bev;
|
struct bufferevent *bev = &bev_ssl->bev.bev;
|
||||||
@ -1131,10 +1136,13 @@ be_openssl_outbuf_cb(struct evbuffer *buf,
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
/* XXX need to hold a reference here. */
|
/* XXX need to hold a reference here. */
|
||||||
|
|
||||||
if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN &&
|
if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) {
|
||||||
cbinfo->orig_size == 0) {
|
if (cbinfo->orig_size == 0)
|
||||||
r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
|
r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
|
||||||
&bev_ssl->bev.bev.timeout_write);
|
&bev_ssl->bev.bev.timeout_write);
|
||||||
|
|
||||||
|
if (bev_ssl->underlying)
|
||||||
|
consider_writing(bev_ssl);
|
||||||
}
|
}
|
||||||
/* XXX Handle r < 0 */
|
/* XXX Handle r < 0 */
|
||||||
(void)r;
|
(void)r;
|
||||||
@ -1286,17 +1294,24 @@ be_openssl_ctrl(struct bufferevent *bev,
|
|||||||
struct bufferevent_openssl *bev_ssl = upcast(bev);
|
struct bufferevent_openssl *bev_ssl = upcast(bev);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case BEV_CTRL_SET_FD:
|
case BEV_CTRL_SET_FD:
|
||||||
if (bev_ssl->underlying)
|
if (!bev_ssl->underlying) {
|
||||||
return -1;
|
|
||||||
{
|
|
||||||
BIO *bio;
|
BIO *bio;
|
||||||
bio = BIO_new_socket(data->fd, 0);
|
bio = BIO_new_socket(data->fd, 0);
|
||||||
SSL_set_bio(bev_ssl->ssl, bio, bio);
|
SSL_set_bio(bev_ssl->ssl, bio, bio);
|
||||||
|
} else {
|
||||||
|
BIO *bio;
|
||||||
|
if (!(bio = BIO_new_bufferevent(bev_ssl->underlying, 0)))
|
||||||
|
return -1;
|
||||||
|
SSL_set_bio(bev_ssl->ssl, bio, bio);
|
||||||
}
|
}
|
||||||
|
|
||||||
return be_openssl_set_fd(bev_ssl, bev_ssl->old_state, data->fd);
|
return be_openssl_set_fd(bev_ssl, bev_ssl->old_state, data->fd);
|
||||||
case BEV_CTRL_GET_FD:
|
case BEV_CTRL_GET_FD:
|
||||||
data->fd = event_get_fd(&bev->ev_read);
|
if (bev_ssl->underlying) {
|
||||||
|
data->fd = event_get_fd(&bev_ssl->underlying->ev_read);
|
||||||
|
} else {
|
||||||
|
data->fd = event_get_fd(&bev->ev_read);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
case BEV_CTRL_GET_UNDERLYING:
|
case BEV_CTRL_GET_UNDERLYING:
|
||||||
data->ptr = bev_ssl->underlying;
|
data->ptr = bev_ssl->underlying;
|
||||||
|
@ -249,8 +249,8 @@ bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
|
|||||||
/* we need to fake the error if the connection was refused
|
/* we need to fake the error if the connection was refused
|
||||||
* immediately - usually connection to localhost on BSD */
|
* immediately - usually connection to localhost on BSD */
|
||||||
if (bufev_p->connection_refused) {
|
if (bufev_p->connection_refused) {
|
||||||
bufev_p->connection_refused = 0;
|
bufev_p->connection_refused = 0;
|
||||||
c = -1;
|
c = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
@ -438,13 +438,12 @@ bufferevent_socket_connect(struct bufferevent *bev,
|
|||||||
/* The connect succeeded already. How very BSD of it. */
|
/* The connect succeeded already. How very BSD of it. */
|
||||||
result = 0;
|
result = 0;
|
||||||
bufev_p->connecting = 1;
|
bufev_p->connecting = 1;
|
||||||
event_active(&bev->ev_write, EV_WRITE, 1);
|
bufferevent_trigger_nolock_(bev, EV_WRITE, BEV_OPT_DEFER_CALLBACKS);
|
||||||
} else {
|
} else {
|
||||||
/* The connect failed already. How very BSD of it. */
|
/* The connect failed already. How very BSD of it. */
|
||||||
bufev_p->connection_refused = 1;
|
|
||||||
bufev_p->connecting = 1;
|
|
||||||
result = 0;
|
result = 0;
|
||||||
event_active(&bev->ev_write, EV_WRITE, 1);
|
bufferevent_run_eventcb_(bev, BEV_EVENT_ERROR, BEV_OPT_DEFER_CALLBACKS);
|
||||||
|
bufferevent_disable(bev, EV_WRITE|EV_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -85,6 +85,7 @@ static void http_on_complete_cb(struct evhttp_request *req, void *arg);
|
|||||||
|
|
||||||
#define HTTP_BIND_IPV6 1
|
#define HTTP_BIND_IPV6 1
|
||||||
#define HTTP_BIND_SSL 2
|
#define HTTP_BIND_SSL 2
|
||||||
|
#define HTTP_SSL_FILTER 4
|
||||||
static int
|
static int
|
||||||
http_bind(struct evhttp *myhttp, ev_uint16_t *pport, int mask)
|
http_bind(struct evhttp *myhttp, ev_uint16_t *pport, int mask)
|
||||||
{
|
{
|
||||||
@ -424,18 +425,25 @@ http_complete_write(evutil_socket_t fd, short what, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct bufferevent *
|
static struct bufferevent *
|
||||||
create_bev(struct event_base *base, int fd, int ssl)
|
create_bev(struct event_base *base, int fd, int ssl_mask)
|
||||||
{
|
{
|
||||||
int flags = BEV_OPT_DEFER_CALLBACKS;
|
int flags = BEV_OPT_DEFER_CALLBACKS;
|
||||||
struct bufferevent *bev = NULL;
|
struct bufferevent *bev = NULL;
|
||||||
|
|
||||||
if (!ssl) {
|
if (!ssl_mask) {
|
||||||
bev = bufferevent_socket_new(base, fd, flags);
|
bev = bufferevent_socket_new(base, fd, flags);
|
||||||
} else {
|
} else {
|
||||||
#ifdef EVENT__HAVE_OPENSSL
|
#ifdef EVENT__HAVE_OPENSSL
|
||||||
SSL *ssl = SSL_new(get_ssl_ctx());
|
SSL *ssl = SSL_new(get_ssl_ctx());
|
||||||
bev = bufferevent_openssl_socket_new(
|
if (ssl_mask & HTTP_SSL_FILTER) {
|
||||||
base, fd, ssl, BUFFEREVENT_SSL_CONNECTING, flags);
|
struct bufferevent *underlying =
|
||||||
|
bufferevent_socket_new(base, fd, flags);
|
||||||
|
bev = bufferevent_openssl_filter_new(
|
||||||
|
base, underlying, ssl, BUFFEREVENT_SSL_CONNECTING, flags);
|
||||||
|
} else {
|
||||||
|
bev = bufferevent_openssl_socket_new(
|
||||||
|
base, fd, ssl, BUFFEREVENT_SSL_CONNECTING, flags);
|
||||||
|
}
|
||||||
bufferevent_openssl_set_allow_dirty_shutdown(bev, 1);
|
bufferevent_openssl_set_allow_dirty_shutdown(bev, 1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -4519,6 +4527,8 @@ http_request_own_test(void *arg)
|
|||||||
#ifdef EVENT__HAVE_OPENSSL
|
#ifdef EVENT__HAVE_OPENSSL
|
||||||
static void https_basic_test(void *arg)
|
static void https_basic_test(void *arg)
|
||||||
{ return http_basic_test_impl(arg, 1); }
|
{ return http_basic_test_impl(arg, 1); }
|
||||||
|
static void https_filter_basic_test(void *arg)
|
||||||
|
{ return http_basic_test_impl(arg, 1 | HTTP_SSL_FILTER); }
|
||||||
static void https_incomplete_test(void *arg)
|
static void https_incomplete_test(void *arg)
|
||||||
{ http_incomplete_test_(arg, 0, 1); }
|
{ http_incomplete_test_(arg, 0, 1); }
|
||||||
static void https_incomplete_timeout_test(void *arg)
|
static void https_incomplete_timeout_test(void *arg)
|
||||||
@ -4533,6 +4543,8 @@ static void https_connection_retry_test(void *arg)
|
|||||||
{ return http_connection_retry_test_impl(arg, 1); }
|
{ return http_connection_retry_test_impl(arg, 1); }
|
||||||
static void https_chunk_out_test(void *arg)
|
static void https_chunk_out_test(void *arg)
|
||||||
{ return http_chunk_out_test_impl(arg, 1); }
|
{ return http_chunk_out_test_impl(arg, 1); }
|
||||||
|
static void https_filter_chunk_out_test(void *arg)
|
||||||
|
{ return http_chunk_out_test_impl(arg, 1 | HTTP_SSL_FILTER); }
|
||||||
static void https_stream_out_test(void *arg)
|
static void https_stream_out_test(void *arg)
|
||||||
{ return http_stream_out_test_impl(arg, 1); }
|
{ return http_stream_out_test_impl(arg, 1); }
|
||||||
static void https_connection_fail_test(void *arg)
|
static void https_connection_fail_test(void *arg)
|
||||||
@ -4620,6 +4632,7 @@ struct testcase_t http_testcases[] = {
|
|||||||
|
|
||||||
#ifdef EVENT__HAVE_OPENSSL
|
#ifdef EVENT__HAVE_OPENSSL
|
||||||
HTTPS(basic),
|
HTTPS(basic),
|
||||||
|
HTTPS(filter_basic),
|
||||||
HTTPS(simple),
|
HTTPS(simple),
|
||||||
HTTPS(simple_dirty),
|
HTTPS(simple_dirty),
|
||||||
HTTPS(incomplete),
|
HTTPS(incomplete),
|
||||||
@ -4628,6 +4641,7 @@ struct testcase_t http_testcases[] = {
|
|||||||
{ "https_connection_retry_conn_address", https_connection_retry_conn_address_test,
|
{ "https_connection_retry_conn_address", https_connection_retry_conn_address_test,
|
||||||
TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, NULL },
|
TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, NULL },
|
||||||
HTTPS(chunk_out),
|
HTTPS(chunk_out),
|
||||||
|
HTTPS(filter_chunk_out),
|
||||||
HTTPS(stream_out),
|
HTTPS(stream_out),
|
||||||
HTTPS(connection_fail),
|
HTTPS(connection_fail),
|
||||||
HTTPS(write_during_read),
|
HTTPS(write_during_read),
|
||||||
|
@ -227,19 +227,20 @@ enum regress_openssl_type
|
|||||||
REGRESS_OPENSSL_FREED = 256,
|
REGRESS_OPENSSL_FREED = 256,
|
||||||
REGRESS_OPENSSL_TIMEOUT = 512,
|
REGRESS_OPENSSL_TIMEOUT = 512,
|
||||||
REGRESS_OPENSSL_SLEEP = 1024,
|
REGRESS_OPENSSL_SLEEP = 1024,
|
||||||
|
|
||||||
|
REGRESS_OPENSSL_CLIENT_WRITE = 2048,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bufferevent_openssl_check_fd(struct bufferevent *bev, int filter)
|
bufferevent_openssl_check_fd(struct bufferevent *bev, int filter)
|
||||||
{
|
{
|
||||||
|
tt_int_op(bufferevent_getfd(bev), !=, -1);
|
||||||
|
tt_int_op(bufferevent_setfd(bev, -1), ==, 0);
|
||||||
if (filter) {
|
if (filter) {
|
||||||
tt_int_op(bufferevent_getfd(bev), ==, -1);
|
|
||||||
tt_int_op(bufferevent_setfd(bev, -1), ==, -1);
|
|
||||||
} else {
|
|
||||||
tt_int_op(bufferevent_getfd(bev), !=, -1);
|
tt_int_op(bufferevent_getfd(bev), !=, -1);
|
||||||
tt_int_op(bufferevent_setfd(bev, -1), ==, 0);
|
} else {
|
||||||
|
tt_int_op(bufferevent_getfd(bev), ==, -1);
|
||||||
}
|
}
|
||||||
tt_int_op(bufferevent_getfd(bev), ==, -1);
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
;
|
;
|
||||||
@ -322,6 +323,9 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
|
|||||||
if (--pending_connect_events == 0)
|
if (--pending_connect_events == 0)
|
||||||
event_base_loopexit(exit_base, NULL);
|
event_base_loopexit(exit_base, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((type & REGRESS_OPENSSL_CLIENT_WRITE) && (type & REGRESS_OPENSSL_CLIENT))
|
||||||
|
evbuffer_add_printf(bufferevent_get_output(bev), "1\n");
|
||||||
} else if (what & BEV_EVENT_EOF) {
|
} else if (what & BEV_EVENT_EOF) {
|
||||||
TT_BLATHER(("Got a good EOF"));
|
TT_BLATHER(("Got a good EOF"));
|
||||||
++got_close;
|
++got_close;
|
||||||
@ -465,7 +469,8 @@ regress_bufferevent_openssl(void *arg)
|
|||||||
bufferevent_enable(bev1, EV_READ|EV_WRITE);
|
bufferevent_enable(bev1, EV_READ|EV_WRITE);
|
||||||
bufferevent_enable(bev2, EV_READ|EV_WRITE);
|
bufferevent_enable(bev2, EV_READ|EV_WRITE);
|
||||||
|
|
||||||
evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
|
if (!(type & REGRESS_OPENSSL_CLIENT_WRITE))
|
||||||
|
evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
|
||||||
|
|
||||||
event_base_dispatch(data->base);
|
event_base_dispatch(data->base);
|
||||||
|
|
||||||
@ -488,7 +493,8 @@ regress_bufferevent_openssl(void *arg)
|
|||||||
|
|
||||||
bufferevent_set_timeouts(bev1, &t, &t);
|
bufferevent_set_timeouts(bev1, &t, &t);
|
||||||
|
|
||||||
evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
|
if (!(type & REGRESS_OPENSSL_CLIENT_WRITE))
|
||||||
|
evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
|
||||||
|
|
||||||
event_base_dispatch(data->base);
|
event_base_dispatch(data->base);
|
||||||
|
|
||||||
@ -731,8 +737,14 @@ struct testcase_t ssl_testcases[] = {
|
|||||||
#define T(a) ((void *)(a))
|
#define T(a) ((void *)(a))
|
||||||
{ "bufferevent_socketpair", regress_bufferevent_openssl,
|
{ "bufferevent_socketpair", regress_bufferevent_openssl,
|
||||||
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
|
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
|
||||||
|
{ "bufferevent_socketpair_write_after_connect", regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_SOCKETPAIR|REGRESS_OPENSSL_CLIENT_WRITE) },
|
||||||
{ "bufferevent_filter", regress_bufferevent_openssl,
|
{ "bufferevent_filter", regress_bufferevent_openssl,
|
||||||
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_FILTER) },
|
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_FILTER) },
|
||||||
|
{ "bufferevent_filter_write_after_connect", regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_FILTER|REGRESS_OPENSSL_CLIENT_WRITE) },
|
||||||
{ "bufferevent_renegotiate_socketpair", regress_bufferevent_openssl,
|
{ "bufferevent_renegotiate_socketpair", regress_bufferevent_openssl,
|
||||||
TT_ISOLATED, &basic_setup,
|
TT_ISOLATED, &basic_setup,
|
||||||
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE) },
|
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE) },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user