diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/TlsPacket.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/TlsPacket.java index 9b5ddda..34b1c14 100644 --- a/src/main/java/ru/serega6531/packmate/service/optimization/tls/TlsPacket.java +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/TlsPacket.java @@ -97,7 +97,7 @@ public class TlsPacket extends AbstractPacket { } private TlsHeader(byte[] rawData, int offset, int length) throws IllegalRawDataException { - //TODO check length + ByteArrays.validateBounds(rawData, offset, RECORD_OFFSET); this.contentType = ContentType.getInstance(ByteArrays.getByte(rawData, CONTENT_TYPE_OFFSET + offset)); this.version = TlsVersion.getInstance(ByteArrays.getShort(rawData, VERSION_OFFSET + offset)); this.recordLength = ByteArrays.getShort(rawData, LENGTH_OFFSET + offset); @@ -109,9 +109,9 @@ public class TlsPacket extends AbstractPacket { } else if (contentType == ContentType.APPLICATION_DATA) { this.record = ApplicationDataRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength); } else if (contentType == ContentType.ALERT) { - this.record = new AlertRecord(rawData, offset + RECORD_OFFSET, recordLength); + this.record = AlertRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength); } else if (contentType == ContentType.HEARTBEAT) { - //TODO + this.record = HeartbeatRecord.newInstance(rawData, offset + RECORD_OFFSET, recordLength); } else { throw new IllegalArgumentException("Unknown content type: " + contentType); } diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/AlertLevel.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/AlertLevel.java index 5b15de9..1f2c069 100644 --- a/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/AlertLevel.java +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/AlertLevel.java @@ -13,7 +13,6 @@ public class AlertLevel extends NamedNumber { public static final AlertLevel WARNING = new AlertLevel((byte) 1, "warning"); public static final AlertLevel FATAL = new AlertLevel((byte) 2, "fatal"); - public AlertLevel(Byte value, String name) { super(value, name); registry.put(value, this); diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/HeartbeatMessageType.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/HeartbeatMessageType.java new file mode 100644 index 0000000..a2c293a --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/numbers/HeartbeatMessageType.java @@ -0,0 +1,33 @@ +package ru.serega6531.packmate.service.optimization.tls.numbers; + +import org.pcap4j.packet.namednumber.NamedNumber; + +import java.util.HashMap; +import java.util.Map; + +public class HeartbeatMessageType extends NamedNumber { + + private static final Map registry = new HashMap<>(); + + public static final HeartbeatMessageType HEARTBEAT_REQUEST = new HeartbeatMessageType((byte) 1, "heartbeat_request"); + public static final HeartbeatMessageType HEARTBEAT_RESPONSE = new HeartbeatMessageType((byte) 2, "heartbeat_response"); + + public HeartbeatMessageType(Byte value, String name) { + super(value, name); + registry.put(value, this); + } + + public static HeartbeatMessageType getInstance(Byte value) { + if (registry.containsKey(value)) { + return registry.get(value); + } else { + throw new IllegalArgumentException("Unknown heartbeat message type: " + value); + } + } + + @Override + public int compareTo(HeartbeatMessageType o) { + return value().compareTo(o.value()); + } + +} diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/ChangeCipherSpecRecord.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/ChangeCipherSpecRecord.java index f5147ae..b6db856 100644 --- a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/ChangeCipherSpecRecord.java +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/ChangeCipherSpecRecord.java @@ -4,7 +4,7 @@ import org.pcap4j.util.ByteArrays; public class ChangeCipherSpecRecord implements TlsRecord { - /* + /** 0x0 - Change Cipher Spec Message 0x1 - End */ diff --git a/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/HeartbeatRecord.java b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/HeartbeatRecord.java new file mode 100644 index 0000000..8628d43 --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/service/optimization/tls/records/HeartbeatRecord.java @@ -0,0 +1,53 @@ +package ru.serega6531.packmate.service.optimization.tls.records; + +import org.pcap4j.util.ByteArrays; +import ru.serega6531.packmate.service.optimization.tls.numbers.HeartbeatMessageType; + +import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BYTES; +import static org.pcap4j.util.ByteArrays.SHORT_SIZE_IN_BYTES; + +public class HeartbeatRecord implements TlsRecord { + + //https://tools.ietf.org/html/rfc6520 + + private static final int TYPE_OFFSET = 0; + private static final int PAYLOAD_LENGTH_OFFSET = TYPE_OFFSET + BYTE_SIZE_IN_BYTES; + private static final int PAYLOAD_OFFSET = PAYLOAD_LENGTH_OFFSET + SHORT_SIZE_IN_BYTES; + + private HeartbeatMessageType type; + private short payloadLength; + private byte[] payload; + private byte[] padding; + + public static HeartbeatRecord newInstance(byte[] rawData, int offset, int length) { + ByteArrays.validateBounds(rawData, offset, length); + return new HeartbeatRecord(rawData, offset, length); + } + + public HeartbeatRecord(byte[] rawData, int offset, int length) { + this.type = HeartbeatMessageType.getInstance(ByteArrays.getByte(rawData, TYPE_OFFSET + offset)); + this.payloadLength = ByteArrays.getShort(rawData, PAYLOAD_LENGTH_OFFSET + offset); + this.payload = ByteArrays.getSubArray(rawData, PAYLOAD_OFFSET + offset, payloadLength); + this.padding = ByteArrays.getSubArray(rawData, PAYLOAD_OFFSET + payloadLength + offset); + } + + public HeartbeatMessageType getType() { + return type; + } + + public byte[] getPayload() { + return payload; + } + + public byte[] getPadding() { + return padding; + } + + @Override + public String toString() { + return " Heartbeat (" + type.name() + + ") [" + payloadLength + " bytes payload, " + + padding.length + " bytes padding]"; + } + +}