Browse Source

Fix parsing of fixed length IP addresses.

tags/1.0.5
Vsevolod Stakhov 8 years ago
parent
commit
9370ea45e1

+ 3
- 1
src/libmime/message.c View File

@@ -1566,7 +1566,9 @@ rspamd_message_parse (struct rspamd_task *task)
if (task->received->len > 0 && (task->flags & RSPAMD_TASK_FLAG_NO_IP)) {
recv = g_ptr_array_index (task->received, 0);
if (recv->real_ip) {
if (!rspamd_parse_inet_address (&task->from_addr, recv->real_ip)) {
if (!rspamd_parse_inet_address (&task->from_addr,
recv->real_ip,
0)) {
msg_warn_task ("cannot get IP from received header: '%s'",
recv->real_ip);
task->from_addr = NULL;

+ 1
- 1
src/libserver/cfg_rcl.c View File

@@ -2343,7 +2343,7 @@ rspamd_rcl_parse_struct_addr (rspamd_mempool_t *pool,
if (ucl_object_type (obj) == UCL_STRING) {
val = ucl_object_tostring (obj);

if (!rspamd_parse_inet_address (target, val)) {
if (!rspamd_parse_inet_address (target, val, 0)) {
g_set_error (err,
CFG_RCL_ERROR,
EINVAL,

+ 1
- 1
src/libserver/protocol.c View File

@@ -389,7 +389,7 @@ rspamd_protocol_handle_headers (struct rspamd_task *task,
case 'i':
case 'I':
if (g_ascii_strncasecmp (headern, IP_ADDR_HEADER, hlen) == 0) {
if (!rspamd_parse_inet_address (&task->from_addr, hv->str)) {
if (!rspamd_parse_inet_address (&task->from_addr, hv->str, 0)) {
msg_err_task ("bad ip header: '%V'", hv);
return FALSE;
}

+ 184
- 10
src/libutil/addr.c View File

@@ -352,7 +352,175 @@ err:
}

gboolean
rspamd_parse_inet_address (rspamd_inet_addr_t **target, const char *src)
rspamd_parse_inet_address_ip4 (const guchar *text, gsize len, gpointer target)
{
const guchar *p;
guchar c;
guint32 addr = 0, *addrptr = target;
guint octet = 0, n = 0;

g_assert (text != NULL);
g_assert (target != NULL);

if (len == 0) {
len = strlen (text);
}

for (p = text; p < text + len; p++) {
c = *p;

if (c >= '0' && c <= '9') {
octet = octet * 10 + (c - '0');

if (octet > 255) {
return FALSE;
}

continue;
}

if (c == '.') {
addr = (addr << 8) + octet;
octet = 0;
n++;
continue;
}

return FALSE;
}

if (n == 3) {
addr = (addr << 8) + octet;
*addrptr = ntohl (addr);

return TRUE;
}

return FALSE;
}

gboolean
rspamd_parse_inet_address_ip6 (const guchar *text, gsize len, gpointer target)
{
guchar t, *zero = NULL, *s, *d, *addr = target;
const guchar *p, *digit = NULL;
gsize len4 = 0;
guint n = 8, nibbles = 0, word = 0;

g_assert (text != NULL);
g_assert (target != NULL);

if (len == 0) {
len = strlen (text);
}

/* Ignore trailing semicolon */
if (text[0] == ':') {
p = text + 1;
len--;
}
else {
p = text;
}

for (/* void */; len; len--) {
t = *p++;

if (t == ':') {
if (nibbles) {
digit = p;
len4 = len;
*addr++ = (u_char) (word >> 8);
*addr++ = (u_char) (word & 0xff);

if (--n) {
nibbles = 0;
word = 0;
continue;
}
} else {
if (zero == NULL) {
digit = p;
len4 = len;
zero = addr;
continue;
}
}

return FALSE;
}

if (t == '.' && nibbles) {
if (n < 2 || digit == NULL) {
return FALSE;
}

/* IPv4 encoded in IPv6 */
if (!rspamd_parse_inet_address_ip4 (digit, len4 - 1, &word)) {
return FALSE;
}

word = ntohl (word);
*addr++ = (guchar) ((word >> 24) & 0xff);
*addr++ = (guchar) ((word >> 16) & 0xff);
n--;
break;
}

if (++nibbles > 4) {
/* Too many dots */
return FALSE;
}

/* Restore from hex */
if (t >= '0' && t <= '9') {
word = word * 16 + (t - '0');
continue;
}

t |= 0x20;

if (t >= 'a' && t <= 'f') {
word = word * 16 + (t - 'a') + 10;
continue;
}

return FALSE;
}

if (nibbles == 0 && zero == NULL) {
return FALSE;
}

*addr++ = (guchar) (word >> 8);
*addr++ = (guchar) (word & 0xff);

if (--n) {
if (zero) {
n *= 2;
s = addr - 1;
d = s + n;
while (s >= zero) {
*d-- = *s--;
}
memset (zero, 0, n);

return TRUE;
}

} else {
if (zero == NULL) {
return TRUE;
}
}

return FALSE;
}

gboolean
rspamd_parse_inet_address (rspamd_inet_addr_t **target,
const char *src,
gsize srclen)
{
gboolean ret = FALSE;
rspamd_inet_addr_t *addr = NULL;
@@ -360,11 +528,15 @@ rspamd_parse_inet_address (rspamd_inet_addr_t **target, const char *src)
const char *end;
char ipbuf[INET6_ADDRSTRLEN + 1];
guint iplen;
guint portnum;
gulong portnum;

g_assert (src != NULL);
g_assert (target != NULL);

if (srclen == 0) {
srclen = strlen (src);
}

rspamd_ip_check_ipv6 ();

if (src[0] == '/' || src[0] == '.') {
@@ -388,7 +560,8 @@ rspamd_parse_inet_address (rspamd_inet_addr_t **target, const char *src)
rspamd_strlcpy (ipbuf, src + 1, iplen);

if (ipv6_status == RSPAMD_IPV6_SUPPORTED &&
inet_pton (AF_INET6, ipbuf, &su.s6.sin6_addr) == 1) {
rspamd_parse_inet_address_ip6 (ipbuf, iplen - 1,
&su.s6.sin6_addr)) {
addr = rspamd_inet_addr_create (AF_INET6);
memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr,
sizeof (struct in6_addr));
@@ -397,7 +570,7 @@ rspamd_parse_inet_address (rspamd_inet_addr_t **target, const char *src)

if (ret && end[1] == ':') {
/* Port part */
portnum = strtoul (end + 1, NULL, 10);
rspamd_strtoul (end + 1, srclen - iplen - 1, &portnum);
rspamd_inet_address_set_port (addr, portnum);
}
}
@@ -406,7 +579,7 @@ rspamd_parse_inet_address (rspamd_inet_addr_t **target, const char *src)
if ((end = strchr (src, ':')) != NULL) {
/* This is either port number and ipv4 addr or ipv6 addr */
if (ipv6_status == RSPAMD_IPV6_SUPPORTED &&
inet_pton (AF_INET6, src, &su.s6.sin6_addr) == 1) {
rspamd_parse_inet_address_ip6 (src, srclen, &su.s6.sin6_addr)) {
addr = rspamd_inet_addr_create (AF_INET6);
memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr,
sizeof (struct in6_addr));
@@ -423,25 +596,26 @@ rspamd_parse_inet_address (rspamd_inet_addr_t **target, const char *src)
rspamd_strlcpy (ipbuf, src, iplen);
}

if (inet_pton (AF_INET, ipbuf, &su.s4.sin_addr) == 1) {
if (rspamd_parse_inet_address_ip4 (ipbuf, iplen - 1,
&su.s4.sin_addr)) {
addr = rspamd_inet_addr_create (AF_INET);
memcpy (&addr->u.in.addr.s4.sin_addr, &su.s4.sin_addr,
sizeof (struct in_addr));
portnum = strtoul (end + 1, NULL, 10);
rspamd_strtoul (end + 1, srclen - iplen - 1, &portnum);
rspamd_inet_address_set_port (addr, portnum);
ret = TRUE;
}
}
}
else {
if (inet_pton (AF_INET, src, &su.s4.sin_addr) == 1) {
if (rspamd_parse_inet_address_ip4 (src, srclen, &su.s4.sin_addr)) {
addr = rspamd_inet_addr_create (AF_INET);
memcpy (&addr->u.in.addr.s4.sin_addr, &su.s4.sin_addr,
sizeof (struct in_addr));
ret = TRUE;
}
else if (ipv6_status == RSPAMD_IPV6_SUPPORTED &&
inet_pton (AF_INET6, src, &su.s6.sin6_addr) == 1) {
rspamd_parse_inet_address_ip6 (src, srclen, &su.s6.sin6_addr)) {
addr = rspamd_inet_addr_create (AF_INET6);
memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr,
sizeof (struct in6_addr));
@@ -820,7 +994,7 @@ rspamd_parse_host_port_priority_strv (gchar **tokens,
rspamd_ptr_array_free_hard, *addrs);
}

if (!rspamd_parse_inet_address (&cur_addr, tokens[0])) {
if (!rspamd_parse_inet_address (&cur_addr, tokens[0], 0)) {
msg_err ("cannot parse unix socket definition %s: %s",
tokens[0],
strerror (errno));

+ 24
- 1
src/libutil/addr.h View File

@@ -63,6 +63,28 @@ rspamd_inet_addr_t * rspamd_inet_address_new (int af, const void *init);
rspamd_inet_addr_t * rspamd_inet_address_from_sa (const struct sockaddr *sa,
socklen_t slen);

/**
* Parse string with ipv6 address of length `len` to `target` which should be
* at least sizeof (in6_addr_t)
* @param text input string
* @param len lenth of `text` (if 0, then `text` must be zero terminated)
* @param target target structure
* @return TRUE if the address has been parsed, otherwise `target` content is undefined
*/
gboolean rspamd_parse_inet_address_ip6 (const guchar *text, gsize len,
gpointer target);

/**
* Parse string with ipv4 address of length `len` to `target` which should be
* at least sizeof (in4_addr_t)
* @param text input string
* @param len lenth of `text` (if 0, then `text` must be zero terminated)
* @param target target structure
* @return TRUE if the address has been parsed, otherwise `target` content is undefined
*/
gboolean rspamd_parse_inet_address_ip4 (const guchar *text, gsize len,
gpointer target);

/**
* Try to parse address from string
* @param target target to fill
@@ -70,7 +92,8 @@ rspamd_inet_addr_t * rspamd_inet_address_from_sa (const struct sockaddr *sa,
* @return TRUE if addr has been parsed
*/
gboolean rspamd_parse_inet_address (rspamd_inet_addr_t **target,
const char *src);
const char *src,
gsize srclen);

/**
* Returns string representation of inet address

+ 1
- 1
src/lua/lua_http.c View File

@@ -449,7 +449,7 @@ lua_http_request (lua_State *L)
rspamd_session_watcher_push (session);
}

if (rspamd_parse_inet_address (&cbd->addr, msg->host->str)) {
if (rspamd_parse_inet_address (&cbd->addr, msg->host->str, 0)) {
/* Host is numeric IP, no need to resolve */
if (!lua_http_make_connection (cbd)) {
lua_http_maybe_free (cbd);

+ 2
- 2
src/lua/lua_ip.c View File

@@ -359,7 +359,7 @@ lua_ip_from_string (lua_State *L)
ip_str = luaL_checkstring (L, 1);
if (ip_str) {
ip = lua_ip_new (L, NULL);
rspamd_parse_inet_address (&ip->addr, ip_str);
rspamd_parse_inet_address (&ip->addr, ip_str, 0);
}
else {
lua_pushnil (L);
@@ -511,7 +511,7 @@ rspamd_lua_ip_push_fromstring (lua_State *L, const gchar *ip_str)
}
else {
ip = g_slice_alloc0 (sizeof (struct rspamd_lua_ip));
rspamd_parse_inet_address (&ip->addr, ip_str);
rspamd_parse_inet_address (&ip->addr, ip_str, 0);

pip = lua_newuserdata (L, sizeof (struct rspamd_lua_ip *));
rspamd_lua_setclass (L, "rspamd{ip}", -1);

+ 1
- 1
src/lua/lua_tcp.c View File

@@ -600,7 +600,7 @@ lua_tcp_request (lua_State *L)
g_quark_from_static_string ("lua tcp"));
}

if (rspamd_parse_inet_address (&cbd->addr, host)) {
if (rspamd_parse_inet_address (&cbd->addr, host, 0)) {
rspamd_inet_address_set_port (cbd->addr, port);
/* Host is numeric IP, no need to resolve */
if (!lua_tcp_make_connection (cbd)) {

+ 2
- 1
src/rspamd.c View File

@@ -979,7 +979,8 @@ main (gint argc, gchar **argv, gchar **env)
control_fd = -1;
if (rspamd_main->cfg->control_socket_path) {
if (!rspamd_parse_inet_address (&control_addr,
rspamd_main->cfg->control_socket_path)) {
rspamd_main->cfg->control_socket_path,
0)) {
msg_err_main ("cannot parse inet address %s",
rspamd_main->cfg->control_socket_path);
}

+ 1
- 1
test/rspamd_http_test.c View File

@@ -244,7 +244,7 @@ rspamd_http_test_func (void)

mtx = rspamd_mempool_get_mutex (pool);

rspamd_parse_inet_address (&addr, "127.0.0.1");
rspamd_parse_inet_address (&addr, "127.0.0.1", 0);
rspamd_inet_address_set_port (addr, ottery_rand_range (30000) + 32768);
serv_key = rspamd_http_connection_gen_key ();
client_key = rspamd_http_connection_gen_key ();

+ 2
- 2
test/rspamd_upstream_test.c View File

@@ -138,9 +138,9 @@ rspamd_upstream_test_func (void)
nls = rspamd_upstreams_create ();
g_assert (rspamd_upstreams_add_upstream (nls, "127.0.0.1", 0, NULL));
up = rspamd_upstream_get (nls, RSPAMD_UPSTREAM_RANDOM);
rspamd_parse_inet_address(&paddr, "127.0.0.2");
rspamd_parse_inet_address (&paddr, "127.0.0.2", 0);
g_assert (rspamd_upstream_add_addr (up, paddr));
rspamd_parse_inet_address(&paddr, "::1");
rspamd_parse_inet_address (&paddr, "::1", 0);
g_assert (rspamd_upstream_add_addr (up, paddr));
addr = rspamd_upstream_addr (up);
for (i = 0; i < 256; i ++) {

Loading…
Cancel
Save