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 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package android.ipsec.ike.cts; 17 18 import static android.net.ipsec.ike.IkeSessionConfiguration.EXTENSION_TYPE_FRAGMENTATION; 19 import static android.system.OsConstants.AF_INET; 20 import static android.system.OsConstants.AF_INET6; 21 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertNotNull; 24 import static org.junit.Assert.assertTrue; 25 26 import android.annotation.NonNull; 27 import android.app.AppOpsManager; 28 import android.content.pm.PackageManager; 29 import android.ipsec.ike.cts.IkeTunUtils.PortPair; 30 import android.net.InetAddresses; 31 import android.net.IpSecManager; 32 import android.net.IpSecTransform; 33 import android.net.LinkAddress; 34 import android.net.ipsec.ike.ChildSessionCallback; 35 import android.net.ipsec.ike.ChildSessionConfiguration; 36 import android.net.ipsec.ike.IkeSessionCallback; 37 import android.net.ipsec.ike.IkeSessionConfiguration; 38 import android.net.ipsec.ike.IkeSessionConnectionInfo; 39 import android.net.ipsec.ike.IkeTrafficSelector; 40 import android.net.ipsec.ike.TransportModeChildSessionParams; 41 import android.net.ipsec.ike.TunnelModeChildSessionParams; 42 import android.net.ipsec.ike.exceptions.IkeException; 43 import android.os.UserHandle; 44 import android.platform.test.annotations.AppModeFull; 45 46 import androidx.test.ext.junit.runners.AndroidJUnit4; 47 48 import com.android.compatibility.common.util.SystemUtil; 49 import com.android.internal.net.annotations.PolicyDirection; 50 import com.android.net.module.util.ArrayTrackRecord; 51 52 import org.junit.After; 53 import org.junit.Before; 54 import org.junit.runner.RunWith; 55 56 import java.net.Inet4Address; 57 import java.net.Inet6Address; 58 import java.net.InetAddress; 59 import java.util.ArrayList; 60 import java.util.HashSet; 61 import java.util.List; 62 import java.util.Objects; 63 import java.util.Set; 64 import java.util.concurrent.CompletableFuture; 65 import java.util.concurrent.Executor; 66 import java.util.concurrent.Executors; 67 import java.util.concurrent.TimeUnit; 68 69 /** 70 * Package private base class for testing IkeSessionParams and IKE exchanges. 71 * 72 * <p>Subclasses MUST explicitly call #setUpTestNetwork and #tearDownTestNetwork to be able to use 73 * the test network 74 * 75 * <p>All IKE Sessions running in test mode will generate SPIs deterministically. That is to say 76 * each IKE Session will always generate the same IKE INIT SPI and test vectors are generated based 77 * on this deterministic IKE SPI. Each test will use different local and remote addresses to avoid 78 * the case that the next test try to allocate the same SPI before the previous test has released 79 * it, since SPI resources are not released in testing thread. Similarly, each test MUST use 80 * different Network instances to avoid sharing the same IkeSocket and hitting IKE SPI collision. 81 */ 82 @RunWith(AndroidJUnit4.class) 83 @AppModeFull(reason = "MANAGE_TEST_NETWORKS permission can't be granted to instant apps") 84 abstract class IkeSessionTestBase extends IkeTestNetworkBase { 85 // Package-wide common expected results that will be shared by all IKE/Child SA creation tests 86 static final String EXPECTED_REMOTE_APP_VERSION_EMPTY = ""; 87 static final byte[] EXPECTED_PROTOCOL_ERROR_DATA_NONE = new byte[0]; 88 89 static final InetAddress EXPECTED_DNS_SERVERS_ONE = 90 InetAddresses.parseNumericAddress("8.8.8.8"); 91 static final InetAddress EXPECTED_DNS_SERVERS_TWO = 92 InetAddresses.parseNumericAddress("8.8.4.4"); 93 94 static final InetAddress EXPECTED_INTERNAL_ADDR = 95 InetAddresses.parseNumericAddress("198.51.100.10"); 96 static final LinkAddress EXPECTED_INTERNAL_LINK_ADDR = 97 new LinkAddress(EXPECTED_INTERNAL_ADDR, IP4_PREFIX_LEN); 98 static final InetAddress EXPECTED_INTERNAL_ADDR_V6 = 99 InetAddresses.parseNumericAddress("2001:db8::2"); 100 static final LinkAddress EXPECTED_INTERNAL_LINK_ADDR_V6 = 101 new LinkAddress(EXPECTED_INTERNAL_ADDR_V6, IP6_PREFIX_LEN); 102 103 static final IkeTrafficSelector TUNNEL_MODE_INBOUND_TS = 104 new IkeTrafficSelector( 105 MIN_PORT, MAX_PORT, EXPECTED_INTERNAL_ADDR, EXPECTED_INTERNAL_ADDR); 106 static final IkeTrafficSelector TUNNEL_MODE_OUTBOUND_TS = DEFAULT_V4_TS; 107 static final IkeTrafficSelector TUNNEL_MODE_INBOUND_TS_V6 = 108 new IkeTrafficSelector( 109 MIN_PORT, MAX_PORT, EXPECTED_INTERNAL_ADDR_V6, EXPECTED_INTERNAL_ADDR_V6); 110 static final IkeTrafficSelector TUNNEL_MODE_OUTBOUND_TS_V6 = DEFAULT_V6_TS; 111 112 // This value is align with the test vectors hex that are generated in an IPv4 environment 113 static final IkeTrafficSelector TRANSPORT_MODE_OUTBOUND_TS = 114 new IkeTrafficSelector( 115 MIN_PORT, 116 MAX_PORT, 117 InetAddresses.parseNumericAddress("10.138.0.2"), 118 InetAddresses.parseNumericAddress("10.138.0.2")); 119 120 static final long IKE_DETERMINISTIC_INITIATOR_SPI = Long.parseLong("46B8ECA1E0D72A18", 16); 121 122 private static final int TIMEOUT_MS = 2000; 123 124 // Constants to be used for providing different IP addresses for each tests 125 private static final byte IP_ADDR_LAST_BYTE_MAX = (byte) 100; 126 private static final byte[] INITIAL_AVAILABLE_IP4_ADDR_LOCAL = 127 InetAddresses.parseNumericAddress("192.0.2.1").getAddress(); 128 private static final byte[] INITIAL_AVAILABLE_IP4_ADDR_REMOTE = 129 InetAddresses.parseNumericAddress("198.51.100.1").getAddress(); 130 private static final byte[] NEXT_AVAILABLE_IP4_ADDR_LOCAL = INITIAL_AVAILABLE_IP4_ADDR_LOCAL; 131 private static final byte[] NEXT_AVAILABLE_IP4_ADDR_REMOTE = INITIAL_AVAILABLE_IP4_ADDR_REMOTE; 132 133 private static final byte[] INITIAL_AVAILABLE_IP6_ADDR_LOCAL = 134 InetAddresses.parseNumericAddress("2a00:1000::0").getAddress(); 135 private static final byte[] INITIAL_AVAILABLE_IP6_ADDR_REMOTE = 136 InetAddresses.parseNumericAddress("2404:6800:4004:820::2004").getAddress(); 137 private static final byte[] NEXT_AVAILABLE_IP6_ADDR_LOCAL = INITIAL_AVAILABLE_IP6_ADDR_LOCAL; 138 private static final byte[] NEXT_AVAILABLE_IP6_ADDR_REMOTE = INITIAL_AVAILABLE_IP6_ADDR_REMOTE; 139 140 TunNetworkContext mTunNetworkContext; 141 142 InetAddress mLocalAddress; 143 InetAddress mRemoteAddress; 144 145 Executor mUserCbExecutor; 146 TestIkeSessionCallback mIkeSessionCallback; 147 TestChildSessionCallback mFirstChildSessionCallback; 148 149 @Before setUp()150 public void setUp() throws Exception { 151 mLocalAddress = getNextAvailableIpv4AddressLocal(); 152 mRemoteAddress = getNextAvailableIpv4AddressRemote(); 153 mTunNetworkContext = new TunNetworkContext(mLocalAddress); 154 155 mUserCbExecutor = Executors.newSingleThreadExecutor(); 156 mIkeSessionCallback = new DefaultTestIkeSessionCallback(); 157 mFirstChildSessionCallback = new DefaultTestChildSessionCallback(); 158 } 159 160 @After tearDown()161 public void tearDown() throws Exception { 162 if (mTunNetworkContext != null) { 163 mTunNetworkContext.close(); 164 } 165 } 166 setAppOp(int appop, boolean allow)167 static void setAppOp(int appop, boolean allow) { 168 String opName = AppOpsManager.opToName(appop); 169 for (String pkg : new String[] {"com.android.shell", sContext.getPackageName()}) { 170 String cmd = 171 String.format( 172 "appops set --user %d %s %s %s", 173 UserHandle.myUserId(), // user id 174 pkg, // Package name 175 opName, // Appop 176 (allow ? "allow" : "deny")); // Action 177 178 SystemUtil.runShellCommand(cmd); 179 } 180 } 181 getNextAvailableIpv4AddressLocal()182 Inet4Address getNextAvailableIpv4AddressLocal() throws Exception { 183 return (Inet4Address) 184 getNextAvailableAddress( 185 NEXT_AVAILABLE_IP4_ADDR_LOCAL, 186 INITIAL_AVAILABLE_IP4_ADDR_LOCAL, 187 false /* isIp6 */); 188 } 189 getNextAvailableIpv4AddressRemote()190 Inet4Address getNextAvailableIpv4AddressRemote() throws Exception { 191 return (Inet4Address) 192 getNextAvailableAddress( 193 NEXT_AVAILABLE_IP4_ADDR_REMOTE, 194 INITIAL_AVAILABLE_IP4_ADDR_REMOTE, 195 false /* isIp6 */); 196 } 197 getNextAvailableIpv6AddressLocal()198 Inet6Address getNextAvailableIpv6AddressLocal() throws Exception { 199 return (Inet6Address) 200 getNextAvailableAddress( 201 NEXT_AVAILABLE_IP6_ADDR_LOCAL, 202 INITIAL_AVAILABLE_IP6_ADDR_LOCAL, 203 true /* isIp6 */); 204 } 205 getNextAvailableIpv6AddressRemote()206 Inet6Address getNextAvailableIpv6AddressRemote() throws Exception { 207 return (Inet6Address) 208 getNextAvailableAddress( 209 NEXT_AVAILABLE_IP6_ADDR_REMOTE, 210 INITIAL_AVAILABLE_IP6_ADDR_REMOTE, 211 true /* isIp6 */); 212 } 213 getNextAvailableAddress( byte[] nextAddressBytes, byte[] initialAddressBytes, boolean isIp6)214 InetAddress getNextAvailableAddress( 215 byte[] nextAddressBytes, byte[] initialAddressBytes, boolean isIp6) throws Exception { 216 int addressLen = isIp6 ? IP6_ADDRESS_LEN : IP4_ADDRESS_LEN; 217 218 synchronized (nextAddressBytes) { 219 if (nextAddressBytes[addressLen - 1] == IP_ADDR_LAST_BYTE_MAX) { 220 resetNextAvailableAddress(nextAddressBytes, initialAddressBytes); 221 } 222 223 InetAddress address = InetAddress.getByAddress(nextAddressBytes); 224 nextAddressBytes[addressLen - 1]++; 225 return address; 226 } 227 } 228 resetNextAvailableAddress(byte[] nextAddressBytes, byte[] initialAddressBytes)229 private void resetNextAvailableAddress(byte[] nextAddressBytes, byte[] initialAddressBytes) { 230 synchronized (nextAddressBytes) { 231 System.arraycopy( 232 nextAddressBytes, 0, initialAddressBytes, 0, initialAddressBytes.length); 233 } 234 } 235 buildTransportModeChildParamsWithTs( IkeTrafficSelector inboundTs, IkeTrafficSelector outboundTs)236 TransportModeChildSessionParams buildTransportModeChildParamsWithTs( 237 IkeTrafficSelector inboundTs, IkeTrafficSelector outboundTs) { 238 return new TransportModeChildSessionParams.Builder() 239 .addSaProposal(SaProposalTest.buildChildSaProposalWithCombinedModeCipher()) 240 .addSaProposal(SaProposalTest.buildChildSaProposalWithNormalModeCipher()) 241 .addInboundTrafficSelectors(inboundTs) 242 .addOutboundTrafficSelectors(outboundTs) 243 .build(); 244 } 245 buildTransportModeChildParamsWithDefaultTs()246 TransportModeChildSessionParams buildTransportModeChildParamsWithDefaultTs() { 247 return new TransportModeChildSessionParams.Builder() 248 .addSaProposal(SaProposalTest.buildChildSaProposalWithCombinedModeCipher()) 249 .addSaProposal(SaProposalTest.buildChildSaProposalWithNormalModeCipher()) 250 .build(); 251 } 252 buildTunnelModeChildSessionParams()253 TunnelModeChildSessionParams buildTunnelModeChildSessionParams() { 254 return new TunnelModeChildSessionParams.Builder() 255 .addSaProposal(SaProposalTest.buildChildSaProposalWithNormalModeCipher()) 256 .addSaProposal(SaProposalTest.buildChildSaProposalWithCombinedModeCipher()) 257 .addInternalAddressRequest(AF_INET) 258 .addInternalAddressRequest(AF_INET6) 259 .build(); 260 } 261 performSetupIkeAndFirstChildBlocking(String ikeInitRespHex, String... ikeAuthRespHexes)262 PortPair performSetupIkeAndFirstChildBlocking(String ikeInitRespHex, String... ikeAuthRespHexes) 263 throws Exception { 264 return performSetupIkeAndFirstChildBlocking( 265 ikeInitRespHex, 266 1 /* expectedAuthReqPktCnt */, 267 true /*expectedAuthUseEncap*/, 268 ikeAuthRespHexes); 269 } 270 performSetupIkeAndFirstChildBlocking( String ikeInitRespHex, boolean expectedAuthUseEncap, String... ikeAuthRespHexes)271 PortPair performSetupIkeAndFirstChildBlocking( 272 String ikeInitRespHex, boolean expectedAuthUseEncap, String... ikeAuthRespHexes) 273 throws Exception { 274 return performSetupIkeAndFirstChildBlocking( 275 ikeInitRespHex, 276 1 /* expectedAuthReqPktCnt */, 277 expectedAuthUseEncap, 278 ikeAuthRespHexes); 279 } 280 performSetupIkeAndFirstChildBlocking( String ikeInitRespHex, int expectedAuthReqPktCnt, boolean expectedAuthUseEncap, String... ikeAuthRespHexes)281 PortPair performSetupIkeAndFirstChildBlocking( 282 String ikeInitRespHex, 283 int expectedAuthReqPktCnt, 284 boolean expectedAuthUseEncap, 285 String... ikeAuthRespHexes) 286 throws Exception { 287 mTunNetworkContext.tunUtils.awaitReqAndInjectResp( 288 IKE_DETERMINISTIC_INITIATOR_SPI, 289 0 /* expectedMsgId */, 290 false /* expectedUseEncap */, 291 ikeInitRespHex); 292 293 byte[] ikeAuthReqPkt = 294 mTunNetworkContext 295 .tunUtils 296 .awaitReqAndInjectResp( 297 IKE_DETERMINISTIC_INITIATOR_SPI, 298 1 /* expectedMsgId */, 299 expectedAuthUseEncap, 300 expectedAuthReqPktCnt, 301 ikeAuthRespHexes) 302 .get(0); 303 return IkeTunUtils.getSrcDestPortPair(ikeAuthReqPkt); 304 } 305 performCloseIkeBlocking(int expectedMsgId, String deleteIkeRespHex)306 void performCloseIkeBlocking(int expectedMsgId, String deleteIkeRespHex) throws Exception { 307 performCloseIkeBlocking(expectedMsgId, true /* expectedUseEncap*/, deleteIkeRespHex); 308 } 309 performCloseIkeBlocking( int expectedMsgId, boolean expectedUseEncap, String deleteIkeRespHex)310 void performCloseIkeBlocking( 311 int expectedMsgId, boolean expectedUseEncap, String deleteIkeRespHex) throws Exception { 312 mTunNetworkContext.tunUtils.awaitReqAndInjectResp( 313 IKE_DETERMINISTIC_INITIATOR_SPI, expectedMsgId, expectedUseEncap, deleteIkeRespHex); 314 } 315 316 /** 317 * Base testing callback that allows caller to block current thread until a method get called 318 */ 319 abstract static class TestIkeSessionCallback implements IkeSessionCallback { 320 private CompletableFuture<IkeSessionConfiguration> mFutureIkeConfig = 321 new CompletableFuture<>(); 322 private CompletableFuture<Boolean> mFutureOnClosedCall = new CompletableFuture<>(); 323 private CompletableFuture<IkeSessionConnectionInfo> mFutureConnectionConfig = 324 new CompletableFuture<>(); 325 326 private int mOnErrorExceptionsCount = 0; 327 private ArrayTrackRecord<IkeException> mOnErrorExceptionsTrackRecord = 328 new ArrayTrackRecord<>(); 329 330 protected CompletableFuture<IkeException> mFutureOnClosedException = 331 new CompletableFuture<>(); 332 333 private int mOnLivenessStatusCount = 0; 334 private ArrayTrackRecord<Integer> mOnLivenessStatusTrackRecord = new ArrayTrackRecord<>(); 335 336 @Override onOpened(@onNull IkeSessionConfiguration sessionConfiguration)337 public void onOpened(@NonNull IkeSessionConfiguration sessionConfiguration) { 338 mFutureIkeConfig.complete(sessionConfiguration); 339 } 340 341 @Override onClosed()342 public void onClosed() { 343 mFutureOnClosedCall.complete(true /* unused */); 344 } 345 346 @Override onError(@onNull IkeException exception)347 public void onError(@NonNull IkeException exception) { 348 IkeSessionCallback.super.onError(exception); 349 mOnErrorExceptionsTrackRecord.add(exception); 350 } 351 352 @Override onIkeSessionConnectionInfoChanged( @onNull IkeSessionConnectionInfo connectionInfo)353 public void onIkeSessionConnectionInfoChanged( 354 @NonNull IkeSessionConnectionInfo connectionInfo) { 355 IkeSessionCallback.super.onIkeSessionConnectionInfoChanged(connectionInfo); 356 mFutureConnectionConfig.complete(connectionInfo); 357 } 358 359 @Override onLivenessStatusChanged(int livenessStatus)360 public void onLivenessStatusChanged(int livenessStatus) { 361 IkeSessionCallback.super.onLivenessStatusChanged(livenessStatus); 362 mOnLivenessStatusTrackRecord.add(livenessStatus); 363 } 364 awaitIkeConfig()365 public IkeSessionConfiguration awaitIkeConfig() throws Exception { 366 return mFutureIkeConfig.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); 367 } 368 awaitOnClosedException()369 public IkeException awaitOnClosedException() throws Exception { 370 return mFutureOnClosedException.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); 371 } 372 awaitNextOnErrorException()373 public IkeException awaitNextOnErrorException() { 374 return mOnErrorExceptionsTrackRecord.poll( 375 (long) TIMEOUT_MS, 376 mOnErrorExceptionsCount++, 377 (transform) -> { 378 return true; 379 }); 380 } 381 awaitOnClosed()382 public void awaitOnClosed() throws Exception { 383 mFutureOnClosedCall.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); 384 } 385 awaitOnIkeSessionConnectionInfoChanged()386 public IkeSessionConnectionInfo awaitOnIkeSessionConnectionInfoChanged() throws Exception { 387 return mFutureConnectionConfig.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); 388 } 389 awaitNextOnLivenessStatus()390 public int awaitNextOnLivenessStatus() throws Exception { 391 return mOnLivenessStatusTrackRecord.poll( 392 (long) TIMEOUT_MS, 393 mOnLivenessStatusCount++, 394 (transform) -> { 395 return true; 396 }); 397 } 398 } 399 400 /** Default testing callback for all IKE exchange tests */ 401 static class DefaultTestIkeSessionCallback extends TestIkeSessionCallback { 402 @Override 403 public void onClosedWithException(@NonNull IkeException exception) { 404 mFutureOnClosedException.complete(exception); 405 } 406 } 407 408 /** Testing callback to verify deprecated methods before they are removed */ 409 static class LegacyTestIkeSessionCallback extends TestIkeSessionCallback { 410 @Override 411 public void onClosedExceptionally(@NonNull IkeException exception) { 412 mFutureOnClosedException.complete(exception); 413 } 414 } 415 416 /** 417 * Base testing callback that allows caller to block current thread until a method get called 418 */ 419 abstract static class TestChildSessionCallback implements ChildSessionCallback { 420 private CompletableFuture<ChildSessionConfiguration> mFutureChildConfig = 421 new CompletableFuture<>(); 422 private CompletableFuture<Boolean> mFutureOnClosedCall = new CompletableFuture<>(); 423 424 protected CompletableFuture<IkeException> mFutureOnClosedException = 425 new CompletableFuture<>(); 426 427 private int mCreatedIpSecTransformCount = 0; 428 private int mMigratedIpSecTransformCount = 0; 429 private int mDeletedIpSecTransformCount = 0; 430 private ArrayTrackRecord<IpSecTransformCallRecord> mCreatedIpSecTransformsTrackRecord = 431 new ArrayTrackRecord<>(); 432 private ArrayTrackRecord<IpSecTransformCallRecord[]> mMigratedIpSecTransformsTrackRecord = 433 new ArrayTrackRecord<>(); 434 private ArrayTrackRecord<IpSecTransformCallRecord> mDeletedIpSecTransformsTrackRecord = 435 new ArrayTrackRecord<>(); 436 437 @Override 438 public void onOpened(@NonNull ChildSessionConfiguration sessionConfiguration) { 439 mFutureChildConfig.complete(sessionConfiguration); 440 } 441 442 @Override 443 public void onClosed() { 444 mFutureOnClosedCall.complete(true /* unused */); 445 } 446 447 @Override 448 public void onIpSecTransformCreated(@NonNull IpSecTransform ipSecTransform, int direction) { 449 mCreatedIpSecTransformsTrackRecord.add( 450 new IpSecTransformCallRecord(ipSecTransform, direction)); 451 } 452 453 @Override 454 public void onIpSecTransformsMigrated( 455 IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform) { 456 ChildSessionCallback.super.onIpSecTransformsMigrated( 457 inIpSecTransform, outIpSecTransform); 458 459 IpSecTransformCallRecord inRecord = 460 new IpSecTransformCallRecord(inIpSecTransform, IpSecManager.DIRECTION_IN); 461 IpSecTransformCallRecord outRecord = 462 new IpSecTransformCallRecord(outIpSecTransform, IpSecManager.DIRECTION_OUT); 463 mMigratedIpSecTransformsTrackRecord.add( 464 new IpSecTransformCallRecord[] {inRecord, outRecord}); 465 } 466 467 @Override 468 public void onIpSecTransformDeleted(@NonNull IpSecTransform ipSecTransform, int direction) { 469 mDeletedIpSecTransformsTrackRecord.add( 470 new IpSecTransformCallRecord(ipSecTransform, direction)); 471 } 472 473 public ChildSessionConfiguration awaitChildConfig() throws Exception { 474 return mFutureChildConfig.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); 475 } 476 477 public IkeException awaitOnClosedException() throws Exception { 478 return mFutureOnClosedException.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); 479 } 480 481 public IpSecTransformCallRecord awaitNextCreatedIpSecTransform() { 482 return mCreatedIpSecTransformsTrackRecord.poll( 483 (long) TIMEOUT_MS, 484 mCreatedIpSecTransformCount++, 485 (transform) -> { 486 return true; 487 }); 488 } 489 490 public IpSecTransformCallRecord[] awaitNextMigratedIpSecTransform() { 491 return mMigratedIpSecTransformsTrackRecord.poll( 492 (long) TIMEOUT_MS, 493 mMigratedIpSecTransformCount++, 494 (transform) -> { 495 return true; 496 }); 497 } 498 499 public IpSecTransformCallRecord awaitNextDeletedIpSecTransform() { 500 return mDeletedIpSecTransformsTrackRecord.poll( 501 (long) TIMEOUT_MS, 502 mDeletedIpSecTransformCount++, 503 (transform) -> { 504 return true; 505 }); 506 } 507 508 public void awaitOnClosed() throws Exception { 509 mFutureOnClosedCall.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); 510 } 511 } 512 513 /** Default testing callback for all IKE exchange tests */ 514 static class DefaultTestChildSessionCallback extends TestChildSessionCallback { 515 @Override 516 public void onClosedWithException(@NonNull IkeException exception) { 517 mFutureOnClosedException.complete(exception); 518 } 519 } 520 521 /** Testing callback to verify deprecated methods before they are removed */ 522 static class LegacyTestChildSessionCallback extends TestChildSessionCallback { 523 @Override 524 public void onClosedExceptionally(@NonNull IkeException exception) { 525 mFutureOnClosedException.complete(exception); 526 } 527 } 528 529 /** 530 * This class represents a created or deleted IpSecTransfrom that is provided by 531 * ChildSessionCallback 532 */ 533 static class IpSecTransformCallRecord { 534 public final IpSecTransform ipSecTransform; 535 public final int direction; 536 537 IpSecTransformCallRecord(IpSecTransform ipSecTransform, @PolicyDirection int direction) { 538 this.ipSecTransform = ipSecTransform; 539 this.direction = direction; 540 } 541 542 @Override 543 public int hashCode() { 544 return Objects.hash(ipSecTransform, direction); 545 } 546 547 @Override 548 public boolean equals(Object o) { 549 if (!(o instanceof IpSecTransformCallRecord)) return false; 550 551 IpSecTransformCallRecord record = (IpSecTransformCallRecord) o; 552 return ipSecTransform.equals(record.ipSecTransform) && direction == record.direction; 553 } 554 } 555 556 // TODO: b/275938211 Rename the method to reflect that it will return a value besides doing 557 // validations 558 IkeSessionConnectionInfo verifyIkeSessionSetupBlocking() throws Exception { 559 return verifyIkeSessionSetupBlocking(EXTENSION_TYPE_FRAGMENTATION); 560 } 561 562 IkeSessionConnectionInfo verifyIkeSessionSetupBlocking(int... expectedIkeExtensions) 563 throws Exception { 564 IkeSessionConfiguration ikeConfig = mIkeSessionCallback.awaitIkeConfig(); 565 assertNotNull(ikeConfig); 566 assertEquals(EXPECTED_REMOTE_APP_VERSION_EMPTY, ikeConfig.getRemoteApplicationVersion()); 567 assertTrue(ikeConfig.getRemoteVendorIds().isEmpty()); 568 assertTrue(ikeConfig.getPcscfServers().isEmpty()); 569 for (int ikeExtension : expectedIkeExtensions) { 570 assertTrue(ikeConfig.isIkeExtensionEnabled(ikeExtension)); 571 } 572 573 IkeSessionConnectionInfo ikeConnectInfo = ikeConfig.getIkeSessionConnectionInfo(); 574 assertNotNull(ikeConnectInfo); 575 assertEquals(mLocalAddress, ikeConnectInfo.getLocalAddress()); 576 assertEquals(mRemoteAddress, ikeConnectInfo.getRemoteAddress()); 577 assertEquals(mTunNetworkContext.tunNetwork, ikeConnectInfo.getNetwork()); 578 579 return ikeConnectInfo; 580 } 581 582 ChildSessionConfiguration verifyChildSessionSetupBlocking( 583 TestChildSessionCallback childCallback, 584 List<IkeTrafficSelector> expectedInboundTs, 585 List<IkeTrafficSelector> expectedOutboundTs, 586 List<LinkAddress> expectedInternalAddresses) 587 throws Exception { 588 return verifyChildSessionSetupBlocking( 589 childCallback, 590 expectedInboundTs, 591 expectedOutboundTs, 592 expectedInternalAddresses, 593 new ArrayList<InetAddress>() /* expectedDnsServers */); 594 } 595 596 ChildSessionConfiguration verifyChildSessionSetupBlocking( 597 TestChildSessionCallback childCallback, 598 List<IkeTrafficSelector> expectedInboundTs, 599 List<IkeTrafficSelector> expectedOutboundTs, 600 List<LinkAddress> expectedInternalAddresses, 601 List<InetAddress> expectedDnsServers) 602 throws Exception { 603 ChildSessionConfiguration childConfig = childCallback.awaitChildConfig(); 604 assertNotNull(childConfig); 605 assertEquals(expectedInboundTs, childConfig.getInboundTrafficSelectors()); 606 assertEquals(expectedOutboundTs, childConfig.getOutboundTrafficSelectors()); 607 assertEquals(expectedInternalAddresses, childConfig.getInternalAddresses()); 608 assertEquals(expectedDnsServers, childConfig.getInternalDnsServers()); 609 assertTrue(childConfig.getInternalSubnets().isEmpty()); 610 assertTrue(childConfig.getInternalDhcpServers().isEmpty()); 611 return childConfig; 612 } 613 614 void verifyCloseIkeAndChildBlocking( 615 IpSecTransformCallRecord expectedTransformRecordA, 616 IpSecTransformCallRecord expectedTransformRecordB) 617 throws Exception { 618 verifyDeleteIpSecTransformPair( 619 mFirstChildSessionCallback, expectedTransformRecordA, expectedTransformRecordB); 620 mFirstChildSessionCallback.awaitOnClosed(); 621 mIkeSessionCallback.awaitOnClosed(); 622 } 623 624 static void verifyCreateIpSecTransformPair( 625 IpSecTransformCallRecord transformRecordA, IpSecTransformCallRecord transformRecordB) { 626 IpSecTransform transformA = transformRecordA.ipSecTransform; 627 IpSecTransform transformB = transformRecordB.ipSecTransform; 628 629 assertNotNull(transformA); 630 assertNotNull(transformB); 631 632 Set<Integer> expectedDirections = new HashSet<>(); 633 expectedDirections.add(IpSecManager.DIRECTION_IN); 634 expectedDirections.add(IpSecManager.DIRECTION_OUT); 635 636 Set<Integer> resultDirections = new HashSet<>(); 637 resultDirections.add(transformRecordA.direction); 638 resultDirections.add(transformRecordB.direction); 639 640 assertEquals(expectedDirections, resultDirections); 641 } 642 643 static void verifyDeleteIpSecTransformPair( 644 TestChildSessionCallback childCb, 645 IpSecTransformCallRecord expectedTransformRecordA, 646 IpSecTransformCallRecord expectedTransformRecordB) { 647 Set<IpSecTransformCallRecord> expectedTransforms = new HashSet<>(); 648 expectedTransforms.add(expectedTransformRecordA); 649 expectedTransforms.add(expectedTransformRecordB); 650 651 Set<IpSecTransformCallRecord> resultTransforms = new HashSet<>(); 652 resultTransforms.add(childCb.awaitNextDeletedIpSecTransform()); 653 resultTransforms.add(childCb.awaitNextDeletedIpSecTransform()); 654 655 assertEquals(expectedTransforms, resultTransforms); 656 } 657 658 /** Package private method to check if device has IPsec tunnels feature */ 659 static boolean hasTunnelsFeature() { 660 return sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS); 661 } 662 663 /** Package private method to check if device has IPsec tunnel migration feature */ 664 static boolean hasTunnelMigrationFeature() { 665 return sContext.getPackageManager() 666 .hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNEL_MIGRATION); 667 } 668 669 // TODO(b/148689509): Verify hostname based creation 670 } 671