Merge "Add NetworkSecurityConfigProvider" am: d1c469e876
am: 8c89f4d28c
* commit '8c89f4d28c927ffe81c6e46159d0e5d3a0dd2986':
Add NetworkSecurityConfigProvider
This commit is contained in:
@@ -30,6 +30,9 @@ import javax.net.ssl.X509TrustManager;
|
||||
* @hide
|
||||
*/
|
||||
public final class ApplicationConfig {
|
||||
private static ApplicationConfig sInstance;
|
||||
private static Object sLock = new Object();
|
||||
|
||||
private Set<Pair<Domain, NetworkSecurityConfig>> mConfigs;
|
||||
private NetworkSecurityConfig mDefaultConfig;
|
||||
private X509TrustManager mTrustManager;
|
||||
@@ -129,4 +132,16 @@ public final class ApplicationConfig {
|
||||
mInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setDefaultInstance(ApplicationConfig config) {
|
||||
synchronized (sLock) {
|
||||
sInstance = config;
|
||||
}
|
||||
}
|
||||
|
||||
public static ApplicationConfig getDefaultInstance() {
|
||||
synchronized (sLock) {
|
||||
return sInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 android.security.net.config;
|
||||
|
||||
import android.util.ArraySet;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@link CertificateSource} which provides certificates from trusted certificate entries of a
|
||||
* {@link KeyStore}.
|
||||
*/
|
||||
class KeyStoreCertificateSource implements CertificateSource {
|
||||
private final Object mLock = new Object();
|
||||
private final KeyStore mKeyStore;
|
||||
private Set<X509Certificate> mCertificates;
|
||||
|
||||
public KeyStoreCertificateSource(KeyStore ks) {
|
||||
mKeyStore = ks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<X509Certificate> getCertificates() {
|
||||
synchronized (mLock) {
|
||||
if (mCertificates != null) {
|
||||
return mCertificates;
|
||||
}
|
||||
try {
|
||||
Set<X509Certificate> certificates = new ArraySet<>(mKeyStore.size());
|
||||
for (Enumeration<String> en = mKeyStore.aliases(); en.hasMoreElements();) {
|
||||
String alias = en.nextElement();
|
||||
if (!mKeyStore.isCertificateEntry(alias)) {
|
||||
continue;
|
||||
}
|
||||
X509Certificate cert = (X509Certificate) mKeyStore.getCertificate(alias);
|
||||
if (cert != null) {
|
||||
certificates.add(cert);
|
||||
}
|
||||
}
|
||||
mCertificates = certificates;
|
||||
return mCertificates;
|
||||
} catch (KeyStoreException e) {
|
||||
throw new RuntimeException("Failed to load certificates from KeyStore", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 android.security.net.config;
|
||||
|
||||
import android.util.Pair;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@link ConfigSource} with a single default config based on a {@link KeyStore} and no per domain
|
||||
* configs.
|
||||
*/
|
||||
class KeyStoreConfigSource implements ConfigSource {
|
||||
private final NetworkSecurityConfig mConfig;
|
||||
|
||||
public KeyStoreConfigSource(KeyStore ks) {
|
||||
mConfig = new NetworkSecurityConfig.Builder()
|
||||
.addCertificatesEntryRef(
|
||||
// Use the KeyStore and do not override pins (of which there are none).
|
||||
new CertificatesEntryRef(new KeyStoreCertificateSource(ks), false))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Pair<Domain, NetworkSecurityConfig>> getPerDomainConfigs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkSecurityConfig getDefaultConfig() {
|
||||
return mConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 android.security.net.config;
|
||||
|
||||
import java.security.Provider;
|
||||
|
||||
/** @hide */
|
||||
public final class NetworkSecurityConfigProvider extends Provider {
|
||||
|
||||
private static String PREFIX =
|
||||
NetworkSecurityConfigProvider.class.getPackage().getName() + ".";
|
||||
|
||||
public NetworkSecurityConfigProvider() {
|
||||
// TODO: More clever name than this
|
||||
super("AndroidNSSP", 1.0, "Android Network Security Policy Provider");
|
||||
put("TrustManagerFactory.PKIX", PREFIX + "RootTrustManagerFactorySpi");
|
||||
put("Alg.Alias.TrustManagerFactory.X509", "PKIX");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 android.security.net.config;
|
||||
|
||||
import android.util.Pair;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.util.Set;
|
||||
import javax.net.ssl.ManagerFactoryParameters;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.TrustManagerFactorySpi;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
/** @hide */
|
||||
public class RootTrustManagerFactorySpi extends TrustManagerFactorySpi {
|
||||
private ApplicationConfig mApplicationConfig;
|
||||
private NetworkSecurityConfig mConfig;
|
||||
|
||||
@Override
|
||||
public void engineInit(ManagerFactoryParameters spec)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
if (!(spec instanceof ApplicationConfigParameters)) {
|
||||
throw new InvalidAlgorithmParameterException("Unsupported spec: " + spec + ". Only "
|
||||
+ ApplicationConfigParameters.class.getName() + " supported");
|
||||
|
||||
}
|
||||
mApplicationConfig = ((ApplicationConfigParameters) spec).config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void engineInit(KeyStore ks) throws KeyStoreException {
|
||||
if (ks != null) {
|
||||
mApplicationConfig = new ApplicationConfig(new KeyStoreConfigSource(ks));
|
||||
} else {
|
||||
mApplicationConfig = ApplicationConfig.getDefaultInstance();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrustManager[] engineGetTrustManagers() {
|
||||
if (mApplicationConfig == null) {
|
||||
throw new IllegalStateException("TrustManagerFactory not initialized");
|
||||
}
|
||||
return new TrustManager[] { mApplicationConfig.getTrustManager() };
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static final class ApplicationConfigParameters implements ManagerFactoryParameters {
|
||||
public final ApplicationConfig config;
|
||||
public ApplicationConfigParameters(ApplicationConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
@@ -69,8 +70,11 @@ public final class TestUtils extends Assert {
|
||||
|
||||
public static SSLContext getSSLContext(ConfigSource source) throws Exception {
|
||||
ApplicationConfig config = new ApplicationConfig(source);
|
||||
TrustManagerFactory tmf =
|
||||
TrustManagerFactory.getInstance("PKIX", new NetworkSecurityConfigProvider());
|
||||
tmf.init(new RootTrustManagerFactorySpi.ApplicationConfigParameters(config));
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, new TrustManager[] {config.getTrustManager()}, null);
|
||||
context.init(null, tmf.getTrustManagers(), null);
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@ import android.util.Pair;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.URL;
|
||||
import java.security.KeyStore;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
@@ -31,6 +35,7 @@ import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
public class XmlConfigTests extends AndroidTestCase {
|
||||
|
||||
@@ -375,4 +380,26 @@ public class XmlConfigTests extends AndroidTestCase {
|
||||
public void testBadConfig5() throws Exception {
|
||||
testBadConfig(R.xml.bad_config4);
|
||||
}
|
||||
|
||||
public void testTrustManagerKeystore() throws Exception {
|
||||
XmlConfigSource source = new XmlConfigSource(getContext(), R.xml.bad_pin, true);
|
||||
ApplicationConfig appConfig = new ApplicationConfig(source);
|
||||
Provider provider = new NetworkSecurityConfigProvider();
|
||||
TrustManagerFactory tmf =
|
||||
TrustManagerFactory.getInstance("PKIX", provider);
|
||||
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keystore.load(null);
|
||||
int i = 0;
|
||||
for (X509Certificate cert : SystemCertificateSource.getInstance().getCertificates()) {
|
||||
keystore.setEntry(String.valueOf(i),
|
||||
new KeyStore.TrustedCertificateEntry(cert),
|
||||
null);
|
||||
i++;
|
||||
}
|
||||
tmf.init(keystore);
|
||||
TrustManager[] tms = tmf.getTrustManagers();
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, tms, null);
|
||||
TestUtils.assertConnectionSucceeds(context, "android.com" , 443);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user