]> git.kaiwu.me - nginx.git/commitdiff
QUIC: client certificate validation with OCSP.
authorSergey Kandaurov <pluknet@nginx.com>
Wed, 4 Aug 2021 12:49:18 +0000 (15:49 +0300)
committerSergey Kandaurov <pluknet@nginx.com>
Wed, 4 Aug 2021 12:49:18 +0000 (15:49 +0300)
src/event/quic/ngx_event_quic.c
src/event/quic/ngx_event_quic.h
src/event/quic/ngx_event_quic_connection.h
src/event/quic/ngx_event_quic_ssl.c
src/event/quic/ngx_event_quic_streams.c
src/event/quic/ngx_event_quic_streams.h

index 515fb9b55e03b0ffe82df16b85f8f60ba5b10ce8..e79a24e8a97a68d77217ff71c50eb062357ec881 100644 (file)
@@ -304,6 +304,8 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf,
     ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY;
     ctp->active_connection_id_limit = 2;
 
+    ngx_queue_init(&qc->streams.uninitialized);
+
     qc->streams.recv_max_data = qc->tp.initial_max_data;
     qc->streams.recv_window = qc->streams.recv_max_data;
 
index d3429cbe457b1aabacaec368d0e0e15d527598da..d425cee31687e8ff28c48fd1c9f1ac766580ddb1 100644 (file)
@@ -69,6 +69,7 @@ typedef struct {
 
 struct ngx_quic_stream_s {
     ngx_rbtree_node_t          node;
+    ngx_queue_t                queue;
     ngx_connection_t          *parent;
     ngx_connection_t          *connection;
     uint64_t                   id;
index 8e6cea5b62ae4b210344fc39b4824edd022da82b..f3de5b136fa54a7337b40f722df8ac3fab1928da 100644 (file)
@@ -114,6 +114,7 @@ struct ngx_quic_socket_s {
 typedef struct {
     ngx_rbtree_t                      tree;
     ngx_rbtree_node_t                 sentinel;
+    ngx_queue_t                       uninitialized;
 
     uint64_t                          sent;
     uint64_t                          recv_offset;
@@ -131,6 +132,9 @@ typedef struct {
     uint64_t                          client_max_streams_bidi;
     uint64_t                          client_streams_uni;
     uint64_t                          client_streams_bidi;
+
+    ngx_uint_t                        initialized;
+                                                 /* unsigned  initialized:1; */
 } ngx_quic_streams_t;
 
 
index 5e2827f230a18011e23e8dbfc0f527d67d216993..9083ad1e3db09efcf3c0cc8500b27f2eafc62a2a 100644 (file)
@@ -361,6 +361,7 @@ static ngx_int_t
 ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data)
 {
     int                     n, sslerr;
+    ngx_int_t               rc;
     ngx_buf_t              *b;
     ngx_chain_t            *cl;
     ngx_ssl_conn_t         *ssl_conn;
@@ -462,6 +463,19 @@ ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data)
         return NGX_ERROR;
     }
 
+    rc = ngx_ssl_ocsp_validate(c);
+
+    if (rc == NGX_ERROR) {
+        return NGX_ERROR;
+    }
+
+    if (rc == NGX_AGAIN) {
+        c->ssl->handler = ngx_quic_init_streams;
+        return NGX_OK;
+    }
+
+    ngx_quic_init_streams(c);
+
     return NGX_OK;
 }
 
index 58639a6f965d60c1bad6b1c2719989a60af71dca..c4fd4eb3eacc7234394e4a60a911490b56fc62e6 100644 (file)
 
 static ngx_quic_stream_t *ngx_quic_create_client_stream(ngx_connection_t *c,
     uint64_t id);
+static ngx_int_t ngx_quic_init_stream(ngx_quic_stream_t *qs);
 static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c,
     uint64_t id);
+static void ngx_quic_empty_handler(ngx_event_t *ev);
 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf,
     size_t size);
 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf,
