comparison src/event/ngx_event_quic.c @ 7689:61f9b873e2e7 quic

Firefox fixes. + support for more than one initial packet + workaround for trailing zeroes in packet + ignore application data packet if no keys yet (issue in draft 27/ff nightly) + fixed PING frame parser + STREAM frames need to be acknowledged The following HTTP configuration is used for firefox (v74): http { ssl_certificate_key localhost.key; ssl_certificate localhost.crt; ssl_protocols TLSv1.2 TLSv1.3; server { listen 127.0.0.1:10368 reuseport http3; ssl_quic on; server_name localhost; location / { return 200 "This-is-QUICK\n"; } } server { listen 127.0.0.1:5555 ssl; # point the browser here server_name localhost; location / { add_header Alt-Svc 'h3-24=":10368";ma=100'; return 200 "ALT-SVC"; } } }
author Vladimir Homutov <vl@nginx.com>
date Tue, 17 Mar 2020 14:10:37 +0300
parents bec4cd55361e
children ae35ccba7aa6
comparison
equal deleted inserted replaced
7688:bec4cd55361e 7689:61f9b873e2e7
203 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); 203 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
204 204
205 static void ngx_quic_handshake_handler(ngx_event_t *rev); 205 static void ngx_quic_handshake_handler(ngx_event_t *rev);
206 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c, 206 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c,
207 ngx_quic_header_t *pkt); 207 ngx_quic_header_t *pkt);
208 static ngx_int_t ngx_quic_initial_input(ngx_connection_t *c,
209 ngx_quic_header_t *pkt);
208 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c, 210 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c,
209 ngx_quic_header_t *pkt); 211 ngx_quic_header_t *pkt);
210 212
211 213
212 #if BORINGSSL_API_VERSION >= 10 214 #if BORINGSSL_API_VERSION >= 10
387 389
388 static ngx_int_t 390 static ngx_int_t
389 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b) 391 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b)
390 { 392 {
391 u_char *p; 393 u_char *p;
394 ngx_int_t rc;
392 ngx_quic_header_t pkt; 395 ngx_quic_header_t pkt;
393 396
394 if (c->quic == NULL) { 397 if (c->quic == NULL) {
395 // XXX: possible? 398 // XXX: possible?
396 ngx_log_error(NGX_LOG_INFO, c->log, 0, "BUG: no QUIC in connection"); 399 ngx_log_error(NGX_LOG_INFO, c->log, 0, "BUG: no QUIC in connection");
403 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); 406 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
404 pkt.raw = b; 407 pkt.raw = b;
405 pkt.data = p; 408 pkt.data = p;
406 pkt.len = b->last - p; 409 pkt.len = b->last - p;
407 410
411 if (p[0] == 0) {
412 /* XXX: no idea WTF is this, just ignore */
413 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "FIREFOX: ZEROES");
414 break;
415 }
416
417 // TODO: check current state
408 if (p[0] & NGX_QUIC_PKT_LONG) { 418 if (p[0] & NGX_QUIC_PKT_LONG) {
409 // TODO: check current state 419
410 if (ngx_quic_handshake_input(c, &pkt) != NGX_OK) { 420 if ((p[0] & 0xf0) == NGX_QUIC_PKT_INITIAL) {
421 rc = ngx_quic_initial_input(c, &pkt);
422
423 } else if ((p[0] & 0xf0) == NGX_QUIC_PKT_HANDSHAKE) {
424 rc = ngx_quic_handshake_input(c, &pkt);
425
426 } else {
427 ngx_log_error(NGX_LOG_INFO, c->log, 0,
428 "BUG: unknown quic state");
411 return NGX_ERROR; 429 return NGX_ERROR;
412 } 430 }
431
413 } else { 432 } else {
414 433 rc = ngx_quic_app_input(c, &pkt);
415 if (ngx_quic_app_input(c, &pkt) != NGX_OK) { 434 }
416 return NGX_ERROR; 435
417 } 436 if (rc == NGX_ERROR) {
437 return NGX_ERROR;
418 } 438 }
419 439
420 /* b->pos is at header end, adjust by actual packet length */ 440 /* b->pos is at header end, adjust by actual packet length */
421 p = b->pos + pkt.len; 441 p = b->pos + pkt.len;
422 b->pos = p; /* reset b->pos to the next packet start */ 442 b->pos = p; /* reset b->pos to the next packet start */
1071 1091
1072 break; 1092 break;
1073 1093
1074 case NGX_QUIC_FT_PING: 1094 case NGX_QUIC_FT_PING:
1075 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "PING frame"); 1095 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "PING frame");
1076 p++;
1077 break; 1096 break;
1078 1097
1079 case NGX_QUIC_FT_NEW_CONNECTION_ID: 1098 case NGX_QUIC_FT_NEW_CONNECTION_ID:
1080 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "NCID frame"); 1099 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "NCID frame");
1081 1100
1487 case NGX_QUIC_FT_STREAM4: 1506 case NGX_QUIC_FT_STREAM4:
1488 case NGX_QUIC_FT_STREAM5: 1507 case NGX_QUIC_FT_STREAM5:
1489 case NGX_QUIC_FT_STREAM6: 1508 case NGX_QUIC_FT_STREAM6:
1490 case NGX_QUIC_FT_STREAM7: 1509 case NGX_QUIC_FT_STREAM7:
1491 1510
1511 ack_this = 1;
1512
1492 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0, 1513 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
1493 "STREAM frame 0x%xi id 0x%xi offset 0x%xi len 0x%xi bits:off=%d len=%d fin=%d", 1514 "STREAM frame 0x%xi id 0x%xi offset 0x%xi len 0x%xi bits:off=%d len=%d fin=%d",
1494 frame.type, 1515 frame.type,
1495 frame.u.stream.stream_id, 1516 frame.u.stream.stream_id,
1496 frame.u.stream.offset, 1517 frame.u.stream.offset,
1773 return ngx_quic_payload_handler(c, pkt); 1794 return ngx_quic_payload_handler(c, pkt);
1774 } 1795 }
1775 1796
1776 1797
1777 static ngx_int_t 1798 static ngx_int_t
1799 ngx_quic_initial_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
1800 {
1801 ngx_ssl_conn_t *ssl_conn;
1802 ngx_quic_connection_t *qc;
1803
1804 qc = c->quic;
1805 ssl_conn = c->ssl->connection;
1806
1807 if (ngx_quic_process_long_header(c, pkt) != NGX_OK) {
1808 return NGX_ERROR;
1809 }
1810
1811 if (ngx_quic_process_initial_header(c, pkt) != NGX_OK) {
1812 return NGX_ERROR;
1813 }
1814
1815 pkt->secret = &qc->secrets.client.in;
1816 pkt->level = ssl_encryption_initial;
1817
1818 if (ngx_quic_decrypt(c->pool, ssl_conn, pkt) != NGX_OK) {
1819 return NGX_ERROR;
1820 }
1821
1822 return ngx_quic_payload_handler(c, pkt);
1823 }
1824
1825
1826 static ngx_int_t
1778 ngx_quic_handshake_input(ngx_connection_t *c, ngx_quic_header_t *pkt) 1827 ngx_quic_handshake_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
1779 { 1828 {
1780 ngx_ssl_conn_t *ssl_conn; 1829 ngx_ssl_conn_t *ssl_conn;
1781 ngx_quic_connection_t *qc; 1830 ngx_quic_connection_t *qc;
1782 1831
1834 { 1883 {
1835 ngx_quic_connection_t *qc; 1884 ngx_quic_connection_t *qc;
1836 1885
1837 qc = c->quic; 1886 qc = c->quic;
1838 1887
1839 /* TODO: this is a stub, untested */ 1888 if (qc->secrets.client.ad.key.len == 0) {
1889 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1890 "no read keys yet, packet ignored");
1891 return NGX_DECLINED;
1892 }
1840 1893
1841 if (ngx_quic_process_short_header(c, pkt) != NGX_OK) { 1894 if (ngx_quic_process_short_header(c, pkt) != NGX_OK) {
1842 return NGX_ERROR; 1895 return NGX_ERROR;
1843 } 1896 }
1844 1897