Skip to content

Commit 2d25fb8

Browse files
Fix bugs, robustness issues, and style issues from code review
Bugs: - cert_in_connection << 2 changed to cert_in_session << 2 in pp_info_add_ssl() - Added NULL check after malloc() in pp_info_add_ssl(), returns 0 on failure - Added NULL check after malloc() in pp_info_add_aws_vpce_id(), returns 0 on failure - Added NULL check after malloc() in pp_info_add_azure_linkid(), returns 0 on failure - Added minus sign to 4 error return statements in v1 address parsing (ERR_PP1_IPV4_SRC_IP, ERR_PP1_IPV6_SRC_IP, ERR_PP1_IPV4_DST_IP, ERR_PP1_IPV6_DST_IP) - Split the if (!tlv || !tlv_array_append_tlv()) condition in tlv_array_append_tlv_new() and tlv_array_append_tlv_new_usascii() so that tlv is freed when append fails - Moved tlv_array->size += 5 after the realloc success check, using (tlv_array->size + 5) in the realloc call itself Robustness: - parse_port() now accepts port 0 using endptr from strtoul to distinguish "0" from invalid input - Added length checks (> 5) before memcpy into 6-byte port string buffers to prevent buffer overflow on malformed v1 input - AF_UNIX parsing now advances buffer and sets tlv_vectors_len so TLVs after UNIX addresses are parsed Style: - PP1_MAX_LENGHT renamed to PP1_MAX_LENGTH - Removed double semicolons at two locations - Inpects changed to Inspects in proxy_protocol.h - ALl changed to All in test.c
1 parent 2ad76fa commit 2d25fb8

3 files changed

Lines changed: 53 additions & 19 deletions

File tree

src/proxy_protocol.c

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ So a 108-byte buffer is always enough to store all the line and a trailing zero
6565
for string processing.
6666
*/
6767

68-
#define PP1_MAX_LENGHT 108
68+
#define PP1_MAX_LENGTH 108
6969
#define PP1_SIG "PROXY"
7070
#define CRLF "\r\n"
7171

@@ -215,8 +215,9 @@ const char *pp_strerror(int32_t error)
215215

