1 /* 2 * Copyright (C) 2019 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 com.android.internal.net; 18 19 import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS; 20 import static android.net.cts.util.IkeSessionTestUtils.IKE_PARAMS_V4; 21 22 import static com.android.modules.utils.build.SdkLevel.isAtLeastT; 23 import static com.android.modules.utils.build.SdkLevel.isAtLeastU; 24 import static com.android.testutils.ParcelUtils.assertParcelSane; 25 26 import static org.junit.Assert.assertEquals; 27 import static org.junit.Assert.assertFalse; 28 import static org.junit.Assert.assertNotEquals; 29 import static org.junit.Assert.assertNull; 30 import static org.junit.Assert.assertTrue; 31 32 import android.net.IpSecAlgorithm; 33 import android.net.ipsec.ike.IkeTunnelConnectionParams; 34 import android.os.Build; 35 36 import androidx.test.filters.SmallTest; 37 38 import com.android.testutils.DevSdkIgnoreRule; 39 import com.android.testutils.DevSdkIgnoreRunner; 40 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 44 import java.util.ArrayList; 45 import java.util.Arrays; 46 import java.util.List; 47 48 /** Unit tests for {@link VpnProfile}. */ 49 @SmallTest 50 @RunWith(DevSdkIgnoreRunner.class) 51 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) 52 public class VpnProfileTest { 53 private static final String DUMMY_PROFILE_KEY = "Test"; 54 55 private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23; 56 private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24; 57 private static final int ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE = 25; 58 private static final int ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION = 26; 59 private static final int ENCODED_INDEX_IKE_TUN_CONN_PARAMS = 27; 60 private static final int ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED = 28; 61 private static final int ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED = 29; 62 63 @Test testDefaults()64 public void testDefaults() throws Exception { 65 final VpnProfile p = new VpnProfile(DUMMY_PROFILE_KEY); 66 67 assertEquals(DUMMY_PROFILE_KEY, p.key); 68 assertEquals("", p.name); 69 assertEquals(VpnProfile.TYPE_PPTP, p.type); 70 assertEquals("", p.server); 71 assertEquals("", p.username); 72 assertEquals("", p.password); 73 assertEquals("", p.dnsServers); 74 assertEquals("", p.searchDomains); 75 assertEquals("", p.routes); 76 assertTrue(p.mppe); 77 assertEquals("", p.l2tpSecret); 78 assertEquals("", p.ipsecIdentifier); 79 assertEquals("", p.ipsecSecret); 80 assertEquals("", p.ipsecUserCert); 81 assertEquals("", p.ipsecCaCert); 82 assertEquals("", p.ipsecServerCert); 83 assertEquals(null, p.proxy); 84 assertTrue(p.getAllowedAlgorithms() != null && p.getAllowedAlgorithms().isEmpty()); 85 assertFalse(p.isBypassable); 86 assertFalse(p.isMetered); 87 assertEquals(1360, p.maxMtu); 88 assertFalse(p.areAuthParamsInline); 89 assertFalse(p.isRestrictedToTestNetworks); 90 assertFalse(p.excludeLocalRoutes); 91 assertFalse(p.requiresInternetValidation); 92 assertFalse(p.automaticNattKeepaliveTimerEnabled); 93 assertFalse(p.automaticIpVersionSelectionEnabled); 94 } 95 getSampleIkev2Profile(String key)96 private VpnProfile getSampleIkev2Profile(String key) { 97 final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */, 98 false /* excludesLocalRoutes */, true /* requiresPlatformValidation */, 99 null /* ikeTunConnParams */, true /* mAutomaticNattKeepaliveTimerEnabled */, 100 true /* automaticIpVersionSelectionEnabled */); 101 102 p.name = "foo"; 103 p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS; 104 p.server = "bar"; 105 p.username = "baz"; 106 p.password = "qux"; 107 p.dnsServers = "8.8.8.8"; 108 p.searchDomains = ""; 109 p.routes = "0.0.0.0/0"; 110 p.mppe = false; 111 p.l2tpSecret = ""; 112 p.ipsecIdentifier = "quux"; 113 p.ipsecSecret = "quuz"; 114 p.ipsecUserCert = "corge"; 115 p.ipsecCaCert = "grault"; 116 p.ipsecServerCert = "garply"; 117 p.proxy = null; 118 p.setAllowedAlgorithms( 119 Arrays.asList( 120 IpSecAlgorithm.AUTH_CRYPT_AES_GCM, 121 IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305, 122 IpSecAlgorithm.AUTH_HMAC_SHA512, 123 IpSecAlgorithm.CRYPT_AES_CBC)); 124 p.isBypassable = true; 125 p.isMetered = true; 126 p.maxMtu = 1350; 127 p.areAuthParamsInline = true; 128 129 // Not saved, but also not compared. 130 p.saveLogin = true; 131 132 return p; 133 } 134 getSampleIkev2ProfileWithIkeTunConnParams(String key)135 private VpnProfile getSampleIkev2ProfileWithIkeTunConnParams(String key) { 136 final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */, 137 false /* excludesLocalRoutes */, true /* requiresPlatformValidation */, 138 new IkeTunnelConnectionParams(IKE_PARAMS_V4, CHILD_PARAMS), 139 true /* mAutomaticNattKeepaliveTimerEnabled */, 140 true /* automaticIpVersionSelectionEnabled */); 141 142 p.name = "foo"; 143 p.server = "bar"; 144 p.dnsServers = "8.8.8.8"; 145 p.searchDomains = ""; 146 p.routes = "0.0.0.0/0"; 147 p.mppe = false; 148 p.proxy = null; 149 p.setAllowedAlgorithms( 150 Arrays.asList( 151 IpSecAlgorithm.AUTH_CRYPT_AES_GCM, 152 IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305, 153 IpSecAlgorithm.AUTH_HMAC_SHA512, 154 IpSecAlgorithm.CRYPT_AES_CBC)); 155 p.isBypassable = true; 156 p.isMetered = true; 157 p.maxMtu = 1350; 158 p.areAuthParamsInline = true; 159 160 // Not saved, but also not compared. 161 p.saveLogin = true; 162 163 return p; 164 } 165 166 @Test testEquals()167 public void testEquals() { 168 assertEquals( 169 getSampleIkev2Profile(DUMMY_PROFILE_KEY), getSampleIkev2Profile(DUMMY_PROFILE_KEY)); 170 171 final VpnProfile modified = getSampleIkev2Profile(DUMMY_PROFILE_KEY); 172 modified.maxMtu--; 173 assertNotEquals(getSampleIkev2Profile(DUMMY_PROFILE_KEY), modified); 174 } 175 176 @Test testParcelUnparcel()177 public void testParcelUnparcel() { 178 if (isAtLeastU()) { 179 // automaticNattKeepaliveTimerEnabled, automaticIpVersionSelectionEnabled added in U. 180 assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 28); 181 assertParcelSane(getSampleIkev2ProfileWithIkeTunConnParams(DUMMY_PROFILE_KEY), 28); 182 } else if (isAtLeastT()) { 183 // excludeLocalRoutes, requiresPlatformValidation were added in T. 184 assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 26); 185 assertParcelSane(getSampleIkev2ProfileWithIkeTunConnParams(DUMMY_PROFILE_KEY), 26); 186 } else { 187 assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23); 188 } 189 } 190 191 @Test testEncodeDecodeWithIkeTunConnParams()192 public void testEncodeDecodeWithIkeTunConnParams() { 193 final VpnProfile profile = getSampleIkev2ProfileWithIkeTunConnParams(DUMMY_PROFILE_KEY); 194 final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode()); 195 assertEquals(profile, decoded); 196 } 197 198 @Test testEncodeDecode()199 public void testEncodeDecode() { 200 final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY); 201 final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode()); 202 assertEquals(profile, decoded); 203 } 204 205 @Test testEncodeDecodeTooManyValues()206 public void testEncodeDecodeTooManyValues() { 207 final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY); 208 final byte[] tooManyValues = 209 (new String(profile.encode()) + VpnProfile.VALUE_DELIMITER + "invalid").getBytes(); 210 211 assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooManyValues)); 212 } 213 getEncodedDecodedIkev2ProfileMissingValues(int... missingIndices)214 private String getEncodedDecodedIkev2ProfileMissingValues(int... missingIndices) { 215 // Sort to ensure when we remove, we can do it from greatest first. 216 Arrays.sort(missingIndices); 217 218 final String encoded = new String(getSampleIkev2Profile(DUMMY_PROFILE_KEY).encode()); 219 final List<String> parts = 220 new ArrayList<>(Arrays.asList(encoded.split(VpnProfile.VALUE_DELIMITER))); 221 222 // Remove from back first to ensure indexing is consistent. 223 for (int i = missingIndices.length - 1; i >= 0; i--) { 224 parts.remove(missingIndices[i]); 225 } 226 227 return String.join(VpnProfile.VALUE_DELIMITER, parts.toArray(new String[0])); 228 } 229 230 @Test testEncodeDecodeInvalidNumberOfValues()231 public void testEncodeDecodeInvalidNumberOfValues() { 232 final String tooFewValues = 233 getEncodedDecodedIkev2ProfileMissingValues( 234 ENCODED_INDEX_AUTH_PARAMS_INLINE, 235 ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS, 236 ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE, 237 ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION, 238 ENCODED_INDEX_IKE_TUN_CONN_PARAMS, 239 ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED, 240 ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED 241 /* missingIndices */); 242 243 assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes())); 244 } 245 getEncodedDecodedIkev2ProfileWithtooFewValues()246 private String getEncodedDecodedIkev2ProfileWithtooFewValues() { 247 return getEncodedDecodedIkev2ProfileMissingValues( 248 ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS, 249 ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE, 250 ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION, 251 ENCODED_INDEX_IKE_TUN_CONN_PARAMS, 252 ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED, 253 ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED /* missingIndices */); 254 } 255 256 @Test testEncodeDecodeMissingIsRestrictedToTestNetworks()257 public void testEncodeDecodeMissingIsRestrictedToTestNetworks() { 258 final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues(); 259 260 // Verify decoding without isRestrictedToTestNetworks defaults to false 261 final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()); 262 assertFalse(decoded.isRestrictedToTestNetworks); 263 } 264 265 @Test testEncodeDecodeMissingExcludeLocalRoutes()266 public void testEncodeDecodeMissingExcludeLocalRoutes() { 267 final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues(); 268 269 // Verify decoding without excludeLocalRoutes defaults to false 270 final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()); 271 assertFalse(decoded.excludeLocalRoutes); 272 } 273 274 @Test testEncodeDecodeMissingRequiresValidation()275 public void testEncodeDecodeMissingRequiresValidation() { 276 final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues(); 277 278 // Verify decoding without requiresValidation defaults to false 279 final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()); 280 assertFalse(decoded.requiresInternetValidation); 281 } 282 283 @Test testEncodeDecodeMissingAutomaticNattKeepaliveTimerEnabled()284 public void testEncodeDecodeMissingAutomaticNattKeepaliveTimerEnabled() { 285 final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues(); 286 287 // Verify decoding without automaticNattKeepaliveTimerEnabled defaults to false 288 final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()); 289 assertFalse(decoded.automaticNattKeepaliveTimerEnabled); 290 } 291 292 @Test testEncodeDecodeMissingAutomaticIpVersionSelectionEnabled()293 public void testEncodeDecodeMissingAutomaticIpVersionSelectionEnabled() { 294 final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues(); 295 296 // Verify decoding without automaticIpVersionSelectionEnabled defaults to false 297 final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()); 298 assertFalse(decoded.automaticIpVersionSelectionEnabled); 299 } 300 301 @Test testEncodeDecodeLoginsNotSaved()302 public void testEncodeDecodeLoginsNotSaved() { 303 final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY); 304 profile.saveLogin = false; 305 306 final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode()); 307 assertNotEquals(profile, decoded); 308 309 // Add the username/password back, everything else must be equal. 310 decoded.username = profile.username; 311 decoded.password = profile.password; 312 assertEquals(profile, decoded); 313 } 314 } 315