]> git.kaiwu.me - nginx.git/commitdiff
QUIC: added ALPN checks.
authorVladimir Homutov <vl@nginx.com>
Thu, 18 Jun 2020 10:58:46 +0000 (13:58 +0300)
committerVladimir Homutov <vl@nginx.com>
Thu, 18 Jun 2020 10:58:46 +0000 (13:58 +0300)
quic-transport draft 29:

    section 7:

    *  authenticated negotiation of an application protocol (TLS uses
       ALPN [RFC7301] for this purpose)

    ...

    Endpoints MUST explicitly negotiate an application protocol.  This
    avoids situations where there is a disagreement about the protocol
    that is in use.

    section 8.1:

    When using ALPN, endpoints MUST immediately close a connection (see
    Section 10.3 of [QUIC-TRANSPORT]) with a no_application_protocol TLS
    alert (QUIC error code 0x178; see Section 4.10) if an application
    protocol is not negotiated.

Changes in ngx_quic_close_quic() function are required to avoid attempts
to generated and send packets without proper keys, what happens in case
of failed ALPN check.

src/event/ngx_event_quic.c
src/event/ngx_event_quic.h

index 562a215ea3f6b428a282bb78ca48988c3165dab4..46827861a84300eeb4c35da61aad3b24d6b4d6ed 100644 (file)
@@ -393,6 +393,31 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
                    "quic ngx_quic_add_handshake_data");
 
     if (!qc->client_tp_done) {
+        /*
+         * things to do once during handshake: check ALPN and transport
+         * parameters; we want to break handshake if something is wrong
+         * here;
+         */
+
+#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
+        {
+        unsigned int          len;
+        const unsigned char  *data;
+
+        SSL_get0_alpn_selected(c->ssl->connection, &data, &len);
+
+        if (len != NGX_QUIC_ALPN_LEN
+            || ngx_strncmp(data, NGX_QUIC_ALPN_STR, NGX_QUIC_ALPN_LEN) != 0)
+        {
+            qc->error = 0x100 + SSL_AD_NO_APPLICATION_PROTOCOL;
+            qc->error_reason = "unsupported protocol in ALPN extension";
+
+            ngx_log_error(NGX_LOG_INFO, c->log, 0,
+                          "quic unsupported protocol in ALPN extension");
+            return 0;
+        }
+        }
+#endif
 
         SSL_get_peer_quic_transport_params(ssl_conn, &client_params,
                                            &client_params_len);
@@ -1298,9 +1323,8 @@ ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc)
                                qc->error_reason ? qc->error_reason : "");
             }
 
-            level = (qc->state == ssl_encryption_early_data)
-                    ? ssl_encryption_handshake
-                    : qc->state;
+            level = c->ssl ? SSL_quic_read_level(c->ssl->connection)
+                           : ssl_encryption_initial;
 
             (void) ngx_quic_send_cc(c, level, err, qc->error_ftype,
                                     qc->error_reason);
index fe67c3e6a28d61b2a3d644dbdfaff42b29f6cb96..8974a3392fe4c182fcea1cdc70eb696f1bb55f69 100644 (file)
 #endif
 #define NGX_QUIC_VERSION  (0xff000000 + NGX_QUIC_DRAFT_VERSION)
 
+#define NGX_QUIC_ALPN(s)         NGX_QUIC_ALPN_DRAFT(s)
+#define NGX_QUIC_ALPN_DRAFT(s)   "h3-" #s
+#define NGX_QUIC_ALPN_STR        NGX_QUIC_ALPN(NGX_QUIC_DRAFT_VERSION)
+#define NGX_QUIC_ALPN_LEN        (sizeof(NGX_QUIC_ALPN_STR) - 1)
+
 #define NGX_QUIC_MAX_SHORT_HEADER            25 /* 1 flags + 20 dcid + 4 pn */
 #define NGX_QUIC_MAX_LONG_HEADER             56
     /* 1 flags + 4 version + 2 x (1 + 20) s/dcid + 4 pn + 4 len + token len */