From 724b14cef67d37c9f6b09dddaf1186327fc054f6 Mon Sep 17 00:00:00 2001 From: Alexander Reelsen Date: Fri, 8 Aug 2014 08:48:38 +0200 Subject: [PATCH] Mapping API: Improve IP address validation Until now, IP addresses were only checked for four dots, which allowed invalid values like 127.0.0.111111 This adds an additional check for validation. Closes #7131 --- .../index/mapper/ip/IpFieldMapper.java | 6 +- .../index/mapper/ip/SimpleIpMappingTests.java | 78 +++++++++++++------ 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java index 8b273d907a6..472fc53dcdd 100644 --- a/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java @@ -19,6 +19,7 @@ package org.elasticsearch.index.mapper.ip; +import com.google.common.net.InetAddresses; import org.apache.lucene.analysis.NumericTokenStream; import org.apache.lucene.document.Field; import org.apache.lucene.document.FieldType; @@ -79,9 +80,12 @@ public class IpFieldMapper extends NumberFieldMapper { public static long ipToLong(String ip) throws ElasticsearchIllegalArgumentException { try { + if (!InetAddresses.isInetAddress(ip)) { + throw new ElasticsearchIllegalArgumentException("failed to parse ip [" + ip + "], not a valid ip address"); + } String[] octets = pattern.split(ip); if (octets.length != 4) { - throw new ElasticsearchIllegalArgumentException("failed to parse ip [" + ip + "], not full ip address (4 dots)"); + throw new ElasticsearchIllegalArgumentException("failed to parse ip [" + ip + "], not a valid ipv4 address (4 dots)"); } return (Long.parseLong(octets[0]) << 24) + (Integer.parseInt(octets[1]) << 16) + (Integer.parseInt(octets[2]) << 8) + Integer.parseInt(octets[3]); diff --git a/src/test/java/org/elasticsearch/index/mapper/ip/SimpleIpMappingTests.java b/src/test/java/org/elasticsearch/index/mapper/ip/SimpleIpMappingTests.java index 88cd8d688cb..7c2575c341e 100644 --- a/src/test/java/org/elasticsearch/index/mapper/ip/SimpleIpMappingTests.java +++ b/src/test/java/org/elasticsearch/index/mapper/ip/SimpleIpMappingTests.java @@ -19,34 +19,62 @@ package org.elasticsearch.index.mapper.ip; -import org.elasticsearch.test.ElasticsearchTestCase; -import org.junit.Ignore; +import org.elasticsearch.ElasticsearchIllegalArgumentException; +import org.elasticsearch.bootstrap.Elasticsearch; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.index.mapper.DocumentMapper; +import org.elasticsearch.index.mapper.ParsedDocument; +import org.elasticsearch.test.ElasticsearchSingleNodeTest; +import org.junit.Test; + +import static org.hamcrest.Matchers.*; /** * */ -@Ignore("No tests?") -public class SimpleIpMappingTests extends ElasticsearchTestCase { +public class SimpleIpMappingTests extends ElasticsearchSingleNodeTest { + + @Test + public void testSimpleMapping() throws Exception { + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("ip").field("type", "ip").endObject().endObject() + .endObject().endObject().string(); + + DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser().parse(mapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject() + .field("ip", "127.0.0.1") + .endObject() + .bytes()); + + assertThat(doc.rootDoc().getField("ip").numericValue().longValue(), is(2130706433L)); + assertThat(doc.rootDoc().get("ip"), is(nullValue())); + } + + @Test + public void testThatValidIpCanBeConvertedToLong() throws Exception { + assertThat(IpFieldMapper.ipToLong("127.0.0.1"), is(2130706433L)); + } + + @Test + public void testThatInvalidIpThrowsException() throws Exception { + try { + IpFieldMapper.ipToLong("127.0.011.1111111"); + fail("Expected ip address parsing to fail but did not happen"); + } catch (ElasticsearchIllegalArgumentException e) { + assertThat(e.getMessage(), containsString("not a valid ip address")); + } + } + + @Test + public void testThatIpv6AddressThrowsException() throws Exception { + try { + IpFieldMapper.ipToLong("2001:db8:0:8d3:0:8a2e:70:7344"); + fail("Expected ip address parsing to fail but did not happen"); + } catch (ElasticsearchIllegalArgumentException e) { + assertThat(e.getMessage(), containsString("not a valid ipv4 address")); + } + } - // No Longer enabled... -// @Test public void testAutoIpDetection() throws Exception { -// String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") -// .startObject("properties").endObject() -// .endObject().endObject().string(); -// -// XContentDocumentMapper defaultMapper = MapperTests.newParser().parse(mapping); -// -// ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() -// .startObject() -// .field("ip1", "127.0.0.1") -// .field("ip2", "0.1") -// .field("ip3", "127.0.0.1.2") -// .endObject() -// .copiedBytes()); -// -// assertThat(doc.doc().getFieldable("ip1"), notNullValue()); -// assertThat(doc.doc().get("ip1"), nullValue()); // its numeric -// assertThat(doc.doc().get("ip2"), equalTo("0.1")); -// assertThat(doc.doc().get("ip3"), equalTo("127.0.0.1.2")); -// } }