Skip to content

Commit 347df83

Browse files
committed
fix: properly handle IPv6 addresses in HTTP Host headers
This commit fixes IPv6 address handling in HTTP client Host headers by adding bracket notation when required and improving URL parsing validation. - Add automatic bracket wrapping for unbracketed IPv6 addresses in Host headers when combined with port numbers - Fix off-by-one error in IPv6 bracket stripping (was removing one extra character) - Fix incorrect length calculation in flb_utils_copy_host_sds for bracketed IPv6 extraction (changed from absolute position to relative length to properly account for pos_init offset) - Add IPv6 bracket validation to detect malformed URLs with missing or mismatched brackets - Improve error handling in URL parsing with proper cleanup on failure - Update TLS flag checking to use flb_stream_get_flag_status() for more reliable detection Signed-off-by: Shelby Hagman <shelbyzh@amazon.com>
1 parent 4f8c50b commit 347df83

File tree

5 files changed

+317
-8
lines changed

5 files changed

+317
-8
lines changed

src/flb_http_client.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,13 @@
3333
#define _GNU_SOURCE
3434
#include <string.h>
3535

36+
#ifdef FLB_SYSTEM_WINDOWS
37+
#include <winsock2.h>
38+
#include <ws2tcpip.h>
39+
#endif
40+
3641
#include <fluent-bit/flb_info.h>
42+
#include <fluent-bit/flb_compat.h>
3743
#include <fluent-bit/flb_kv.h>
3844
#include <fluent-bit/flb_log.h>
3945
#include <fluent-bit/flb_mem.h>
@@ -617,11 +623,23 @@ static int add_host_and_content_length(struct flb_http_client *c)
617623
out_port = c->port;
618624
}
619625

