diff options
| author | nharold <nharold@google.com> | 2017-10-04 20:35:20 +0000 |
|---|---|---|
| committer | android-build-merger <android-build-merger@google.com> | 2017-10-04 20:35:20 +0000 |
| commit | 4e793fd0b5165204426fb4dfffc70ab8789caab3 (patch) | |
| tree | 7f7bf726ede54fce487babdfd58e78cc58beeb2c /core/java | |
| parent | 5dfce858ea04b7e5ec12e405a82242713fdd8aa6 (diff) | |
| parent | ae61e0c6e82c187c8fabf5a40c0bffa8f1923215 (diff) | |
Merge changes from topic "ipsec-svc-cleanup" am: 9778c7884f
am: ae61e0c6e8
Change-Id: If8803e2fc98adb2f08a5bf2944fc60d0f0e71acd
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/net/IpSecAlgorithm.java | 17 | ||||
| -rw-r--r-- | core/java/android/net/IpSecConfig.java | 273 | ||||
| -rw-r--r-- | core/java/android/net/IpSecManager.java | 8 | ||||
| -rw-r--r-- | core/java/android/net/IpSecTransform.java | 103 |
4 files changed, 215 insertions, 186 deletions
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index ead406c20c93..79310e295a27 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -24,6 +24,7 @@ import com.android.internal.util.HexDump; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; /** * IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to @@ -75,13 +76,7 @@ public final class IpSecAlgorithm implements Parcelable { public static final String AUTH_HMAC_SHA512 = "hmac(sha512)"; /** @hide */ - @StringDef({ - CRYPT_AES_CBC, - AUTH_HMAC_MD5, - AUTH_HMAC_SHA1, - AUTH_HMAC_SHA256, - AUTH_HMAC_SHA512 - }) + @StringDef({CRYPT_AES_CBC, AUTH_HMAC_MD5, AUTH_HMAC_SHA1, AUTH_HMAC_SHA256, AUTH_HMAC_SHA512}) @Retention(RetentionPolicy.SOURCE) public @interface AlgorithmName {} @@ -197,4 +192,12 @@ public final class IpSecAlgorithm implements Parcelable { .append("}") .toString(); } + + /** package */ + static boolean equals(IpSecAlgorithm lhs, IpSecAlgorithm rhs) { + if (lhs == null || rhs == null) return (lhs == rhs); + return (lhs.mName.equals(rhs.mName) + && Arrays.equals(lhs.mKey, rhs.mKey) + && lhs.mTruncLenBits == rhs.mTruncLenBits); + } }; diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index 5a5c740c7aa8..ceccc07c3c43 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -17,105 +17,170 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; -import android.util.Log; -import java.net.InetAddress; -import java.net.UnknownHostException; + +import com.android.internal.annotations.VisibleForTesting; /** @hide */ public final class IpSecConfig implements Parcelable { private static final String TAG = "IpSecConfig"; - //MODE_TRANSPORT or MODE_TUNNEL - int mode; + // MODE_TRANSPORT or MODE_TUNNEL + private int mMode = IpSecTransform.MODE_TRANSPORT; - // For tunnel mode - InetAddress localAddress; + // Needs to be valid only for tunnel mode + // Preventing this from being null simplifies Java->Native binder + private String mLocalAddress = ""; - InetAddress remoteAddress; + // Preventing this from being null simplifies Java->Native binder + private String mRemoteAddress = ""; - // Limit selection by network interface - Network network; + // The underlying network interface that represents the "gateway" Network + // for outbound packets. It may also be used to select packets. + private Network mNetwork; public static class Flow { // Minimum requirements for identifying a transform // SPI identifying the IPsec flow in packet processing // and a remote IP address - int spiResourceId; + private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID; // Encryption Algorithm - IpSecAlgorithm encryption; + private IpSecAlgorithm mEncryption; // Authentication Algorithm - IpSecAlgorithm authentication; + private IpSecAlgorithm mAuthentication; @Override public String toString() { return new StringBuilder() - .append("{spiResourceId=") - .append(spiResourceId) - .append(", encryption=") - .append(encryption) - .append(", authentication=") - .append(authentication) + .append("{mSpiResourceId=") + .append(mSpiResourceId) + .append(", mEncryption=") + .append(mEncryption) + .append(", mAuthentication=") + .append(mAuthentication) .append("}") .toString(); } + + static boolean equals(IpSecConfig.Flow lhs, IpSecConfig.Flow rhs) { + if (lhs == null || rhs == null) return (lhs == rhs); + return (lhs.mSpiResourceId == rhs.mSpiResourceId + && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption) + && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication)); + } } - final Flow[] flow = new Flow[] {new Flow(), new Flow()}; + private final Flow[] mFlow = new Flow[] {new Flow(), new Flow()}; // For tunnel mode IPv4 UDP Encapsulation // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE - int encapType; - int encapLocalPortResourceId; - int encapRemotePort; + private int mEncapType = IpSecTransform.ENCAP_NONE; + private int mEncapSocketResourceId = IpSecManager.INVALID_RESOURCE_ID; + private int mEncapRemotePort; // An interval, in seconds between the NattKeepalive packets - int nattKeepaliveInterval; + private int mNattKeepaliveInterval; + + /** Set the mode for this IPsec transform */ + public void setMode(int mode) { + mMode = mode; + } + + /** Set the local IP address for Tunnel mode */ + public void setLocalAddress(String localAddress) { + if (localAddress == null) { + throw new IllegalArgumentException("localAddress may not be null!"); + } + mLocalAddress = localAddress; + } + + /** Set the remote IP address for this IPsec transform */ + public void setRemoteAddress(String remoteAddress) { + if (remoteAddress == null) { + throw new IllegalArgumentException("remoteAddress may not be null!"); + } + mRemoteAddress = remoteAddress; + } + + /** Set the SPI for a given direction by resource ID */ + public void setSpiResourceId(int direction, int resourceId) { + mFlow[direction].mSpiResourceId = resourceId; + } + + /** Set the encryption algorithm for a given direction */ + public void setEncryption(int direction, IpSecAlgorithm encryption) { + mFlow[direction].mEncryption = encryption; + } + + /** Set the authentication algorithm for a given direction */ + public void setAuthentication(int direction, IpSecAlgorithm authentication) { + mFlow[direction].mAuthentication = authentication; + } + + public void setNetwork(Network network) { + mNetwork = network; + } + + public void setEncapType(int encapType) { + mEncapType = encapType; + } + + public void setEncapSocketResourceId(int resourceId) { + mEncapSocketResourceId = resourceId; + } + + public void setEncapRemotePort(int port) { + mEncapRemotePort = port; + } + + public void setNattKeepaliveInterval(int interval) { + mNattKeepaliveInterval = interval; + } // Transport or Tunnel public int getMode() { - return mode; + return mMode; } - public InetAddress getLocalAddress() { - return localAddress; + public String getLocalAddress() { + return mLocalAddress; } public int getSpiResourceId(int direction) { - return flow[direction].spiResourceId; + return mFlow[direction].mSpiResourceId; } - public InetAddress getRemoteAddress() { - return remoteAddress; + public String getRemoteAddress() { + return mRemoteAddress; } public IpSecAlgorithm getEncryption(int direction) { - return flow[direction].encryption; + return mFlow[direction].mEncryption; } public IpSecAlgorithm getAuthentication(int direction) { - return flow[direction].authentication; + return mFlow[direction].mAuthentication; } public Network getNetwork() { - return network; + return mNetwork; } public int getEncapType() { - return encapType; + return mEncapType; } - public int getEncapLocalResourceId() { - return encapLocalPortResourceId; + public int getEncapSocketResourceId() { + return mEncapSocketResourceId; } public int getEncapRemotePort() { - return encapRemotePort; + return mEncapRemotePort; } public int getNattKeepaliveInterval() { - return nattKeepaliveInterval; + return mNattKeepaliveInterval; } // Parcelable Methods @@ -127,82 +192,70 @@ public final class IpSecConfig implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { - // TODO: Use a byte array or other better method for storing IPs that can also include scope - out.writeString((localAddress != null) ? localAddress.getHostAddress() : null); - // TODO: Use a byte array or other better method for storing IPs that can also include scope - out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null); - out.writeParcelable(network, flags); - out.writeInt(flow[IpSecTransform.DIRECTION_IN].spiResourceId); - out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryption, flags); - out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authentication, flags); - out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spiResourceId); - out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryption, flags); - out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authentication, flags); - out.writeInt(encapType); - out.writeInt(encapLocalPortResourceId); - out.writeInt(encapRemotePort); - } - - // Package Private: Used by the IpSecTransform.Builder; - // there should be no public constructor for this object - IpSecConfig() {} - - private static InetAddress readInetAddressFromParcel(Parcel in) { - String addrString = in.readString(); - if (addrString == null) { - return null; - } - try { - return InetAddress.getByName(addrString); - } catch (UnknownHostException e) { - Log.wtf(TAG, "Invalid IpAddress " + addrString); - return null; - } + out.writeInt(mMode); + out.writeString(mLocalAddress); + out.writeString(mRemoteAddress); + out.writeParcelable(mNetwork, flags); + out.writeInt(mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId); + out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mEncryption, flags); + out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthentication, flags); + out.writeInt(mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId); + out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mEncryption, flags); + out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication, flags); + out.writeInt(mEncapType); + out.writeInt(mEncapSocketResourceId); + out.writeInt(mEncapRemotePort); + out.writeInt(mNattKeepaliveInterval); } + @VisibleForTesting + public IpSecConfig() {} + private IpSecConfig(Parcel in) { - localAddress = readInetAddressFromParcel(in); - remoteAddress = readInetAddressFromParcel(in); - network = (Network) in.readParcelable(Network.class.getClassLoader()); - flow[IpSecTransform.DIRECTION_IN].spiResourceId = in.readInt(); - flow[IpSecTransform.DIRECTION_IN].encryption = + mMode = in.readInt(); + mLocalAddress = in.readString(); + mRemoteAddress = in.readString(); + mNetwork = (Network) in.readParcelable(Network.class.getClassLoader()); + mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId = in.readInt(); + mFlow[IpSecTransform.DIRECTION_IN].mEncryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - flow[IpSecTransform.DIRECTION_IN].authentication = + mFlow[IpSecTransform.DIRECTION_IN].mAuthentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - flow[IpSecTransform.DIRECTION_OUT].spiResourceId = in.readInt(); - flow[IpSecTransform.DIRECTION_OUT].encryption = + mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId = in.readInt(); + mFlow[IpSecTransform.DIRECTION_OUT].mEncryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - flow[IpSecTransform.DIRECTION_OUT].authentication = + mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - encapType = in.readInt(); - encapLocalPortResourceId = in.readInt(); - encapRemotePort = in.readInt(); + mEncapType = in.readInt(); + mEncapSocketResourceId = in.readInt(); + mEncapRemotePort = in.readInt(); + mNattKeepaliveInterval = in.readInt(); } @Override public String toString() { StringBuilder strBuilder = new StringBuilder(); strBuilder - .append("{mode=") - .append(mode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT") - .append(", localAddress=") - .append(localAddress) - .append(", remoteAddress=") - .append(remoteAddress) - .append(", network=") - .append(network) - .append(", encapType=") - .append(encapType) - .append(", encapLocalPortResourceId=") - .append(encapLocalPortResourceId) - .append(", encapRemotePort=") - .append(encapRemotePort) - .append(", nattKeepaliveInterval=") - .append(nattKeepaliveInterval) - .append(", flow[OUT]=") - .append(flow[IpSecTransform.DIRECTION_OUT]) - .append(", flow[IN]=") - .append(flow[IpSecTransform.DIRECTION_IN]) + .append("{mMode=") + .append(mMode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT") + .append(", mLocalAddress=") + .append(mLocalAddress) + .append(", mRemoteAddress=") + .append(mRemoteAddress) + .append(", mNetwork=") + .append(mNetwork) + .append(", mEncapType=") + .append(mEncapType) + .append(", mEncapSocketResourceId=") + .append(mEncapSocketResourceId) + .append(", mEncapRemotePort=") + .append(mEncapRemotePort) + .append(", mNattKeepaliveInterval=") + .append(mNattKeepaliveInterval) + .append(", mFlow[OUT]=") + .append(mFlow[IpSecTransform.DIRECTION_OUT]) + .append(", mFlow[IN]=") + .append(mFlow[IpSecTransform.DIRECTION_IN]) .append("}"); return strBuilder.toString(); @@ -218,4 +271,22 @@ public final class IpSecConfig implements Parcelable { return new IpSecConfig[size]; } }; + + @VisibleForTesting + public static boolean equals(IpSecConfig lhs, IpSecConfig rhs) { + if (lhs == null || rhs == null) return (lhs == rhs); + return (lhs.mMode == rhs.mMode + && lhs.mLocalAddress.equals(rhs.mLocalAddress) + && lhs.mRemoteAddress.equals(rhs.mRemoteAddress) + && ((lhs.mNetwork != null && lhs.mNetwork.equals(rhs.mNetwork)) + || (lhs.mNetwork == rhs.mNetwork)) + && lhs.mEncapType == rhs.mEncapType + && lhs.mEncapSocketResourceId == rhs.mEncapSocketResourceId + && lhs.mEncapRemotePort == rhs.mEncapRemotePort + && lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval + && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_OUT], + rhs.mFlow[IpSecTransform.DIRECTION_OUT]) + && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_IN], + rhs.mFlow[IpSecTransform.DIRECTION_IN])); + } } diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index d7908c8ceef8..d7b325613fee 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -26,6 +26,8 @@ import android.os.RemoteException; import android.util.AndroidException; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + import dalvik.system.CloseGuard; import java.io.FileDescriptor; @@ -188,7 +190,8 @@ public final class IpSecManager { } /** @hide */ - int getResourceId() { + @VisibleForTesting + public int getResourceId() { return mResourceId; } } @@ -489,7 +492,8 @@ public final class IpSecManager { } /** @hide */ - int getResourceId() { + @VisibleForTesting + public int getResourceId() { return mResourceId; } }; diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 62fd65b9c176..529cf1a4956e 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -68,10 +68,10 @@ public final class IpSecTransform implements AutoCloseable { public @interface TransformDirection {} /** @hide */ - public static final int MODE_TUNNEL = 0; + public static final int MODE_TRANSPORT = 0; /** @hide */ - public static final int MODE_TRANSPORT = 1; + public static final int MODE_TUNNEL = 1; /** @hide */ public static final int ENCAP_NONE = 0; @@ -113,7 +113,11 @@ public final class IpSecTransform implements AutoCloseable { return IIpSecService.Stub.asInterface(b); } - private void checkResultStatusAndThrow(int status) + /** + * Checks the result status and throws an appropriate exception if + * the status is not Status.OK. + */ + private void checkResultStatus(int status) throws IOException, IpSecManager.ResourceUnavailableException, IpSecManager.SpiUnavailableException { switch (status) { @@ -141,7 +145,7 @@ public final class IpSecTransform implements AutoCloseable { IpSecTransformResponse result = svc.createTransportModeTransform(mConfig, new Binder()); int status = result.status; - checkResultStatusAndThrow(status); + checkResultStatus(status); mResourceId = result.resourceId; /* Keepalive will silently fail if not needed by the config; but, if needed and @@ -243,61 +247,20 @@ public final class IpSecTransform implements AutoCloseable { /* Package */ void startKeepalive(Context c) { - // FIXME: NO_KEEPALIVE needs to be a constant - if (mConfig.getNattKeepaliveInterval() == 0) { - return; - } - - ConnectivityManager cm = - (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE); - - if (mKeepalive != null) { - Log.wtf(TAG, "Keepalive already started for this IpSecTransform."); - return; - } - - synchronized (mKeepaliveSyncLock) { - mKeepalive = - cm.startNattKeepalive( - mConfig.getNetwork(), - mConfig.getNattKeepaliveInterval(), - mKeepaliveCallback, - mConfig.getLocalAddress(), - 0x1234, /* FIXME: get the real port number again, - which we need to retrieve from the provided - EncapsulationSocket, and which isn't currently - stashed in IpSecConfig */ - mConfig.getRemoteAddress()); - try { - // FIXME: this is still a horrible way to fudge the synchronous callback - mKeepaliveSyncLock.wait(2000); - } catch (InterruptedException e) { - } - } - if (mKeepaliveStatus != ConnectivityManager.PacketKeepalive.SUCCESS) { - throw new UnsupportedOperationException("Packet Keepalive cannot be started"); + if (mConfig.getNattKeepaliveInterval() != 0) { + Log.wtf(TAG, "Keepalive not yet supported."); } } - /* Package */ - int getResourceId() { + /** @hide */ + @VisibleForTesting + public int getResourceId() { return mResourceId; } /* Package */ void stopKeepalive() { - if (mKeepalive == null) { - return; - } - mKeepalive.stop(); - synchronized (mKeepaliveSyncLock) { - if (mKeepaliveStatus == ConnectivityManager.PacketKeepalive.SUCCESS) { - try { - mKeepaliveSyncLock.wait(2000); - } catch (InterruptedException e) { - } - } - } + return; } /** @@ -323,7 +286,7 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setEncryption( @TransformDirection int direction, IpSecAlgorithm algo) { - mConfig.flow[direction].encryption = algo; + mConfig.setEncryption(direction, algo); return this; } @@ -338,7 +301,7 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setAuthentication( @TransformDirection int direction, IpSecAlgorithm algo) { - mConfig.flow[direction].authentication = algo; + mConfig.setAuthentication(direction, algo); return this; } @@ -361,9 +324,7 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setSpi( @TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) { - // TODO: convert to using the resource Id of the SPI. Then build() can validate - // the owner in the IpSecService - mConfig.flow[direction].spiResourceId = spi.getResourceId(); + mConfig.setSpiResourceId(direction, spi.getResourceId()); return this; } @@ -378,7 +339,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi public IpSecTransform.Builder setUnderlyingNetwork(Network net) { - mConfig.network = net; + mConfig.setNetwork(net); return this; } @@ -395,10 +356,9 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setIpv4Encapsulation( IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { - // TODO: check encap type is valid. - mConfig.encapType = ENCAP_ESPINUDP; - mConfig.encapLocalPortResourceId = localSocket.getResourceId(); - mConfig.encapRemotePort = remotePort; + mConfig.setEncapType(ENCAP_ESPINUDP); + mConfig.setEncapSocketResourceId(localSocket.getResourceId()); + mConfig.setEncapRemotePort(remotePort); return this; } @@ -416,7 +376,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) { - mConfig.nattKeepaliveInterval = intervalSeconds; + mConfig.setNattKeepaliveInterval(intervalSeconds); return this; } @@ -451,8 +411,8 @@ public final class IpSecTransform implements AutoCloseable { IpSecManager.SpiUnavailableException, IOException { //FIXME: argument validation here //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation"); - mConfig.mode = MODE_TRANSPORT; - mConfig.remoteAddress = remoteAddress; + mConfig.setMode(MODE_TRANSPORT); + mConfig.setRemoteAddress(remoteAddress.getHostAddress()); return new IpSecTransform(mContext, mConfig).activate(); } @@ -473,9 +433,9 @@ public final class IpSecTransform implements AutoCloseable { InetAddress localAddress, InetAddress remoteAddress) { //FIXME: argument validation here //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation"); - mConfig.localAddress = localAddress; - mConfig.remoteAddress = remoteAddress; - mConfig.mode = MODE_TUNNEL; + mConfig.setLocalAddress(localAddress.getHostAddress()); + mConfig.setRemoteAddress(remoteAddress.getHostAddress()); + mConfig.setMode(MODE_TUNNEL); return new IpSecTransform(mContext, mConfig); } @@ -489,14 +449,5 @@ public final class IpSecTransform implements AutoCloseable { mContext = context; mConfig = new IpSecConfig(); } - - /** - * Return an {@link IpSecConfig} object for testing purposes. - * @hide - */ - @VisibleForTesting - public IpSecConfig getIpSecConfig() { - return mConfig; - } } } |
