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