diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h index d84e3e63d..abd0ebe6c 100644 --- a/src/event/quic/ngx_event_quic_connection.h +++ b/src/event/quic/ngx_event_quic_connection.h @@ -106,8 +106,7 @@ struct ngx_quic_path_s { size_t max_mtu; off_t sent; off_t received; - u_char challenge1[8]; - u_char challenge2[8]; + u_char challenge[2][8]; uint64_t seqnum; uint64_t mtu_pnum[NGX_QUIC_PATH_RETRIES]; ngx_str_t addr_text; diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c index bcec9af1d..2fccafa41 100644 --- a/src/event/quic/ngx_event_quic_migration.c +++ b/src/event/quic/ngx_event_quic_migration.c @@ -36,6 +36,7 @@ ngx_int_t ngx_quic_handle_path_challenge_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, ngx_quic_path_challenge_frame_t *f) { + size_t min; ngx_quic_frame_t frame, *fp; ngx_quic_connection_t *qc; @@ -57,8 +58,14 @@ ngx_quic_handle_path_challenge_frame(ngx_connection_t *c, /* * 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. */ - if (ngx_quic_frame_sendto(c, &frame, 1200, pkt->path) == NGX_ERROR) { + + min = (ngx_quic_path_limit(c, pkt->path, 1200) < 1200) ? 0 : 1200; + + if (ngx_quic_frame_sendto(c, &frame, min, pkt->path) == NGX_ERROR) { return NGX_ERROR; } @@ -113,8 +120,8 @@ ngx_quic_handle_path_response_frame(ngx_connection_t *c, continue; } - if (ngx_memcmp(path->challenge1, f->data, sizeof(f->data)) == 0 - || ngx_memcmp(path->challenge2, f->data, sizeof(f->data)) == 0) + if (ngx_memcmp(path->challenge[0], f->data, sizeof(f->data)) == 0 + || ngx_memcmp(path->challenge[1], f->data, sizeof(f->data)) == 0) { goto valid; } @@ -510,11 +517,7 @@ ngx_quic_validate_path(ngx_connection_t *c, ngx_quic_path_t *path) path->tries = 0; - if (RAND_bytes(path->challenge1, 8) != 1) { - return NGX_ERROR; - } - - if (RAND_bytes(path->challenge2, 8) != 1) { + if (RAND_bytes((u_char *) path->challenge, sizeof(path->challenge)) != 1) { return NGX_ERROR; } @@ -535,6 +538,8 @@ ngx_quic_validate_path(ngx_connection_t *c, ngx_quic_path_t *path) static ngx_int_t ngx_quic_send_path_challenge(ngx_connection_t *c, ngx_quic_path_t *path) { + size_t min; + ngx_uint_t n; ngx_quic_frame_t frame; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, @@ -546,26 +551,24 @@ ngx_quic_send_path_challenge(ngx_connection_t *c, ngx_quic_path_t *path) frame.level = ssl_encryption_application; frame.type = NGX_QUIC_FT_PATH_CHALLENGE; - ngx_memcpy(frame.u.path_challenge.data, path->challenge1, 8); + for (n = 0; n < 2; n++) { - /* - * RFC 9000, 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. - */ + ngx_memcpy(frame.u.path_challenge.data, path->challenge[n], 8); - /* same applies to PATH_RESPONSE frames */ - if (ngx_quic_frame_sendto(c, &frame, 1200, path) == NGX_ERROR) { - return NGX_ERROR; - } + /* + * RFC 9000, 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. + */ - ngx_memcpy(frame.u.path_challenge.data, path->challenge2, 8); + min = (ngx_quic_path_limit(c, path, 1200) < 1200) ? 0 : 1200; - if (ngx_quic_frame_sendto(c, &frame, 1200, path) == NGX_ERROR) { - return NGX_ERROR; + if (ngx_quic_frame_sendto(c, &frame, min, path) == NGX_ERROR) { + return NGX_ERROR; + } } return NGX_OK; diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c index 914d81921..a0acdb700 100644 --- a/src/event/quic/ngx_event_quic_output.c +++ b/src/event/quic/ngx_event_quic_output.c @@ -63,8 +63,6 @@ static ssize_t ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len, struct sockaddr *sockaddr, socklen_t socklen); static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt, ngx_quic_send_ctx_t *ctx); -static size_t ngx_quic_path_limit(ngx_connection_t *c, ngx_quic_path_t *path, - size_t size); ngx_int_t @@ -1250,7 +1248,7 @@ ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame, } -static size_t +size_t ngx_quic_path_limit(ngx_connection_t *c, ngx_quic_path_t *path, size_t size) { off_t max; diff --git a/src/event/quic/ngx_event_quic_output.h b/src/event/quic/ngx_event_quic_output.h index 19f8990f4..52d8a374f 100644 --- a/src/event/quic/ngx_event_quic_output.h +++ b/src/event/quic/ngx_event_quic_output.h @@ -34,5 +34,7 @@ ngx_int_t ngx_quic_send_ack_range(ngx_connection_t *c, ngx_int_t ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame, size_t min, ngx_quic_path_t *path); +size_t ngx_quic_path_limit(ngx_connection_t *c, ngx_quic_path_t *path, + size_t size); #endif /* _NGX_EVENT_QUIC_OUTPUT_H_INCLUDED_ */