You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by rm...@apache.org on 2018/08/17 13:47:47 UTC

metron git commit: METRON-1739 UDP packets are not handled (merrimanr) closes apache/metron#1168

Repository: metron
Updated Branches:
  refs/heads/feature/METRON-1554-pcap-query-panel 076a6a197 -> 14e80b3c2


METRON-1739 UDP packets are not handled (merrimanr) closes apache/metron#1168


Project: http://git-wip-us.apache.org/repos/asf/metron/repo
Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/14e80b3c
Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/14e80b3c
Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/14e80b3c

Branch: refs/heads/feature/METRON-1554-pcap-query-panel
Commit: 14e80b3c229ea2e5a8d615c87d822d4b44d8ec98
Parents: 076a6a1
Author: merrimanr <me...@gmail.com>
Authored: Fri Aug 17 08:47:32 2018 -0500
Committer: rmerriman <me...@gmail.com>
Committed: Fri Aug 17 08:47:32 2018 -0500

----------------------------------------------------------------------
 .../src/app/pcap/model/pdml.mock.ts             | 31 ++++++++
 .../pcap-packet-line.component.spec.ts          | 53 ++++++++++++--
 .../pcap-packet-line.component.ts               | 15 ++--
 .../java/org/apache/metron/pcap/PcapHelper.java | 18 ++++-
 .../org/apache/metron/pcap/PcapHelperTest.java  | 76 ++++++++++++++++++++
 5 files changed, 180 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/metron/blob/14e80b3c/metron-interface/metron-alerts/src/app/pcap/model/pdml.mock.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/model/pdml.mock.ts b/metron-interface/metron-alerts/src/app/pcap/model/pdml.mock.ts
index 6316b92..2520da1 100644
--- a/metron-interface/metron-alerts/src/app/pcap/model/pdml.mock.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/model/pdml.mock.ts
@@ -60,3 +60,34 @@ export const fakePacket = {
     } as PdmlProto
   ]
 } as PdmlPacket;
