comparison src/event/quic/ngx_event_quic_migration.c @ 9189:fcec773dd249

QUIC: avoid partial expansion of PATH_CHALLENGE/PATH_RESPONSE. By default packets with these frames are expanded to 1200 bytes. Previously, if anti-amplification limit did not allow this expansion, it was limited to whatever size was allowed. However RFC 9000 clearly states no partial expansion should happen in both cases. Section 8.2.1. Initiating Path Validation: An endpoint MUST expand datagrams that contain a PATH_CHALLENGE frame to at least the smallest allowed maximum datagram size of 1200 bytes, unless the anti-amplification limit for the path does not permit sending a datagram of this size. Section 8.2.2. Path Validation Responses: An endpoint MUST expand datagrams that contain a PATH_RESPONSE frame to at least the smallest allowed maximum datagram size of 1200 bytes. ... However, an endpoint MUST NOT expand the datagram containing the PATH_RESPONSE if the resulting data exceeds the anti-amplification limit.
author Roman Arutyunyan <arut@nginx.com>
date Wed, 29 Nov 2023 18:13:25 +0400
parents f6b6f3dd7ca0
children 3a67dd34b6cc
comparison
equal deleted inserted replaced
9188:b05c622715fa 9189:fcec773dd249
34 34
35 ngx_int_t 35 ngx_int_t
36 ngx_quic_handle_path_challenge_frame(ngx_connection_t *c, 36 ngx_quic_handle_path_challenge_frame(ngx_connection_t *c,
37 ngx_quic_header_t *pkt, ngx_quic_path_challenge_frame_t *f) 37 ngx_quic_header_t *pkt, ngx_quic_path_challenge_frame_t *f)
38 { 38 {
39 size_t min;
39 ngx_quic_frame_t frame, *fp; 40 ngx_quic_frame_t frame, *fp;
40 ngx_quic_connection_t *qc; 41 ngx_quic_connection_t *qc;
41 42
42 qc = ngx_quic_get_connection(c); 43 qc = ngx_quic_get_connection(c);
43 44
55 */ 56 */
56 57
57 /* 58 /*
58 * An endpoint MUST expand datagrams that contain a PATH_RESPONSE frame 59 * An endpoint MUST expand datagrams that contain a PATH_RESPONSE frame
59 * to at least the smallest allowed maximum datagram size of 1200 bytes. 60 * to at least the smallest allowed maximum datagram size of 1200 bytes.
60 */ 61 * ...
61 if (ngx_quic_frame_sendto(c, &frame, 1200, pkt->path) == NGX_ERROR) { 62 * However, an endpoint MUST NOT expand the datagram containing the
63 * PATH_RESPONSE if the resulting data exceeds the anti-amplification limit.
64 */
65
66 min = (ngx_quic_path_limit(c, pkt->path, 1200) < 1200) ? 0 : 1200;
67
68 if (ngx_quic_frame_sendto(c, &frame, min, pkt->path) == NGX_ERROR) {
62 return NGX_ERROR; 69 return NGX_ERROR;
63 } 70 }
64 71
65 if (pkt->path == qc->path) { 72 if (pkt->path == qc->path) {
66 /* 73 /*
111 118
112 if (path->state != NGX_QUIC_PATH_VALIDATING) { 119 if (path->state != NGX_QUIC_PATH_VALIDATING) {
113 continue; 120 continue;
114 } 121 }
115 122
116 if (ngx_memcmp(path->challenge1, f->data, sizeof(f->data)) == 0 123 if (ngx_memcmp(path->challenge[0], f->data, sizeof(f->data)) == 0
117 || ngx_memcmp(path->challenge2, f->data, sizeof(f->data)) == 0) 124 || ngx_memcmp(path->challenge[1], f->data, sizeof(f->data)) == 0)
118 { 125 {
119 goto valid; 126 goto valid;
120 } 127 }
121 } 128 }
122 129
508 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 515 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
509 "quic initiated validation of path seq:%uL", path->seqnum); 516 "quic initiated validation of path seq:%uL", path->seqnum);
510 517
511 path->tries = 0; 518 path->tries = 0;
512 519
513 if (RAND_bytes(path->challenge1, 8) != 1) { 520 if (RAND_bytes((u_char *) path->challenge, sizeof(path->challenge)) != 1) {
514 return NGX_ERROR;
515 }
516
517 if (RAND_bytes(path->challenge2, 8) != 1) {
518 return NGX_ERROR; 521 return NGX_ERROR;
519 } 522 }
520 523
521 (void) ngx_quic_send_path_challenge(c, path); 524 (void) ngx_quic_send_path_challenge(c, path);
522 525
533 536
534 537
535 static ngx_int_t 538 static ngx_int_t
536 ngx_quic_send_path_challenge(ngx_connection_t *c, ngx_quic_path_t *path) 539 ngx_quic_send_path_challenge(ngx_connection_t *c, ngx_quic_path_t *path)
537 { 540 {
541 size_t min;
542 ngx_uint_t n;
538 ngx_quic_frame_t frame; 543 ngx_quic_frame_t frame;
539 544
540 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 545 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
541 "quic path seq:%uL send path_challenge tries:%ui", 546 "quic path seq:%uL send path_challenge tries:%ui",
542 path->seqnum, path->tries); 547 path->seqnum, path->tries);
544 ngx_memzero(&frame, sizeof(ngx_quic_frame_t)); 549 ngx_memzero(&frame, sizeof(ngx_quic_frame_t));
545 550
546 frame.level = ssl_encryption_application; 551 frame.level = ssl_encryption_application;
547 frame.type = NGX_QUIC_FT_PATH_CHALLENGE; 552 frame.type = NGX_QUIC_FT_PATH_CHALLENGE;
548 553
549 ngx_memcpy(frame.u.path_challenge.data, path->challenge1, 8); 554 for (n = 0; n < 2; n++) {
550 555
551 /* 556 ngx_memcpy(frame.u.path_challenge.data, path->challenge[n], 8);
552 * RFC 9000, 8.2.1. Initiating Path Validation 557
553 * 558 /*
554 * An endpoint MUST expand datagrams that contain a PATH_CHALLENGE frame 559 * RFC 9000, 8.2.1. Initiating Path Validation
555 * to at least the smallest allowed maximum datagram size of 1200 bytes, 560 *
556 * unless the anti-amplification limit for the path does not permit 561 * An endpoint MUST expand datagrams that contain a PATH_CHALLENGE frame
557 * sending a datagram of this size. 562 * to at least the smallest allowed maximum datagram size of 1200 bytes,
558 */ 563 * unless the anti-amplification limit for the path does not permit
559 564 * sending a datagram of this size.
560 /* same applies to PATH_RESPONSE frames */ 565 */
561 if (ngx_quic_frame_sendto(c, &frame, 1200, path) == NGX_ERROR) { 566
562 return NGX_ERROR; 567 min = (ngx_quic_path_limit(c, path, 1200) < 1200) ? 0 : 1200;
563 } 568
564 569 if (ngx_quic_frame_sendto(c, &frame, min, path) == NGX_ERROR) {
565 ngx_memcpy(frame.u.path_challenge.data, path->challenge2, 8); 570 return NGX_ERROR;
566 571 }
567 if (ngx_quic_frame_sendto(c, &frame, 1200, path) == NGX_ERROR) {
568 return NGX_ERROR;
569 } 572 }
570 573
571 return NGX_OK; 574 return NGX_OK;
572 } 575 }
573 576