Skip to content

Commit b4e3719

Browse files
Merge pull request #5 from kosmas-valianos/sslTLVs
Add parsing support for PP2_TYPE_SSL
2 parents 37b50c9 + 1a9c7bc commit b4e3719

2 files changed

Lines changed: 100 additions & 47 deletions

File tree

src/proxy_protocol.c

Lines changed: 84 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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

154155
const 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+
216238
static 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))

src/proxy_protocol.h

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,21 @@ enum
3636
ERR_PP2_IPV6_DST_IP = -10,
3737
ERR_PP2_TLV_LENGTH = -11,
3838
ERR_PP2_TYPE_CRC32C = -12,
39-
ERR_PP2_TYPE_UNIQUE_ID = -13,
40-
ERR_PP2_TYPE_AWS = -14,
41-
ERR_PP2_TYPE_AZURE = -15,
42-
ERR_PP1_CRLF = -16,
43-
ERR_PP1_PROXY = -17,
44-
ERR_PP1_SPACE = -18,
45-
ERR_PP1_TRANSPORT_FAMILY = -19,
46-
ERR_PP1_IPV4_SRC_IP = -20,
47-
ERR_PP1_IPV4_DST_IP = -21,
48-
ERR_PP1_IPV6_SRC_IP = -22,
49-
ERR_PP1_IPV6_DST_IP = -23,
50-
ERR_PP1_SRC_PORT = -24,
51-
ERR_PP1_DST_PORT = -25,
52-
ERR_HEAP_ALLOC = -26,
39+
ERR_PP2_TYPE_SSL = -13,
40+
ERR_PP2_TYPE_UNIQUE_ID = -14,
41+
ERR_PP2_TYPE_AWS = -15,
42+
ERR_PP2_TYPE_AZURE = -16,
43+
ERR_PP1_CRLF = -17,
44+
ERR_PP1_PROXY = -18,
45+
ERR_PP1_SPACE = -19,
46+
ERR_PP1_TRANSPORT_FAMILY = -20,
47+
ERR_PP1_IPV4_SRC_IP = -21,
48+
ERR_PP1_IPV4_DST_IP = -22,
49+
ERR_PP1_IPV6_SRC_IP = -23,
50+
ERR_PP1_IPV6_DST_IP = -24,
51+
ERR_PP1_SRC_PORT = -25,
52+
ERR_PP1_DST_PORT = -26,
53+
ERR_HEAP_ALLOC = -27,
5354
};
5455

5556
/* Type-Length-Value (TLV vectors) */
@@ -69,7 +70,7 @@ enum
6970
#define PP2_TYPE_AWS 0xEA
7071
#define PP2_TYPE_AZURE 0xEE
7172

72-
/* PP2_TYPE_SSL subtypes */
73+
/* PP2_TYPE_SSL <client> bit field */
7374
#define PP2_CLIENT_SSL 0x01
7475
#define PP2_CLIENT_CERT_CONN 0x02
7576
#define PP2_CLIENT_CERT_SESS 0x04

0 commit comments

Comments
 (0)