]> granicus.if.org Git - libevent/commitdiff
Introduce new API for flags of the SSL bufferevent
authorAzat Khuzhin <azat@libevent.org>
Sat, 31 Oct 2020 18:45:22 +0000 (21:45 +0300)
committerAzat Khuzhin <azat@libevent.org>
Sat, 31 Oct 2020 19:51:40 +0000 (22:51 +0300)
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()

bufferevent_mbedtls.c
bufferevent_openssl.c
bufferevent_ssl.c
include/event2/bufferevent_ssl.h
ssl-compat.h

index e188abed820f59addc9c90cec37427babdc9a7e9..e535c86f993286ba9fe6df6a41e7c799aca40fe1 100644 (file)
@@ -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));
index 34259ce5aba65ac2e5ad8c11cbe051c7176f9ad9..6ace1e3aea215ec1bd51d9cb2c2943261bcbff9f 100644 (file)
@@ -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);
index 5c6956d5db9d26193c21d8f4851025b6d33d6a45..dd013c98809dcbea77e806fa6210a8dbc6f8027f 100644 (file)
@@ -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);
 }
index 69fb40b763cda1078f0383f129f5b26f52014d6b..5abcb790be0d0169c91d5bc9a4afd64169995f10 100644 (file)
@@ -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);
index a19c457f78a940d489ec3b9e8b28a6975f74c649..4dccb52a97b62270910e17af7d91b89a9d7e573b 100644 (file)
@@ -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,