package edu.uci.iotproject;
+import edu.uci.iotproject.analysis.TcpConversationUtils;
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.*;
*/
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}.
* List of RST packets associated with this conversation.
*/
private final List<PcapPacket> mRstPackets;
+
+ /**
+ * Boolean to mark the packet as Application Data based on the previous packet that reaches MTU
+ */
+ private boolean mApplicationData;
/* End instance properties */
/**
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.mFinPackets = new ArrayList<>();
this.mRstPackets = new ArrayList<>();
+ this.mApplicationData = false;
}
/**
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) {
+ if (rawPayload[0] == 23) {
+ mTlsApplicationDataPackets.add(packet);
+ // Consider the following packet a data packet if this packet's size == MTU size 1448
+ if (rawPayload.length >= 1448)
+ mApplicationData = true;
+ } else if (rawPayload[0] == 20) {
+ // Do nothing for now - CHANGE_CIPHER_SPEC
+ } else if (rawPayload[0] == 21) {
+ // Do nothing for now - ALERT
+ } else if (rawPayload[0] == 22) {
+ // Do nothing for now - HANDSHAKE
+ } else {
+ // If it is TLS with payload, but rawPayload[0] != 23
+ if (mApplicationData == true) {
+ // It is a continuation of the previous packet if the previous packet reaches MTU size 1448 and
+ // it is not either type 20, 21, or 22
+ mTlsApplicationDataPackets.add(packet);
+ if (rawPayload.length < 1448)
+ mApplicationData = false;
+ }
+ }
+ }
+ }
}
/**
}
}
+ /**
+ * <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.
+ *
+ * 08/31/18: Added unconvetional TLS ports used by WeMo plugs and LiFX bulb.
+ * 09/20/18: Moved hardcoded ports to other class to allow other classes to query the set of TLS ports.
+ */
+ return TcpConversationUtils.isTlsPort(mServerPort);
+ }
+
+ /**
+ * 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.
}
/**
- * Determine the direction of {@code packet}.
+ * Determine the direction of {@code packet}. An {@link IllegalArgumentException} is thrown if {@code packet} does
+ * not pertain to this conversation.
+ *
* @param packet The packet whose direction is to be determined.
* @return A {@link Direction} indicating the direction of the packet.
*/
- private Direction getDirection(PcapPacket packet) {
+ public Direction getDirection(PcapPacket packet) {
IpV4Packet ipPacket = packet.get(IpV4Packet.class);
String ipSrc = ipPacket.getHeader().getSrcAddr().getHostAddress();
String ipDst = ipPacket.getHeader().getDstAddr().getHostAddress();
/**
* Utility enum for expressing the direction of a packet pertaining to this {@code Conversation}.
*/
- private enum Direction {
- CLIENT_TO_SERVER, SERVER_TO_CLIENT
+ public enum Direction {
+
+ CLIENT_TO_SERVER {
+ @Override
+ public String toCompactString() {
+ return "*";
+ }
+ },
+ SERVER_TO_CLIENT {
+ @Override
+ public String toCompactString() {
+ return "";
+ }
+ };
+
+ /**
+ * Get a compact string representation of this {@code Direction}.
+ * @return a compact string representation of this {@code Direction}.
+ */
+ abstract public String toCompactString();
+
}
-}
\ No newline at end of file
+}