+
+export const fakeUdpPacket = {
+  "name": '',
+  "expanded": false,
+  "protos": [
+    {
+      "name": "geninfo",
+      "showname": "",
+      "fields": [
+        { "name": "timestamp", "pos": "0", "showname": "Captured Time", "size": "342", "value": "1534414874.932794000", "show": "Aug 16, 2018 10:21:14.932794000 UTC", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField
+      ]
+    } as PdmlProto,
+    {
+      "name": "ip",
+      "showname": "",
+      "fields": [
+        { "name": "ip.proto", "pos": "23", "showname": "Protocol: UDP (17)", "size": "1", "value": "11", "show": "17", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField,
+        { "name": "ip.src", "pos": "26", "showname": "Source: 0.0.0.0 (0.0.0.0)", "size": "4", "value": "00000000", "show": "0.0.0.0", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField,
+        { "name": "ip.dst", "pos": "30", "showname": "Destination: 255.255.255.255 (255.255.255.255)", "size": "4", "value": "ffffffff", "show": "255.255.255.255", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField
+      ]
+    } as PdmlProto,
+    {
+      "name": "udp",
+      "showname": "User Datagram Protocol, Src Port: bootpc (68), Dst Port: bootps (67)",
+      "fields": [
+        { "name": "udp.srcport", "pos": "34", "showname": "Source port: bootpc (68)", "size": "2", "value": "0044", "show": "68", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField,
+        { "name": "udp.dstport", "pos": "36", "showname": "Destination port: bootps (67)", "size": "2", "value": "0043", "show": "67", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField
+      ],
+    } as PdmlProto
+  ]
+} as PdmlPacket;

http://git-wip-us.apache.org/repos/asf/metron/blob/14e80b3c/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts
index d01c0cb..00f081f 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts
@@ -17,6 +17,7 @@
  */
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 import { fakePacket } from '../model/pdml.mock';
+import { fakeUdpPacket } from '../model/pdml.mock';
 
 import { PcapPacketLineComponent } from './pcap-packet-line.component';
 
@@ -34,8 +35,6 @@ describe('PcapPacketLineComponent', () => {
   beforeEach(() => {
     fixture = TestBed.createComponent(PcapPacketLineComponent);
     component = fixture.componentInstance;
-    component.packet = fakePacket;
-    fixture.detectChanges();
   });
 
   it('should be created', () => {
@@ -43,6 +42,8 @@ describe('PcapPacketLineComponent', () => {
   });
 
   it('should extract timestamp fields', () => {
+    component.packet = fakePacket;
+    fixture.detectChanges();
     expect(component.ip.timestamp).toEqual({ 
       "name": "timestamp", 
       "pos": "0", 
@@ -59,6 +60,8 @@ describe('PcapPacketLineComponent', () => {
   });
 
   it('should extract ipSrcAddr fields', () => {
+    component.packet = fakePacket;
+    fixture.detectChanges();
     expect(component.ip.ipSrcAddr).toEqual({ 
       "name": "ip.src", 
       "pos": "26", 
@@ -74,6 +77,8 @@ describe('PcapPacketLineComponent', () => {
   });
 
   it('should extract ipSrcPort fields', () => {
+    component.packet = fakePacket;
+    fixture.detectChanges();
     expect(component.ip.ipSrcPort).toEqual({ 
       "name": "tcp.srcport", 
       "pos": "34", 
@@ -88,7 +93,9 @@ describe('PcapPacketLineComponent', () => {
     });
   });
 
-  it('should extract ipDestAddr fields', () => {
+  it('should extract TCP ipDestAddr fields', () => {
+    component.packet = fakePacket;
+    fixture.detectChanges();
     expect(component.ip.ipDestAddr).toEqual({ 
       "name": "ip.dst", 
       "pos": "30", 
@@ -103,7 +110,9 @@ describe('PcapPacketLineComponent', () => {
     });
   });
   
-  it('should extract ipDestPort fields', () => {
+  it('should extract TCP ipDestPort fields', () => {
+    component.packet = fakePacket;
+    fixture.detectChanges();
     expect(component.ip.ipDestPort).toEqual({ 
       "name": "tcp.dstport", 
       "pos": "36", 
@@ -119,6 +128,8 @@ describe('PcapPacketLineComponent', () => {
   });
   
   it('should extract protocol fields', () => {
+    component.packet = fakePacket;
+    fixture.detectChanges();
     expect(component.ip.protocol).toEqual({ 
       "name": "ip.proto", 
       "pos": "23", 
@@ -132,4 +143,38 @@ describe('PcapPacketLineComponent', () => {
       "protos": null 
     });
   });
+
+  it('should extract UDP ipSrcPort fields', () => {
+    component.packet = fakeUdpPacket;
+    fixture.detectChanges();
+    expect(component.ip.ipSrcPort).toEqual({
+      "name": "udp.srcport",
+      "pos": "34",
+      "showname": "Source port: bootpc (68)",
+      "size": "2",
+      "value": "0044",
+      "show": "68",
+      "unmaskedvalue": null,
+      "hide": null,
+      "fields": null,
+      "protos": null
+    });
+  });
+
+  it('should extract UDP ipDestPort fields', () => {
+    component.packet = fakeUdpPacket;
+    fixture.detectChanges();
+    expect(component.ip.ipDestPort).toEqual({
+      "name": "udp.dstport",
+      "pos": "36",
+      "showname": "Destination port: bootps (67)",
+      "size": "2",
+      "value": "0043",
+      "show": "67",
+      "unmaskedvalue": null,
+      "hide": null,
+      "fields": null,
+      "protos": null
+    });
+  });
 });

http://git-wip-us.apache.org/repos/asf/metron/blob/14e80b3c/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts
index bb160a0..b1546af 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts
@@ -25,28 +25,29 @@ import { PdmlPacket, PdmlProto, PdmlField } from '../model/pdml'
 })
 export class PcapPacketLineComponent implements OnInit {
 
-  @Input() packet: PdmlPacket
+  @Input() packet: PdmlPacket;
 
   ip: {
     timestamp: PdmlField,
     ipSrcAddr: PdmlField, ipSrcPort: PdmlField,
     ipDestAddr: PdmlField, ipDestPort: PdmlField,
     protocol: PdmlField
-  }
+  };
 
   constructor() { }
 
   ngOnInit() {
-    const genProto: PdmlProto = this.packet.protos.filter(p => p.name == "geninfo")[0]
-    const ipProto: PdmlProto = this.packet.protos.filter(p => p.name == "ip")[0]
-    const tcpProto: PdmlProto = this.packet.protos.filter(p => p.name == "tcp")[0]
+    const genProto: PdmlProto = this.packet.protos.filter(p => p.name == "geninfo")[0];
+    const ipProto: PdmlProto = this.packet.protos.filter(p => p.name == "ip")[0];
+    const tcpProto: PdmlProto = this.packet.protos.filter(p => p.name == "tcp")[0];
+    const udpProto: PdmlProto = this.packet.protos.filter(p => p.name == "udp")[0];
 
     this.ip = {
       timestamp: PdmlProto.findField(genProto,'timestamp'),
       ipSrcAddr: PdmlProto.findField(ipProto,'ip.src'),
-      ipSrcPort: PdmlProto.findField(tcpProto,'tcp.srcport'),
+      ipSrcPort: tcpProto ? PdmlProto.findField(tcpProto,'tcp.srcport') : PdmlProto.findField(udpProto,'udp.srcport'),
       ipDestAddr: PdmlProto.findField(ipProto,'ip.dst'),
-      ipDestPort: PdmlProto.findField(tcpProto,'tcp.dstport'),
+      ipDestPort: tcpProto ? PdmlProto.findField(tcpProto,'tcp.dstport') : PdmlProto.findField(udpProto,'udp.dstport'),
       protocol: PdmlProto.findField(ipProto,'ip.proto')
     };
   }

http://git-wip-us.apache.org/repos/asf/metron/blob/14e80b3c/metron-platform/metron-pcap/src/main/java/org/apache/metron/pcap/PcapHelper.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-pcap/src/main/java/org/apache/metron/pcap/PcapHelper.java b/metron-platform/metron-pcap/src/main/java/org/apache/metron/pcap/PcapHelper.java
index 1ebdf7c..aa3eafe 100644
--- a/metron-platform/metron-pcap/src/main/java/org/apache/metron/pcap/PcapHelper.java
+++ b/metron-platform/metron-pcap/src/main/java/org/apache/metron/pcap/PcapHelper.java
@@ -257,9 +257,23 @@ public class PcapHelper {
       if(pi.getTcpPacket().getDestination() != null ) {
         ret.put(org.apache.metron.common.Constants.Fields.DST_PORT.getName(), pi.getTcpPacket().getDestination().getPort());
       }
-      if(pi.getIpv4Packet() != null) {
-        ret.put(org.apache.metron.common.Constants.Fields.PROTOCOL.getName(), pi.getIpv4Packet().getProtocol());
+    }
+    if(pi.getUdpPacket() != null) {
+      if (pi.getUdpPacket().getSource() != null) {
+        if(pi.getUdpPacket().getSource().getAddress() != null) {
+          ret.put(org.apache.metron.common.Constants.Fields.SRC_ADDR.getName(), pi.getUdpPacket().getSource().getAddress().getHostAddress());
+        }
+        ret.put(org.apache.metron.common.Constants.Fields.SRC_PORT.getName(), pi.getUdpPacket().getSource().getPort());
       }
+      if (pi.getUdpPacket().getDestination() != null) {
+        if(pi.getUdpPacket().getDestination().getAddress() != null ) {
+          ret.put(org.apache.metron.common.Constants.Fields.DST_ADDR.getName(), pi.getUdpPacket().getDestination().getAddress().getHostAddress());
+        }
+        ret.put(org.apache.metron.common.Constants.Fields.DST_PORT.getName(), pi.getUdpPacket().getDestination().getPort());
+      }
+    }
+    if(pi.getIpv4Packet() != null) {
+      ret.put(org.apache.metron.common.Constants.Fields.PROTOCOL.getName(), pi.getIpv4Packet().getProtocol());
     }
     return ret;
   }

http://git-wip-us.apache.org/repos/asf/metron/blob/14e80b3c/metron-platform/metron-pcap/src/test/java/org/apache/metron/pcap/PcapHelperTest.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-pcap/src/test/java/org/apache/metron/pcap/PcapHelperTest.java b/metron-platform/metron-pcap/src/test/java/org/apache/metron/pcap/PcapHelperTest.java
index 5d2bee0..73f359d 100644
--- a/metron-platform/metron-pcap/src/test/java/org/apache/metron/pcap/PcapHelperTest.java
+++ b/metron-platform/metron-pcap/src/test/java/org/apache/metron/pcap/PcapHelperTest.java
@@ -27,11 +27,22 @@ import org.apache.hadoop.io.SequenceFile;
 import org.apache.metron.spout.pcap.Endianness;
 import org.junit.Assert;
 import org.junit.Test;
+import org.krakenapps.pcap.decoder.ip.Ipv4Packet;
+import org.krakenapps.pcap.decoder.tcp.TcpPacket;
+import org.krakenapps.pcap.decoder.udp.UdpPacket;
 
 import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
+
+import static org.apache.metron.common.Constants.Fields;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 public class PcapHelperTest {
   public static List<byte[]> readSamplePackets(String pcapLoc) throws IOException {
@@ -75,4 +86,69 @@ public class PcapHelperTest {
       }
     }
   }
+
+  @Test
+  public void packetToFieldsShouldProperlyParserTcpPackets() throws Exception {
+    PacketInfo packetInfo = mock(PacketInfo.class);
+    when(packetInfo.getPacketBytes()).thenReturn("packet bytes".getBytes(StandardCharsets.UTF_8));
+    TcpPacket tcpPacket = mock(TcpPacket.class);
+    // Tcp source address and port
+    InetAddress tcpSourceInetAddress = mock(InetAddress.class);
+    when(tcpSourceInetAddress.getHostAddress()).thenReturn("tcp source address");
+    when(tcpPacket.getSourceAddress()).thenReturn(tcpSourceInetAddress);
+    InetSocketAddress tcpSourceInetSocketAddress = new InetSocketAddress(22);
+    when(tcpPacket.getSource()).thenReturn(tcpSourceInetSocketAddress);
+    // Tcp destination address and port
+    InetAddress tcpDestinationInetAddress = mock(InetAddress.class);
+    when(tcpDestinationInetAddress.getHostAddress()).thenReturn("tcp destination address");
+    when(tcpPacket.getDestinationAddress()).thenReturn(tcpDestinationInetAddress);
+    InetSocketAddress tcpDestinationInetSocketAddress = new InetSocketAddress(55791);
+    when(tcpPacket.getDestination()).thenReturn(tcpDestinationInetSocketAddress);
+    when(packetInfo.getTcpPacket()).thenReturn(tcpPacket);
+
+    Ipv4Packet ipv4Packet = mock(Ipv4Packet.class);
+    when(ipv4Packet.getProtocol()).thenReturn(6);
+    when(packetInfo.getIpv4Packet()).thenReturn(ipv4Packet);
+
+    Map<String, Object> actualFields = PcapHelper.packetToFields(packetInfo);
+    Assert.assertArrayEquals("packet bytes".getBytes(StandardCharsets.UTF_8),
+            (byte[]) actualFields.get(PcapHelper.PacketFields.PACKET_DATA.getName()));
+    Assert.assertEquals("tcp source address", actualFields.get(Fields.SRC_ADDR.getName()));
+    Assert.assertEquals(22, actualFields.get(Fields.SRC_PORT.getName()));
+    Assert.assertEquals("tcp destination address", actualFields.get(Fields.DST_ADDR.getName()));
+    Assert.assertEquals(55791, actualFields.get(Fields.DST_PORT.getName()));
+    Assert.assertEquals(6, actualFields.get(Fields.PROTOCOL.getName()));
+  }
+
+  @Test
+  public void packetToFieldsShouldProperlyParserUdpPackets() throws Exception {
+    PacketInfo packetInfo = mock(PacketInfo.class);
+    when(packetInfo.getPacketBytes()).thenReturn("packet bytes".getBytes(StandardCharsets.UTF_8));
+
+    UdpPacket udpPacket = mock(UdpPacket.class);
+    // Udp source address and port
+    InetAddress udpSourceInetAddress = mock(InetAddress.class);
+    when(udpSourceInetAddress.getHostAddress()).thenReturn("udp source address");
+    InetSocketAddress udpSourceInetSocketAddress = new InetSocketAddress(udpSourceInetAddress, 68);
+    when(udpPacket.getSource()).thenReturn(udpSourceInetSocketAddress);
+    // Udp destination address and port
+    InetAddress udpDestinationInetAddress = mock(InetAddress.class);
+    when(udpDestinationInetAddress.getHostAddress()).thenReturn("udp destination address");
+    InetSocketAddress udpDestinationInetSocketAddress = new InetSocketAddress(udpDestinationInetAddress, 67);
+    when(udpPacket.getDestination()).thenReturn(udpDestinationInetSocketAddress);
+    when(packetInfo.getUdpPacket()).thenReturn(udpPacket);
+
+    Ipv4Packet ipv4Packet = mock(Ipv4Packet.class);
+    when(ipv4Packet.getProtocol()).thenReturn(17);
+    when(packetInfo.getIpv4Packet()).thenReturn(ipv4Packet);
+
+    Map<String, Object> actualFields = PcapHelper.packetToFields(packetInfo);
+    Assert.assertArrayEquals("packet bytes".getBytes(StandardCharsets.UTF_8),
+            (byte[]) actualFields.get(PcapHelper.PacketFields.PACKET_DATA.getName()));
+    Assert.assertEquals("udp source address", actualFields.get(Fields.SRC_ADDR.getName()));
+    Assert.assertEquals(68, actualFields.get(Fields.SRC_PORT.getName()));
+    Assert.assertEquals("udp destination address", actualFields.get(Fields.DST_ADDR.getName()));
+    Assert.assertEquals(67, actualFields.get(Fields.DST_PORT.getName()));
+    Assert.assertEquals(17, actualFields.get(Fields.PROTOCOL.getName()));
+  }
 }