620-
if (c->flags & FLB_IO_TLS && out_port == 443) {
626+
/* Check if connection uses TLS and port is 443 (HTTPS default) */
627+
if (flb_stream_get_flag_status(&u->base, FLB_IO_TLS) && out_port == 443) {
628+
/* HTTPS on default port 443 - omit port from Host header */
621629
tmp = flb_sds_copy(host, out_host, strlen(out_host));
622630
}
623631
else {
624-
tmp = flb_sds_printf(&host, "%s:%i", out_host, out_port);
632+
struct in6_addr addr;
633+
634+
/* Check if out_host is an unbracketed IPv6 address */
635+
if (out_host && out_host[0] != '[' && inet_pton(AF_INET6, out_host, &addr) == 1) {
636+
/* IPv6 address needs brackets when combined with port */
637+
tmp = flb_sds_printf(&host, "[%s]:%i", out_host, out_port);
638+
}
639+
else {
640+
/* IPv4 address, domain name, or already bracketed IPv6 */
641+
tmp = flb_sds_printf(&host, "%s:%i", out_host, out_port);
642+
}
625643
}
626644

627645
if (!tmp) {

src/flb_network.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#ifdef FLB_SYSTEM_WINDOWS
3131
#define poll WSAPoll
3232
#include <winsock2.h>
33+
#include <ws2tcpip.h>
3334
#else
3435
#include <sys/poll.h>
3536
#endif

src/flb_utils.c

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,13 +1431,36 @@ static char *flb_utils_copy_host_sds(const char *string, int pos_init, int pos_e
14311431
if (string[pos_end-1] != ']') {
14321432
return NULL;
14331433
}
1434-
return flb_sds_create_len(string + pos_init + 1, pos_end - 1);
1434+
return flb_sds_create_len(string + pos_init + 1, pos_end - pos_init - 2);
14351435
}
14361436
else {
1437-
return flb_sds_create_len(string + pos_init, pos_end);
1437+
return flb_sds_create_len(string + pos_init, pos_end - pos_init);
14381438
}
14391439
}
14401440

1441+
/* Validate IPv6 bracket syntax in URL host part */
1442+
static int validate_ipv6_brackets(const char *p, char **out_bracket)
1443+
{
1444+
char *bracket = NULL;
1445+
1446+
if (p[0] == '[') {
1447+
bracket = strchr(p, ']');
1448+
if (!bracket || bracket == p + 1) {
1449+
/* Missing closing bracket or empty brackets [] */
1450+
return -1;
1451+
}
1452+
}
1453+
else if (strchr(p, ']')) {
1454+
/* Has closing bracket but no opening bracket */
1455+
return -1;
1456+
}
1457+
1458+
if (out_bracket) {
1459+
*out_bracket = bracket;
1460+
}
1461+
return 0;
1462+
}
1463+
14411464
int flb_utils_url_split(const char *in_url, char **out_protocol,
14421465
char **out_host, char **out_port, char **out_uri)
14431466
{
@@ -1448,6 +1471,7 @@ int flb_utils_url_split(const char *in_url, char **out_protocol,
14481471
char *p;
14491472
char *tmp;
14501473
char *sep;
1474+
char *bracket = NULL;
14511475

14521476
/* Protocol */
14531477
p = strstr(in_url, "://");
@@ -1467,9 +1491,17 @@ int flb_utils_url_split(const char *in_url, char **out_protocol,
14671491
/* Advance position after protocol */
14681492
p += 3;
14691493

1470-
/* Check for first '/' */
1494+
/* Validate IPv6 brackets */
14711495
sep = strchr(p, '/');
1472-
tmp = strchr(p, ':');
1496+
if (validate_ipv6_brackets(p, &bracket) < 0) {
1497+
flb_errno();
1498+
goto error;
1499+
}
1500+
if (bracket) {
1501+
tmp = strchr(bracket, ':');
1502+
} else {
1503+
tmp = strchr(p, ':');
1504+
}
14731505

14741506
/* Validate port separator is found before the first slash */
14751507
if (sep && tmp) {
@@ -1501,10 +1533,18 @@ int flb_utils_url_split(const char *in_url, char **out_protocol,
15011533
tmp = strchr(p, '/');
15021534
if (tmp) {
15031535
host = flb_copy_host(p, 0, tmp - p);
1536+
if (!host) {
1537+
flb_errno();
1538+
goto error;
1539+
}
15041540
uri = flb_strdup(tmp);
15051541
}
15061542
else {
15071543
host = flb_copy_host(p, 0, strlen(p));
1544+
if (!host) {
1545+
flb_errno();
1546+
goto error;
1547+
}
15081548
uri = flb_strdup("/");
15091549
}
15101550
}
@@ -1529,6 +1569,15 @@ int flb_utils_url_split(const char *in_url, char **out_protocol,
15291569
if (protocol) {
15301570
flb_free(protocol);
15311571
}
1572+
if (host) {
1573+
flb_free(host);
1574+
}
1575+
if (port) {
1576+
flb_free(port);
1577+
}
1578+
if (uri) {
1579+
flb_free(uri);
1580+
}
15321581

15331582
return -1;
15341583
}
@@ -1544,6 +1593,7 @@ int flb_utils_url_split_sds(const flb_sds_t in_url, flb_sds_t *out_protocol,
15441593
char *p = NULL;
15451594
char *tmp = NULL;
15461595
char *sep = NULL;
1596+
char *bracket = NULL;
15471597

15481598
/* Protocol */
15491599
p = strstr(in_url, "://");
@@ -1563,9 +1613,17 @@ int flb_utils_url_split_sds(const flb_sds_t in_url, flb_sds_t *out_protocol,
15631613
/* Advance position after protocol */
15641614
p += 3;
15651615

1566-
/* Check for first '/' */
1616+
/* Validate IPv6 brackets */
15671617
sep = strchr(p, '/');
1568-
tmp = strchr(p, ':');
1618+
if (validate_ipv6_brackets(p, &bracket) < 0) {
1619+
flb_errno();
1620+
goto error;
1621+
}
1622+
if (bracket) {
1623+
tmp = strchr(bracket, ':');
1624+
} else {
1625+
tmp = strchr(p, ':');
1626+
}
15691627

15701628
/* Validate port separator is found before the first slash */
15711629
if (sep && tmp) {
@@ -1597,10 +1655,18 @@ int flb_utils_url_split_sds(const flb_sds_t in_url, flb_sds_t *out_protocol,
15971655
tmp = strchr(p, '/');
15981656
if (tmp) {
15991657
host = flb_utils_copy_host_sds(p, 0, tmp - p);
1658+
if (!host) {
1659+
flb_errno();
1660+
goto error;
1661+
}
16001662
uri = flb_sds_create(tmp);
16011663
}
16021664
else {
16031665
host = flb_utils_copy_host_sds(p, 0, strlen(p));
1666+
if (!host) {
1667+
flb_errno();
1668+
goto error;
1669+
}
16041670
uri = flb_sds_create("/");
16051671
}
16061672
}

0 commit comments

Comments
 (0)