summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzat Khuzhin <azat@libevent.org>2020-10-31 21:45:22 +0300
committerAzat Khuzhin <azat@libevent.org>2020-10-31 22:51:40 +0300
commit7e0fc878c5646f45273f38dbf5b8d325a20c81df (patch)
treee68ab53a93f59853b6bd2dfc21774e789d11c971
parent587f6c83a3557c048fce6e541e7fc534082b0e85 (diff)
downloadlibevent-7e0fc878c5646f45273f38dbf5b8d325a20c81df.tar.gz
Introduce new API for flags of the SSL bufferevent
Introduce more generic API (like for evbuffer): - bufferevent_ssl_set_flags() - bufferevent_ssl_clear_flags() - bufferevent_ssl_get_flags() And deprecate existing: - bufferevent_openssl_get_allow_dirty_shutdown() - bufferevent_openssl_set_allow_dirty_shutdown() - bufferevent_mbedtls_get_allow_dirty_shutdown() - bufferevent_mbedtls_set_allow_dirty_shutdown()
-rw-r--r--bufferevent_mbedtls.c2
-rw-r--r--bufferevent_openssl.c2
-rw-r--r--bufferevent_ssl.c84
-rw-r--r--include/event2/bufferevent_ssl.h102
-rw-r--r--ssl-compat.h4
5 files changed, 141 insertions, 53 deletions
diff --git a/bufferevent_mbedtls.c b/bufferevent_mbedtls.c
index e188abed..e535c86f 100644
--- a/bufferevent_mbedtls.c
+++ b/bufferevent_mbedtls.c
@@ -210,7 +210,7 @@ conn_closed(struct bufferevent_ssl *bev_ssl, int when, int errcode, int ret)
char buf[100];
if (when & BEV_EVENT_READING && ret == 0) {
- if (bev_ssl->allow_dirty_shutdown)
+ if (bev_ssl->flags & BUFFEREVENT_SSL_DIRTY_SHUTDOWN)
event = BEV_EVENT_EOF;
} else {
mbedtls_strerror(errcode, buf, sizeof(buf));
diff --git a/bufferevent_openssl.c b/bufferevent_openssl.c
index 34259ce5..6ace1e3a 100644
--- a/bufferevent_openssl.c
+++ b/bufferevent_openssl.c
@@ -281,7 +281,7 @@ conn_closed(struct bufferevent_ssl *bev_ssl, int when, int errcode, int ret)
bufferevent_ssl_put_error(bev_ssl, err);
}
- if (dirty_shutdown && bev_ssl->allow_dirty_shutdown)
+ if (dirty_shutdown && bev_ssl->flags & BUFFEREVENT_SSL_DIRTY_SHUTDOWN)
event = BEV_EVENT_EOF;
bufferevent_ssl_stop_reading(bev_ssl);
diff --git a/bufferevent_ssl.c b/bufferevent_ssl.c
index 5c6956d5..dd013c98 100644
--- a/bufferevent_ssl.c
+++ b/bufferevent_ssl.c
@@ -581,7 +581,7 @@ be_ssl_eventcb(struct bufferevent *bev_base, short what, void *ctx)
int event = 0;
if (what & BEV_EVENT_EOF) {
- if (bev_ssl->allow_dirty_shutdown)
+ if (bev_ssl->flags & BUFFEREVENT_SSL_DIRTY_SHUTDOWN)
event = BEV_EVENT_EOF;
else
event = BEV_EVENT_ERROR;
@@ -1052,41 +1052,91 @@ err:
return NULL;
}
-int
-bufferevent_ssl_get_allow_dirty_shutdown(struct bufferevent *bev)
+unsigned long
+bufferevent_get_ssl_error(struct bufferevent *bev)
{
- int allow_dirty_shutdown = -1;
+ unsigned long err = 0;
struct bufferevent_ssl *bev_ssl;
BEV_LOCK(bev);
bev_ssl = bufferevent_ssl_upcast(bev);
- if (bev_ssl)
- allow_dirty_shutdown = bev_ssl->allow_dirty_shutdown;
+ if (bev_ssl && bev_ssl->n_errors) {
+ err = bev_ssl->errors[--bev_ssl->n_errors];
+ }
BEV_UNLOCK(bev);
- return allow_dirty_shutdown;
+ return err;
}
-void
-bufferevent_ssl_set_allow_dirty_shutdown(struct bufferevent *bev,
- int allow_dirty_shutdown)
+ev_uint64_t bufferevent_ssl_get_flags(struct bufferevent *bev)
{
+ ev_uint64_t flags = EV_UINT64_MAX;
struct bufferevent_ssl *bev_ssl;
+
BEV_LOCK(bev);
bev_ssl = bufferevent_ssl_upcast(bev);
if (bev_ssl)
- bev_ssl->allow_dirty_shutdown = !!allow_dirty_shutdown;
+ flags = bev_ssl->flags;
BEV_UNLOCK(bev);
+
+ return flags;
}
+ev_uint64_t bufferevent_ssl_set_flags(struct bufferevent *bev, ev_uint64_t flags)
+{
+ ev_uint64_t old_flags = EV_UINT64_MAX;
+ struct bufferevent_ssl *bev_ssl;
-unsigned long
-bufferevent_get_ssl_error(struct bufferevent *bev)
+ flags &= (BUFFEREVENT_SSL_DIRTY_SHUTDOWN);
+ if (!flags)
+ return old_flags;
+
+ BEV_LOCK(bev);
+ bev_ssl = bufferevent_ssl_upcast(bev);
+ if (bev_ssl) {
+ old_flags = bev_ssl->flags;
+ bev_ssl->flags |= flags;
+ }
+ BEV_UNLOCK(bev);
+
+ return old_flags;
+}
+ev_uint64_t bufferevent_ssl_clear_flags(struct bufferevent *bev, ev_uint64_t flags)
{
- unsigned long err = 0;
+ ev_uint64_t old_flags = EV_UINT64_MAX;
struct bufferevent_ssl *bev_ssl;
+
+ flags &= (BUFFEREVENT_SSL_DIRTY_SHUTDOWN);
+ if (!flags)
+ return old_flags;
+
BEV_LOCK(bev);
bev_ssl = bufferevent_ssl_upcast(bev);
- if (bev_ssl && bev_ssl->n_errors) {
- err = bev_ssl->errors[--bev_ssl->n_errors];
+ if (bev_ssl) {
+ old_flags = bev_ssl->flags;
+ bev_ssl->flags &= ~flags;
}
BEV_UNLOCK(bev);
- return err;
+
+ return old_flags;
+}
+
+int
+bufferevent_ssl_get_allow_dirty_shutdown(struct bufferevent *bev)
+{
+ ev_uint64_t flags = bufferevent_ssl_get_flags(bev);
+ if (flags == EV_UINT64_MAX)
+ return flags;
+ return !!(flags & BUFFEREVENT_SSL_DIRTY_SHUTDOWN);
+}
+
+void
+bufferevent_ssl_set_allow_dirty_shutdown(
+ struct bufferevent *bev, int allow_dirty_shutdown)
+{
+ BEV_LOCK(bev);
+
+ if (allow_dirty_shutdown)
+ bufferevent_ssl_set_flags(bev, BUFFEREVENT_SSL_DIRTY_SHUTDOWN);
+ else
+ bufferevent_ssl_clear_flags(bev, BUFFEREVENT_SSL_DIRTY_SHUTDOWN);
+
+ BEV_UNLOCK(bev);
}
diff --git a/include/event2/bufferevent_ssl.h b/include/event2/bufferevent_ssl.h
index 69fb40b7..5abcb790 100644
--- a/include/event2/bufferevent_ssl.h
+++ b/include/event2/bufferevent_ssl.h
@@ -49,6 +49,23 @@ enum bufferevent_ssl_state {
BUFFEREVENT_SSL_ACCEPTING = 2
};
+/** Control how to report dirty SSL shutdowns.
+
+ If the peer (or the network, or an attacker) closes the TCP
+ connection before closing the SSL channel, and the protocol is SSL >= v3,
+ this is a "dirty" shutdown. If BUFFEREVENT_SSL_DIRTY_SHUTDOWN is not set
+ (default), this is reported as BEV_EVENT_ERROR.
+
+ If instead BUFFEREVENT_SSL_DIRTY_SHUTDOWN is set, a dirty shutdown is
+ reported as BEV_EVENT_EOF.
+
+ (Note that if the protocol is < SSLv3, you will always receive
+ BEV_EVENT_EOF, since SSL 2 and earlier cannot distinguish a secure
+ connection close from a dirty one. This is one reason (among many)
+ not to use SSL 2.)
+*/
+#define BUFFEREVENT_SSL_DIRTY_SHUTDOWN 1
+
#if defined(EVENT__HAVE_OPENSSL) || defined(EVENT_IN_DOXYGEN_)
/* This is what openssl's SSL objects are underneath. */
struct ssl_st;
@@ -90,28 +107,51 @@ bufferevent_openssl_socket_new(struct event_base *base,
enum bufferevent_ssl_state state,
int options);
-/** Control how to report dirty SSL shutdowns.
-
- If the peer (or the network, or an attacker) closes the TCP
- connection before closing the SSL channel, and the protocol is SSL >= v3,
- this is a "dirty" shutdown. If allow_dirty_shutdown is 0 (default),
- this is reported as BEV_EVENT_ERROR.
-
- If instead allow_dirty_shutdown=1, a dirty shutdown is reported as
- BEV_EVENT_EOF.
-
- (Note that if the protocol is < SSLv3, you will always receive
- BEV_EVENT_EOF, since SSL 2 and earlier cannot distinguish a secure
- connection close from a dirty one. This is one reason (among many)
- not to use SSL 2.)
-*/
-
+/**
+ * Get value of the BUFFEREVENT_SSL_DIRTY_SHUTDOWN flag.
+ *
+ * @see BUFFEREVENT_SSL_DIRTY_SHUTDOWN
+ * @deprecated This function is deprecated, use bufferevent_ssl_get_flags() instead.
+ * @see bufferevent_ssl_get_flags()
+ */
EVENT2_EXPORT_SYMBOL
int bufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent *bev);
+/**
+ * Set value of the BUFFEREVENT_SSL_DIRTY_SHUTDOWN flag.
+ *
+ * @see BUFFEREVENT_SSL_DIRTY_SHUTDOWN
+ * @deprecated This function is deprecated, use bufferevent_ssl_set_flags() instead.
+ * @see bufferevent_ssl_set_flags()
+ */
EVENT2_EXPORT_SYMBOL
void bufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent *bev,
int allow_dirty_shutdown);
+/**
+ * Get flags of the SSL bufferevent.
+ *
+ * @see BUFFEREVENT_SSL_*
+ * @return flags or SIZE_MAX in case of error (if bufferevent is not SSL).
+ */
+EVENT2_EXPORT_SYMBOL
+ev_uint64_t bufferevent_ssl_get_flags(struct bufferevent *bev);
+/** Change the flags that are set for an ssl bufferevent by adding more.
+ *
+ * @param bev the ssl bufferevent.
+ * @param flags One or more BUFFEREVENT_SSL_* options
+ * @return old flags success, EV_UINT64_MAX on failure.
+ */
+EVENT2_EXPORT_SYMBOL
+ev_uint64_t bufferevent_ssl_set_flags(struct bufferevent *bev, ev_uint64_t flags);
+/** Change the flags that are set for an ssl bufferevent by removing some.
+ *
+ * @param bev the bufferevent.
+ * @param flags One or more BUFFEREVENT_SSL_* options
+ * @return old flags success, EV_UINT64_MAX on failure.
+ */
+EVENT2_EXPORT_SYMBOL
+ev_uint64_t bufferevent_ssl_clear_flags(struct bufferevent *bev, ev_uint64_t flags);
+
/** Return the underlying openssl SSL * object for an SSL bufferevent. */
EVENT2_EXPORT_SYMBOL
struct ssl_st *
@@ -165,24 +205,22 @@ bufferevent_mbedtls_socket_new(struct event_base *base,
enum bufferevent_ssl_state state,
int options);
-/** Control how to report dirty SSL shutdowns.
-
- If the peer (or the network, or an attacker) closes the TCP
- connection before closing the SSL channel, and the protocol is SSL >= v3,
- this is a "dirty" shutdown. If allow_dirty_shutdown is 0 (default),
- this is reported as BEV_EVENT_ERROR.
-
- If instead allow_dirty_shutdown=1, a dirty shutdown is reported as
- BEV_EVENT_EOF.
-
- (Note that if the protocol is < SSLv3, you will always receive
- BEV_EVENT_EOF, since SSL 2 and earlier cannot distinguish a secure
- connection close from a dirty one. This is one reason (among many)
- not to use SSL 2.)
-*/
-
+/**
+ * Get value of the BUFFEREVENT_SSL_DIRTY_SHUTDOWN flag.
+ *
+ * @see BUFFEREVENT_SSL_DIRTY_SHUTDOWN
+ * @deprecated This function is deprecated, use bufferevent_ssl_get_flags() instead.
+ * @see bufferevent_ssl_get_flags()
+ */
EVENT2_EXPORT_SYMBOL
int bufferevent_mbedtls_get_allow_dirty_shutdown(struct bufferevent *bev);
+/**
+ * Set value of the BUFFEREVENT_SSL_DIRTY_SHUTDOWN flag.
+ *
+ * @see BUFFEREVENT_SSL_DIRTY_SHUTDOWN
+ * @deprecated This function is deprecated, use bufferevent_ssl_set_flags() instead.
+ * @see bufferevent_ssl_set_flags()
+ */
EVENT2_EXPORT_SYMBOL
void bufferevent_mbedtls_set_allow_dirty_shutdown(struct bufferevent *bev,
int allow_dirty_shutdown);
diff --git a/ssl-compat.h b/ssl-compat.h
index a19c457f..4dccb52a 100644
--- a/ssl-compat.h
+++ b/ssl-compat.h
@@ -73,8 +73,6 @@ struct bufferevent_ssl {
unsigned read_blocked_on_write : 1;
/* When we next get data, we should say "write" instead of "read". */
unsigned write_blocked_on_read : 1;
- /* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */
- unsigned allow_dirty_shutdown : 1;
/* XXX */
unsigned n_errors : 2;
@@ -82,6 +80,8 @@ struct bufferevent_ssl {
unsigned state : 2;
/* If we reset fd, we sould reset state too */
unsigned old_state : 2;
+
+ ev_uint64_t flags;
};
struct bufferevent *bufferevent_ssl_new_impl(struct event_base *base,