diff --git a/tests/app/src/com/android/settings/vpn2/CertInstallerHelper.java b/tests/app/src/com/android/settings/vpn2/CertInstallerHelper.java deleted file mode 100644 index fa2638ff995..00000000000 --- a/tests/app/src/com/android/settings/vpn2/CertInstallerHelper.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.vpn2; - -import android.os.Environment; -import android.security.Credentials; -import android.security.KeyStore; -import android.util.Log; - -import com.android.internal.net.VpnProfile; -import com.android.org.bouncycastle.asn1.ASN1InputStream; -import com.android.org.bouncycastle.asn1.ASN1Sequence; -import com.android.org.bouncycastle.asn1.DEROctetString; -import com.android.org.bouncycastle.asn1.x509.BasicConstraints; - -import junit.framework.Assert; - -import libcore.io.Streams; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.KeyStore.PasswordProtection; -import java.security.KeyStore.PrivateKeyEntry; -import java.security.PrivateKey; -import java.security.UnrecoverableEntryException; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; - -/** - * Certificate installer helper to extract information from a provided file - * and install certificates to keystore. - */ -public class CertInstallerHelper { - private static final String TAG = "CertInstallerHelper"; - /* Define a password to unlock keystore after it is reset */ - private static final String CERT_STORE_PASSWORD = "password"; - private final int mUid = KeyStore.UID_SELF; - private PrivateKey mUserKey; // private key - private X509Certificate mUserCert; // user certificate - private List mCaCerts = new ArrayList(); - private KeyStore mKeyStore = KeyStore.getInstance(); - - /** - * Unlock keystore and set password - */ - public CertInstallerHelper() { - mKeyStore.reset(); - mKeyStore.onUserPasswordChanged(CERT_STORE_PASSWORD); - } - - private void extractCertificate(String certFile, String password) { - InputStream in = null; - final byte[] raw; - java.security.KeyStore keystore = null; - try { - // Read .p12 file from SDCARD and extract with password - in = new FileInputStream(new File( - Environment.getExternalStorageDirectory(), certFile)); - raw = Streams.readFully(in); - - keystore = java.security.KeyStore.getInstance("PKCS12"); - PasswordProtection passwordProtection = new PasswordProtection(password.toCharArray()); - keystore.load(new ByteArrayInputStream(raw), passwordProtection.getPassword()); - - // Install certificates and private keys - Enumeration aliases = keystore.aliases(); - if (!aliases.hasMoreElements()) { - Assert.fail("key store failed to put in keychain"); - } - ArrayList aliasesList = Collections.list(aliases); - // The keystore is initialized for each test case, there will - // be only one alias in the keystore - Assert.assertEquals(1, aliasesList.size()); - String alias = aliasesList.get(0); - java.security.KeyStore.Entry entry = keystore.getEntry(alias, passwordProtection); - Log.d(TAG, "extracted alias = " + alias + ", entry=" + entry.getClass()); - - if (entry instanceof PrivateKeyEntry) { - Assert.assertTrue(installFrom((PrivateKeyEntry) entry)); - } - } catch (IOException e) { - Assert.fail("Failed to read certficate: " + e); - } catch (KeyStoreException e) { - Log.e(TAG, "failed to extract certificate" + e); - } catch (NoSuchAlgorithmException e) { - Log.e(TAG, "failed to extract certificate" + e); - } catch (CertificateException e) { - Log.e(TAG, "failed to extract certificate" + e); - } catch (UnrecoverableEntryException e) { - Log.e(TAG, "failed to extract certificate" + e); - } - finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - Log.e(TAG, "close FileInputStream error: " + e); - } - } - } - } - - /** - * Extract private keys, user certificates and ca certificates - */ - private synchronized boolean installFrom(PrivateKeyEntry entry) { - mUserKey = entry.getPrivateKey(); - mUserCert = (X509Certificate) entry.getCertificate(); - - Certificate[] certs = entry.getCertificateChain(); - Log.d(TAG, "# certs extracted = " + certs.length); - mCaCerts = new ArrayList(certs.length); - for (Certificate c : certs) { - X509Certificate cert = (X509Certificate) c; - if (isCa(cert)) { - mCaCerts.add(cert); - } - } - Log.d(TAG, "# ca certs extracted = " + mCaCerts.size()); - return true; - } - - private boolean isCa(X509Certificate cert) { - try { - byte[] asn1EncodedBytes = cert.getExtensionValue("2.5.29.19"); - if (asn1EncodedBytes == null) { - return false; - } - DEROctetString derOctetString = (DEROctetString) - new ASN1InputStream(asn1EncodedBytes).readObject(); - byte[] octets = derOctetString.getOctets(); - ASN1Sequence sequence = (ASN1Sequence) - new ASN1InputStream(octets).readObject(); - return BasicConstraints.getInstance(sequence).isCA(); - } catch (IOException e) { - return false; - } - } - - /** - * Extract certificate from the given file, and install it to keystore - * @param name certificate name - * @param certFile .p12 file which includes certificates - * @param password password to extract the .p12 file - */ - public void installCertificate(VpnProfile profile, String certFile, String password) { - // extract private keys, certificates from the provided file - extractCertificate(certFile, password); - // install certificate to the keystore - int flags = KeyStore.FLAG_ENCRYPTED; - try { - if (mUserKey != null) { - Log.v(TAG, "has private key"); - String key = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert; - byte[] value = mUserKey.getEncoded(); - - if (!mKeyStore.importKey(key, value, mUid, flags)) { - Log.e(TAG, "Failed to install " + key + " as user " + mUid); - return; - } - Log.v(TAG, "install " + key + " as user " + mUid + " is successful"); - } - - if (mUserCert != null) { - String certName = Credentials.USER_CERTIFICATE + profile.ipsecUserCert; - byte[] certData = Credentials.convertToPem(mUserCert); - - if (!mKeyStore.put(certName, certData, mUid, flags)) { - Log.e(TAG, "Failed to install " + certName + " as user " + mUid); - return; - } - Log.v(TAG, "install " + certName + " as user" + mUid + " is successful."); - } - - if (!mCaCerts.isEmpty()) { - String caListName = Credentials.CA_CERTIFICATE + profile.ipsecCaCert; - X509Certificate[] caCerts = mCaCerts.toArray(new X509Certificate[mCaCerts.size()]); - byte[] caListData = Credentials.convertToPem(caCerts); - - if (!mKeyStore.put(caListName, caListData, mUid, flags)) { - Log.e(TAG, "Failed to install " + caListName + " as user " + mUid); - return; - } - Log.v(TAG, " install " + caListName + " as user " + mUid + " is successful"); - } - } catch (CertificateEncodingException e) { - Log.e(TAG, "Exception while convert certificates to pem " + e); - throw new AssertionError(e); - } catch (IOException e) { - Log.e(TAG, "IOException while convert to pem: " + e); - } - } - - public int getUid() { - return mUid; - } -} diff --git a/tests/app/src/com/android/settings/vpn2/VpnInfo.java b/tests/app/src/com/android/settings/vpn2/VpnInfo.java deleted file mode 100644 index ab7fb0f3d07..00000000000 --- a/tests/app/src/com/android/settings/vpn2/VpnInfo.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.vpn2; - -import com.android.internal.net.VpnProfile; - -/** - * Wrapper for VPN Profile and associated certificate files - */ -public class VpnInfo { - // VPN Profile - private VpnProfile mVpnProfile; - // Certificate file in PC12 format for user certificates and private keys - private String mCertificateFile = null; - // Password to extract certificates from the file - private String mPassword = null; - - public VpnInfo(VpnProfile vpnProfile, String certFile, String password) { - mVpnProfile = vpnProfile; - mCertificateFile = certFile; - mPassword = password; - } - - public VpnInfo(VpnProfile vpnProfile) { - mVpnProfile = vpnProfile; - } - - public void setVpnProfile(VpnProfile vpnProfile) { - mVpnProfile = vpnProfile; - } - - public void setCertificateFile(String certFile) { - mCertificateFile = certFile; - } - - public void setPassword(String password) { - mPassword = password; - } - - public VpnProfile getVpnProfile() { - return mVpnProfile; - } - - public String getCertificateFile() { - return mCertificateFile; - } - - public String getPassword() { - return mPassword; - } -} diff --git a/tests/app/src/com/android/settings/vpn2/VpnProfileParser.java b/tests/app/src/com/android/settings/vpn2/VpnProfileParser.java deleted file mode 100644 index 51c2550eb1d..00000000000 --- a/tests/app/src/com/android/settings/vpn2/VpnProfileParser.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.vpn2; - -import android.util.Log; - -import com.android.internal.net.VpnProfile; - -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -/** - * Parse VPN profiles from an XML file - */ -public class VpnProfileParser { - private final static String TAG = "VpnProfileParser"; - private static Map mVpnPool = new HashMap(); - - static DefaultHandler mHandler = new DefaultHandler() { - boolean name; - boolean type; - boolean server; - boolean username; - boolean password; - boolean dnsServers; - boolean searchDomains; - boolean routes; - boolean mppe; - boolean l2tpSecret; - boolean ipsecIdentifier; - boolean ipsecSecret; - boolean ipsecUserCert; - boolean ipsecCaCert; - boolean ipsecServerCert; - boolean certFile; - boolean certFilePassword; - VpnProfile profile = null; - VpnInfo vpnInfo = null; - - - @Override - public void startElement(String uri, String localName, String tagName, - Attributes attributes) throws SAXException { - if (tagName.equalsIgnoreCase("vpn")) { - //create a new VPN profile - profile = new VpnProfile(Long.toHexString(System.currentTimeMillis())); - vpnInfo = new VpnInfo(profile); - } - if (tagName.equalsIgnoreCase("name")) { - name = true; - } - if (tagName.equalsIgnoreCase("type")) { - type = true; - } - if (tagName.equalsIgnoreCase("server")) { - server = true; - } - if (tagName.equalsIgnoreCase("username")) { - username = true; - } - if (tagName.equalsIgnoreCase("password")) { - password = true; - } - if (tagName.equalsIgnoreCase("dnsServers")) { - dnsServers = true; - } - if (tagName.equalsIgnoreCase("searchDomains")) { - searchDomains = true; - } - if (tagName.equalsIgnoreCase("mppe")) { - mppe = true; - } - if (tagName.equalsIgnoreCase("l2tpSecret")) { - l2tpSecret = true; - } - if (tagName.equalsIgnoreCase("ipsecIdentifier")) { - ipsecIdentifier = true; - } - if (tagName.equalsIgnoreCase("ipsecSecret")) { - ipsecSecret = true; - } - if (tagName.equalsIgnoreCase("ipsecUserCert")) { - ipsecUserCert = true; - } - if (tagName.equalsIgnoreCase("ipsecCaCert")) { - ipsecCaCert = true; - } - if (tagName.equalsIgnoreCase("ipsecServerCert")) { - ipsecServerCert = true; - } - if (tagName.equalsIgnoreCase("routes")) { - routes = true; - } - if (tagName.equalsIgnoreCase("cert-file")) { - certFile = true; - } - if (tagName.equalsIgnoreCase("cert-file-password")) { - certFilePassword = true; - } - } - - @Override - public void endElement(String uri, String localName, String tagName) throws SAXException { - if (tagName.equalsIgnoreCase("vpn")) { - mVpnPool.put(profile.type, vpnInfo); - } - } - - @Override - public void characters(char ch[], int start, int length) throws SAXException { - String strValue = new String(ch, start, length); - if (name) { - profile.name = strValue; - name = false; - } - if (type) { - int t = getVpnProfileType(strValue); - if (t < 0) { - throw new SAXException("not a valid VPN type"); - } else { - profile.type = t; - } - type = false; - } - if (server) { - profile.server = strValue; - server = false; - } - if (username) { - profile.username = strValue; - username = false; - } - if (password) { - profile.password = strValue; - password = false; - } - if (dnsServers) { - profile.dnsServers = strValue; - dnsServers = false; - } - if (searchDomains) { - profile.searchDomains = strValue; - searchDomains = false; - } - if (mppe) { - profile.mppe = Boolean.valueOf(strValue); - mppe = false; - } - if (l2tpSecret) { - profile.l2tpSecret = strValue; - l2tpSecret = false; - } - if (ipsecIdentifier) { - profile.ipsecIdentifier = strValue; - ipsecIdentifier = false; - } - if (ipsecSecret) { - profile.ipsecSecret = strValue; - ipsecSecret = false; - } - if (ipsecUserCert) { - profile.ipsecUserCert = strValue; - ipsecUserCert = false; - } - if (ipsecCaCert) { - profile.ipsecCaCert = strValue; - ipsecCaCert = false; - } - if (ipsecServerCert) { - profile.ipsecServerCert = strValue; - ipsecServerCert = false; - } - if (routes) { - profile.routes = strValue; - routes = false; - } - if (certFile) { - vpnInfo.setCertificateFile(strValue); - certFile = false; - } - if (certFilePassword) { - vpnInfo.setPassword(strValue); - certFilePassword = false; - } - } - - private int getVpnProfileType(String type) { - if (type.equalsIgnoreCase("TYPE_PPTP")) { - return VpnProfile.TYPE_PPTP; - } else if (type.equalsIgnoreCase("TYPE_L2TP_IPSEC_PSK")) { - return VpnProfile.TYPE_L2TP_IPSEC_PSK; - } else if (type.equalsIgnoreCase("TYPE_L2TP_IPSEC_RSA")) { - return VpnProfile.TYPE_L2TP_IPSEC_RSA; - } else if (type.equalsIgnoreCase("TYPE_IPSEC_XAUTH_PSK")) { - return VpnProfile.TYPE_IPSEC_XAUTH_PSK; - } else if (type.equalsIgnoreCase("TYPE_IPSEC_XAUTH_RSA")) { - return VpnProfile.TYPE_IPSEC_XAUTH_RSA; - } else if (type.equalsIgnoreCase("TYPE_IPSEC_HYBRID_RSA")) { - return VpnProfile.TYPE_IPSEC_HYBRID_RSA; - } else { - Log.v(TAG, "Invalid VPN type: " + type); - return -1; - } - } - }; - - public static Map parse(InputStream in) { - try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - SAXParser saxParser = factory.newSAXParser(); - saxParser.parse(in, mHandler); - } catch (SAXException e) { - Log.e(TAG, "Parse vpn profile exception: " + e.toString()); - } catch (IOException e) { - Log.e(TAG, "Parse vpn profile exception: " + e.toString()); - } catch (ParserConfigurationException e) { - Log.e(TAG, "Parse vpn profile exception: " + e.toString()); - } finally { - return mVpnPool; - } - } -} diff --git a/tests/app/src/com/android/settings/vpn2/VpnTests.java b/tests/app/src/com/android/settings/vpn2/VpnTests.java deleted file mode 100644 index 11e82655c69..00000000000 --- a/tests/app/src/com/android/settings/vpn2/VpnTests.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.vpn2; - -import android.content.Context; -import android.net.IConnectivityManager; -import android.os.Bundle; -import android.os.Environment; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.UserHandle; -import android.security.Credentials; -import android.security.KeyStore; -import android.security.NetworkSecurityPolicy; -import android.test.InstrumentationTestCase; -import android.test.InstrumentationTestRunner; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; - -import com.android.internal.net.LegacyVpnInfo; -import com.android.internal.net.VpnConfig; -import com.android.internal.net.VpnProfile; - -import java.net.HttpURLConnection; -import java.net.URL; -import junit.framework.Assert; - -import libcore.io.Streams; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.UnknownHostException; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; - -/** - * Legacy VPN connection tests - * - * To run the test, use command: - * adb shell am instrument -e class com.android.settings.vpn2.VpnTests -e profile foo.xml - * -w com.android.settings.tests/android.test.InstrumentationTestRunner - * - * VPN profiles are saved in an xml file and will be loaded through {@link VpnProfileParser}. - * Push the profile (foo.xml) to the external storage, e.g adb push foo.xml /sdcard/ before running - * the above command. - * - * A typical profile looks like the following: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * VPN types include: TYPE_PPTP, TYPE_L2TP_IPSEC_PSK, TYPE_L2TP_IPSEC_RSA, - * TYPE_IPSEC_XAUTH_PSK, TYPE_IPSEC_XAUTH_RSA, TYPE_IPSEC_HYBRID_RSA - */ -public class VpnTests extends InstrumentationTestCase { - private static final String TAG = "VpnTests"; - /* Maximum time to wait for VPN connection */ - private static final long MAX_CONNECTION_TIME = 5 * 60 * 1000; - private static final long VPN_STAY_TIME = 60 * 1000; - private static final int MAX_DISCONNECTION_TRIES = 3; - private static final String EXTERNAL_SERVER = - "http://ip2country.sourceforge.net/ip2c.php?format=JSON"; - private static final String VPN_INTERFACE = "ppp0"; - private final IConnectivityManager mService = IConnectivityManager.Stub - .asInterface(ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); - private Map mVpnInfoPool = null; - private Context mContext; - private CertInstallerHelper mCertHelper = null; - private KeyStore mKeyStore = KeyStore.getInstance(); - private String mPreviousIpAddress = null; - private boolean DEBUG = false; - - @Override - protected void setUp() throws Exception { - super.setUp(); - InputStream in = null; - InstrumentationTestRunner mRunner = (InstrumentationTestRunner)getInstrumentation(); - mContext = mRunner.getContext(); - Bundle arguments = mRunner.getArguments(); - String PROFILE_NAME = arguments.getString("profile"); - Assert.assertNotNull("Push profile to external storage and load with" - + "'-e profile '", PROFILE_NAME); - File profileFile = new File(Environment.getExternalStorageDirectory(), PROFILE_NAME); - in = new FileInputStream(profileFile); - mVpnInfoPool = VpnProfileParser.parse(in); - Assert.assertNotNull("no VPN profiles are parsed", mVpnInfoPool); - if (DEBUG) { - Log.v(TAG, "print out the vpn profiles"); - for (Map.Entry profileEntrySet: mVpnInfoPool.entrySet()) { - VpnInfo vpnInfo = profileEntrySet.getValue(); - printVpnProfile(vpnInfo.getVpnProfile()); - if (vpnInfo.getCertificateFile() != null) { - Log.d(TAG, "certificate file for this vpn is " + vpnInfo.getCertificateFile()); - } - if (vpnInfo.getPassword() != null) { - Log.d(TAG, "password for the certificate file is: " + vpnInfo.getPassword()); - } - } - } - // disconnect existing vpn if there is any - LegacyVpnInfo oldVpn = mService.getLegacyVpnInfo(UserHandle.myUserId()); - if (oldVpn != null) { - Log.v(TAG, "disconnect legacy VPN"); - disconnect(); - // wait till the legacy VPN is disconnected. - int tries = 0; - while (tries < MAX_DISCONNECTION_TRIES && - mService.getLegacyVpnInfo(UserHandle.myUserId()) != null) { - tries++; - Thread.sleep(10 * 1000); - Log.v(TAG, "Wait for legacy VPN to be disconnected."); - } - Assert.assertNull("Failed to disconect VPN", - mService.getLegacyVpnInfo(UserHandle.myUserId())); - // wait for 30 seconds after the previous VPN is disconnected. - sleep(30 * 1000); - } - // Create CertInstallerHelper to initialize the keystore - mCertHelper = new CertInstallerHelper(); - } - - @Override - protected void tearDown() throws Exception { - sleep(VPN_STAY_TIME); - super.tearDown(); - } - - private void printVpnProfile(VpnProfile profile) { - Log.v(TAG, "profile: "); - Log.v(TAG, "key: " + profile.key); - Log.v(TAG, "name: " + profile.name); - Log.v(TAG, "type: " + profile.type); - Log.v(TAG, "server: " + profile.server); - Log.v(TAG, "username: " + profile.username); - Log.v(TAG, "password: " + profile.password); - Log.v(TAG, "dnsServers: " + profile.dnsServers); - Log.v(TAG, "searchDomains: " + profile.searchDomains); - Log.v(TAG, "routes: " + profile.routes); - Log.v(TAG, "mppe: " + profile.mppe); - Log.v(TAG, "l2tpSecret: " + profile.l2tpSecret); - Log.v(TAG, "ipsecIdentifier: " + profile.ipsecIdentifier); - Log.v(TAG, "ipsecSecret: " + profile.ipsecSecret); - Log.v(TAG, "ipsecUserCert: " + profile.ipsecUserCert); - Log.v(TAG, "ipsecCaCert: " + profile.ipsecCaCert); - Log.v(TAG, "ipsecServerCert: " + profile.ipsecServerCert); - } - - private void printKeyStore(VpnProfile profile) { - // print out the information from keystore - String privateKey = ""; - String userCert = ""; - String caCert = ""; - String serverCert = ""; - if (!profile.ipsecUserCert.isEmpty()) { - privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert; - byte[] value = mKeyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert); - userCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); - } - if (!profile.ipsecCaCert.isEmpty()) { - byte[] value = mKeyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert); - caCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); - } - if (!profile.ipsecServerCert.isEmpty()) { - byte[] value = mKeyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert); - serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); - } - Log.v(TAG, "privateKey: \n" + ((privateKey == null) ? "" : privateKey)); - Log.v(TAG, "userCert: \n" + ((userCert == null) ? "" : userCert)); - Log.v(TAG, "caCert: \n" + ((caCert == null) ? "" : caCert)); - Log.v(TAG, "serverCert: \n" + ((serverCert == null) ? "" : serverCert)); - } - - /** - * Connect legacy VPN - */ - private void connect(VpnProfile profile) throws Exception { - try { - mService.startLegacyVpn(profile); - } catch (IllegalStateException e) { - fail(String.format("start legacy vpn: %s failed: %s", profile.name, e.toString())); - } - } - - /** - * Disconnect legacy VPN - */ - private void disconnect() throws Exception { - try { - mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, UserHandle.myUserId()); - } catch (RemoteException e) { - Log.e(TAG, String.format("disconnect VPN exception: %s", e.toString())); - } - } - - /** - * Get external IP address - */ - private String getIpAddress() { - String ip = null; - HttpURLConnection urlConnection = null; - // TODO: Rewrite this test to use an HTTPS URL. - // Because this test uses cleartext HTTP, the network security policy of this app needs to - // be temporarily relaxed to permit such traffic. - NetworkSecurityPolicy networkSecurityPolicy = NetworkSecurityPolicy.getInstance(); - boolean cleartextTrafficPermittedBeforeTest = - networkSecurityPolicy.isCleartextTrafficPermitted(); - networkSecurityPolicy.setCleartextTrafficPermitted(true); - try { - URL url = new URL(EXTERNAL_SERVER); - urlConnection = (HttpURLConnection) url.openConnection(); - Log.i(TAG, "Response from httpget: " + urlConnection.getResponseCode()); - - InputStream is = urlConnection.getInputStream(); - String response; - try { - response = new String(Streams.readFully(is), StandardCharsets.UTF_8); - } finally { - is.close(); - } - - JSONObject json_data = new JSONObject(response); - ip = json_data.getString("ip"); - Log.v(TAG, "json_data: " + ip); - } catch (IllegalArgumentException e) { - Log.e(TAG, "exception while getting external IP: " + e.toString()); - } catch (IOException e) { - Log.e(TAG, "IOException while getting IP: " + e.toString()); - } catch (JSONException e) { - Log.e(TAG, "exception while creating JSONObject: " + e.toString()); - } finally { - networkSecurityPolicy.setCleartextTrafficPermitted(cleartextTrafficPermittedBeforeTest); - if (urlConnection != null) { - urlConnection.disconnect(); - } - } - return ip; - } - - /** - * Verify the vpn connection by checking the VPN state and external IP - */ - private void validateVpnConnection(VpnProfile profile) throws Exception { - validateVpnConnection(profile, false); - } - - /** - * Verify the vpn connection by checking the VPN state, external IP or ping test - */ - private void validateVpnConnection(VpnProfile profile, boolean pingTestFlag) throws Exception { - LegacyVpnInfo legacyVpnInfo = mService.getLegacyVpnInfo(UserHandle.myUserId()); - Assert.assertTrue(legacyVpnInfo != null); - - long start = System.currentTimeMillis(); - while (((System.currentTimeMillis() - start) < MAX_CONNECTION_TIME) && - (legacyVpnInfo.state != LegacyVpnInfo.STATE_CONNECTED)) { - Log.v(TAG, "vpn state: " + legacyVpnInfo.state); - sleep(10 * 1000); - legacyVpnInfo = mService.getLegacyVpnInfo(UserHandle.myUserId()); - } - - // the vpn state should be CONNECTED - Assert.assertTrue(legacyVpnInfo.state == LegacyVpnInfo.STATE_CONNECTED); - if (pingTestFlag) { - Assert.assertTrue(pingTest(profile.server)); - } else { - String curIpAddress = getIpAddress(); - // the outgoing IP address should be the same as the VPN server address - Assert.assertEquals(profile.server, curIpAddress); - } - } - - private boolean pingTest(String server) { - final long PING_TIMER = 3 * 60 * 1000; // 3 minutes - if (server == null || server.isEmpty()) { - return false; - } - long startTime = System.currentTimeMillis(); - while ((System.currentTimeMillis() - startTime) < PING_TIMER) { - try { - Log.v(TAG, "Start ping test, ping " + server); - Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + server); - int status = p.waitFor(); - if (status == 0) { - // if any of the ping test is successful, return true - return true; - } - } catch (UnknownHostException e) { - Log.e(TAG, "Ping test Fail: Unknown Host"); - } catch (IOException e) { - Log.e(TAG, "Ping test Fail: IOException"); - } catch (InterruptedException e) { - Log.e(TAG, "Ping test Fail: InterruptedException"); - } - } - // ping test timeout - return false; - } - - /** - * Install certificates from a file loaded in external stroage on the device - * @param profile vpn profile - * @param fileName certificate file name - * @param password password to extract certificate file - */ - private void installCertificatesFromFile(VpnProfile profile, String fileName, String password) - throws Exception { - if (profile == null || fileName == null || password == null) { - throw new Exception ("vpn profile, certificate file name and password can not be null"); - } - - int curUid = mContext.getUserId(); - mCertHelper.installCertificate(profile, fileName, password); - - if (DEBUG) { - printKeyStore(profile); - } - } - - private void sleep(long time) { - try { - Thread.sleep(time); - } catch (InterruptedException e) { - Log.e(TAG, "interrupted: " + e.toString()); - } - } - - /** - * Test PPTP VPN connection - */ - @LargeTest - public void testPPTPConnection() throws Exception { - mPreviousIpAddress = getIpAddress(); - VpnInfo curVpnInfo = mVpnInfoPool.get(VpnProfile.TYPE_PPTP); - VpnProfile vpnProfile = curVpnInfo.getVpnProfile(); - connect(vpnProfile); - validateVpnConnection(vpnProfile); - } - - /** - * Test L2TP/IPSec PSK VPN connection - */ - @LargeTest - public void testL2tpIpsecPskConnection() throws Exception { - mPreviousIpAddress = getIpAddress(); - VpnInfo curVpnInfo = mVpnInfoPool.get(VpnProfile.TYPE_L2TP_IPSEC_PSK); - VpnProfile vpnProfile = curVpnInfo.getVpnProfile(); - connect(vpnProfile); - validateVpnConnection(vpnProfile); - } - - /** - * Test L2TP/IPSec RSA VPN connection - */ - @LargeTest - public void testL2tpIpsecRsaConnection() throws Exception { - mPreviousIpAddress = getIpAddress(); - VpnInfo curVpnInfo = mVpnInfoPool.get(VpnProfile.TYPE_L2TP_IPSEC_RSA); - VpnProfile vpnProfile = curVpnInfo.getVpnProfile(); - if (DEBUG) { - printVpnProfile(vpnProfile); - } - String certFile = curVpnInfo.getCertificateFile(); - String password = curVpnInfo.getPassword(); - installCertificatesFromFile(vpnProfile, certFile, password); - connect(vpnProfile); - validateVpnConnection(vpnProfile); - } - - /** - * Test IPSec Xauth RSA VPN connection - */ - @LargeTest - public void testIpsecXauthRsaConnection() throws Exception { - mPreviousIpAddress = getIpAddress(); - VpnInfo curVpnInfo = mVpnInfoPool.get(VpnProfile.TYPE_IPSEC_XAUTH_RSA); - VpnProfile vpnProfile = curVpnInfo.getVpnProfile(); - if (DEBUG) { - printVpnProfile(vpnProfile); - } - String certFile = curVpnInfo.getCertificateFile(); - String password = curVpnInfo.getPassword(); - installCertificatesFromFile(vpnProfile, certFile, password); - connect(vpnProfile); - validateVpnConnection(vpnProfile); - } - - /** - * Test IPSec Xauth PSK VPN connection - */ - @LargeTest - public void testIpsecXauthPskConnection() throws Exception { - VpnInfo curVpnInfo = mVpnInfoPool.get(VpnProfile.TYPE_IPSEC_XAUTH_PSK); - VpnProfile vpnProfile = curVpnInfo.getVpnProfile(); - if (DEBUG) { - printVpnProfile(vpnProfile); - } - connect(vpnProfile); - validateVpnConnection(vpnProfile, true); - } - - /** - * Test IPSec Hybrid RSA VPN connection - */ - @LargeTest - public void testIpsecHybridRsaConnection() throws Exception { - mPreviousIpAddress = getIpAddress(); - VpnInfo curVpnInfo = mVpnInfoPool.get(VpnProfile.TYPE_IPSEC_HYBRID_RSA); - VpnProfile vpnProfile = curVpnInfo.getVpnProfile(); - if (DEBUG) { - printVpnProfile(vpnProfile); - } - connect(vpnProfile); - validateVpnConnection(vpnProfile); - } -}