Skip to content

Commit 99cdea0

Browse files
Save all the v2 SSL information
1 parent c00c7de commit 99cdea0

4 files changed

Lines changed: 85 additions & 47 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
#
1818

19-
CFLAGS := -Wall -Wextra -Wshadow -ansi -fshort-enums -fpic
19+
CFLAGS := -Wall -Wextra -Wshadow -Wimplicit-fallthrough=0 -ansi -fshort-enums -fpic
2020

2121
all: build
2222

src/proxy_protocol.c

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,20 @@ typedef struct
121121

122122
#pragma pack()
123123

124+
typedef struct
125+
{
126+
uint8_t type;
127+
uint16_t length;
128+
uint8_t value[1];
129+
} tlv_t;
130+
131+
struct _tlv_array_t
132+
{
133+
uint32_t len; /* Number of elements */
134+
uint32_t size; /* Allocated elements */
135+
tlv_t **tlvs; /* Pointer to tlv_t* elements */
136+
};
137+
124138
static const char *errors[] = {
125139
"No error",
126140
"Invalid PROXY protocol version given. Only 1 and 2 are valid",
@@ -246,21 +260,21 @@ static void tlv_array_clear(tlv_array_t *tlv_array)
246260
tlv_array->len = 0;
247261
tlv_array->size = 0;
248262
free(tlv_array->tlvs);
249-
263+
tlv_array->tlvs = NULL;
250264
}
251265

