@@ -181,7 +181,7 @@ static int read_sock(int sockfd, void *buf, size_t reqlen) {
181
181
182
182
session .total_raw_in += reqlen ;
183
183
184
- if (res == remainlen ) {
184
+ if (( size_t ) res == remainlen ) {
185
185
break ;
186
186
}
187
187
@@ -616,6 +616,220 @@ static int read_haproxy_v1(pool *p, conn_t *conn,
616
616
617
617
static const char haproxy_v2_sig [12 ] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A" ;
618
618
619
+ /* The TLS TLV is convoluted enough to warrant its own special function. */
620
+ static int read_haproxy_v2_tls_tlv (pool * p , void * tlv_val , size_t tlv_valsz ) {
621
+ uint8_t client ;
622
+ uint32_t verify ;
623
+ unsigned char * ptr ;
624
+ size_t len ;
625
+
626
+ ptr = tlv_val ;
627
+ len = tlv_valsz ;
628
+
629
+ memcpy (& client , ptr , sizeof (client ));
630
+ ptr += sizeof (client );
631
+ len -= sizeof (client );
632
+
633
+ memcpy (& verify , ptr , sizeof (verify ));
634
+ ptr += sizeof (verify );
635
+ len -= sizeof (verify );
636
+
637
+ if (client > 0 ) {
638
+ /* CLIENT_CERT_CONN */
639
+ if (client & 0x02 ) {
640
+ pr_trace_msg (trace_channel , 19 ,
641
+ "TLS TLV: client provided certificate over current connection" );
642
+
643
+ /* CLIENT_CERT_SESS */
644
+ } else if (client & 0x04 ) {
645
+ pr_trace_msg (trace_channel , 19 ,
646
+ "TLS TLV: client provided certificate over current TLS session" );
647
+
648
+ } else {
649
+ pr_trace_msg (trace_channel , 19 , "TLS TLV: client connected using TLS" );
650
+ }
651
+
652
+ } else {
653
+ pr_trace_msg (trace_channel , 19 , "TLS TLV: client did connect using TLS" );
654
+ }
655
+
656
+ if (verify > 0 ) {
657
+ pr_trace_msg (trace_channel , 19 ,
658
+ "TLS TLV: client provided verified certificate" );
659
+ }
660
+
661
+ while (len > 0 ) {
662
+ uint8_t tls_type ;
663
+ uint16_t tls_len ;
664
+ void * tls_val ;
665
+ size_t tls_valsz ;
666
+
667
+ pr_signals_handle ();
668
+
669
+ memcpy (& tls_type , ptr , sizeof (tls_type ));
670
+ ptr += sizeof (tls_type );
671
+ len -= sizeof (tls_type );
672
+
673
+ memcpy (& tls_len , ptr , sizeof (tls_len ));
674
+ ptr += sizeof (tls_len );
675
+ len -= sizeof (tls_len );
676
+
677
+ tls_valsz = ntohs (tls_len );
678
+ tls_val = ptr ;
679
+ len -= tls_valsz ;
680
+
681
+ switch (tls_type ) {
682
+ /* TLS version */
683
+ case 0x21 :
684
+ pr_trace_msg (trace_channel , 19 ,
685
+ "TLS TLV: TLS version: %.*s" , (int ) tls_valsz , (char * ) tls_val );
686
+ break ;
687
+
688
+ /* TLS CN */
689
+ case 0x22 :
690
+ pr_trace_msg (trace_channel , 19 ,
691
+ "TLS TLV: TLS CN: %*.s" , (int ) tls_valsz , (char * ) tls_val );
692
+ break ;
693
+
694
+ /* TLS cipher */
695
+ case 0x23 :
696
+ pr_trace_msg (trace_channel , 19 ,
697
+ "TLS TLV: TLS cipher: %.*s" , (int ) tls_valsz , (char * ) tls_val );
698
+ break ;
699
+
700
+ /* TLS signature algorithm */
701
+ case 0x24 :
702
+ pr_trace_msg (trace_channel , 19 ,
703
+ "TLS TLV: TLS signature algorithm: %.*s" , (int ) tls_valsz ,
704
+ (char * ) tls_val );
705
+ break ;
706
+
707
+ /* TLS key algorithm */
708
+ case 0x25 :
709
+ pr_trace_msg (trace_channel , 19 ,
710
+ "TLS TLV: TLS key algorithm: %.*s" , (int ) tls_valsz ,
711
+ (char * ) tls_val );
712
+ break ;
713
+
714
+ default :
715
+ pr_trace_msg (trace_channel , 3 ,
716
+ "unsupported TLS TLV: %0x" , tls_type );
717
+ }
718
+ }
719
+
720
+ return 0 ;
721
+ }
722
+
723
+ static int read_haproxy_v2_tlvs (pool * p , conn_t * conn , size_t len ) {
724
+ while (len > 0 ) {
725
+ int res ;
726
+ uint8_t tlv_type ;
727
+ uint16_t tlv_len ;
728
+ size_t tlv_valsz ;
729
+ void * tlv_val ;
730
+ struct iovec tlv_hdr [2 ];
731
+
732
+ pr_signals_handle ();
733
+
734
+ tlv_hdr [0 ].iov_base = (void * ) & tlv_type ;
735
+ tlv_hdr [0 ].iov_len = sizeof (tlv_type );
736
+ tlv_hdr [1 ].iov_base = (void * ) & tlv_len ;
737
+ tlv_hdr [1 ].iov_len = sizeof (tlv_len );
738
+
739
+ res = readv_sock (conn -> rfd , tlv_hdr , 2 );
740
+ if (res < 0 ) {
741
+ return -1 ;
742
+ }
743
+
744
+ if (res != 3 ) {
745
+ pr_trace_msg (trace_channel , 20 , "read %lu TLV bytes, expected %lu bytes" ,
746
+ (unsigned long ) res , (unsigned long ) 3 );
747
+ errno = EPERM ;
748
+ return -1 ;
749
+ }
750
+
751
+ len -= res ;
752
+
753
+ tlv_valsz = ntohs (tlv_len );
754
+ tlv_val = palloc (p , tlv_valsz );
755
+
756
+ /* TODO: Handle short reads, interrupted reads better? */
757
+ res = read (conn -> rfd , tlv_val , tlv_valsz );
758
+ if (res < 0 ) {
759
+ return -1 ;
760
+ }
761
+
762
+ if ((size_t ) res != tlv_valsz ) {
763
+ pr_trace_msg (trace_channel , 20 , "read %lu TLV bytes, expected %lu bytes" ,
764
+ (unsigned long ) res , (unsigned long ) tlv_valsz );
765
+ errno = EPERM ;
766
+ return -1 ;
767
+ }
768
+
769
+ len -= res ;
770
+
771
+ switch (tlv_type ) {
772
+ /* ALPN */
773
+ case 0x01 :
774
+ pr_trace_msg (trace_channel , 19 ,
775
+ "received proxy protocol V2 ALPN: %.*s" , (int ) tlv_valsz ,
776
+ (char * ) tlv_val );
777
+ break ;
778
+
779
+ /* "Authority" (server name, ala SNI) */
780
+ case 0x02 :
781
+ pr_trace_msg (trace_channel , 19 ,
782
+ "received proxy protocol V2 SNI: %.*s" , (int ) tlv_valsz ,
783
+ (char * ) tlv_val );
784
+ break ;
785
+
786
+ /* CRC32 */
787
+ case 0x03 :
788
+ pr_trace_msg (trace_channel , 19 ,
789
+ "received proxy protocol V2 CRC32 TLV (%lu bytes)" ,
790
+ (unsigned long ) tlv_valsz );
791
+ break ;
792
+
793
+ /* NOOP */
794
+ case 0x04 :
795
+ pr_trace_msg (trace_channel , 19 ,
796
+ "received proxy protocol V2 NOOP TLV (%lu bytes)" ,
797
+ (unsigned long ) tlv_valsz );
798
+ break ;
799
+
800
+ /* Unique ID */
801
+ case 0x05 :
802
+ pr_trace_msg (trace_channel , 19 ,
803
+ "received proxy protocol V2 Unique ID TLV (%lu bytes)" ,
804
+ (unsigned long ) tlv_valsz );
805
+ break ;
806
+
807
+ /* TLS */
808
+ case 0x20 :
809
+ pr_trace_msg (trace_channel , 19 ,
810
+ "received proxy protocol V2 TLS TLV (%lu bytes)" ,
811
+ (unsigned long ) tlv_valsz );
812
+ if (read_haproxy_v2_tls_tlv (p , tlv_val , tlv_valsz ) < 0 ) {
813
+ return -1 ;
814
+ }
815
+ break ;
816
+
817
+ /* Network namespace */
818
+ case 0x30 :
819
+ pr_trace_msg (trace_channel , 19 ,
820
+ "received proxy protocol V2 Network Namespace: %.*s" ,
821
+ (int ) tlv_valsz , (char * ) tlv_val );
822
+ break ;
823
+
824
+ default :
825
+ pr_trace_msg (trace_channel , 3 ,
826
+ "unsupported proxy protocol TLV: %0x" , tlv_type );
827
+ }
828
+ }
829
+
830
+ return 0 ;
831
+ }
832
+
619
833
static int read_haproxy_v2 (pool * p , conn_t * conn ,
620
834
const pr_netaddr_t * * proxied_addr , unsigned int * proxied_port ) {
621
835
int res = 0 ;
@@ -668,18 +882,18 @@ static int read_haproxy_v2(pool *p, conn_t *conn,
668
882
uint16_t src_port , dst_port ;
669
883
struct iovec ipv4 [4 ];
670
884
struct sockaddr_in * saddr ;
885
+ size_t tlv_len = 0 ;
671
886
672
887
pr_trace_msg (trace_channel , 17 ,
673
888
"received proxy protocol V2 TCP/IPv4 transport family (%lu bytes)" ,
674
889
(unsigned long ) ntohs (v2_len ));
675
890
676
- if (ntohs (v2_len ) != 12 ) {
891
+ if (ntohs (v2_len ) > 12 ) {
892
+ /* The addresses are followed by TLVs. */
893
+ tlv_len = ntohs (v2_len ) - 12 ;
677
894
pr_trace_msg (trace_channel , 3 ,
678
- "proxy protocol V2 TCP/IPv4 transport family sent %lu bytes, "
679
- "expected %lu bytes" , (unsigned long ) ntohs (v2_len ),
680
- (unsigned long ) 12 );
681
- errno = EINVAL ;
682
- return -1 ;
895
+ "proxy protocol V2 TCP/IPv4 transport family received %lu bytes "
896
+ "of TLV data" , (unsigned long ) tlv_len );
683
897
}
684
898
685
899
ipv4 [0 ].iov_base = (void * ) & src_ipv4 ;
@@ -696,6 +910,12 @@ static int read_haproxy_v2(pool *p, conn_t *conn,
696
910
return -1 ;
697
911
}
698
912
913
+ if (tlv_len > 0 ) {
914
+ if (read_haproxy_v2_tlvs (p , conn , tlv_len ) < 0 ) {
915
+ return -1 ;
916
+ }
917
+ }
918
+
699
919
src_addr = pr_netaddr_alloc (p );
700
920
pr_netaddr_set_family ((pr_netaddr_t * ) src_addr , AF_INET );
701
921
saddr = (struct sockaddr_in * ) pr_netaddr_get_sockaddr (src_addr );
@@ -729,18 +949,18 @@ static int read_haproxy_v2(pool *p, conn_t *conn,
729
949
uint16_t src_port , dst_port ;
730
950
struct iovec ipv6 [4 ];
731
951
struct sockaddr_in6 * saddr ;
952
+ size_t tlv_len = 0 ;
732
953
733
954
pr_trace_msg (trace_channel , 17 ,
734
955
"received proxy protocol V2 TCP/IPv6 transport family (%lu bytes)" ,
735
956
(unsigned long ) ntohs (v2_len ));
736
957
737
- if (ntohs (v2_len ) != 36 ) {
958
+ if (ntohs (v2_len ) > 36 ) {
959
+ /* The addresses are followed by TLVs. */
960
+ tlv_len = ntohs (v2_len ) - 36 ;
738
961
pr_trace_msg (trace_channel , 3 ,
739
- "proxy protocol V2 TCP/IPv6 transport family sent %lu bytes, "
740
- "expected %lu bytes" , (unsigned long ) ntohs (v2_len ),
741
- (unsigned long ) 36 );
742
- errno = EINVAL ;
743
- return -1 ;
962
+ "proxy protocol V2 TCP/IPv4 transport family received %lu bytes "
963
+ "of TLV data" , (unsigned long ) tlv_len );
744
964
}
745
965
746
966
#ifdef PR_USE_IPV6
@@ -758,6 +978,12 @@ static int read_haproxy_v2(pool *p, conn_t *conn,
758
978
return -1 ;
759
979
}
760
980
981
+ if (tlv_len > 0 ) {
982
+ if (read_haproxy_v2_tlvs (p , conn , tlv_len ) < 0 ) {
983
+ return -1 ;
984
+ }
985
+ }
986
+
761
987
src_addr = pr_netaddr_alloc (p );
762
988
pr_netaddr_set_family ((pr_netaddr_t * ) src_addr , AF_INET6 );
763
989
saddr = (struct sockaddr_in6 * ) pr_netaddr_get_sockaddr (src_addr );
@@ -885,14 +1111,6 @@ static int read_haproxy_v2(pool *p, conn_t *conn,
885
1111
return 0 ;
886
1112
}
887
1113
888
- if (ntohs (pr_netaddr_get_port (dst_addr )) > 65535 ) {
889
- pr_log_debug (DEBUG0 , MOD_PROXY_PROTOCOL_VERSION
890
- ": out-of-range destination port provided: %u" ,
891
- ntohs (pr_netaddr_get_port (dst_addr )));
892
- errno = EINVAL ;
893
- return -1 ;
894
- }
895
-
896
1114
/* Paranoidly check the given source address/port against the
897
1115
* destination address/port. If the two tuples match, then the remote
898
1116
* client is lying to us (it's not possible to have a TCP connection
0 commit comments