216216
static uint8_t parse_port(const char *value, uint16_t *usport)
217217
{
218-
uint64_t port = strtoul(value, NULL, 10);
219-
if (port == 0 || port > UINT16_MAX)
218+
char *endptr = NULL;
219+
uint64_t port = strtoul(value, &endptr, 10);
220+
if (endptr == value || port > UINT16_MAX)
220221
{
221222
return 0;
222223
}
@@ -254,12 +255,12 @@ static uint8_t tlv_array_append_tlv(tlv_array_t *tlv_array, pp2_tlv_t *tlv)
254255
if (tlv_array->size == tlv_array->len)
255256
{
256257
pp2_tlv_t **tlvs = NULL;
257-
tlv_array->size += 5;
258-
tlvs = realloc(tlv_array->tlvs, tlv_array->size * sizeof(pp2_tlv_t*));
258+
tlvs = realloc(tlv_array->tlvs, (tlv_array->size + 5) * sizeof(pp2_tlv_t*));
259259
if (!tlvs)
260260
{
261261
return 0;
262262
}
263+
tlv_array->size += 5;
263264
tlv_array->tlvs = tlvs;
264265
}
265266

@@ -271,20 +272,30 @@ static uint8_t tlv_array_append_tlv(tlv_array_t *tlv_array, pp2_tlv_t *tlv)
271272
static uint8_t tlv_array_append_tlv_new(tlv_array_t *tlv_array, uint8_t type, uint16_t length, const void *value)
272273
{
273274
pp2_tlv_t *tlv = tlv_new(type, length, value);
274-
if (!tlv || !tlv_array_append_tlv(tlv_array, tlv))
275+
if (!tlv)
275276
{
276277
return 0;
277278
}
279+
if (!tlv_array_append_tlv(tlv_array, tlv))
280+
{
281+
free(tlv);
282+
return 0;
283+
}
278284
return 1;
279285
}
280286

281287
static uint8_t tlv_array_append_tlv_new_usascii(tlv_array_t *tlv_array, uint8_t type, uint16_t length, const void *value)
282288
{
283289
pp2_tlv_t *tlv = tlv_new(type, length + 1, value);
284-
if (!tlv || !tlv_array_append_tlv(tlv_array, tlv))
290+
if (!tlv)
285291
{
286292
return 0;
287293
}
294+
if (!tlv_array_append_tlv(tlv_array, tlv))
295+
{
296+
free(tlv);
297+
return 0;
298+
}
288299
tlv->value[length] = '\0';
289300
return 1;
290301
}
@@ -324,7 +335,7 @@ static void pp_info_add_subtype_ssl(uint8_t *value, uint16_t *index, uint8_t sub
324335
uint8_t pp_info_add_ssl(pp_info_t *pp_info, const char *version, const char *cipher, const char *sig_alg, const char *key_alg, const char *group, const char *sig_scheme, const uint8_t *cn, uint16_t cn_value_len, const uint8_t *client_cert, uint16_t client_cert_len)
325336
{
326337
const pp2_ssl_info_t *pp2_ssl_info = &pp_info->pp2_info.pp2_ssl_info;
327-
uint8_t client = pp2_ssl_info->ssl | pp2_ssl_info->cert_in_connection << 1 | pp2_ssl_info->cert_in_connection << 2;
338+
uint8_t client = pp2_ssl_info->ssl | pp2_ssl_info->cert_in_connection << 1 | pp2_ssl_info->cert_in_session << 2;
328339
uint32_t verify = !pp2_ssl_info->cert_verified;
329340
size_t version_value_len = version ? strlen(version) : 0;
330341
size_t cipher_value_len = cipher ? strlen(cipher) : 0;
@@ -376,6 +387,10 @@ uint8_t pp_info_add_ssl(pp_info_t *pp_info, const char *version, const char *cip
376387
}
377388

378389
value = malloc(length);
390+
if (!value)
391+
{
392+
return 0;
393+
}
379394
value[index++] = client;
380395
memcpy(value + index, &verify, sizeof(verify));
381396
index += sizeof(verify);
@@ -402,6 +417,10 @@ uint8_t pp_info_add_aws_vpce_id(pp_info_t *pp_info, const char *vpce_id)
402417
uint16_t length = sizeof_pp2_tlv_aws_t + (uint16_t) strlen(vpce_id);
403418
pp2_tlv_aws_t *pp2_tlv_aws = malloc(length);
404419
uint8_t rc;
420+
if (!pp2_tlv_aws)
421+
{
422+
return 0;
423+
}
405424
pp2_tlv_aws->type = PP2_SUBTYPE_AWS_VPCE_ID;
406425
memcpy(pp2_tlv_aws->value, vpce_id, strlen(vpce_id));
407426
rc = tlv_array_append_tlv_new(&pp_info->pp2_info.tlv_array, PP2_TYPE_AWS, length, pp2_tlv_aws);
@@ -414,6 +433,10 @@ uint8_t pp_info_add_azure_linkid(pp_info_t *pp_info, uint32_t linkid)
414433
uint16_t length = (uint16_t) sizeof(pp2_tlv_azure_t);
415434
pp2_tlv_azure_t *pp2_tlv_azure = malloc(length);
416435
uint8_t rc;
436+
if (!pp2_tlv_azure)
437+
{
438+
return 0;
439+
}
417440
pp2_tlv_azure->type = PP2_SUBTYPE_AZURE_PRIVATEENDPOINT_LINKID;
418441
pp2_tlv_azure->linkid = linkid;
419442
rc = tlv_array_append_tlv_new(&pp_info->pp2_info.tlv_array, PP2_TYPE_AZURE, length, pp2_tlv_azure);
@@ -811,7 +834,7 @@ uint8_t *pp2_create_healthcheck_hdr(uint16_t *pp2_hdr_len, int32_t *error)
811834

812835
static uint8_t *pp1_create_hdr(const pp_info_t *pp_info, uint16_t *pp1_hdr_len, int32_t *error)
813836
{
814-
char block[PP1_MAX_LENGHT];
837+
char block[PP1_MAX_LENGTH];
815838
uint8_t *pp1_hdr = NULL;
816839

817840
if (pp_info->transport_protocol != TRANSPORT_PROTOCOL_UNSPEC && pp_info->transport_protocol != TRANSPORT_PROTOCOL_STREAM)
@@ -1022,6 +1045,9 @@ static int32_t pp2_parse_hdr(const uint8_t *buffer, uint32_t buffer_length, pp_i
10221045
{
10231046
memcpy(pp_info->src_addr, addr->unix_addr.src_addr, sizeof(addr->unix_addr.src_addr));
10241047
memcpy(pp_info->dst_addr, addr->unix_addr.dst_addr, sizeof(addr->unix_addr.dst_addr));
1048+
1049+
buffer += sizeof(addr->unix_addr);
1050+
tlv_vectors_len = len - sizeof(addr->unix_addr);
10251051
}
10261052
else
10271053
{
@@ -1207,7 +1233,7 @@ static int32_t pp2_parse_hdr(const uint8_t *buffer, uint32_t buffer_length, pp_i
12071233

12081234
static int32_t pp1_parse_hdr(const uint8_t *buffer, uint32_t buffer_length, pp_info_t *pp_info)
12091235
{
1210-
char block[PP1_MAX_LENGHT] = { 0 };
1236+
char block[PP1_MAX_LENGTH] = { 0 };
12111237
char *ptr = block;
12121238
int32_t pp1_hdr_len = 0;
12131239
char *block_end = NULL;
@@ -1222,7 +1248,7 @@ static int32_t pp1_parse_hdr(const uint8_t *buffer, uint32_t buffer_length, pp_i
12221248
char src_port_str[6] = { 0 };
12231249
char dst_port_str[6] = { 0 };
12241250

1225-
memcpy(block, buffer, buffer_length < PP1_MAX_LENGHT ? buffer_length : PP1_MAX_LENGHT);
1251+
memcpy(block, buffer, buffer_length < PP1_MAX_LENGTH ? buffer_length : PP1_MAX_LENGTH);
12261252

12271253
block_end = strstr(block, CRLF);
12281254
if (!block_end)
@@ -1282,7 +1308,7 @@ static int32_t pp1_parse_hdr(const uint8_t *buffer, uint32_t buffer_length, pp_i
12821308
}
12831309
else
12841310
{
1285-
return -ERR_PP1_TRANSPORT_FAMILY;;
1311+
return -ERR_PP1_TRANSPORT_FAMILY;
12861312
}
12871313

12881314
/* Exactly one space */
@@ -1296,13 +1322,13 @@ static int32_t pp1_parse_hdr(const uint8_t *buffer, uint32_t buffer_length, pp_i
12961322
src_address_end = strchr(ptr, ' ');
12971323
if (!src_address_end)
12981324
{
1299-
return sa_family == AF_INET ? ERR_PP1_IPV4_SRC_IP : ERR_PP1_IPV6_SRC_IP;
1325+
return sa_family == AF_INET ? -ERR_PP1_IPV4_SRC_IP : -ERR_PP1_IPV6_SRC_IP;
13001326
}
13011327
src_address_length = src_address_end - ptr;
13021328
memcpy(pp_info->src_addr, ptr, src_address_length);
13031329
if (inet_pton(sa_family, pp_info->src_addr, &src_sin_addr) != 1)
13041330
{
1305-
return sa_family == AF_INET ? ERR_PP1_IPV4_SRC_IP : ERR_PP1_IPV6_SRC_IP;
1331+
return sa_family == AF_INET ? -ERR_PP1_IPV4_SRC_IP : -ERR_PP1_IPV6_SRC_IP;
13061332
}
13071333
ptr += src_address_length;
13081334

@@ -1317,13 +1343,13 @@ static int32_t pp1_parse_hdr(const uint8_t *buffer, uint32_t buffer_length, pp_i
13171343
dst_address_end = strchr(ptr, ' ');
13181344
if (!dst_address_end)
13191345
{
1320-
return sa_family == AF_INET ? ERR_PP1_IPV4_DST_IP : ERR_PP1_IPV6_DST_IP;
1346+
return sa_family == AF_INET ? -ERR_PP1_IPV4_DST_IP : -ERR_PP1_IPV6_DST_IP;
13211347
}
13221348
dst_address_length = dst_address_end - ptr;
13231349
memcpy(pp_info->dst_addr, ptr, dst_address_length);
13241350
if (inet_pton(sa_family, pp_info->dst_addr, &dst_sin_addr) != 1)
13251351
{
1326-
return sa_family == AF_INET ? ERR_PP1_IPV4_DST_IP : ERR_PP1_IPV6_DST_IP;
1352+
return sa_family == AF_INET ? -ERR_PP1_IPV4_DST_IP : -ERR_PP1_IPV6_DST_IP;
13271353
}
13281354
ptr += dst_address_length;
13291355

@@ -1341,6 +1367,10 @@ static int32_t pp1_parse_hdr(const uint8_t *buffer, uint32_t buffer_length, pp_i
13411367
return -ERR_PP1_SRC_PORT;
13421368
}
13431369
src_port_length = src_port_end - ptr;
1370+
if (src_port_length == 0 || src_port_length > 5)
1371+
{
1372+
return -ERR_PP1_SRC_PORT;
1373+
}
13441374
memcpy(src_port_str, ptr, src_port_length);
13451375
if (!parse_port(src_port_str, &pp_info->src_port))
13461376
{
@@ -1362,6 +1392,10 @@ static int32_t pp1_parse_hdr(const uint8_t *buffer, uint32_t buffer_length, pp_i
13621392
return -ERR_PP1_DST_PORT;
13631393
}
13641394
dst_port_length = dst_port_end - ptr;
1395+
if (dst_port_length == 0 || dst_port_length > 5)
1396+
{
1397+
return -ERR_PP1_DST_PORT;
1398+
}
13651399
memcpy(dst_port_str, ptr, dst_port_length);
13661400
if (!parse_port(dst_port_str, &pp_info->dst_port))
13671401
{
@@ -1387,7 +1421,7 @@ int32_t pp_parse_hdr(const uint8_t *buffer, uint32_t buffer_length, pp_info_t *p
13871421
}
13881422
else if (buffer_length >= 8 && !memcmp(buffer, PP1_SIG, 5))
13891423
{
1390-
return pp1_parse_hdr(buffer, buffer_length, pp_info);;
1424+
return pp1_parse_hdr(buffer, buffer_length, pp_info);
13911425
}
13921426
else
13931427
{

src/proxy_protocol.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ uint8_t *pp2_create_healthcheck_hdr(uint16_t *pp2_hdr_len, int32_t *error);
205205
*/
206206
uint8_t *pp_create_hdr(uint8_t version, const pp_info_t *pp_info, uint16_t *pp_hdr_len, int32_t *error);
207207

208-
/* Inpects the buffer for a PROXY protocol header and extracts all the information if any
208+
/* Inspects the buffer for a PROXY protocol header and extracts all the information if any
209209
*
210210
* buffer Buffer to be inspected and parsed. Typically the buffer given for a read operation
211211
* buffer_length Buffer's length. Typically the bytes read from the read operation

tests/test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,6 @@ int main(void)
964964
}
965965
printf("PASSED\n");
966966

967-
printf("ALl tests completed successfully\n");
967+
printf("All tests completed successfully\n");
968968
return EXIT_SUCCESS;
969969
}

0 commit comments

Comments
 (0)