Conversation.java: implemented logging of TLS application data packets.
authorJanus Varmarken <varmarken@gmail.com>
Sat, 25 Aug 2018 07:14:50 +0000 (00:14 -0700)
committerJanus Varmarken <varmarken@gmail.com>
Sat, 25 Aug 2018 07:15:30 +0000 (00:15 -0700)
Code/Projects/SmartPlugDetector/.idea/modules/SmartPlugDetector_main.iml
Code/Projects/SmartPlugDetector/.idea/modules/SmartPlugDetector_test.iml
Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/Conversation.java

index 0932ae09f252045eb7dd24107daed23c34b62067..5134c0a60323a32356c2c1f8949322984a55c924 100644 (file)
@@ -5,6 +5,7 @@
     <exclude-output />
     <content url="file://$MODULE_DIR$/../../src/main">
       <sourceFolder url="file://$MODULE_DIR$/../../src/main/java" isTestSource="false" />
     <exclude-output />
     <content url="file://$MODULE_DIR$/../../src/main">
       <sourceFolder url="file://$MODULE_DIR$/../../src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/../../src/main/resources" type="java-resource" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
index 4d22f1820043a547e944150395323fa5db5b3790..b332c40ce1731f704f4b9b00fa9c7c545f54745a 100644 (file)
@@ -5,6 +5,7 @@
     <exclude-output />
     <content url="file://$MODULE_DIR$/../../src/test">
       <sourceFolder url="file://$MODULE_DIR$/../../src/test/java" isTestSource="true" />
     <exclude-output />
     <content url="file://$MODULE_DIR$/../../src/test">
       <sourceFolder url="file://$MODULE_DIR$/../../src/test/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/../../src/test/resources" type="java-test-resource" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
index e7ebf3b13ede9e8799825d2b1a23dd9b4dbfe1e1..da1f2867b734c24a17a54bd6aa5dcecb2f6ee891 100644 (file)
@@ -3,6 +3,7 @@ package edu.uci.iotproject;
 import edu.uci.iotproject.util.PcapPacketUtils;
 import org.pcap4j.core.PcapPacket;
 import org.pcap4j.packet.IpV4Packet;
 import edu.uci.iotproject.util.PcapPacketUtils;
 import org.pcap4j.core.PcapPacket;
 import org.pcap4j.packet.IpV4Packet;
+import org.pcap4j.packet.Packet;
 import org.pcap4j.packet.TcpPacket;
 
 import java.util.*;
 import org.pcap4j.packet.TcpPacket;
 
 import java.util.*;
@@ -47,6 +48,12 @@ public class Conversation {
      */
     private final List<PcapPacket> mPackets;
 
      */
     private final List<PcapPacket> mPackets;
 
+    /**
+     * If {@link #isTls()} is {@code true}, this list contains the subset of {@link #mPackets} which are TLS Application
+     * Data packets.
+     */
+    private final List<PcapPacket> mTlsApplicationDataPackets;
+
     /**
      * Contains the sequence numbers used thus far by the host that is considered the <em>client</em> in this
      * {@code Conversation}.
     /**
      * Contains the sequence numbers used thus far by the host that is considered the <em>client</em> in this
      * {@code Conversation}.
@@ -114,6 +121,7 @@ public class Conversation {
         this.mServerIp = serverIp;
         this.mServerPort = serverPort;
         this.mPackets = new ArrayList<>();
         this.mServerIp = serverIp;
         this.mServerPort = serverPort;
         this.mPackets = new ArrayList<>();
+        this.mTlsApplicationDataPackets = new ArrayList<>();
         this.mSeqNumbersClient = new HashSet<>();
         this.mSeqNumbersSrv = new HashSet<>();
         this.mSynPackets = new ArrayList<>();
         this.mSeqNumbersClient = new HashSet<>();
         this.mSeqNumbersSrv = new HashSet<>();
         this.mSynPackets = new ArrayList<>();
@@ -150,6 +158,21 @@ public class Conversation {
                 else { return 0; }
             });
         }
                 else { return 0; }
             });
         }
+        // If TLS, inspect packet to see if it's a TLS Application Data packet, and if so add it to the list of TLS
+        // Application Data packets.
+        if (isTls()) {
+            TcpPacket tcpPacket = packet.get(TcpPacket.class);
+            Packet tcpPayload = tcpPacket.getPayload();
+            if (tcpPayload == null) {
+                return;
+            }
+            byte[] rawPayload = tcpPayload.getRawData();
+            // The SSL record header is at the front of the payload and is 5 bytes long.
+            // The SSL record header type field (the first byte) is set to 23 if it is an Application Data packet.
+            if (rawPayload != null && rawPayload.length >= 5 && rawPayload[0] == 23) {
+                mTlsApplicationDataPackets.add(packet);
+            }
+        }
     }
 
     /**
     }
 
     /**
@@ -412,6 +435,45 @@ public class Conversation {
         }
     }
 
         }
     }
 
+    /**
+     * <p>
+     *     Is this {@code Conversation} a TLS session?
+     * </p>
+     *
+     * <em>Note: the current implementation simply examines the port number(s) for 443; it does <b>not</b> verify if the
+     * application data is indeed encrypted.</em>
+     *
+     * @return {@code true} if this {@code Conversation} is interpreted as a TLS session, {@code false} otherwise.
+     */
+    public boolean isTls() {
+        /*
+         * TODO:
+         * - may want to change this to be "return mServerPort == 443 || mClientPort == 443;" in order to also detect
+         *   TLS in those cases where it is not possible to correctly label who is the client and who is the server,
+         *   i.e., when the trace does not contain the SYN/SYNACK exchange.
+         * - current implementation relies on the server using the conventional TLS port number; may instead want to
+         *   inspect the first 4 bytes of each potential TLS packet to see if they match the SSL record header.
+         */
+        return mServerPort == 443;
+    }
+
+    /**
+     * If this {@code Conversation} is backing a TLS session (i.e., if the value of {@link #isTls()} is {@code true}),
+     * get the packets labeled as TLS Application Data packets. This is a subset of the full set of payload-carrying
+     * packets (as returned by {@link #getPackets()}). An exception is thrown if this method is invoked on a
+     * {@code Conversation} for which {@link #isTls()} returns {@code false}.
+     *
+     * @return A list containing exactly those packets that could be identified as TLS Application Data packets (through
+     *         inspecting of the SSL record header). The list may be empty, if no TLS application data packets have been
+     *         recorded for this {@code Conversation}.
+     */
+    public List<PcapPacket> getTlsApplicationDataPackets() {
+        if (!isTls()) {
+            throw new NoSuchElementException("cannot get TLS Application Data packets for non-TLS TCP conversation");
+        }
+        return Collections.unmodifiableList(mTlsApplicationDataPackets);
+    }
+
     /**
      * Extracts the TCP sequence number from {@code packet} and adds it to the proper set of sequence numbers by
      * analyzing the direction of the packet.
     /**
      * Extracts the TCP sequence number from {@code packet} and adds it to the proper set of sequence numbers by
      * analyzing the direction of the packet.