1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.cts; 18 19 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; 20 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; 21 import static android.net.NetworkCapabilities.TRANSPORT_VPN; 22 import static android.net.cts.util.CtsNetUtils.TestNetworkCallback; 23 24 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 25 import static com.android.modules.utils.build.SdkLevel.isAtLeastT; 26 import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2; 27 28 import static org.junit.Assert.assertArrayEquals; 29 import static org.junit.Assert.assertEquals; 30 import static org.junit.Assert.assertFalse; 31 import static org.junit.Assert.assertNotNull; 32 import static org.junit.Assert.assertNull; 33 import static org.junit.Assert.assertThrows; 34 import static org.junit.Assert.assertTrue; 35 import static org.junit.Assert.fail; 36 import static org.junit.Assume.assumeTrue; 37 38 import android.Manifest; 39 import android.annotation.NonNull; 40 import android.app.AppOpsManager; 41 import android.content.Context; 42 import android.content.Intent; 43 import android.net.ConnectivityManager; 44 import android.net.Ikev2VpnProfile; 45 import android.net.IpSecAlgorithm; 46 import android.net.Network; 47 import android.net.NetworkRequest; 48 import android.net.ProxyInfo; 49 import android.net.TestNetworkInterface; 50 import android.net.VpnManager; 51 import android.net.cts.util.CtsNetUtils; 52 import android.net.cts.util.IkeSessionTestUtils; 53 import android.net.ipsec.ike.IkeTunnelConnectionParams; 54 import android.os.Build; 55 import android.os.Process; 56 import android.platform.test.annotations.AppModeFull; 57 import android.text.TextUtils; 58 59 import androidx.test.InstrumentationRegistry; 60 61 import com.android.internal.util.HexDump; 62 import com.android.networkstack.apishim.ConstantsShim; 63 import com.android.networkstack.apishim.Ikev2VpnProfileBuilderShimImpl; 64 import com.android.networkstack.apishim.Ikev2VpnProfileShimImpl; 65 import com.android.networkstack.apishim.VpnManagerShimImpl; 66 import com.android.networkstack.apishim.common.Ikev2VpnProfileBuilderShim; 67 import com.android.networkstack.apishim.common.Ikev2VpnProfileShim; 68 import com.android.networkstack.apishim.common.VpnManagerShim; 69 import com.android.networkstack.apishim.common.VpnProfileStateShim; 70 import com.android.testutils.DevSdkIgnoreRule; 71 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; 72 import com.android.testutils.DevSdkIgnoreRunner; 73 import com.android.testutils.RecorderCallback.CallbackEntry; 74 import com.android.testutils.TestableNetworkCallback; 75 76 import org.bouncycastle.x509.X509V1CertificateGenerator; 77 import org.junit.After; 78 import org.junit.Rule; 79 import org.junit.Test; 80 import org.junit.runner.RunWith; 81 82 import java.math.BigInteger; 83 import java.net.InetAddress; 84 import java.security.KeyPair; 85 import java.security.KeyPairGenerator; 86 import java.security.PrivateKey; 87 import java.security.cert.X509Certificate; 88 import java.util.ArrayList; 89 import java.util.Arrays; 90 import java.util.Date; 91 import java.util.List; 92 import java.util.concurrent.TimeUnit; 93 94 import javax.security.auth.x500.X500Principal; 95 96 @RunWith(DevSdkIgnoreRunner.class) 97 @IgnoreUpTo(Build.VERSION_CODES.Q) 98 @AppModeFull(reason = "Appops state changes disallowed for instant apps (OP_ACTIVATE_PLATFORM_VPN)") 99 public class Ikev2VpnTest { 100 private static final String TAG = Ikev2VpnTest.class.getSimpleName(); 101 102 @Rule 103 public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); 104 105 // Test vectors for IKE negotiation in test mode. 106 private static final String SUCCESSFUL_IKE_INIT_RESP_V4 = 107 "46b8eca1e0d72a18b2b5d9006d47a0022120222000000000000002d0220000300000002c01010004030000" 108 + "0c0100000c800e0100030000080300000c030000080200000400000008040000102800020800" 109 + "100000b8070f159fe5141d8754ca86f72ecc28d66f514927e96cbe9eec0adb42bf2c276a0ab7" 110 + "a97fa93555f4be9218c14e7f286bb28c6b4fb13825a420f2ffc165854f200bab37d69c8963d4" 111 + "0acb831d983163aa50622fd35c182efe882cf54d6106222abcfaa597255d302f1b95ab71c142" 112 + "c279ea5839a180070bff73f9d03fab815f0d5ee2adec7e409d1e35979f8bd92ffd8aab13d1a0" 113 + "0657d816643ae767e9ae84d2ccfa2bcce1a50572be8d3748ae4863c41ae90da16271e014270f" 114 + "77edd5cd2e3299f3ab27d7203f93d770bacf816041cdcecd0f9af249033979da4369cb242dd9" 115 + "6d172e60513ff3db02de63e50eb7d7f596ada55d7946cad0af0669d1f3e2804846ab3f2a930d" 116 + "df56f7f025f25c25ada694e6231abbb87ee8cfd072c8481dc0b0f6b083fdc3bd89b080e49feb" 117 + "0288eef6fdf8a26ee2fc564a11e7385215cf2deaf2a9965638fc279c908ccdf04094988d91a2" 118 + "464b4a8c0326533aff5119ed79ecbd9d99a218b44f506a5eb09351e67da86698b4c58718db25" 119 + "d55f426fb4c76471b27a41fbce00777bc233c7f6e842e39146f466826de94f564cad8b92bfbe" 120 + "87c99c4c7973ec5f1eea8795e7da82819753aa7c4fcfdab77066c56b939330c4b0d354c23f83" 121 + "ea82fa7a64c4b108f1188379ea0eb4918ee009d804100e6bf118771b9058d42141c847d5ec37" 122 + "6e5ec591c71fc9dac01063c2bd31f9c783b28bf1182900002430f3d5de3449462b31dd28bc27" 123 + "297b6ad169bccce4f66c5399c6e0be9120166f2900001c0000400428b8df2e66f69c8584a186" 124 + "c5eac66783551d49b72900001c000040054e7a622e802d5cbfb96d5f30a6e433994370173529" 125 + "0000080000402e290000100000402f00020003000400050000000800004014"; 126 private static final String SUCCESSFUL_IKE_INIT_RESP_V6 = 127 "46b8eca1e0d72a1800d9ea1babce26bf2120222000000000000002d0220000300000002c01010004030000" 128 + "0c0100000c800e0100030000080300000c030000080200000400000008040000102800020800" 129 + "100000ea0e6dd9ca5930a9a45c323a41f64bfd8cdef7730f5fbff37d7c377da427f489a42aa8" 130 + "c89233380e6e925990d49de35c2cdcf63a61302c731a4b3569df1ee1bf2457e55a6751838ede" 131 + "abb75cc63ba5c9e4355e8e784f383a5efe8a44727dc14aeaf8dacc2620fb1c8875416dc07739" 132 + "7fe4decc1bd514a9c7d270cf21fd734c63a25c34b30b68686e54e8a198f37f27cb491fe27235" 133 + "fab5476b036d875ccab9a68d65fbf3006197f9bebbf94de0d3802b4fafe1d48d931ce3a1a346" 134 + "2d65bd639e9bd7fa46299650a9dbaf9b324e40b466942d91a59f41ef8042f8474c4850ed0f63" 135 + "e9238949d41cd8bbaea9aefdb65443a6405792839563aa5dc5c36b5ce8326ccf8a94d9622b85" 136 + "038d390d5fc0299e14e1f022966d4ac66515f6108ca04faec44821fe5bbf2ed4f84ff5671219" 137 + "608cb4c36b44a31ba010c9088f8d5ff943bb9ff857f74be1755f57a5783874adc57f42bb174e" 138 + "4ad3215de628707014dbcb1707bd214658118fdd7a42b3e1638b991ce5b812a667f1145be811" 139 + "685e3cd3baf9b18d062657b64c206a4d19a531c252a6a51a04aeaf42c618620cdbab65baca23" 140 + "82c57ed888422aeaacf7f1bc3fe2247ff7e7eaca218b74d7b31d02f2b0afa123f802529e7e6c" 141 + "3259d418290740ddbf55686e26998d7edcbbf895664972fed666f2f20af40503aa2af436ec6d" 142 + "4ec981ab19b9088755d94ae7a7c2066ea331d4e56e290000243fefe5555fce552d57a84e682c" 143 + "d4a6dfb3f2f94a94464d5bec3d88b88e9559642900001c00004004eb4afff764e7b79bca78b1" 144 + "3a89100d36d678ae982900001c00004005d177216a3c26f782076e12570d40bfaaa148822929" 145 + "0000080000402e290000100000402f00020003000400050000000800004014"; 146 private static final String SUCCESSFUL_IKE_AUTH_RESP_V4 = 147 "46b8eca1e0d72a18b2b5d9006d47a0022e20232000000001000000e0240000c420a2500a3da4c66fa6929e" 148 + "600f36349ba0e38de14f78a3ad0416cba8c058735712a3d3f9a0a6ed36de09b5e9e02697e7c4" 149 + "2d210ac86cfbd709503cfa51e2eab8cfdc6427d136313c072968f6506a546eb5927164200592" 150 + "6e36a16ee994e63f029432a67bc7d37ca619e1bd6e1678df14853067ecf816b48b81e8746069" 151 + "406363e5aa55f13cb2afda9dbebee94256c29d630b17dd7f1ee52351f92b6e1c3d8551c513f1" 152 + "d74ac52a80b2041397e109fe0aeb3c105b0d4be0ae343a943398764281"; 153 private static final String SUCCESSFUL_IKE_AUTH_RESP_V6 = 154 "46b8eca1e0d72a1800d9ea1babce26bf2e20232000000001000000f0240000d4aaf6eaa6c06b50447e6f54" 155 + "827fd8a9d9d6ac8015c1ebb3e8cb03fc6e54b49a107441f50004027cc5021600828026367f03" 156 + "bc425821cd7772ee98637361300c9b76056e874fea2bd4a17212370b291894264d8c023a01d1" 157 + "c3b691fd4b7c0b534e8c95af4c4638e2d125cb21c6267e2507cd745d72e8da109c47b9259c6c" 158 + "57a26f6bc5b337b9b9496d54bdde0333d7a32e6e1335c9ee730c3ecd607a8689aa7b0577b74f" 159 + "3bf437696a9fd5fc0aee3ed346cd9e15d1dda293df89eb388a8719388a60ca7625754de12cdb" 160 + "efe4c886c5c401"; 161 private static final long IKE_INITIATOR_SPI = Long.parseLong("46B8ECA1E0D72A18", 16); 162 163 private static final InetAddress LOCAL_OUTER_4 = InetAddress.parseNumericAddress("192.0.2.1"); 164 private static final InetAddress LOCAL_OUTER_6 = 165 InetAddress.parseNumericAddress("2001:db8::1"); 166 167 private static final int IP4_PREFIX_LEN = 32; 168 private static final int IP6_PREFIX_LEN = 128; 169 170 // TODO: Use IPv6 address when we can generate test vectors (GCE does not allow IPv6 yet). 171 private static final String TEST_SERVER_ADDR_V4 = "192.0.2.2"; 172 private static final String TEST_SERVER_ADDR_V6 = "2001:db8::2"; 173 private static final String TEST_IDENTITY = "client.cts.android.com"; 174 private static final List<String> TEST_ALLOWED_ALGORITHMS = 175 Arrays.asList(IpSecAlgorithm.AUTH_CRYPT_AES_GCM); 176 177 private static final ProxyInfo TEST_PROXY_INFO = 178 ProxyInfo.buildDirectProxy("proxy.cts.android.com", 1234); 179 private static final int TEST_MTU = 1300; 180 181 private static final byte[] TEST_PSK = "ikeAndroidPsk".getBytes(); 182 private static final String TEST_USER = "username"; 183 private static final String TEST_PASSWORD = "pa55w0rd"; 184 185 // Static state to reduce setup/teardown 186 private static final Context sContext = InstrumentationRegistry.getContext(); 187 private static final ConnectivityManager sCM = 188 (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE); 189 private static final VpnManager sVpnMgr = 190 (VpnManager) sContext.getSystemService(Context.VPN_MANAGEMENT_SERVICE); 191 private static final CtsNetUtils mCtsNetUtils = new CtsNetUtils(sContext); 192 private static final long TIMEOUT_MS = 15_000; 193 194 private VpnManagerShim mVmShim = VpnManagerShimImpl.newInstance(sContext); 195 196 private final X509Certificate mServerRootCa; 197 private final CertificateAndKey mUserCertKey; 198 private final List<TestableNetworkCallback> mCallbacksToUnregister = new ArrayList<>(); 199 Ikev2VpnTest()200 public Ikev2VpnTest() throws Exception { 201 // Build certificates 202 mServerRootCa = generateRandomCertAndKeyPair().cert; 203 mUserCertKey = generateRandomCertAndKeyPair(); 204 } 205 206 @After tearDown()207 public void tearDown() { 208 for (TestableNetworkCallback callback : mCallbacksToUnregister) { 209 sCM.unregisterNetworkCallback(callback); 210 } 211 setAppop(AppOpsManager.OP_ACTIVATE_VPN, false); 212 setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false); 213 } 214 215 /** 216 * Sets the given appop using shell commands 217 * 218 * <p>This method must NEVER be called from within a shell permission, as it will attempt to 219 * acquire, and then drop the shell permission identity. This results in the caller losing the 220 * shell permission identity due to these calls not being reference counted. 221 */ setAppop(int appop, boolean allow)222 public void setAppop(int appop, boolean allow) { 223 // Requires shell permission to update appops. 224 runWithShellPermissionIdentity(() -> { 225 mCtsNetUtils.setAppopPrivileged(appop, allow); 226 }, Manifest.permission.MANAGE_TEST_NETWORKS); 227 } 228 buildIkev2VpnProfileCommon( @onNull Ikev2VpnProfileBuilderShim builderShim, boolean isRestrictedToTestNetworks, boolean requiresValidation, boolean automaticIpVersionSelectionEnabled, boolean automaticNattKeepaliveTimerEnabled)229 private Ikev2VpnProfile buildIkev2VpnProfileCommon( 230 @NonNull Ikev2VpnProfileBuilderShim builderShim, boolean isRestrictedToTestNetworks, 231 boolean requiresValidation, boolean automaticIpVersionSelectionEnabled, 232 boolean automaticNattKeepaliveTimerEnabled) throws Exception { 233 234 builderShim.setBypassable(true) 235 .setAllowedAlgorithms(TEST_ALLOWED_ALGORITHMS) 236 .setProxy(TEST_PROXY_INFO) 237 .setMaxMtu(TEST_MTU) 238 .setMetered(false); 239 if (TestUtils.shouldTestTApis()) { 240 builderShim.setRequiresInternetValidation(requiresValidation); 241 } 242 243 if (TestUtils.shouldTestUApis()) { 244 builderShim.setAutomaticIpVersionSelectionEnabled(automaticIpVersionSelectionEnabled); 245 builderShim.setAutomaticNattKeepaliveTimerEnabled(automaticNattKeepaliveTimerEnabled); 246 } 247 248 // Convert shim back to Ikev2VpnProfile.Builder since restrictToTestNetworks is a hidden 249 // method and is not defined in shims. 250 // TODO: replace it in alternative way to remove the hidden method usage 251 final Ikev2VpnProfile.Builder builder = (Ikev2VpnProfile.Builder) builderShim.getBuilder(); 252 if (isRestrictedToTestNetworks) { 253 builder.restrictToTestNetworks(); 254 } 255 256 return builder.build(); 257 } 258 buildIkev2VpnProfileIkeTunConnParams( final boolean isRestrictedToTestNetworks, final boolean requiresValidation, final boolean testIpv6)259 private Ikev2VpnProfile buildIkev2VpnProfileIkeTunConnParams( 260 final boolean isRestrictedToTestNetworks, final boolean requiresValidation, 261 final boolean testIpv6) throws Exception { 262 final IkeTunnelConnectionParams params = 263 new IkeTunnelConnectionParams(testIpv6 264 ? IkeSessionTestUtils.IKE_PARAMS_V6 : IkeSessionTestUtils.IKE_PARAMS_V4, 265 IkeSessionTestUtils.CHILD_PARAMS); 266 267 final Ikev2VpnProfileBuilderShim builderShim = 268 Ikev2VpnProfileBuilderShimImpl.newInstance(params) 269 .setRequiresInternetValidation(requiresValidation) 270 .setProxy(TEST_PROXY_INFO) 271 .setMaxMtu(TEST_MTU) 272 .setMetered(false); 273 // Convert shim back to Ikev2VpnProfile.Builder since restrictToTestNetworks is a hidden 274 // method and is not defined in shims. 275 // TODO: replace it in alternative way to remove the hidden method usage 276 final Ikev2VpnProfile.Builder builder = (Ikev2VpnProfile.Builder) builderShim.getBuilder(); 277 if (isRestrictedToTestNetworks) { 278 builder.restrictToTestNetworks(); 279 } 280 return builder.build(); 281 } 282 buildIkev2VpnProfilePsk(@onNull String remote, boolean isRestrictedToTestNetworks, boolean requiresValidation)283 private Ikev2VpnProfile buildIkev2VpnProfilePsk(@NonNull String remote, 284 boolean isRestrictedToTestNetworks, boolean requiresValidation) 285 throws Exception { 286 final Ikev2VpnProfileBuilderShim builder = 287 Ikev2VpnProfileBuilderShimImpl.newInstance(remote, TEST_IDENTITY) 288 .setAuthPsk(TEST_PSK); 289 return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks, 290 requiresValidation, false /* automaticIpVersionSelectionEnabled */, 291 false /* automaticNattKeepaliveTimerEnabled */); 292 } 293 buildIkev2VpnProfileUsernamePassword(boolean isRestrictedToTestNetworks)294 private Ikev2VpnProfile buildIkev2VpnProfileUsernamePassword(boolean isRestrictedToTestNetworks) 295 throws Exception { 296 final Ikev2VpnProfileBuilderShim builder = 297 Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY) 298 .setAuthUsernamePassword(TEST_USER, TEST_PASSWORD, mServerRootCa); 299 return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks, 300 false /* requiresValidation */, false /* automaticIpVersionSelectionEnabled */, 301 false /* automaticNattKeepaliveTimerEnabled */); 302 } 303 buildIkev2VpnProfileDigitalSignature(boolean isRestrictedToTestNetworks)304 private Ikev2VpnProfile buildIkev2VpnProfileDigitalSignature(boolean isRestrictedToTestNetworks) 305 throws Exception { 306 final Ikev2VpnProfileBuilderShim builder = 307 Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY) 308 .setAuthDigitalSignature( 309 mUserCertKey.cert, mUserCertKey.key, mServerRootCa); 310 return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks, 311 false /* requiresValidation */, false /* automaticIpVersionSelectionEnabled */, 312 false /* automaticNattKeepaliveTimerEnabled */); 313 } 314 checkBasicIkev2VpnProfile(@onNull Ikev2VpnProfile profile)315 private void checkBasicIkev2VpnProfile(@NonNull Ikev2VpnProfile profile) throws Exception { 316 assertEquals(TEST_SERVER_ADDR_V6, profile.getServerAddr()); 317 assertEquals(TEST_IDENTITY, profile.getUserIdentity()); 318 assertEquals(TEST_PROXY_INFO, profile.getProxyInfo()); 319 assertEquals(TEST_ALLOWED_ALGORITHMS, profile.getAllowedAlgorithms()); 320 assertTrue(profile.isBypassable()); 321 assertFalse(profile.isMetered()); 322 assertEquals(TEST_MTU, profile.getMaxMtu()); 323 assertFalse(profile.isRestrictedToTestNetworks()); 324 } 325 doTestBuildIkev2VpnProfilePsk(final boolean requiresValidation)326 public void doTestBuildIkev2VpnProfilePsk(final boolean requiresValidation) throws Exception { 327 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 328 329 final Ikev2VpnProfile profile = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6, 330 false /* isRestrictedToTestNetworks */, requiresValidation); 331 332 checkBasicIkev2VpnProfile(profile); 333 assertArrayEquals(TEST_PSK, profile.getPresharedKey()); 334 335 // Verify nothing else is set. 336 assertNull(profile.getUsername()); 337 assertNull(profile.getPassword()); 338 assertNull(profile.getServerRootCaCert()); 339 assertNull(profile.getRsaPrivateKey()); 340 assertNull(profile.getUserCert()); 341 if (isAtLeastT()) { 342 assertEquals(requiresValidation, profile.isInternetValidationRequired()); 343 } 344 } 345 346 @IgnoreUpTo(SC_V2) 347 @Test testBuildIkev2VpnProfileWithIkeTunnelConnectionParams()348 public void testBuildIkev2VpnProfileWithIkeTunnelConnectionParams() throws Exception { 349 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 350 assumeTrue(TestUtils.shouldTestTApis()); 351 352 final IkeTunnelConnectionParams expectedParams = new IkeTunnelConnectionParams( 353 IkeSessionTestUtils.IKE_PARAMS_V6, IkeSessionTestUtils.CHILD_PARAMS); 354 final Ikev2VpnProfile.Builder ikeProfileBuilder = 355 new Ikev2VpnProfile.Builder(expectedParams); 356 // Verify the other Ike options could not be set with IkeTunnelConnectionParams. 357 final Class<IllegalArgumentException> expected = IllegalArgumentException.class; 358 assertThrows(expected, () -> ikeProfileBuilder.setAuthPsk(TEST_PSK)); 359 assertThrows(expected, () -> 360 ikeProfileBuilder.setAuthUsernamePassword(TEST_USER, TEST_PASSWORD, mServerRootCa)); 361 assertThrows(expected, () -> ikeProfileBuilder.setAuthDigitalSignature( 362 mUserCertKey.cert, mUserCertKey.key, mServerRootCa)); 363 364 final Ikev2VpnProfile profile = ikeProfileBuilder.build(); 365 366 assertEquals(expectedParams, profile.getIkeTunnelConnectionParams()); 367 } 368 369 @Test testBuildIkev2VpnProfilePsk()370 public void testBuildIkev2VpnProfilePsk() throws Exception { 371 doTestBuildIkev2VpnProfilePsk(true /* requiresValidation */); 372 doTestBuildIkev2VpnProfilePsk(false /* requiresValidation */); 373 } 374 375 @Test testBuildIkev2VpnProfileUsernamePassword()376 public void testBuildIkev2VpnProfileUsernamePassword() throws Exception { 377 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 378 379 final Ikev2VpnProfile profile = 380 buildIkev2VpnProfileUsernamePassword(false /* isRestrictedToTestNetworks */); 381 382 checkBasicIkev2VpnProfile(profile); 383 assertEquals(TEST_USER, profile.getUsername()); 384 assertEquals(TEST_PASSWORD, profile.getPassword()); 385 assertEquals(mServerRootCa, profile.getServerRootCaCert()); 386 387 // Verify nothing else is set. 388 assertNull(profile.getPresharedKey()); 389 assertNull(profile.getRsaPrivateKey()); 390 assertNull(profile.getUserCert()); 391 } 392 393 @Test testBuildIkev2VpnProfileDigitalSignature()394 public void testBuildIkev2VpnProfileDigitalSignature() throws Exception { 395 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 396 397 final Ikev2VpnProfile profile = 398 buildIkev2VpnProfileDigitalSignature(false /* isRestrictedToTestNetworks */); 399 400 checkBasicIkev2VpnProfile(profile); 401 assertEquals(mUserCertKey.cert, profile.getUserCert()); 402 assertEquals(mUserCertKey.key, profile.getRsaPrivateKey()); 403 assertEquals(mServerRootCa, profile.getServerRootCaCert()); 404 405 // Verify nothing else is set. 406 assertNull(profile.getUsername()); 407 assertNull(profile.getPassword()); 408 assertNull(profile.getPresharedKey()); 409 } 410 verifyProvisionVpnProfile( boolean hasActivateVpn, boolean hasActivatePlatformVpn, boolean expectIntent)411 private void verifyProvisionVpnProfile( 412 boolean hasActivateVpn, boolean hasActivatePlatformVpn, boolean expectIntent) 413 throws Exception { 414 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 415 416 setAppop(AppOpsManager.OP_ACTIVATE_VPN, hasActivateVpn); 417 setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, hasActivatePlatformVpn); 418 419 final Ikev2VpnProfile profile = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6, 420 false /* isRestrictedToTestNetworks */, false /* requiresValidation */); 421 final Intent intent = sVpnMgr.provisionVpnProfile(profile); 422 assertEquals(expectIntent, intent != null); 423 } 424 425 @Test testProvisionVpnProfileNoPreviousConsent()426 public void testProvisionVpnProfileNoPreviousConsent() throws Exception { 427 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 428 429 verifyProvisionVpnProfile(false /* hasActivateVpn */, 430 false /* hasActivatePlatformVpn */, true /* expectIntent */); 431 } 432 433 @Test testProvisionVpnProfilePlatformVpnConsented()434 public void testProvisionVpnProfilePlatformVpnConsented() throws Exception { 435 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 436 437 verifyProvisionVpnProfile(false /* hasActivateVpn */, 438 true /* hasActivatePlatformVpn */, false /* expectIntent */); 439 } 440 441 @Test testProvisionVpnProfileVpnServiceConsented()442 public void testProvisionVpnProfileVpnServiceConsented() throws Exception { 443 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 444 445 verifyProvisionVpnProfile(true /* hasActivateVpn */, 446 false /* hasActivatePlatformVpn */, false /* expectIntent */); 447 } 448 449 @Test testProvisionVpnProfileAllPreConsented()450 public void testProvisionVpnProfileAllPreConsented() throws Exception { 451 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 452 453 verifyProvisionVpnProfile(true /* hasActivateVpn */, 454 true /* hasActivatePlatformVpn */, false /* expectIntent */); 455 } 456 457 @Test testDeleteVpnProfile()458 public void testDeleteVpnProfile() throws Exception { 459 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 460 461 setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true); 462 463 final Ikev2VpnProfile profile = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6, 464 false /* isRestrictedToTestNetworks */, false /* requiresValidation */); 465 assertNull(sVpnMgr.provisionVpnProfile(profile)); 466 467 // Verify that deleting the profile works (even without the appop) 468 setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false); 469 sVpnMgr.deleteProvisionedVpnProfile(); 470 471 // Test that the profile was deleted - starting it should throw an IAE. 472 try { 473 setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true); 474 sVpnMgr.startProvisionedVpnProfile(); 475 fail("Expected IllegalArgumentException due to missing profile"); 476 } catch (IllegalArgumentException expected) { 477 } 478 } 479 480 @Test testStartVpnProfileNoPreviousConsent()481 public void testStartVpnProfileNoPreviousConsent() throws Exception { 482 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 483 484 setAppop(AppOpsManager.OP_ACTIVATE_VPN, false); 485 setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false); 486 487 // Make sure the VpnProfile is not provisioned already. 488 sVpnMgr.stopProvisionedVpnProfile(); 489 490 try { 491 sVpnMgr.startProvisionedVpnProfile(); 492 fail("Expected SecurityException for missing consent"); 493 } catch (SecurityException expected) { 494 } 495 } 496 checkStartStopVpnProfileBuildsNetworks(@onNull IkeTunUtils tunUtils, boolean testIpv6, boolean requiresValidation, boolean testSessionKey, boolean testIkeTunConnParams)497 private void checkStartStopVpnProfileBuildsNetworks(@NonNull IkeTunUtils tunUtils, 498 boolean testIpv6, boolean requiresValidation, boolean testSessionKey, 499 boolean testIkeTunConnParams) 500 throws Exception { 501 String serverAddr = testIpv6 ? TEST_SERVER_ADDR_V6 : TEST_SERVER_ADDR_V4; 502 String initResp = testIpv6 ? SUCCESSFUL_IKE_INIT_RESP_V6 : SUCCESSFUL_IKE_INIT_RESP_V4; 503 String authResp = testIpv6 ? SUCCESSFUL_IKE_AUTH_RESP_V6 : SUCCESSFUL_IKE_AUTH_RESP_V4; 504 boolean hasNat = !testIpv6; 505 506 // Requires MANAGE_TEST_NETWORKS to provision a test-mode profile. 507 mCtsNetUtils.setAppopPrivileged(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true); 508 509 final Ikev2VpnProfile profile = testIkeTunConnParams 510 ? buildIkev2VpnProfileIkeTunConnParams(true /* isRestrictedToTestNetworks */, 511 requiresValidation, testIpv6) 512 : buildIkev2VpnProfilePsk(serverAddr, true /* isRestrictedToTestNetworks */, 513 requiresValidation); 514 assertNull(sVpnMgr.provisionVpnProfile(profile)); 515 516 final TestableNetworkCallback cb = new TestableNetworkCallback(TIMEOUT_MS); 517 final NetworkRequest nr = new NetworkRequest.Builder() 518 .clearCapabilities().addTransportType(TRANSPORT_VPN).build(); 519 registerNetworkCallback(nr, cb); 520 521 if (testSessionKey) { 522 // testSessionKey will never be true if running on <T 523 // startProvisionedVpnProfileSession() should return a non-null & non-empty random UUID. 524 final String sessionId = mVmShim.startProvisionedVpnProfileSession(); 525 assertFalse(TextUtils.isEmpty(sessionId)); 526 final VpnProfileStateShim profileState = mVmShim.getProvisionedVpnProfileState(); 527 assertNotNull(profileState); 528 assertEquals(ConstantsShim.VPN_PROFILE_STATE_CONNECTING, profileState.getState()); 529 assertEquals(sessionId, profileState.getSessionId()); 530 assertFalse(profileState.isAlwaysOn()); 531 assertFalse(profileState.isLockdownEnabled()); 532 } else { 533 sVpnMgr.startProvisionedVpnProfile(); 534 } 535 536 // Inject IKE negotiation 537 int expectedMsgId = 0; 538 tunUtils.awaitReqAndInjectResp(IKE_INITIATOR_SPI, expectedMsgId++, false /* isEncap */, 539 HexDump.hexStringToByteArray(initResp)); 540 tunUtils.awaitReqAndInjectResp(IKE_INITIATOR_SPI, expectedMsgId++, hasNat /* isEncap */, 541 HexDump.hexStringToByteArray(authResp)); 542 543 // Verify the VPN network came up 544 final Network vpnNetwork = cb.expect(CallbackEntry.AVAILABLE).getNetwork(); 545 546 if (testSessionKey) { 547 final VpnProfileStateShim profileState = mVmShim.getProvisionedVpnProfileState(); 548 assertNotNull(profileState); 549 assertEquals(ConstantsShim.VPN_PROFILE_STATE_CONNECTED, profileState.getState()); 550 assertFalse(profileState.isAlwaysOn()); 551 assertFalse(profileState.isLockdownEnabled()); 552 } 553 554 cb.expectCaps(vpnNetwork, TIMEOUT_MS, c -> c.hasTransport(TRANSPORT_VPN) 555 && c.hasCapability(NET_CAPABILITY_INTERNET) 556 && !c.hasCapability(NET_CAPABILITY_VALIDATED) 557 && Process.myUid() == c.getOwnerUid()); 558 cb.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, vpnNetwork); 559 cb.expect(CallbackEntry.BLOCKED_STATUS, vpnNetwork); 560 561 // A VPN that requires validation is initially not validated, while one that doesn't 562 // immediately validate automatically. Because this VPN can't actually access Internet, 563 // the VPN only validates if it doesn't require validation. If the VPN requires validation 564 // but unexpectedly sends this callback, expecting LOST below will fail because the next 565 // callback will be the validated capabilities instead. 566 // In S and below, |requiresValidation| is ignored, so this callback is always sent 567 // regardless of its value. However, there is a race in Vpn(see b/228574221) that VPN may 568 // misuse VPN network itself as the underlying network. The fix is not available without 569 // SDK > T platform. Thus, verify this only on T+ platform. 570 if (!requiresValidation && TestUtils.shouldTestTApis()) { 571 cb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, TIMEOUT_MS, 572 entry -> ((CallbackEntry.CapabilitiesChanged) entry).getCaps() 573 .hasCapability(NET_CAPABILITY_VALIDATED)); 574 } 575 576 sVpnMgr.stopProvisionedVpnProfile(); 577 // Using expectCallback may cause the test to be flaky since test may receive other 578 // callbacks such as linkproperties change. 579 cb.eventuallyExpect(CallbackEntry.LOST, TIMEOUT_MS, 580 lost -> vpnNetwork.equals(lost.getNetwork())); 581 } 582 registerNetworkCallback(NetworkRequest request, TestableNetworkCallback callback)583 private void registerNetworkCallback(NetworkRequest request, TestableNetworkCallback callback) { 584 sCM.registerNetworkCallback(request, callback); 585 mCallbacksToUnregister.add(callback); 586 } 587 588 private class VerifyStartStopVpnProfileTest implements TestNetworkRunnable.Test { 589 private final boolean mTestIpv6Only; 590 private final boolean mRequiresValidation; 591 private final boolean mTestSessionKey; 592 private final boolean mTestIkeTunConnParams; 593 594 /** 595 * Constructs the test 596 * 597 * @param testIpv6Only if true, builds a IPv6-only test; otherwise builds a IPv4-only test 598 * @param requiresValidation whether this VPN should request platform validation 599 * @param testSessionKey if true, start VPN by calling startProvisionedVpnProfileSession() 600 */ VerifyStartStopVpnProfileTest(boolean testIpv6Only, boolean requiresValidation, boolean testSessionKey, boolean testIkeTunConnParams)601 VerifyStartStopVpnProfileTest(boolean testIpv6Only, boolean requiresValidation, 602 boolean testSessionKey, boolean testIkeTunConnParams) { 603 mTestIpv6Only = testIpv6Only; 604 mRequiresValidation = requiresValidation; 605 mTestSessionKey = testSessionKey; 606 mTestIkeTunConnParams = testIkeTunConnParams; 607 } 608 609 @Override runTest(TestNetworkInterface testIface, TestNetworkCallback tunNetworkCallback)610 public void runTest(TestNetworkInterface testIface, TestNetworkCallback tunNetworkCallback) 611 throws Exception { 612 final IkeTunUtils tunUtils = new IkeTunUtils(testIface.getFileDescriptor()); 613 614 checkStartStopVpnProfileBuildsNetworks(tunUtils, mTestIpv6Only, mRequiresValidation, 615 mTestSessionKey, mTestIkeTunConnParams); 616 } 617 618 @Override cleanupTest()619 public void cleanupTest() { 620 sVpnMgr.stopProvisionedVpnProfile(); 621 } 622 623 @Override getTestNetworkAddresses()624 public InetAddress[] getTestNetworkAddresses() { 625 if (mTestIpv6Only) { 626 return new InetAddress[] {LOCAL_OUTER_6}; 627 } else { 628 return new InetAddress[] {LOCAL_OUTER_4}; 629 } 630 } 631 } 632 doTestStartStopVpnProfile(boolean testIpv6Only, boolean requiresValidation, boolean testSessionKey, boolean testIkeTunConnParams)633 private void doTestStartStopVpnProfile(boolean testIpv6Only, boolean requiresValidation, 634 boolean testSessionKey, boolean testIkeTunConnParams) throws Exception { 635 assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); 636 // Requires shell permission to update appops. 637 runWithShellPermissionIdentity( 638 new TestNetworkRunnable(new VerifyStartStopVpnProfileTest( 639 testIpv6Only, requiresValidation, testSessionKey , testIkeTunConnParams))); 640 } 641 642 @Test testStartStopVpnProfileV4()643 public void testStartStopVpnProfileV4() throws Exception { 644 doTestStartStopVpnProfile(false /* testIpv6Only */, false /* requiresValidation */, 645 false /* testSessionKey */, false /* testIkeTunConnParams */); 646 } 647 648 @Test @IgnoreUpTo(SC_V2) testStartStopVpnProfileV4WithValidation()649 public void testStartStopVpnProfileV4WithValidation() throws Exception { 650 assumeTrue(TestUtils.shouldTestTApis()); 651 doTestStartStopVpnProfile(false /* testIpv6Only */, true /* requiresValidation */, 652 false /* testSessionKey */, false /* testIkeTunConnParams */); 653 } 654 655 @Test testStartStopVpnProfileV6()656 public void testStartStopVpnProfileV6() throws Exception { 657 doTestStartStopVpnProfile(true /* testIpv6Only */, false /* requiresValidation */, 658 false /* testSessionKey */, false /* testIkeTunConnParams */); 659 } 660 661 @Test @IgnoreUpTo(SC_V2) testStartStopVpnProfileV6WithValidation()662 public void testStartStopVpnProfileV6WithValidation() throws Exception { 663 assumeTrue(TestUtils.shouldTestTApis()); 664 doTestStartStopVpnProfile(true /* testIpv6Only */, true /* requiresValidation */, 665 false /* testSessionKey */, false /* testIkeTunConnParams */); 666 } 667 668 @Test @IgnoreUpTo(SC_V2) testStartStopVpnProfileIkeTunConnParamsV4()669 public void testStartStopVpnProfileIkeTunConnParamsV4() throws Exception { 670 assumeTrue(TestUtils.shouldTestTApis()); 671 doTestStartStopVpnProfile(false /* testIpv6Only */, false /* requiresValidation */, 672 false /* testSessionKey */, true /* testIkeTunConnParams */); 673 } 674 675 @Test @IgnoreUpTo(SC_V2) testStartStopVpnProfileIkeTunConnParamsV4WithValidation()676 public void testStartStopVpnProfileIkeTunConnParamsV4WithValidation() throws Exception { 677 assumeTrue(TestUtils.shouldTestTApis()); 678 doTestStartStopVpnProfile(false /* testIpv6Only */, true /* requiresValidation */, 679 false /* testSessionKey */, true /* testIkeTunConnParams */); 680 } 681 682 @Test @IgnoreUpTo(SC_V2) testStartStopVpnProfileIkeTunConnParamsV6()683 public void testStartStopVpnProfileIkeTunConnParamsV6() throws Exception { 684 assumeTrue(TestUtils.shouldTestTApis()); 685 doTestStartStopVpnProfile(true /* testIpv6Only */, false /* requiresValidation */, 686 false /* testSessionKey */, true /* testIkeTunConnParams */); 687 } 688 689 @Test @IgnoreUpTo(SC_V2) testStartStopVpnProfileIkeTunConnParamsV6WithValidation()690 public void testStartStopVpnProfileIkeTunConnParamsV6WithValidation() throws Exception { 691 assumeTrue(TestUtils.shouldTestTApis()); 692 doTestStartStopVpnProfile(true /* testIpv6Only */, true /* requiresValidation */, 693 false /* testSessionKey */, true /* testIkeTunConnParams */); 694 } 695 696 @IgnoreUpTo(SC_V2) 697 @Test testStartProvisionedVpnV4ProfileSession()698 public void testStartProvisionedVpnV4ProfileSession() throws Exception { 699 assumeTrue(TestUtils.shouldTestTApis()); 700 doTestStartStopVpnProfile(false /* testIpv6Only */, false /* requiresValidation */, 701 true /* testSessionKey */, false /* testIkeTunConnParams */); 702 } 703 704 @IgnoreUpTo(SC_V2) 705 @Test testStartProvisionedVpnV6ProfileSession()706 public void testStartProvisionedVpnV6ProfileSession() throws Exception { 707 assumeTrue(TestUtils.shouldTestTApis()); 708 doTestStartStopVpnProfile(true /* testIpv6Only */, false /* requiresValidation */, 709 true /* testSessionKey */, false /* testIkeTunConnParams */); 710 } 711 712 @Test testBuildIkev2VpnProfileWithAutomaticNattKeepaliveTimerEnabled()713 public void testBuildIkev2VpnProfileWithAutomaticNattKeepaliveTimerEnabled() throws Exception { 714 // Cannot use @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) because this test also requires API 715 // 34 shims, and @IgnoreUpTo does not check that. 716 assumeTrue(TestUtils.shouldTestUApis()); 717 718 final Ikev2VpnProfile profileWithDefaultValue = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6, 719 false /* isRestrictedToTestNetworks */, false /* requiresValidation */); 720 final Ikev2VpnProfileShim<Ikev2VpnProfile> shimWithDefaultValue = 721 Ikev2VpnProfileShimImpl.newInstance(profileWithDefaultValue); 722 assertFalse(shimWithDefaultValue.isAutomaticNattKeepaliveTimerEnabled()); 723 724 final Ikev2VpnProfileBuilderShim builder = 725 Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY) 726 .setAuthPsk(TEST_PSK); 727 final Ikev2VpnProfile profile = buildIkev2VpnProfileCommon(builder, 728 false /* isRestrictedToTestNetworks */, 729 false /* requiresValidation */, 730 false /* automaticIpVersionSelectionEnabled */, 731 true /* automaticNattKeepaliveTimerEnabled */); 732 final Ikev2VpnProfileShim<Ikev2VpnProfile> shim = 733 Ikev2VpnProfileShimImpl.newInstance(profile); 734 assertTrue(shim.isAutomaticNattKeepaliveTimerEnabled()); 735 } 736 737 @Test testBuildIkev2VpnProfileWithAutomaticIpVersionSelectionEnabled()738 public void testBuildIkev2VpnProfileWithAutomaticIpVersionSelectionEnabled() throws Exception { 739 // Cannot use @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) because this test also requires API 740 // 34 shims, and @IgnoreUpTo does not check that. 741 assumeTrue(TestUtils.shouldTestUApis()); 742 743 final Ikev2VpnProfile profileWithDefaultValue = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6, 744 false /* isRestrictedToTestNetworks */, false /* requiresValidation */); 745 final Ikev2VpnProfileShim<Ikev2VpnProfile> shimWithDefaultValue = 746 Ikev2VpnProfileShimImpl.newInstance(profileWithDefaultValue); 747 assertFalse(shimWithDefaultValue.isAutomaticIpVersionSelectionEnabled()); 748 749 final Ikev2VpnProfileBuilderShim builder = 750 Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY) 751 .setAuthPsk(TEST_PSK); 752 final Ikev2VpnProfile profile = buildIkev2VpnProfileCommon(builder, 753 false /* isRestrictedToTestNetworks */, 754 false /* requiresValidation */, 755 true /* automaticIpVersionSelectionEnabled */, 756 false /* automaticNattKeepaliveTimerEnabled */); 757 final Ikev2VpnProfileShim<Ikev2VpnProfile> shim = 758 Ikev2VpnProfileShimImpl.newInstance(profile); 759 assertTrue(shim.isAutomaticIpVersionSelectionEnabled()); 760 } 761 762 private static class CertificateAndKey { 763 public final X509Certificate cert; 764 public final PrivateKey key; 765 CertificateAndKey(X509Certificate cert, PrivateKey key)766 CertificateAndKey(X509Certificate cert, PrivateKey key) { 767 this.cert = cert; 768 this.key = key; 769 } 770 } 771 generateRandomCertAndKeyPair()772 private static CertificateAndKey generateRandomCertAndKeyPair() throws Exception { 773 final Date validityBeginDate = 774 new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1L)); 775 final Date validityEndDate = 776 new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1L)); 777 778 // Generate a keypair 779 final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 780 keyPairGenerator.initialize(512); 781 final KeyPair keyPair = keyPairGenerator.generateKeyPair(); 782 783 final X500Principal dnName = new X500Principal("CN=test.android.com"); 784 final X509V1CertificateGenerator certGen = new X509V1CertificateGenerator(); 785 certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); 786 certGen.setSubjectDN(dnName); 787 certGen.setIssuerDN(dnName); 788 certGen.setNotBefore(validityBeginDate); 789 certGen.setNotAfter(validityEndDate); 790 certGen.setPublicKey(keyPair.getPublic()); 791 certGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); 792 793 final X509Certificate cert = certGen.generate(keyPair.getPrivate(), "AndroidOpenSSL"); 794 return new CertificateAndKey(cert, keyPair.getPrivate()); 795 } 796 } 797