Loading core/java/android/net/IpSecAlgorithm.java +10 −7 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 {} Loading Loading @@ -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); } }; core/java/android/net/IpSecConfig.java +172 −101 Original line number Diff line number Diff line Loading @@ -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; 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 Loading @@ -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(); Loading @@ -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])); } } core/java/android/net/IpSecManager.java +6 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -188,7 +190,8 @@ public final class IpSecManager { } /** @hide */ int getResourceId() { @VisibleForTesting public int getResourceId() { return mResourceId; } } Loading Loading @@ -489,7 +492,8 @@ public final class IpSecManager { } /** @hide */ int getResourceId() { @VisibleForTesting public int getResourceId() { return mResourceId; } }; Loading core/java/android/net/IpSecTransform.java +27 −76 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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 Loading Loading @@ -243,62 +247,21 @@ public final class IpSecTransform implements AutoCloseable { /* Package */ void startKeepalive(Context c) { // FIXME: NO_KEEPALIVE needs to be a constant if (mConfig.getNattKeepaliveInterval() == 0) { return; if (mConfig.getNattKeepaliveInterval() != 0) { Log.wtf(TAG, "Keepalive not yet supported."); } 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"); } } /* 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) { } } } } /** * Builder object to facilitate the creation of IpSecTransform objects. Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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(); } Loading @@ -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); } Loading @@ -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; } } } services/core/java/com/android/server/IpSecService.java +122 −29 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/net/IpSecAlgorithm.java +10 −7 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 {} Loading Loading @@ -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); } };
core/java/android/net/IpSecConfig.java +172 −101 Original line number Diff line number Diff line Loading @@ -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; 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 Loading @@ -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(); Loading @@ -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])); } }
core/java/android/net/IpSecManager.java +6 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -188,7 +190,8 @@ public final class IpSecManager { } /** @hide */ int getResourceId() { @VisibleForTesting public int getResourceId() { return mResourceId; } } Loading Loading @@ -489,7 +492,8 @@ public final class IpSecManager { } /** @hide */ int getResourceId() { @VisibleForTesting public int getResourceId() { return mResourceId; } }; Loading
core/java/android/net/IpSecTransform.java +27 −76 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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 Loading Loading @@ -243,62 +247,21 @@ public final class IpSecTransform implements AutoCloseable { /* Package */ void startKeepalive(Context c) { // FIXME: NO_KEEPALIVE needs to be a constant if (mConfig.getNattKeepaliveInterval() == 0) { return; if (mConfig.getNattKeepaliveInterval() != 0) { Log.wtf(TAG, "Keepalive not yet supported."); } 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"); } } /* 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) { } } } } /** * Builder object to facilitate the creation of IpSecTransform objects. Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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(); } Loading @@ -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); } Loading @@ -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; } } }
services/core/java/com/android/server/IpSecService.java +122 −29 File changed.Preview size limit exceeded, changes collapsed. Show changes