Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 159 additions & 46 deletions src/flb_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1395,92 +1395,205 @@ int flb_utils_proxy_url_split(const char *in_url, char **out_protocol,
char **out_username, char **out_password,
char **out_host, char **out_port)
{
const char *at_sep;
const char *tmp;
const char *port_start;
const char *end;
const char *authority;
char *protocol = NULL;
char *username = NULL;
char *password = NULL;
char *host = NULL;
char *port = NULL;
char *proto_sep;
char *at_sep;
char *tmp;

/* Parse protocol */
proto_sep = strstr(in_url, "://");
if (!proto_sep) {
flb_error("HTTP_PROXY variable must be set in the form of 'http://[username:password@]host:port'");
return -1;
}
if (proto_sep == in_url) {
flb_error("HTTP_PROXY variable must be set in the form of 'http://[username:password@]host:port'");
if (!in_url || *in_url == '\0') {
flb_error("HTTP_PROXY variable must specify a proxy host");
return -1;
}

protocol = mk_string_copy_substr(in_url, 0, proto_sep - in_url);
if (!protocol) {
flb_errno();
return -1;
/* Parse protocol */
tmp = strstr(in_url, "://");
if (tmp) {
if (tmp == in_url) {
flb_error("HTTP_PROXY variable must be set in the form of '[http://][username:password@]host:port'");
return -1;
}

protocol = mk_string_copy_substr(in_url, 0, tmp - in_url);
if (!protocol) {
flb_errno();
return -1;
}

/* Only HTTP proxy is supported for now. */
if (strcmp(protocol, "http") != 0) {
flb_error("only HTTP proxy is supported.");
goto error;
}

authority = tmp + 3;
}
/* Only HTTP proxy is supported for now. */
if (strcmp(protocol, "http") != 0) {
flb_error("only HTTP proxy is supported.");
flb_free(protocol);
return -1;
else {
protocol = flb_strdup("http");
if (!protocol) {
flb_errno();
return -1;
}

authority = in_url;
}

/* Advance position after protocol */
proto_sep += 3;
if (!authority || *authority == '\0') {
flb_error("HTTP_PROXY variable must include a host");
goto error;
}

/* Separate `username:password` and `host:port` */
at_sep = strrchr(proto_sep, '@');
at_sep = strrchr(authority, '@');
if (at_sep) {
/* Parse username:password part. */
tmp = strchr(proto_sep, ':');
if (!tmp) {
flb_free(protocol);
return -1;
tmp = strchr(authority, ':');
if (!tmp || tmp > at_sep) {
flb_error("invalid HTTP proxy credentials");
goto error;
}
username = mk_string_copy_substr(proto_sep, 0, tmp - proto_sep);

username = mk_string_copy_substr(authority, 0, tmp - authority);
if (!username) {
flb_errno();
goto error;
}

tmp += 1;
password = mk_string_copy_substr(tmp, 0, at_sep - tmp);
if (!password) {
flb_errno();
goto error;
}

/* Parse host:port part. */
at_sep += 1;
tmp = strchr(at_sep, ':');
if (tmp) {
host = flb_copy_host(at_sep, 0, tmp - at_sep);
tmp += 1;
port = strdup(tmp);
authority = at_sep + 1;
}

if (!authority || *authority == '\0') {
flb_error("HTTP proxy host is missing");
goto error;
}

if (*authority == '[') {
end = strchr(authority, ']');
if (!end) {
flb_error("invalid HTTP proxy host");
goto error;
}
else {
host = flb_copy_host(at_sep, 0, strlen(at_sep));

host = flb_copy_host(authority, 0, end - authority + 1);
if (!host) {
flb_error("invalid HTTP proxy host");
goto error;
}

if (*(end + 1) == ':') {
port_start = end + 2;
if (*port_start == '\0') {
flb_error("invalid HTTP proxy port");
goto error;
}

port = flb_strdup(port_start);
if (!port) {
flb_errno();
goto error;
}
}
else if (*(end + 1) == '\0') {
port = flb_strdup("80");
if (!port) {
flb_errno();
goto error;
}
}
else {
flb_error("invalid HTTP proxy host");
goto error;
}
}
else {
/* Parse host:port part. */
tmp = strchr(proto_sep, ':');
tmp = strrchr(authority, ':');
if (tmp) {
host = flb_copy_host(proto_sep, 0, tmp - proto_sep);
tmp += 1;
port = strdup(tmp);
host = flb_copy_host(authority, 0, tmp - authority);
if (!host) {
flb_error("invalid HTTP proxy host");
goto error;
}

port_start = tmp + 1;
if (*port_start == '\0') {
flb_error("invalid HTTP proxy port");
goto error;
}

port = flb_strdup(port_start);
if (!port) {
flb_errno();
goto error;
}
}
else {
host = flb_copy_host(proto_sep, 0, strlen(proto_sep));
host = flb_copy_host(authority, 0, strlen(authority));
if (!host) {
flb_error("invalid HTTP proxy host");
goto error;
}

port = flb_strdup("80");
if (!port) {
flb_errno();
goto error;
}
}
}

if (!host || *host == '\0') {
flb_error("HTTP proxy host is missing");
goto error;
}

*out_protocol = protocol;
*out_host = host;
*out_port = port;
if (username) {
if (out_username) {
*out_username = username;
}
if (password) {
else if (username) {
flb_free(username);
}

if (out_password) {
*out_password = password;
}
else if (password) {
flb_free(password);
}

return 0;

error:
if (protocol) {
flb_free(protocol);
}
if (username) {
flb_free(username);
}
if (password) {
flb_free(password);
}
if (host) {
flb_free(host);
}
if (port) {
flb_free(port);
}

return -1;
}


Expand Down
14 changes: 10 additions & 4 deletions tests/internal/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,12 @@ struct proxy_url_check proxy_url_checks[] = {
"http", "proxy.com", "80", NULL, NULL},
{0, "http://proxy.com:8080",
"http", "proxy.com", "8080", NULL, NULL},
{0, "proxy.com:8080",
"http", "proxy.com", "8080", NULL, NULL},
{0, "foo:bar@proxy.com:8080",
"http", "proxy.com", "8080", "foo", "bar"},
{0, "proxy.com",
"http", "proxy.com", "80", NULL, NULL},
/* issue #5530. Password contains @ */
{0, "http://example_user:example_pass_w_@_char@proxy.com:8080",
"http", "proxy.com", "8080", "example_user", "example_pass_w_@_char"},
Expand Down Expand Up @@ -550,8 +556,8 @@ void test_proxy_url_split() {

/* Username */
if (u->username) {
TEST_CHECK(port != NULL);
ret = strcmp(u->port, port);
TEST_CHECK(username != NULL);
ret = strcmp(u->username, username);
TEST_CHECK(ret == 0);
TEST_MSG("Expected username: %s", u->username);
TEST_MSG("Produced username: %s", username);
Expand All @@ -563,8 +569,8 @@ void test_proxy_url_split() {

/* Password */
if (u->password) {
TEST_CHECK(port != NULL);
ret = strcmp(u->port, port);
TEST_CHECK(password != NULL);
ret = strcmp(u->password, password);
TEST_CHECK(ret == 0);
TEST_MSG("Expected password: %s", u->password);
TEST_MSG("Produced password: %s", password);
Expand Down
Loading