comparison src/event/ngx_event_quic.c @ 8240:1f002206a59b quic

Added boundaries checks into frame parser. The ngx_quic_parse_frame() functions now has new 'pkt' argument: the packet header of a currently processed frame. This allows to log errors/debug closer to reasons and perform additional checks regarding possible frame types. The handler only performs processing of good frames. A number of functions like read_uint32(), parse_int[_multi] probably should be implemented as a macro, but currently it is better to have them as functions for simpler debugging.
author Vladimir Homutov <vl@nginx.com>
date Thu, 19 Mar 2020 17:07:12 +0300
parents 5ad7bffd3850
children db745339e54b
comparison
equal deleted inserted replaced
8239:5ad7bffd3850 8240:1f002206a59b
719 ack_this = 0; 719 ack_this = 0;
720 do_close = 0; 720 do_close = 0;
721 721
722 while (p < end) { 722 while (p < end) {
723 723
724 len = ngx_quic_parse_frame(p, end, &frame); 724 len = ngx_quic_parse_frame(pkt, p, end, &frame);
725 if (len < 0) { 725 if (len < 0) {
726 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
727 "failed to parse frame type 0x%xi", frame.type);
728 return NGX_ERROR; 726 return NGX_ERROR;
729 } 727 }
730 728
731 p += len; 729 p += len;
732 730
733 switch (frame.type) { 731 switch (frame.type) {
734 732
735 case NGX_QUIC_FT_ACK: 733 case NGX_QUIC_FT_ACK:
736
737 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
738 "ACK: { largest=%ui delay=%ui first=%ui count=%ui}",
739 frame.u.ack.largest,
740 frame.u.ack.delay,
741 frame.u.ack.first_range,
742 frame.u.ack.range_count);
743
744 if (ngx_quic_handle_ack_frame(c, pkt, &frame.u.ack) != NGX_OK) { 734 if (ngx_quic_handle_ack_frame(c, pkt, &frame.u.ack) != NGX_OK) {
745 return NGX_ERROR; 735 return NGX_ERROR;
746 } 736 }
747 737
748 break; 738 break;
749 739
750 case NGX_QUIC_FT_CRYPTO: 740 case NGX_QUIC_FT_CRYPTO:
751
752 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
753 "quic CRYPTO frame length: %uL off:%uL pp:%p",
754 frame.u.crypto.len, frame.u.crypto.offset,
755 frame.u.crypto.data);
756
757 ngx_quic_hexdump0(c->log, "CRYPTO frame contents",
758 frame.u.crypto.data, frame.u.crypto.len);
759
760 741
761 if (ngx_quic_handle_crypto_frame(c, pkt, &frame.u.crypto) 742 if (ngx_quic_handle_crypto_frame(c, pkt, &frame.u.crypto)
762 != NGX_OK) 743 != NGX_OK)
763 { 744 {
764 return NGX_ERROR; 745 return NGX_ERROR;
774 ack_this = 1; 755 ack_this = 1;
775 break; 756 break;
776 757
777 case NGX_QUIC_FT_NEW_CONNECTION_ID: 758 case NGX_QUIC_FT_NEW_CONNECTION_ID:
778 ack_this = 1; 759 ack_this = 1;
779 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
780 "NCID: { seq=%ui retire=%ui len=%ui}",
781 frame.u.ncid.seqnum,
782 frame.u.ncid.retire,
783 frame.u.ncid.len);
784 break; 760 break;
785 761
786 case NGX_QUIC_FT_CONNECTION_CLOSE: 762 case NGX_QUIC_FT_CONNECTION_CLOSE:
787 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
788 "CONN.CLOSE: { %s (0x%xi) type=0x%xi reason='%V'}",
789 ngx_quic_error_text(frame.u.close.error_code),
790 frame.u.close.error_code,
791 frame.u.close.frame_type,
792 &frame.u.close.reason);
793 763
794 do_close = 1; 764 do_close = 1;
795 break; 765 break;
796 766
797 case NGX_QUIC_FT_STREAM0: 767 case NGX_QUIC_FT_STREAM0:
801 case NGX_QUIC_FT_STREAM4: 771 case NGX_QUIC_FT_STREAM4:
802 case NGX_QUIC_FT_STREAM5: 772 case NGX_QUIC_FT_STREAM5:
803 case NGX_QUIC_FT_STREAM6: 773 case NGX_QUIC_FT_STREAM6:
804 case NGX_QUIC_FT_STREAM7: 774 case NGX_QUIC_FT_STREAM7:
805 775
806 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
807 "STREAM frame { 0x%xi id 0x%xi offset 0x%xi len 0x%xi bits:off=%d len=%d fin=%d }",
808 frame.type,
809 frame.u.stream.stream_id,
810 frame.u.stream.offset,
811 frame.u.stream.length,
812 frame.u.stream.off,
813 frame.u.stream.len,
814 frame.u.stream.fin);
815
816 ngx_quic_hexdump0(c->log, "STREAM frame contents",
817 frame.u.stream.data, frame.u.stream.length);
818
819 if (ngx_quic_handle_stream_frame(c, pkt, &frame.u.stream) 776 if (ngx_quic_handle_stream_frame(c, pkt, &frame.u.stream)
820 != NGX_OK) 777 != NGX_OK)
821 { 778 {
822 return NGX_ERROR; 779 return NGX_ERROR;
823 } 780 }
824 781
825 ack_this = 1; 782 ack_this = 1;
826 break; 783 break;
827 784
828 case NGX_QUIC_FT_MAX_DATA: 785 case NGX_QUIC_FT_MAX_DATA:
829 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
830 "MAX_DATA frame"
831 " { Maximum Data %ui }",
832 frame.u.max_data.max_data);
833
834 c->quic->max_data = frame.u.max_data.max_data; 786 c->quic->max_data = frame.u.max_data.max_data;
835 ack_this = 1; 787 ack_this = 1;
836 break; 788 break;
837 789
838 case NGX_QUIC_FT_RESET_STREAM: 790 case NGX_QUIC_FT_RESET_STREAM:
839 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, 791 /* TODO: handle */
840 "RESET STREAM frame"
841 " { id 0x%xi error_code 0x%xi final_size 0x%xi }",
842 frame.u.reset_stream.id,
843 frame.u.reset_stream.error_code,
844 frame.u.reset_stream.final_size);
845 break; 792 break;
846 793
847 case NGX_QUIC_FT_STOP_SENDING: 794 case NGX_QUIC_FT_STOP_SENDING:
848 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 795 /* TODO: handle; need ack ? */
849 "STOP SENDING frame"
850 " { id 0x%xi error_code 0x%xi}",
851 frame.u.stop_sending.id,
852 frame.u.stop_sending.error_code);
853 break; 796 break;
854 797
855 case NGX_QUIC_FT_STREAMS_BLOCKED: 798 case NGX_QUIC_FT_STREAMS_BLOCKED:
856 case NGX_QUIC_FT_STREAMS_BLOCKED2: 799 case NGX_QUIC_FT_STREAMS_BLOCKED2:
857 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 800 /* TODO: handle; need ack ? */
858 "STREAMS BLOCKED frame"
859 " { limit %i bidi: %d }",
860 frame.u.streams_blocked.limit,
861 frame.u.streams_blocked.bidi);
862 break; 801 break;
863 802
864 default: 803 default:
865 ngx_log_error(NGX_LOG_INFO, c->log, 0,
866 "unsupported frame type 0x%xd in packet", frame.type);
867 return NGX_ERROR; 804 return NGX_ERROR;
868 } 805 }
869 } 806 }
870 807
871 if (p != end) { 808 if (p != end) {