]> git.kaiwu.me - nginx.git/commitdiff
SSL: avoid reading on pending SSL_write_early_data().
authorSergey Kandaurov <pluknet@nginx.com>
Tue, 18 Dec 2018 12:15:15 +0000 (15:15 +0300)
committerSergey Kandaurov <pluknet@nginx.com>
Tue, 18 Dec 2018 12:15:15 +0000 (15:15 +0300)
If SSL_write_early_data() returned SSL_ERROR_WANT_WRITE, stop further reading
using a newly introduced c->ssl->write_blocked flag, as otherwise this would
result in SSL error "ssl3_write_bytes:bad length".  Eventually, normal reading
will be restored by read event posted from successful SSL_write_early_data().

While here, place "SSL_write_early_data: want write" debug on the path.

src/event/ngx_event_openssl.c
src/event/ngx_event_openssl.h

index a281fba9e793d1d080b072520f9286410c2f45d5..37a4b72b68fe783155290b1daca612fdad5e8fbe 100644 (file)
@@ -1839,6 +1839,10 @@ ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, size_t size)
         buf += 1;
     }
 
+    if (c->ssl->write_blocked) {
+        return NGX_AGAIN;
+    }
+
     /*
      * SSL_read_early_data() may return data in parts, so try to read
      * until SSL_read_early_data() would return no data
@@ -2339,6 +2343,11 @@ ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
             ngx_post_event(c->read, &ngx_posted_events);
         }
 
+        if (c->ssl->write_blocked) {
+            c->ssl->write_blocked = 0;
+            ngx_post_event(c->read, &ngx_posted_events);
+        }
+
         c->sent += written;
 
         return written;
@@ -2352,6 +2361,9 @@ ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
 
     if (sslerr == SSL_ERROR_WANT_WRITE) {
 
+        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "SSL_write_early_data: want write");
+
         if (c->ssl->saved_read_handler) {
 
             c->read->handler = c->ssl->saved_read_handler;
@@ -2365,6 +2377,14 @@ ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
             ngx_post_event(c->read, &ngx_posted_events);
         }
 
+        /*
+         * OpenSSL 1.1.1a fails to handle SSL_read_early_data()
+         * if an SSL_write_early_data() call blocked on writing,
+         * see https://github.com/openssl/openssl/issues/7757
+         */
+
+        c->ssl->write_blocked = 1;
+
         c->write->ready = 0;
         return NGX_AGAIN;
     }
index abd84ccf033bdc3d61e077a32891f89910b61b77..9ec001d099cb336db314eee818293c0aa416efd5 100644 (file)
@@ -98,6 +98,7 @@ struct ngx_ssl_connection_s {
     unsigned                    try_early_data:1;
     unsigned                    in_early:1;
     unsigned                    early_preread:1;
+    unsigned                    write_blocked:1;
 };