252266
uint8_t *pp_info_get_tlv_value(const pp_info_t *pp_info, uint8_t type, uint8_t subtype, uint16_t *value_len_out)
253267
{
254268
*value_len_out = 0;
255-
if (!pp_info->tlv_array.tlvs || !pp_info->tlv_array.len)
269+
if (!pp_info->tlv_array->tlvs || !pp_info->tlv_array->len)
256270
{
257271
return NULL;
258272
}
259273

260274
uint32_t i;
261-
for (i = 0; i < pp_info->tlv_array.len; i++)
275+
for (i = 0; i < pp_info->tlv_array->len; i++)
262276
{
263-
tlv_t *tlv = pp_info->tlv_array.tlvs[i];
277+
tlv_t *tlv = pp_info->tlv_array->tlvs[i];
264278
if (tlv->type == type)
265279
{
266280
if (subtype > 0)
@@ -281,15 +295,19 @@ uint8_t *pp_info_get_tlv_value(const pp_info_t *pp_info, uint8_t type, uint8_t s
281295

282296
void pp_info_clear(pp_info_t *pp_info)
283297
{
284-
tlv_array_clear(&pp_info->tlv_array);
298+
if (pp_info->tlv_array)
299+
{
300+
tlv_array_clear(pp_info->tlv_array);
301+
free(pp_info->tlv_array);
302+
}
285303
memset(pp_info, 0, sizeof(*pp_info));
286304
}
287305

288306
uint8_t *pp2_create_hdr(uint8_t fam, const pp_info_t *pp_info, uint32_t *pp2_hdr_len, uint32_t *error)
289307
{
290308
proxy_hdr_v2_t proxy_hdr_v2 = {
291309
.sig = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A",
292-
.ver_cmd = pp_info->v2local ? '\x20' : '\x21',
310+
.ver_cmd = pp_info->pp2_info.local ? '\x20' : '\x21',
293311
};
294312

295313
uint8_t transport_protocol = fam & 0x0f;
@@ -305,7 +323,7 @@ uint8_t *pp2_create_hdr(uint8_t fam, const pp_info_t *pp_info, uint32_t *pp2_hdr
305323
if (address_family == 0x0)
306324
{
307325
len = 0;
308-
if (!pp_info->v2local)
326+
if (!pp_info->pp2_info.local)
309327
{
310328
*error = ERR_PP2_TRANSPORT_FAMILY;
311329
return NULL;
@@ -526,7 +544,7 @@ static uint32_t crc32c(const uint8_t *buf, uint32_t len)
526544
}
527545

528546
/* Verifies and parses a version 2 PROXY protocol header */
529-
static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
547+
static int32_t pp2_parse_hdr(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
530548
{
531549
const uint8_t *ppv2_hdr = pkt;
532550
const proxy_hdr_v2_t *proxy_hdr_v2 = (proxy_hdr_v2_t *) pkt;
@@ -551,11 +569,11 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
551569
uint8_t cmd = proxy_hdr_v2->ver_cmd & 0x0f;
552570
if (cmd == 0x0)
553571
{
554-
pp_info->v2local = 1;
572+
pp_info->pp2_info.local = 1;
555573
}
556574
else if (cmd == 0x1)
557575
{
558-
pp_info->v2local = 0;
576+
pp_info->pp2_info.local = 0;
559577
}
560578
else
561579
{
@@ -662,6 +680,10 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
662680

663681
/* TLVs */
664682
/* Any TLV vector must be at least 3 bytes */
683+
if (tlv_vectors_len > 3)
684+
{
685+
pp_info->tlv_array = malloc(sizeof(*pp_info->tlv_array));
686+
}
665687
while (tlv_vectors_len > 3)
666688
{
667689
pp2_tlv_t *pp2_tlv = (pp2_tlv_t *) pkt;
@@ -676,7 +698,7 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
676698
{
677699
case PP2_TYPE_ALPN: /* Byte sequence */
678700
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))
701+
if (!tlv_array_append_tlv_new(pp_info->tlv_array, pp2_tlv->type, pp2_tlv_len, pp2_tlv->value))
680702
{
681703
return ERR_HEAP_ALLOC;
682704
}
@@ -702,7 +724,7 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
702724
return ERR_PP2_TYPE_CRC32C;
703725
}
704726

705-
if (!tlv_array_append_tlv_new(&pp_info->tlv_array, pp2_tlv->type, pp2_tlv_len, &crc32c_chksum))
727+
if (!tlv_array_append_tlv_new(pp_info->tlv_array, pp2_tlv->type, pp2_tlv_len, &crc32c_chksum))
706728
{
707729
return ERR_HEAP_ALLOC;
708730
}
@@ -715,20 +737,23 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
715737
{
716738
return ERR_PP2_TYPE_UNIQUE_ID;
717739
}
718-
if (!tlv_array_append_tlv_new(&pp_info->tlv_array, pp2_tlv->type, pp2_tlv_len, pp2_tlv->value))
740+
if (!tlv_array_append_tlv_new(pp_info->tlv_array, pp2_tlv->type, pp2_tlv_len, pp2_tlv->value))
719741
{
720742
return ERR_HEAP_ALLOC;
721743
}
722744
break;
723745
case PP2_TYPE_SSL:
724746
{
725747
pp2_tlv_ssl_t *pp2_tlv_ssl = (pp2_tlv_ssl_t*)pp2_tlv->value;
726-
/* TODO save client, verify in pp_info_t */
727-
/*if (!(pp2_tlv_ssl->client & PP2_CLIENT_SSL || pp2_tlv_ssl->client & PP2_CLIENT_CERT_CONN || pp2_tlv_ssl->client & PP2_CLIENT_CERT_SESS))
728-
{
729-
break;
730-
}*/
748+
749+
/* Set the pp2_ssl_info */
750+
pp_info->pp2_info.pp2_ssl_info.ssl = !!(pp2_tlv_ssl->client & PP2_CLIENT_SSL);
751+
pp_info->pp2_info.pp2_ssl_info.cert_in_connection = !!(pp2_tlv_ssl->client & PP2_CLIENT_CERT_CONN);
752+
pp_info->pp2_info.pp2_ssl_info.cert_in_session = !!(pp2_tlv_ssl->client & PP2_CLIENT_CERT_SESS);
753+
pp_info->pp2_info.pp2_ssl_info.cert_verified = !pp2_tlv_ssl->verify;
754+
731755
uint16_t pp2_tlvs_ssl_len = pp2_tlv_len - sizeof(pp2_tlv_ssl->client) - sizeof(pp2_tlv_ssl->verify);
756+
uint8_t tlv_ssl_version_found = 0;
732757
uint16_t pp2_sub_tlv_offset = 0;
733758
while (pp2_sub_tlv_offset < pp2_tlvs_ssl_len)
734759
{
@@ -737,17 +762,17 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
737762
switch (pp2_sub_tlv_ssl->type)
738763
{
739764
case PP2_SUBTYPE_SSL_VERSION: /* US-ASCII */
765+
tlv_ssl_version_found = 1;
740766
case PP2_SUBTYPE_SSL_CIPHER: /* US-ASCII */
741767
case PP2_SUBTYPE_SSL_SIG_ALG: /* US-ASCII */
742768
case PP2_SUBTYPE_SSL_KEY_ALG: /* US-ASCII */
743-
/* +1 to save it as a string */
744-
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))
769+
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))
745770
{
746771
return ERR_HEAP_ALLOC;
747772
}
748773
break;
749774
case PP2_SUBTYPE_SSL_CN: /* UTF8 */
750-
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))
775+
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))
751776
{
752777
return ERR_HEAP_ALLOC;
753778
}
@@ -758,14 +783,14 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
758783

759784
pp2_sub_tlv_offset += 3 + pp2_sub_tlv_ssl_len;
760785
}
761-
if (pp2_sub_tlv_offset > pp2_tlvs_ssl_len)
786+
if (pp2_sub_tlv_offset > pp2_tlvs_ssl_len || (pp_info->pp2_info.pp2_ssl_info.ssl && !tlv_ssl_version_found))
762787
{
763788
return ERR_PP2_TYPE_SSL;
764789
}
765790
break;
766791
}
767792
case PP2_TYPE_NETNS: /* US-ASCII */
768-
if (!tlv_array_append_tlv_new_usascii(&pp_info->tlv_array, pp2_tlv->type, pp2_tlv_len, pp2_tlv->value))
793+
if (!tlv_array_append_tlv_new_usascii(pp_info->tlv_array, pp2_tlv->type, pp2_tlv_len, pp2_tlv->value))
769794
{
770795
return ERR_HEAP_ALLOC;
771796
}
@@ -781,7 +806,7 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
781806
if (pp2_tlv_aws->type == PP2_SUBTYPE_AWS_VPCE_ID) /* US-ASCII */
782807
{
783808
/* Example: \x1vpce-08d2bf15fac5001c9 */
784-
if (!tlv_array_append_tlv_new_usascii(&pp_info->tlv_array, pp2_tlv->type, pp2_tlv_len, pp2_tlv->value))
809+
if (!tlv_array_append_tlv_new_usascii(pp_info->tlv_array, pp2_tlv->type, pp2_tlv_len, pp2_tlv->value))
785810
{
786811
return ERR_HEAP_ALLOC;
787812
}
@@ -799,7 +824,7 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
799824
if (pp2_tlv_azure->type == PP2_TYPE_AZURE) /* 32-bit number */
800825
{
801826
tlv_t *tlv = tlv_new(pp2_tlv->type, pp2_tlv_len, pp2_tlv->value);
802-
if (!tlv || !tlv_array_append_tlv(&pp_info->tlv_array, tlv))
827+
if (!tlv || !tlv_array_append_tlv(pp_info->tlv_array, tlv))
803828
{
804829
return ERR_HEAP_ALLOC;
805830
}
@@ -816,7 +841,7 @@ static int32_t ppv2_parse(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
816841
return sizeof(proxy_hdr_v2_t) + len;
817842
}
818843

819-
static int32_t ppv1_parse(const uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
844+
static int32_t pp1_parse_hdr(const uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
820845
{
821846
char block[PP1_MAX_LENGHT] = { 0 };
822847
char *ptr = block;
@@ -979,11 +1004,11 @@ int32_t pp_parse_hdr(uint8_t *pkt, uint32_t pktlen, pp_info_t *pp_info)
9791004
memset(pp_info, 0, sizeof(*pp_info));
9801005
if (pktlen >= 16 && !memcmp(pkt, "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A", 12))
9811006
{
982-
return ppv2_parse(pkt, pktlen, pp_info);
1007+
return pp2_parse_hdr(pkt, pktlen, pp_info);
9831008
}
9841009
else if (pktlen >= 8 && !memcmp(pkt, "\x50\x52\x4F\x58\x59", 5))
9851010
{
986-
return ppv1_parse(pkt, pktlen, pp_info);;
1011+
return pp1_parse_hdr(pkt, pktlen, pp_info);;
9871012
}
9881013
else
9891014
{

src/proxy_protocol.h

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,28 +81,30 @@ enum
8181
/* PP2_TYPE_AZURE subtypes */
8282
#define PP2_SUBTYPE_AZURE_PRIVATEENDPOINT_LINKID 0x01
8383

84+
typedef struct _tlv_array_t tlv_array_t;
85+
8486
typedef struct
8587
{
86-
uint8_t type;
87-
uint16_t length;
88-
uint8_t value[1];
89-
} tlv_t;
88+
uint8_t ssl; /* 1: client connected over SSL/TLS 0: otherwise */
89+
uint8_t cert_in_connection; /* 1: client provided a certificate over the current connection 0: otherwise */
90+
uint8_t cert_in_session; /* 1: client provided a certificate at least once over the TLS session this connection belongs to 0: otherwise */
91+
uint8_t cert_verified; /* 1: client presented a certificate and it was successfully verified 1: otherwise */
92+
} pp2_ssl_info_t;
9093

9194
typedef struct
9295
{
93-
uint32_t len; /* Number of elements */
94-
uint32_t size; /* Allocated elements */
95-
tlv_t **tlvs; /* Pointer to tlv_t* elements */
96-
} tlv_array_t;
96+
uint8_t local; /* 1: LOCAL 0: PROXY */
97+
pp2_ssl_info_t pp2_ssl_info;
98+
} pp2_info_t;
9799

98100
typedef struct
99101
{
100-
uint8_t v2local; /* Used only in v2. 1: LOCAL 0: PROXY */
101-
char src_addr[108];
102-
char dst_addr[108];
103-
uint16_t src_port;
104-
uint16_t dst_port;
105-
tlv_array_t tlv_array;
102+
char src_addr[108];
103+
char dst_addr[108];
104+
uint16_t src_port;
105+
uint16_t dst_port;
106+
pp2_info_t pp2_info;
107+
tlv_array_t *tlv_array;
106108
} pp_info_t;
107109

108110
const char *pp_strerror(int32_t error);

tests/test.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ static uint8_t pp_verify_tlvs(const pp_info_t *pp_info, const test_tlv_t (*expec
127127

128128
static uint8_t pp_info_equal(const pp_info_t *pp_info_a, const pp_info_t *pp_info_b)
129129
{
130-
if (pp_info_a->v2local != pp_info_b->v2local)
130+
if (pp_info_a->pp2_info.local != pp_info_b->pp2_info.local)
131131
{
132132
return 0;
133133
}
@@ -147,6 +147,10 @@ static uint8_t pp_info_equal(const pp_info_t *pp_info_a, const pp_info_t *pp_inf
147147
{
148148
return 0;
149149
}
150+
if (memcmp(&pp_info_a->pp2_info, &pp_info_b->pp2_info, sizeof(pp2_info_t)))
151+
{
152+
return 0;
153+
}
150154
return 1;
151155
}
152156

@@ -229,8 +233,8 @@ int main()
229233
.name = "v2 PROXY protocol header: LOCAL, AF_UNSPEC create and parse",
230234
.version = 2,
231235
.fam = '\x00',
232-
.pp_info_in = { .v2local = 1 },
233-
.pp_info_out_expected = { .v2local = 1 },
236+
.pp_info_in = { .pp2_info.local = 1 },
237+
.pp_info_out_expected = { .pp2_info.local = 1 },
234238
},
235239
{
236240
.name = "v2 PROXY protocol header: PROXY, TCP over IPv6 create and parse",
@@ -266,7 +270,14 @@ int main()
266270
.src_addr = "192.168.10.100",
267271
.dst_addr = "192.168.11.90",
268272
.src_port = 42332,
269-
.dst_port = 8080
273+
.dst_port = 8080,
274+
.pp2_info = { .local = 0, .pp2_ssl_info = {
275+
.ssl = 1,
276+
.cert_in_connection = 1,
277+
.cert_in_session = 1,
278+
.cert_verified = 1
279+
}
280+
}
270281
},
271282
.expected_tlvs = {
272283
{

0 commit comments

Comments
 (0)