diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-07-02 11:35:51 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-07-02 11:36:28 +0100 |
commit | 31ef21901866b7b76755436646ab0ed2857815a1 (patch) | |
tree | 46ad73bfe7b1ee907d3c964ab715d5988953a71f /src/libserver/url.c | |
parent | 689ed83366449fee3d783848cdb4fed6fbfabdc0 (diff) | |
download | rspamd-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.c | 85 |
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; |