comparison src/event/quic/ngx_event_quic.c @ 8294:ba9e34c03968 quic

QUIC: added check of client transport parameters. Parameters sent by client are verified and defaults are set for parameters omitted by client.
author Vladimir Homutov <vl@nginx.com>
date Mon, 15 Feb 2021 14:05:46 +0300
parents 9ed95726b99b
children d4e02b3b734f
comparison
equal deleted inserted replaced
8293:75603531064a 8294:ba9e34c03968
223 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn); 223 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn);
224 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, 224 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
225 enum ssl_encryption_level_t level, uint8_t alert); 225 enum ssl_encryption_level_t level, uint8_t alert);
226 226
227 227
228 static ngx_int_t ngx_quic_apply_transport_params(ngx_connection_t *c,
229 ngx_quic_tp_t *ctp);
228 static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c, 230 static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c,
229 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); 231 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
230 static ngx_int_t ngx_quic_send_stateless_reset(ngx_connection_t *c, 232 static ngx_int_t ngx_quic_send_stateless_reset(ngx_connection_t *c,
231 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); 233 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
232 static ngx_int_t ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, 234 static ngx_int_t ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid,
830 enum ssl_encryption_level_t level, const uint8_t *data, size_t len) 832 enum ssl_encryption_level_t level, const uint8_t *data, size_t len)
831 { 833 {
832 u_char *p, *end; 834 u_char *p, *end;
833 size_t client_params_len; 835 size_t client_params_len;
834 const uint8_t *client_params; 836 const uint8_t *client_params;
837 ngx_quic_tp_t ctp;
835 ngx_quic_frame_t *frame; 838 ngx_quic_frame_t *frame;
836 ngx_connection_t *c; 839 ngx_connection_t *c;
837 ngx_quic_connection_t *qc; 840 ngx_quic_connection_t *qc;
838 ngx_quic_frames_stream_t *fs; 841 ngx_quic_frames_stream_t *fs;
839 842
886 } 889 }
887 890
888 p = (u_char *) client_params; 891 p = (u_char *) client_params;
889 end = p + client_params_len; 892 end = p + client_params_len;
890 893
891 if (ngx_quic_parse_transport_params(p, end, &qc->ctp, c->log) 894 /* defaults for parameters not sent by client */
895 ngx_memcpy(&ctp, &qc->ctp, sizeof(ngx_quic_tp_t));
896
897 if (ngx_quic_parse_transport_params(p, end, &ctp, c->log)
892 != NGX_OK) 898 != NGX_OK)
893 { 899 {
894 qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR; 900 qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
895 qc->error_reason = "failed to process transport parameters"; 901 qc->error_reason = "failed to process transport parameters";
896 902
897 return 0; 903 return 0;
898 } 904 }
899 905
900 if (qc->ctp.max_idle_timeout > 0 906 if (ngx_quic_apply_transport_params(c, &ctp) != NGX_OK) {
901 && qc->ctp.max_idle_timeout < qc->tp.max_idle_timeout)
902 {
903 qc->tp.max_idle_timeout = qc->ctp.max_idle_timeout;
904 }
905
906 if (qc->ctp.max_udp_payload_size < NGX_QUIC_MIN_INITIAL_SIZE
907 || qc->ctp.max_udp_payload_size > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE)
908 {
909 qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
910 qc->error_reason = "invalid maximum packet size";
911
912 ngx_log_error(NGX_LOG_INFO, c->log, 0,
913 "quic maximum packet size is invalid");
914 return 0; 907 return 0;
915 } 908 }
916
917 if (qc->ctp.max_udp_payload_size > ngx_quic_max_udp_payload(c)) {
918 qc->ctp.max_udp_payload_size = ngx_quic_max_udp_payload(c);
919 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
920 "quic client maximum packet size truncated");
921 }
922
923 #if (NGX_QUIC_DRAFT_VERSION >= 28)
924 if (qc->scid.len != qc->ctp.initial_scid.len
925 || ngx_memcmp(qc->scid.data, qc->ctp.initial_scid.data,
926 qc->scid.len) != 0)
927 {
928 ngx_log_error(NGX_LOG_INFO, c->log, 0,
929 "quic client initial_source_connection_id "
930 "mismatch");
931 return 0;
932 }
933 #endif
934
935 qc->streams.server_max_streams_bidi = qc->ctp.initial_max_streams_bidi;
936 qc->streams.server_max_streams_uni = qc->ctp.initial_max_streams_uni;
937 909
938 qc->client_tp_done = 1; 910 qc->client_tp_done = 1;
939 } 911 }
940 912
941 fs = &qc->crypto[level]; 913 fs = &qc->crypto[level];
1005 if (ngx_quic_send_cc(c) != NGX_OK) { 977 if (ngx_quic_send_cc(c) != NGX_OK) {
1006 return 0; 978 return 0;
1007 } 979 }
1008 980
1009 return 1; 981 return 1;
982 }
983
984
985 static ngx_int_t
986 ngx_quic_apply_transport_params(ngx_connection_t *c, ngx_quic_tp_t *ctp)
987 {
988 ngx_quic_connection_t *qc;
989
990 qc = ngx_quic_get_connection(c);
991
992 #if (NGX_QUIC_DRAFT_VERSION >= 28)
993 if (qc->scid.len != ctp->initial_scid.len
994 || ngx_memcmp(qc->scid.data, ctp->initial_scid.data, qc->scid.len) != 0)
995 {
996 ngx_log_error(NGX_LOG_INFO, c->log, 0,
997 "quic client initial_source_connection_id mismatch");
998 return NGX_ERROR;
999 }
1000 #endif
1001
1002 if (ctp->max_udp_payload_size < NGX_QUIC_MIN_INITIAL_SIZE
1003 || ctp->max_udp_payload_size > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE)
1004 {
1005 qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
1006 qc->error_reason = "invalid maximum packet size";
1007
1008 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1009 "quic maximum packet size is invalid");
1010 return NGX_ERROR;
1011
1012 } else if (ctp->max_udp_payload_size > ngx_quic_max_udp_payload(c)) {
1013 ctp->max_udp_payload_size = ngx_quic_max_udp_payload(c);
1014 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1015 "quic client maximum packet size truncated");
1016 }
1017
1018 if (ctp->active_connection_id_limit < 2) {
1019 qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
1020 qc->error_reason = "invalid active_connection_id_limit";
1021
1022 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1023 "quic active_connection_id_limit is invalid");
1024 return NGX_ERROR;
1025 }
1026
1027 if (ctp->ack_delay_exponent > 20) {
1028 qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
1029 qc->error_reason = "invalid ack_delay_exponent";
1030
1031 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1032 "quic ack_delay_exponent is invalid");
1033 return NGX_ERROR;
1034 }
1035
1036 if (ctp->max_ack_delay > 16384) {
1037 qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
1038 qc->error_reason = "invalid max_ack_delay";
1039
1040 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1041 "quic max_ack_delay is invalid");
1042 return NGX_ERROR;
1043 }
1044
1045 if (ctp->max_idle_timeout > 0
1046 && ctp->max_idle_timeout < qc->tp.max_idle_timeout)
1047 {
1048 qc->tp.max_idle_timeout = ctp->max_idle_timeout;
1049 }
1050
1051 qc->streams.server_max_streams_bidi = ctp->initial_max_streams_bidi;
1052 qc->streams.server_max_streams_uni = ctp->initial_max_streams_uni;
1053
1054 ngx_memcpy(&qc->ctp, ctp, sizeof(ngx_quic_tp_t));
1055
1056 return NGX_OK;
1010 } 1057 }
1011 1058
1012 1059
1013 void 1060 void
1014 ngx_quic_run(ngx_connection_t *c, ngx_quic_conf_t *conf) 1061 ngx_quic_run(ngx_connection_t *c, ngx_quic_conf_t *conf)
1122 ngx_memcpy(qc->sockaddr, c->sockaddr, c->socklen); 1169 ngx_memcpy(qc->sockaddr, c->sockaddr, c->socklen);
1123 qc->socklen = c->socklen; 1170 qc->socklen = c->socklen;
1124 } 1171 }
1125 1172
1126 ctp = &qc->ctp; 1173 ctp = &qc->ctp;
1174
1175 /* defaults to be used before actual client parameters are received */
1127 ctp->max_udp_payload_size = ngx_quic_max_udp_payload(c); 1176 ctp->max_udp_payload_size = ngx_quic_max_udp_payload(c);
1128 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT; 1177 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT;
1129 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY; 1178 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY;
1179 ctp->active_connection_id_limit = 2;
1130 1180
1131 qc->streams.recv_max_data = qc->tp.initial_max_data; 1181 qc->streams.recv_max_data = qc->tp.initial_max_data;
1132 1182
1133 qc->streams.client_max_streams_uni = qc->tp.initial_max_streams_uni; 1183 qc->streams.client_max_streams_uni = qc->tp.initial_max_streams_uni;
1134 qc->streams.client_max_streams_bidi = qc->tp.initial_max_streams_bidi; 1184 qc->streams.client_max_streams_bidi = qc->tp.initial_max_streams_bidi;