@@ -146,6 +148,8 @@ ngx_quic_find_stream(ngx_rbtree_t *rbtree, uint64_t id)
 ngx_int_t
 ngx_quic_close_streams(ngx_connection_t *c, ngx_quic_connection_t *qc)
 {
+    ngx_pool_t         *pool;
+    ngx_queue_t        *q;
     ngx_event_t        *rev, *wev;
     ngx_rbtree_t       *tree;
     ngx_rbtree_node_t  *node;
@@ -155,6 +159,17 @@ ngx_quic_close_streams(ngx_connection_t *c, ngx_quic_connection_t *qc)
     ngx_uint_t          ns;
 #endif
 
+    while (!ngx_queue_empty(&qc->streams.uninitialized)) {
+        q = ngx_queue_head(&qc->streams.uninitialized);
+        ngx_queue_remove(q);
+
+        qs = ngx_queue_data(q, ngx_quic_stream_t, queue);
+        pool = qs->connection->pool;
+
+        ngx_close_connection(qs->connection);
+        ngx_destroy_pool(pool);
+    }
+
     tree = &qc->streams.tree;
 
     if (tree->root == tree->sentinel) {
@@ -310,7 +325,9 @@ ngx_quic_create_client_stream(ngx_connection_t *c, uint64_t id)
             return NULL;
         }
 
-        qs->connection->listening->handler(qs->connection);
+        if (ngx_quic_init_stream(qs) != NGX_OK) {
+            return NULL;
+        }
 
         if (qc->shutdown) {
             return NGX_QUIC_STREAM_GONE;
@@ -321,6 +338,59 @@ ngx_quic_create_client_stream(ngx_connection_t *c, uint64_t id)
 }
 
 
+static ngx_int_t
+ngx_quic_init_stream(ngx_quic_stream_t *qs)
+{
+    ngx_connection_t       *c;
+    ngx_quic_connection_t  *qc;
+
+    qc = ngx_quic_get_connection(qs->parent);
+
+    c = qs->connection;
+
+    if (!qc->streams.initialized) {
+        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "quic postpone stream init");
+
+        ngx_queue_insert_tail(&qc->streams.uninitialized, &qs->queue);
+        return NGX_OK;
+    }
+
+    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic init stream");
+
+    c->listening->handler(c);
+
+    return NGX_OK;
+}
+
+
+void
+ngx_quic_init_streams(ngx_connection_t *c)
+{
+    ngx_queue_t            *q;
+    ngx_quic_stream_t      *qs;
+    ngx_quic_connection_t  *qc;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic init streams");
+
+    qc = ngx_quic_get_connection(c);
+
+    while (!ngx_queue_empty(&qc->streams.uninitialized)) {
+        q = ngx_queue_head(&qc->streams.uninitialized);
+        ngx_queue_remove(q);
+
+        qs = ngx_queue_data(q, ngx_quic_stream_t, queue);
+
+        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, qs->connection->log, 0,
+                       "quic init postponed stream");
+
+        qs->connection->listening->handler(qs->connection);
+    }
+
+    qc->streams.initialized = 1;
+}
+
+
 static ngx_quic_stream_t *
 ngx_quic_create_stream(ngx_connection_t *c, uint64_t id)
 {
@@ -387,6 +457,9 @@ ngx_quic_create_stream(ngx_connection_t *c, uint64_t id)
     sc->read->log = log;
     sc->write->log = log;
 
+    sc->read->handler = ngx_quic_empty_handler;
+    sc->write->handler = ngx_quic_empty_handler;
+
     log->connection = sc->number;
 
     if ((id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0
@@ -432,6 +505,12 @@ ngx_quic_create_stream(ngx_connection_t *c, uint64_t id)
 }
 
 
+static void
+ngx_quic_empty_handler(ngx_event_t *ev)
+{
+}
+
+
 static ssize_t
 ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size)
 {
@@ -832,9 +911,7 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
             goto cleanup;
         }
 
-        sc->listening->handler(sc);
-
-        return NGX_OK;
+        return ngx_quic_init_stream(qs);
     }
 
     sc = qs->connection;
@@ -986,7 +1063,9 @@ ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c,
 
         limit = qs->recv_max_data;
 
-        qs->connection->listening->handler(qs->connection);
+        if (ngx_quic_init_stream(qs) != NGX_OK) {
+            return NGX_ERROR;
+        }
 
     } else {
         limit = qs->recv_max_data;
@@ -1043,9 +1122,7 @@ ngx_quic_handle_max_stream_data_frame(ngx_connection_t *c,
             qs->send_max_data = f->limit;
         }
 
-        qs->connection->listening->handler(qs->connection);
-
-        return NGX_OK;
+        return ngx_quic_init_stream(qs);
     }
 
     if (f->limit <= qs->send_max_data) {
@@ -1117,9 +1194,7 @@ ngx_quic_handle_reset_stream_frame(ngx_connection_t *c,
             goto cleanup;
         }
 
-        sc->listening->handler(sc);
-
-        return NGX_OK;
+        return ngx_quic_init_stream(qs);
     }
 
     sc = qs->connection;
@@ -1202,9 +1277,7 @@ ngx_quic_handle_stop_sending_frame(ngx_connection_t *c,
         wev->error = 1;
         wev->ready = 1;
 
-        sc->listening->handler(sc);
-
-        return NGX_OK;
+        return ngx_quic_init_stream(qs);
     }
 
     wev = qs->connection->write;
index 0ee9c37f2aa03b2d8ff34fdc82aa85bd8a43410c..95cdfca1c4f8dd4f17846a6d0bf589cf84070d6c 100644 (file)
@@ -31,6 +31,7 @@ ngx_int_t ngx_quic_handle_stop_sending_frame(ngx_connection_t *c,
 ngx_int_t ngx_quic_handle_max_streams_frame(ngx_connection_t *c,
     ngx_quic_header_t *pkt, ngx_quic_max_streams_frame_t *f);
 
+void ngx_quic_init_streams(ngx_connection_t *c);
 void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp,
     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
 ngx_quic_stream_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree,