diff options
3 files changed, 115 insertions, 22 deletions
diff --git a/src/java/com/android/ike/ikev2/IkeIdentification.java b/src/java/com/android/ike/ikev2/IkeIdentification.java index aad93bea..52164311 100644 --- a/src/java/com/android/ike/ikev2/IkeIdentification.java +++ b/src/java/com/android/ike/ikev2/IkeIdentification.java @@ -24,7 +24,9 @@ import com.android.ike.ikev2.exceptions.AuthenticationFailedException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.UnknownHostException; +import java.util.Objects; import java.util.Set; /** @@ -78,22 +80,12 @@ public abstract class IkeIdentification { } /** - * Compare this IkeIdentification against specified IkeIdentification. - * - * @param ikeId the IkeIdentification to compare against. - * @return true if two IkeIdentifications are the same; false otherwise. - */ - public abstract boolean equals(IkeIdentification ikeId); - - /** * Return the encoded identification data in a byte array. * * @return the encoded identification data. */ public abstract byte[] getEncodedIdData(); - // TODO: Add abstract method for encoding. - /** IkeIpv4AddrIdentification represents ID information in IPv4 address ID type. */ public static class IkeIpv4AddrIdentification extends IkeIdentification { public final Inet4Address ipv4Address; @@ -109,8 +101,8 @@ public abstract class IkeIdentification { super(ID_TYPE_IPV4_ADDR); try { ipv4Address = (Inet4Address) (Inet4Address.getByAddress(ipv4AddrBytes)); - } catch (UnknownHostException e) { - throw new AuthenticationFailedException("IP4 address is of illegal length."); + } catch (ClassCastException | UnknownHostException e) { + throw new AuthenticationFailedException(e); } } @@ -125,27 +117,80 @@ public abstract class IkeIdentification { ipv4Address = address; } + @Override + public int hashCode() { + return Objects.hash(idType, ipv4Address); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof IkeIpv4AddrIdentification)) return false; + + return ipv4Address.equals(((IkeIpv4AddrIdentification) o).ipv4Address); + } + + /** + * Retrieve the byte-representation of the IPv4 address. + * + * @return the byte-representation of the IPv4 address. + */ + @Override + public byte[] getEncodedIdData() { + return ipv4Address.getAddress(); + } + } + + /** IkeIpv6AddrIdentification represents ID information in IPv6 address ID type. */ + public static class IkeIpv6AddrIdentification extends IkeIdentification { + public final Inet6Address ipv6Address; + /** - * Compare this IkeIpv4AddrIdentification against specified IkeIdentification. + * Construct an instance of IkeIpv6AddrIdentification from decoding an inbound packet. * - * @param ikeId the IkeIdentification to compare against. - * @return true if IkeIdentifications are the same; false otherwise. + * @param ipv6AddrBytes IPv6 address in byte array. + * @throws AuthenticationFailedException for decoding bytes error. */ + public IkeIpv6AddrIdentification(byte[] ipv6AddrBytes) + throws AuthenticationFailedException { + super(ID_TYPE_IPV6_ADDR); + try { + ipv6Address = (Inet6Address) (Inet6Address.getByAddress(ipv6AddrBytes)); + } catch (ClassCastException | UnknownHostException e) { + throw new AuthenticationFailedException(e); + } + } + + /** + * Construct an instance of IkeIpv6AddrIdentification with user provided IPv6 address for + * building outbound packet. + * + * @param address user provided IPv6 address + */ + public IkeIpv6AddrIdentification(Inet6Address address) { + super(ID_TYPE_IPV6_ADDR); + ipv6Address = address; + } + @Override - public boolean equals(IkeIdentification ikeId) { - if (!(ikeId instanceof IkeIpv4AddrIdentification)) return false; + public int hashCode() { + return Objects.hash(idType, ipv6Address); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof IkeIpv6AddrIdentification)) return false; - return ipv4Address.equals(((IkeIpv4AddrIdentification) ikeId).ipv4Address); + return ipv6Address.equals(((IkeIpv6AddrIdentification) o).ipv6Address); } /** - * Return raw IP address in a byte array. + * Retrieve the byte-representation of the IPv6 address. * - * @return the raw IP address in a byte array. + * @return the byte-representation of the IPv6 address. */ @Override public byte[] getEncodedIdData() { - return ipv4Address.getAddress(); + return ipv6Address.getAddress(); } } } diff --git a/src/java/com/android/ike/ikev2/message/IkeIdPayload.java b/src/java/com/android/ike/ikev2/message/IkeIdPayload.java index bdf6647e..9fbfc959 100644 --- a/src/java/com/android/ike/ikev2/message/IkeIdPayload.java +++ b/src/java/com/android/ike/ikev2/message/IkeIdPayload.java @@ -18,6 +18,7 @@ package com.android.ike.ikev2.message; import com.android.ike.ikev2.IkeIdentification; import com.android.ike.ikev2.IkeIdentification.IkeIpv4AddrIdentification; +import com.android.ike.ikev2.IkeIdentification.IkeIpv6AddrIdentification; import com.android.ike.ikev2.exceptions.AuthenticationFailedException; import com.android.ike.ikev2.exceptions.IkeException; import com.android.ike.ikev2.exceptions.InvalidSyntaxException; @@ -72,8 +73,21 @@ public final class IkeIdPayload extends IkePayload { case IkeIdentification.ID_TYPE_IPV4_ADDR: ikeId = new IkeIpv4AddrIdentification(idData); return; + case IkeIdentification.ID_TYPE_FQDN: + // Fall through + case IkeIdentification.ID_TYPE_RFC822_ADDR: + throw new UnsupportedOperationException("ID type is not supported currently."); + case IkeIdentification.ID_TYPE_IPV6_ADDR: + ikeId = new IkeIpv6AddrIdentification(idData); + return; + case IkeIdentification.ID_TYPE_DER_ASN1_DN: + // Fall through + case IkeIdentification.ID_TYPE_DER_ASN1_GN: + // Fall through + case IkeIdentification.ID_TYPE_KEY_ID: + throw new UnsupportedOperationException("ID type is not supported currently."); default: - throw new AuthenticationFailedException("Unsupported ID type."); + throw new AuthenticationFailedException("Unsupported ID type: " + idType); } } diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeIdPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeIdPayloadTest.java index 849393cb..893857a8 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeIdPayloadTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeIdPayloadTest.java @@ -22,11 +22,13 @@ import static org.junit.Assert.fail; import com.android.ike.ikev2.IkeIdentification; import com.android.ike.ikev2.IkeIdentification.IkeIpv4AddrIdentification; +import com.android.ike.ikev2.IkeIdentification.IkeIpv6AddrIdentification; import com.android.ike.ikev2.exceptions.AuthenticationFailedException; import org.junit.Test; import java.net.Inet4Address; +import java.net.Inet6Address; import java.nio.ByteBuffer; public final class IkeIdPayloadTest { @@ -36,6 +38,12 @@ public final class IkeIdPayloadTest { private static final String IPV4_ADDR_ID_PAYLOAD_RESPONDER_BODY_HEX_STRING = "01000000c0000264"; private static final String IPV4_ADDR_STRING = "192.0.2.100"; + private static final String IPV6_ADDR_ID_PAYLOAD_RESPONDER_HEX_STRING = + "27000018050000000000200100000db80000000000000001"; + private static final String IPV6_ADDR_ID_PAYLOAD_RESPONDER_BODY_HEX_STRING = + "050000000000200100000db80000000000000001"; + private static final String IPV6_ADDR_STRING = "0:2001:0:db8::1"; + private static final int ID_TYPE_OFFSET = 0; @Test @@ -52,6 +60,19 @@ public final class IkeIdPayloadTest { } @Test + public void testDecodeIpv6AddrIdPayload() throws Exception { + byte[] inputPacket = + TestUtils.hexStringToByteArray(IPV6_ADDR_ID_PAYLOAD_RESPONDER_BODY_HEX_STRING); + IkeIdPayload payload = new IkeIdPayload(false, inputPacket, false); + + assertEquals(IkePayload.PAYLOAD_TYPE_ID_RESPONDER, payload.payloadType); + assertEquals(IkeIdentification.ID_TYPE_IPV6_ADDR, payload.ikeId.idType); + IkeIpv6AddrIdentification ikeId = (IkeIpv6AddrIdentification) payload.ikeId; + Inet6Address expectedAddr = (Inet6Address) Inet6Address.getByName(IPV6_ADDR_STRING); + assertEquals(expectedAddr, ikeId.ipv6Address); + } + + @Test public void testDecodeUnsupportedIdType() throws Exception { byte[] inputPacket = TestUtils.hexStringToByteArray(IPV4_ADDR_ID_PAYLOAD_RESPONDER_BODY_HEX_STRING); @@ -76,4 +97,17 @@ public final class IkeIdPayloadTest { TestUtils.hexStringToByteArray(IPV4_ADDR_ID_PAYLOAD_RESPONDER_HEX_STRING); assertArrayEquals(expectedBytes, inputBuffer.array()); } + + @Test + public void testConstructAndEncodeIpv6AddrIdPayload() throws Exception { + Inet6Address ipv6Address = (Inet6Address) Inet6Address.getByName(IPV6_ADDR_STRING); + IkeIdPayload payload = new IkeIdPayload(false, new IkeIpv6AddrIdentification(ipv6Address)); + + ByteBuffer inputBuffer = ByteBuffer.allocate(payload.getPayloadLength()); + payload.encodeToByteBuffer(IkePayload.PAYLOAD_TYPE_AUTH, inputBuffer); + + byte[] expectedBytes = + TestUtils.hexStringToByteArray(IPV6_ADDR_ID_PAYLOAD_RESPONDER_HEX_STRING); + assertArrayEquals(expectedBytes, inputBuffer.array()); + } } |