1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-12 14:14:48 +02:00

relay/api: fix connection to remote using an IPv6 address with square brackets (closes #2156)

This commit is contained in:
Sébastien Helleu
2024-07-22 17:24:50 +02:00
parent 9ece7b4d8c
commit 8c48b2f310
4 changed files with 175 additions and 125 deletions
+1
View File
@@ -53,6 +53,7 @@
- ruby: fix builtin functions not available ([#2109](https://github.com/weechat/weechat/issues/2109))
- php: fix return value of function hdata_longlong
- tcl: fix return value of function hdata_longlong ([#2119](https://github.com/weechat/weechat/issues/2119))
- relay/api: fix connection to remote using an IPv6 address with square brackets ([#2156](https://github.com/weechat/weechat/issues/2156))
- relay/api: allow clients without authentication when no relay password is defined and option relay.network.allow_empty_password is on ([#2158](https://github.com/weechat/weechat/issues/2158))
- relay/api: fix connection to remote without password ([#2158](https://github.com/weechat/weechat/issues/2158))
- relay/api: fix timezone of dates sent to clients ([#2151](https://github.com/weechat/weechat/issues/2151))
@@ -57,13 +57,17 @@ relay_remote_network_get_url_resource (struct t_relay_remote *remote,
const char *resource)
{
char *url;
int colon_in_address;
if (!remote || !remote->address || !resource || !resource[0])
return NULL;
weechat_asprintf (&url, "%s://%s:%d/api/%s",
colon_in_address = (strchr (remote->address, ':')) ? 1 : 0;
weechat_asprintf (&url, "%s://%s%s%s:%d/api/%s",
(remote->tls) ? "https" : "http",
(colon_in_address) ? "[" : "",
remote->address,
(colon_in_address) ? "]" : "",
remote->port,
resource);
+103 -91
View File
@@ -185,7 +185,107 @@ relay_remote_name_valid (const char *name)
}
/*
* Checks if a remote URL is valid;
* Extracts TLS, address and port from remote URL.
*
* If address is an IPv6 like "[::1]", the square brackets are removed.
*
* Returns:
* 1: OK
* 0: error, invalid URL
*/
int
relay_remote_parse_url (const char *url,
int *tls, char **address, int *port)
{
const char *ptr_url;
char *pos, *str_port, *error;
long number;
if (tls)
*tls = 0;
if (address)
*address = NULL;
if (port)
*port = RELAY_REMOTE_DEFAULT_PORT;
if (!url || !url[0])
return 0;
/* check scheme and extract TLS flag */
if (strncmp (url, "http://", 7) == 0)
{
ptr_url = url + 7;
}
else if (strncmp (url, "https://", 8) == 0)
{
if (tls)
*tls = 1;
ptr_url = url + 8;
}
else
{
return 0;
}
/* check if there is an IPv6 address with square brackets, like "[::1]" */
if (ptr_url[0] == '[')
{
/* extract IPv6 address between square brackets */
pos = strchr (ptr_url, ']');
if (!pos)
return 0;
if (address)
*address = weechat_strndup (ptr_url + 1, pos - ptr_url - 1);
ptr_url = pos + 1;
}
else
{
/* extract another address */
pos = strrchr (ptr_url, ':');
if (!pos)
pos = strchr (ptr_url, '/');
if (!pos)
pos = strchr (ptr_url, '?');
if (address)
{
*address = (pos) ?
weechat_strndup (ptr_url, pos - ptr_url) : strdup (ptr_url);
}
}
/* extract port number */
pos = strrchr (ptr_url, ':');
if (pos)
{
ptr_url = pos + 1;
pos = strchr (ptr_url, '/');
if (!pos)
pos = strchr (ptr_url, '?');
str_port = (pos) ?
weechat_strndup (ptr_url, pos - ptr_url) : strdup (ptr_url);
if (!str_port)
return 0;
error = NULL;
number = strtol (str_port, &error, 10);
if (error && !error[0] && (number >= 0) && (number <= 65535))
{
if (port)
*port = number;
free (str_port);
}
else
{
free (str_port);
return 0;
}
}
return 1;
}
/*
* Checks if a remote URL is valid.
*
* Returns:
* 1: URL is valid
@@ -195,23 +295,7 @@ relay_remote_name_valid (const char *name)
int
relay_remote_url_valid (const char *url)
{
const char *pos;
if (!url || !url[0])
return 0;
/* URL must start with "https://" or "http://" */
if ((strncmp (url, "https://", 8) != 0) && (strncmp (url, "http://", 7) != 0))
return 0;
pos = strchr (url + 7, ':');
/* invalid port? */
if (pos && !isdigit ((unsigned char)pos[1]))
return 0;
/* URL is valid */
return 1;
return relay_remote_parse_url (url, NULL, NULL, NULL);
}
/*
@@ -229,76 +313,6 @@ relay_remote_send_signal (struct t_relay_remote *remote)
weechat_hook_signal_send (signal, WEECHAT_HOOK_SIGNAL_POINTER, remote);
}
/*
* Extracts address from URL.
*
* Note: result must be free after use.
*/
char *
relay_remote_get_address (const char *url)
{
const char *ptr_start;
char *pos;
if (!url)
return NULL;
if (strncmp (url, "http://", 7) == 0)
ptr_start = url + 7;
else if (strncmp (url, "https://", 8) == 0)
ptr_start = url + 8;
else
return NULL;
pos = strchr (ptr_start, ':');
if (!pos)
pos = strchr (ptr_start, '?');
return (pos) ?
weechat_strndup (ptr_start, pos - ptr_start) : strdup (ptr_start);
}
/*
* Extracts port from URL.
*/
int
relay_remote_get_port (const char *url)
{
char *pos, *pos2, *str_port, *error;
long port;
if (!url)
goto error;
pos = strchr (url + 7, ':');
if (!pos)
goto error;
pos++;
pos2 = strchr (pos, '/');
if (pos2)
str_port = weechat_strndup (pos, pos2 - pos);
else
str_port = strdup (pos);
if (!str_port)
goto error;
error = NULL;
port = strtol (str_port, &error, 10);
if (error && !error[0])
{
free (str_port);
return (int)port;
}
free (str_port);
error:
return RELAY_REMOTE_DEFAULT_PORT;
}
/*
* Allocates and initializes new remote structure.
*
@@ -415,9 +429,7 @@ void
relay_remote_set_url (struct t_relay_remote *remote, const char *url)
{
free (remote->address);
remote->address = relay_remote_get_address (url);
remote->port = relay_remote_get_port (url);
remote->tls = (weechat_strncmp (url, "https:", 6) == 0) ? 1 : 0;
relay_remote_parse_url (url, &remote->tls, &remote->address, &remote->port);
}
/*
+66 -33
View File
@@ -21,6 +21,8 @@
#include "CppUTest/TestHarness.h"
#include "tests/tests.h"
extern "C"
{
#include <stdio.h>
@@ -28,9 +30,21 @@ extern "C"
#include "src/plugins/relay/relay.h"
#include "src/plugins/relay/relay-remote.h"
extern char *relay_remote_get_address (const char *url);
extern int relay_remote_parse_url (const char *url,
int *tls, char **address, int *port);
}
#define WEE_CHECK_PARSE_URL(__result, __result_tls, __result_address, \
__result_port, __url) \
tls = -1; \
address = NULL; \
port = -1; \
relay_remote_parse_url (__url, &tls, &address, &port); \
LONGS_EQUAL(__result_tls, tls); \
STRCMP_EQUAL(__result_address, address); \
LONGS_EQUAL(__result_port, port); \
free (address);
TEST_GROUP(RelayRemote)
{
};
@@ -89,6 +103,57 @@ TEST(RelayRemote, NameValid)
/* TODO: write tests */
}
/*
* Tests functions:
* relay_remote_parse_url
*/
TEST(RelayRemote, ParseUrl)
{
int tls, port;
char *address;
LONGS_EQUAL(0, relay_remote_parse_url (NULL, NULL, NULL, NULL));
LONGS_EQUAL(0, relay_remote_parse_url ("", NULL, NULL, NULL));
LONGS_EQUAL(0, relay_remote_parse_url ("zzz", NULL, NULL, NULL));
LONGS_EQUAL(0, relay_remote_parse_url ("http://[::1", NULL, NULL, NULL));
LONGS_EQUAL(0, relay_remote_parse_url ("https://[::1", NULL, NULL, NULL));
LONGS_EQUAL(1, relay_remote_parse_url ("http://example.com", NULL, NULL, NULL));
LONGS_EQUAL(1, relay_remote_parse_url ("https://example.com", NULL, NULL, NULL));
LONGS_EQUAL(1, relay_remote_parse_url ("https://example.com/", NULL, NULL, NULL));
LONGS_EQUAL(1, relay_remote_parse_url ("https://example.com?option=1", NULL, NULL, NULL));
LONGS_EQUAL(1, relay_remote_parse_url ("https://example.com/?option=1", NULL, NULL, NULL));
LONGS_EQUAL(1, relay_remote_parse_url ("https://example.com:9876", NULL, NULL, NULL));
LONGS_EQUAL(1, relay_remote_parse_url ("https://example.com:9876/", NULL, NULL, NULL));
LONGS_EQUAL(1, relay_remote_parse_url ("https://example.com:9876?option=1", NULL, NULL, NULL));
LONGS_EQUAL(1, relay_remote_parse_url ("https://example.com:9876/?option=1", NULL, NULL, NULL));
WEE_CHECK_PARSE_URL(1, 0, "", RELAY_REMOTE_DEFAULT_PORT, "http://");
WEE_CHECK_PARSE_URL(1, 1, "", RELAY_REMOTE_DEFAULT_PORT, "https://");
WEE_CHECK_PARSE_URL(1, 0, "localhost", RELAY_REMOTE_DEFAULT_PORT, "http://localhost");
WEE_CHECK_PARSE_URL(1, 1, "localhost", RELAY_REMOTE_DEFAULT_PORT, "https://localhost");
WEE_CHECK_PARSE_URL(1, 1, "example.com", RELAY_REMOTE_DEFAULT_PORT, "https://example.com");
WEE_CHECK_PARSE_URL(1, 1, "example.com", RELAY_REMOTE_DEFAULT_PORT, "https://example.com/");
WEE_CHECK_PARSE_URL(1, 1, "example.com", RELAY_REMOTE_DEFAULT_PORT, "https://example.com?option=1");
WEE_CHECK_PARSE_URL(1, 1, "example.com", RELAY_REMOTE_DEFAULT_PORT, "https://example.com/?option=1");
WEE_CHECK_PARSE_URL(1, 1, "example.com", 9876, "https://example.com:9876");
WEE_CHECK_PARSE_URL(1, 1, "example.com", 9876, "https://example.com:9876/");
WEE_CHECK_PARSE_URL(1, 1, "example.com", 9876, "https://example.com:9876?option=1");
WEE_CHECK_PARSE_URL(1, 1, "example.com", 9876, "https://example.com:9876/?option=1");
WEE_CHECK_PARSE_URL(1, 0, "::1", RELAY_REMOTE_DEFAULT_PORT, "http://[::1]");
WEE_CHECK_PARSE_URL(1, 1, "::1", RELAY_REMOTE_DEFAULT_PORT, "https://[::1]");
WEE_CHECK_PARSE_URL(1, 1, "::1", RELAY_REMOTE_DEFAULT_PORT, "https://[::1]/");
WEE_CHECK_PARSE_URL(1, 1, "::1", RELAY_REMOTE_DEFAULT_PORT, "https://[::1]?option=1");
WEE_CHECK_PARSE_URL(1, 1, "::1", RELAY_REMOTE_DEFAULT_PORT, "https://[::1]/?option=1");
WEE_CHECK_PARSE_URL(1, 1, "::1", 9876, "https://[::1]:9876");
WEE_CHECK_PARSE_URL(1, 1, "::1", 9876, "https://[::1]:9876/");
WEE_CHECK_PARSE_URL(1, 1, "::1", 9876, "https://[::1]:9876?option=1");
WEE_CHECK_PARSE_URL(1, 1, "::1", 9876, "https://[::1]:9876/?option=1");
}
/*
* Tests functions:
* relay_remote_url_valid
@@ -109,38 +174,6 @@ TEST(RelayRemote, SendSignal)
/* TODO: write tests */
}
/*
* Tests functions:
* relay_remote_get_address
*/
TEST(RelayRemote, GetAddress)
{
POINTERS_EQUAL(NULL, relay_remote_get_address (NULL));
POINTERS_EQUAL(NULL, relay_remote_get_address (""));
POINTERS_EQUAL(NULL, relay_remote_get_address ("zzz"));
STRCMP_EQUAL("", relay_remote_get_address ("http://"));
STRCMP_EQUAL("", relay_remote_get_address ("https://"));
STRCMP_EQUAL("localhost", relay_remote_get_address ("https://localhost"));
STRCMP_EQUAL("example.com", relay_remote_get_address ("https://example.com"));
STRCMP_EQUAL("example.com", relay_remote_get_address ("https://example.com:8000"));
STRCMP_EQUAL("example.com", relay_remote_get_address ("https://example.com:8000/"));
STRCMP_EQUAL("example.com", relay_remote_get_address ("https://example.com:8000/?option=1"));
STRCMP_EQUAL("example.com", relay_remote_get_address ("https://example.com?option=1"));
}
/*
* Tests functions:
* relay_remote_get_port
*/
TEST(RelayRemote, GetPort)
{
/* TODO: write tests */
}
/*
* Tests functions:
* relay_remote_alloc