@@ -135,6 +135,7 @@ static const char *errors[] = {
135135 "v2 PROXY protocol header: invalid IPv6 dst IP" ,
136136 "v2 PROXY protocol header: invalid TLV vector's length" ,
137137 "v2 PROXY protocol header: invalid PP2_TYPE_CRC32C" ,
138+ "v2 PROXY protocol header: invalid PP2_TYPE_SSL" ,
138139 "v2 PROXY protocol header: invalid PP2_TYPE_UNIQUE_ID" ,
139140 "v2 PROXY protocol header: invalid PP2_TYPE_AWS" ,
140141 "v2 PROXY protocol header: invalid PP2_TYPE_AZURE" ,
@@ -153,7 +154,7 @@ static const char *errors[] = {
153154
154155const char * pp_strerror (int32_t error )
155156{
156- if (error < ERR_PP1_DST_PORT || error > ERR_NULL )
157+ if (error < ERR_HEAP_ALLOC || error > ERR_NULL )
157158 {
158159 return NULL ;
159160 }
@@ -213,6 +214,27 @@ static uint8_t tlv_array_append_tlv(tlv_array_t *tlv_array, tlv_t *tlv)
213214 return 1 ;
214215}
215216
217+ static uint8_t tlv_array_append_tlv_new (tlv_array_t * tlv_array , uint8_t type , uint16_t length , const void * value )
218+ {
219+ tlv_t * tlv = tlv_new (type , length , value );
220+ if (!tlv || !tlv_array_append_tlv (tlv_array , tlv ))
221+ {
222+ return 0 ;
223+ }
224+ return 1 ;
225+ }
226+
227+ static uint8_t tlv_array_append_tlv_new_usascii (tlv_array_t * tlv_array , uint8_t type , uint16_t length , const void * value )
228+ {
229+ tlv_t * tlv = tlv_new (type , length + 1 , value );
230+ if (!tlv || !tlv_array_append_tlv (tlv_array , tlv ))
231+ {
232+ return 0 ;
233+ }
234+ tlv -> value [length ] = '\0' ;
235+ return 1 ;
236+ }
237+
216238static void tlv_array_clear (tlv_array_t * tlv_array )
217239{
218240 uint32_t i ;
@@ -652,28 +674,14 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
652674
653675 switch (pp2_tlv -> type )
654676 {
655- case PP2_TYPE_ALPN :
656- {
657- tlv_t * tlv = tlv_new (pp2_tlv -> type , pp2_tlv_len , pp2_tlv -> value );
658- if (!tlv || !tlv_array_append_tlv (& pp_info -> tlv_array , tlv ))
659- {
660- return ERR_HEAP_ALLOC ;
661- }
662- break ;
663- }
664- case PP2_TYPE_AUTHORITY :
665- case PP2_TYPE_NETNS :
666- {
667- /* +1 to save it as a string */
668- tlv_t * tlv = tlv_new (pp2_tlv -> type , pp2_tlv_len + 1 , pp2_tlv -> value );
669- if (!tlv || !tlv_array_append_tlv (& pp_info -> tlv_array , tlv ))
677+ case PP2_TYPE_ALPN : /* Byte sequence */
678+ case PP2_TYPE_AUTHORITY : /* UTF8 */
679+ if (!tlv_array_append_tlv_new (& pp_info -> tlv_array , pp2_tlv -> type , pp2_tlv_len , pp2_tlv -> value ))
670680 {
671681 return ERR_HEAP_ALLOC ;
672682 }
673- tlv -> value [pp2_tlv_len ] = '\0' ;
674683 break ;
675- }
676- case PP2_TYPE_CRC32C :
684+ case PP2_TYPE_CRC32C : /* 32-bit number */
677685 {
678686 if (pp2_tlv_len != sizeof (uint32_t ))
679687 {
@@ -694,29 +702,75 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
694702 return ERR_PP2_TYPE_CRC32C ;
695703 }
696704
697- tlv_t * tlv = tlv_new (pp2_tlv -> type , pp2_tlv_len , & crc32c_chksum );
698- if (!tlv || !tlv_array_append_tlv (& pp_info -> tlv_array , tlv ))
705+ if (!tlv_array_append_tlv_new (& pp_info -> tlv_array , pp2_tlv -> type , pp2_tlv_len , & crc32c_chksum ))
699706 {
700707 return ERR_HEAP_ALLOC ;
701708 }
702709 break ;
703710 }
704711 case PP2_TYPE_NOOP :
705712 break ;
706- case PP2_TYPE_UNIQUE_ID :
707- {
713+ case PP2_TYPE_UNIQUE_ID : /* Byte sequence */
708714 if (pp2_tlv_len > 128 )
709715 {
710716 return ERR_PP2_TYPE_UNIQUE_ID ;
711717 }
712- tlv_t * tlv = tlv_new (pp2_tlv -> type , pp2_tlv_len , pp2_tlv -> value );
713- if (!tlv || !tlv_array_append_tlv (& pp_info -> tlv_array , tlv ))
718+ if (!tlv_array_append_tlv_new (& pp_info -> tlv_array , pp2_tlv -> type , pp2_tlv_len , pp2_tlv -> value ))
714719 {
715720 return ERR_HEAP_ALLOC ;
716721 }
717722 break ;
718- }
719723 case PP2_TYPE_SSL :
724+ {
725+ pp2_tlv_ssl_t * pp2_tlv_ssl = (pp2_tlv_ssl_t * )pp2_tlv -> value ;
726+ uint16_t pp2_tlvs_ssl_len = pp2_tlv_len - sizeof (pp2_tlv_ssl -> client ) - sizeof (pp2_tlv_ssl -> verify );
727+ uint16_t pp2_sub_tlv_offset = 0 ;
728+ while (pp2_tlvs_ssl_len )
729+ {
730+ if (!(pp2_tlv_ssl -> client & PP2_CLIENT_SSL || pp2_tlv_ssl -> client & PP2_CLIENT_CERT_CONN || pp2_tlv_ssl -> client & PP2_CLIENT_CERT_SESS ))
731+ {
732+ break ;
733+ }
734+ if (pp2_sub_tlv_offset > pp2_tlvs_ssl_len )
735+ {
736+ return ERR_PP2_TYPE_SSL ;
737+ }
738+ pp2_tlv_t * pp2_sub_tlv_ssl = (pp2_tlv_t * )((uint8_t * ) pp2_tlv_ssl -> sub_tlv + pp2_sub_tlv_offset );
739+ uint16_t pp2_sub_tlv_ssl_len = pp2_sub_tlv_ssl -> length_hi << 8 | pp2_sub_tlv_ssl -> length_lo ;
740+ switch (pp2_sub_tlv_ssl -> type )
741+ {
742+ case PP2_SUBTYPE_SSL_VERSION : /* US-ASCII */
743+ case PP2_SUBTYPE_SSL_CIPHER : /* US-ASCII */
744+ case PP2_SUBTYPE_SSL_SIG_ALG : /* US-ASCII */
745+ case PP2_SUBTYPE_SSL_KEY_ALG : /* US-ASCII */
746+ {
747+ /* +1 to save it as a string */
748+ if (!tlv_array_append_tlv_new_usascii (& pp_info -> tlv_array , pp2_sub_tlv_ssl -> type , pp2_sub_tlv_ssl_len , pp2_sub_tlv_ssl -> value ))
749+ {
750+ return ERR_HEAP_ALLOC ;
751+ }
752+ break ;
753+ }
754+ case PP2_SUBTYPE_SSL_CN : /* UTF8 */
755+ if (!tlv_array_append_tlv_new (& pp_info -> tlv_array , pp2_sub_tlv_ssl -> type , pp2_sub_tlv_ssl_len , pp2_sub_tlv_ssl -> value ))
756+ {
757+ return ERR_HEAP_ALLOC ;
758+ }
759+ break ;
760+ default :
761+ return ERR_PP2_TYPE_SSL ;
762+ }
763+
764+ pp2_tlvs_ssl_len = pp2_tlvs_ssl_len - 3 - pp2_sub_tlv_ssl_len ;
765+ pp2_sub_tlv_offset += 3 + pp2_sub_tlv_ssl_len ;
766+ }
767+ break ;
768+ }
769+ case PP2_TYPE_NETNS : /* US-ASCII */
770+ if (!tlv_array_append_tlv_new_usascii (& pp_info -> tlv_array , pp2_tlv -> type , pp2_tlv_len , pp2_tlv -> value ))
771+ {
772+ return ERR_HEAP_ALLOC ;
773+ }
720774 break ;
721775 case PP2_TYPE_AWS :
722776 {
@@ -726,15 +780,13 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
726780 }
727781 pp2_tlv_aws_t * pp2_tlv_aws = (pp2_tlv_aws_t * ) pp2_tlv -> value ;
728782 /* Connection is done through Private Link/Interface VPC endpoint */
729- if (pp2_tlv_aws -> type == PP2_SUBTYPE_AWS_VPCE_ID )
783+ if (pp2_tlv_aws -> type == PP2_SUBTYPE_AWS_VPCE_ID ) /* US-ASCII */
730784 {
731- /* +1 to save it as a string. Example: \x1vpce-08d2bf15fac5001c9 */
732- tlv_t * tlv = tlv_new (pp2_tlv -> type , pp2_tlv_len + 1 , pp2_tlv -> value );
733- if (!tlv || !tlv_array_append_tlv (& pp_info -> tlv_array , tlv ))
785+ /* Example: \x1vpce-08d2bf15fac5001c9 */
786+ if (!tlv_array_append_tlv_new_usascii (& pp_info -> tlv_array , pp2_tlv -> type , pp2_tlv_len , pp2_tlv -> value ))
734787 {
735788 return ERR_HEAP_ALLOC ;
736789 }
737- tlv -> value [pp2_tlv_len ] = '\0' ;
738790 }
739791 break ;
740792 }
@@ -746,7 +798,7 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
746798 }
747799 pp2_tlv_azure_t * pp2_tlv_azure = (pp2_tlv_azure_t * ) pp2_tlv -> value ;
748800 /* Connection is done through Private Link service */
749- if (pp2_tlv_azure -> type == PP2_TYPE_AZURE )
801+ if (pp2_tlv_azure -> type == PP2_TYPE_AZURE ) /* 32-bit number */
750802 {
751803 tlv_t * tlv = tlv_new (pp2_tlv -> type , pp2_tlv_len , pp2_tlv -> value );
752804 if (!tlv || !tlv_array_append_tlv (& pp_info -> tlv_array , tlv ))
0 commit comments