aboutsummaryrefslogtreecommitdiffstats
path: root/src/libserver/url.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-07-02 11:35:51 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-07-02 11:36:28 +0100
commit31ef21901866b7b76755436646ab0ed2857815a1 (patch)
tree46ad73bfe7b1ee907d3c964ab715d5988953a71f /src/libserver/url.c
parent689ed83366449fee3d783848cdb4fed6fbfabdc0 (diff)
downloadrspamd-31ef21901866b7b76755436646ab0ed2857815a1.tar.gz
rspamd-31ef21901866b7b76755436646ab0ed2857815a1.zip
Add workarounds for numeric hosts in URLs.
Diffstat (limited to 'src/libserver/url.c')
-rw-r--r--src/libserver/url.c85
1 files changed, 81 insertions, 4 deletions
diff --git a/src/libserver/url.c b/src/libserver/url.c
index 15606118e..4a9fc7667 100644
--- a/src/libserver/url.c
+++ b/src/libserver/url.c
@@ -1007,11 +1007,12 @@ rspamd_tld_trie_callback (int strnum, int textpos, void *context)
static gboolean
rspamd_url_is_ip (struct rspamd_url *uri, rspamd_mempool_t *pool)
{
- const gchar *p, *end;
- gchar buf[INET6_ADDRSTRLEN + 1];
+ const gchar *p, *end, *c;
+ gchar buf[INET6_ADDRSTRLEN + 1], *errstr;
struct in_addr in4;
struct in6_addr in6;
- gboolean ret = FALSE;
+ gboolean ret = FALSE, check_num = TRUE;
+ guint32 n, dots, t, i, shift, nshift;
p = uri->host;
end = p + uri->hostlen;
@@ -1021,6 +1022,10 @@ rspamd_url_is_ip (struct rspamd_url *uri, rspamd_mempool_t *pool)
end --;
}
+ while (*(end - 1) == '.' && end > p) {
+ end --;
+ }
+
if (end - p > (gint)sizeof (buf) - 1) {
return FALSE;
}
@@ -1047,6 +1052,78 @@ rspamd_url_is_ip (struct rspamd_url *uri, rspamd_mempool_t *pool)
uri->is_numeric = TRUE;
ret = TRUE;
}
+ else {
+ /* Try also numeric notation */
+ c = p;
+ n = 0;
+ dots = 0;
+ shift = 0;
+
+ while (p <= end && check_num) {
+ if (shift < 32 && ((*p == '.' && dots < 3) || (p == end && dots <= 3))) {
+ g_assert (p - c + 1 < (gint)sizeof (buf));
+ rspamd_strlcpy (buf, c, p - c + 1);
+ c = p + 1;
+ dots ++;
+ t = strtoul (buf, &errstr, 0);
+
+ if (errstr == NULL || *errstr == '\0') {
+
+ nshift = (t == 0 ? shift + 8 : shift);
+
+ for (i = 0; i < 4; i ++) {
+ if ((t >> 8 * i) > 0) {
+ nshift += 8;
+ }
+ else {
+ break;
+ }
+ }
+ /*
+ * Here we need to find the proper shift of the previous
+ * components, so we check possible cases:
+ * 1) 1 octet
+ * 2) 2 octets
+ * 3) 3 octets
+ * 4) 4 octets
+ */
+ switch (i) {
+ case 4:
+ n |= (GUINT32_FROM_BE (t)) << shift;
+ break;
+ case 3:
+ n |= (GUINT32_FROM_BE (t)) << (shift - 8);
+ break;
+ case 2:
+ n |= (GUINT16_FROM_BE (t)) << shift;
+ break;
+ default:
+ n |= t << shift;
+ break;
+ }
+
+ shift = nshift;
+ }
+ else {
+ check_num = FALSE;
+ }
+ }
+
+ p ++;
+ }
+
+ if (check_num && dots <= 3) {
+ memcpy (&in4, &n, sizeof (in4));
+ uri->host = rspamd_mempool_alloc (pool, INET_ADDRSTRLEN + 1);
+ memset (uri->host, 0, INET_ADDRSTRLEN + 1);
+ inet_ntop (AF_INET, &in4, uri->host, INET_ADDRSTRLEN);
+ uri->hostlen = strlen (uri->host);
+ uri->tld = uri->host;
+ uri->tldlen = uri->hostlen;
+ uri->is_numeric = TRUE;
+ ret = TRUE;
+ }
+ }
return ret;
}
@@ -1056,7 +1133,7 @@ rspamd_url_parse (struct rspamd_url *uri, gchar *uristring, gsize len,
rspamd_mempool_t *pool)
{
struct http_parser_url u;
- gchar *p, *comp, t;
+ gchar *p, *comp;
const gchar *end;
guint i, complen, ret;
gint state = 0;