diff options
author | Brian Carlstrom <bdc@google.com> | 2010-04-03 08:13:40 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-04-03 08:13:40 -0700 |
commit | c2e77ad88fc2d6244b2d9ee405052eeaaa4663fa (patch) | |
tree | 57f6803957c213eb0991e13e4fd7625b495e5c76 /luni | |
parent | 2d5415be0fe89bca6476964e0e79659e0e061188 (diff) | |
parent | ebabb91c8c87ac2be2dca70ae343130f9755047f (diff) | |
download | libcore-c2e77ad88fc2d6244b2d9ee405052eeaaa4663fa.zip libcore-c2e77ad88fc2d6244b2d9ee405052eeaaa4663fa.tar.gz libcore-c2e77ad88fc2d6244b2d9ee405052eeaaa4663fa.tar.bz2 |
Merge "New "from scratch" Junit tests for javax.net.ssl" into dalvik-dev
Diffstat (limited to 'luni')
-rw-r--r-- | luni/src/test/java/javax/net/ssl/AllTests.java | 32 | ||||
-rw-r--r-- | luni/src/test/java/javax/net/ssl/SSLContextTest.java | 361 | ||||
-rw-r--r-- | luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java | 220 | ||||
-rw-r--r-- | luni/src/test/java/javax/net/ssl/SSLSessionTest.java | 317 | ||||
-rw-r--r-- | luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java | 76 | ||||
-rw-r--r-- | luni/src/test/java/javax/net/ssl/SSLSocketTest.java | 686 | ||||
-rw-r--r-- | luni/src/test/java/tests/AllTests.java | 1 |
7 files changed, 1693 insertions, 0 deletions
diff --git a/luni/src/test/java/javax/net/ssl/AllTests.java b/luni/src/test/java/javax/net/ssl/AllTests.java new file mode 100644 index 0000000..740b788 --- /dev/null +++ b/luni/src/test/java/javax/net/ssl/AllTests.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 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 javax.net.ssl; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AllTests { + public static final Test suite() { + TestSuite suite = new TestSuite(); + suite.addTestSuite(SSLSocketFactoryTest.class); + suite.addTestSuite(SSLContextTest.class); + suite.addTestSuite(SSLSocketTest.class); + suite.addTestSuite(SSLSessionTest.class); + suite.addTestSuite(SSLSessionContextTest.class); + return suite; + } +} diff --git a/luni/src/test/java/javax/net/ssl/SSLContextTest.java b/luni/src/test/java/javax/net/ssl/SSLContextTest.java new file mode 100644 index 0000000..39a59e3 --- /dev/null +++ b/luni/src/test/java/javax/net/ssl/SSLContextTest.java @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2010 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 javax.net.ssl; + +import dalvik.annotation.KnownFailure; +import java.math.BigInteger; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.Date; +import java.util.Hashtable; +import javax.net.ServerSocketFactory; +import javax.net.SocketFactory; +import junit.framework.TestCase; +import org.bouncycastle.jce.X509Principal; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.x509.X509V3CertificateGenerator; + +public class SSLContextTest extends TestCase { + + public static final boolean IS_RI = !"Dalvik Core Library".equals(System.getProperty("java.specification.name")); + public static final String PROVIDER_NAME = (IS_RI) ? "SunJSSE" : "HarmonyJSSE"; + + public void test_SSLContext_getInstance() throws Exception { + try { + SSLContext.getInstance(null); + fail(); + } catch (NullPointerException e) { + } + assertNotNull(SSLContext.getInstance("SSL")); + assertNotNull(SSLContext.getInstance("SSLv3")); + assertNotNull(SSLContext.getInstance("TLS")); + assertNotNull(SSLContext.getInstance("TLSv1")); + + assertNotSame(SSLContext.getInstance("TLS"), + SSLContext.getInstance("TLS")); + + try { + SSLContext.getInstance(null, (String) null); + fail(); + } catch (IllegalArgumentException e) { + } + try { + SSLContext.getInstance(null, ""); + fail(); + } catch (IllegalArgumentException e) { + } + try { + SSLContext.getInstance("TLS", (String) null); + fail(); + } catch (IllegalArgumentException e) { + } + try { + SSLContext.getInstance(null, PROVIDER_NAME); + fail(); + } catch (NullPointerException e) { + } + } + + public void test_SSLContext_getProtocol() throws Exception { + assertProtocolExistsForName("SSL"); + assertProtocolExistsForName("TLS"); + } + + private void assertProtocolExistsForName(String protocolName) throws Exception { + String protocol = SSLContext.getInstance(protocolName).getProtocol(); + assertNotNull(protocol); + assertEquals(protocolName, protocol); + } + + public void test_SSLContext_getProvider() throws Exception { + Provider provider = SSLContext.getInstance("TLS").getProvider(); + assertNotNull(provider); + assertEquals(PROVIDER_NAME, provider.getName()); + } + + public void test_SSLContext_init() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, null, null); + } + + public void test_SSLContext_getSocketFactory() throws Exception { + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.getSocketFactory(); + fail(); + } catch (IllegalStateException e) { + } + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, null, null); + SocketFactory sf = sslContext.getSocketFactory(); + assertNotNull(sf); + assertTrue(SSLSocketFactory.class.isAssignableFrom(sf.getClass())); + } + + public void test_SSLContext_getServerSocketFactory() throws Exception { + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.getServerSocketFactory(); + fail(); + } catch (IllegalStateException e) { + } + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, null, null); + ServerSocketFactory ssf = sslContext.getServerSocketFactory(); + assertNotNull(ssf); + assertTrue(SSLServerSocketFactory.class.isAssignableFrom(ssf.getClass())); + } + + public void test_SSLContext_createSSLEngine() throws Exception { + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.createSSLEngine(); + fail(); + } catch (IllegalStateException e) { + } + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.createSSLEngine(null, -1); + fail(); + } catch (IllegalStateException e) { + } + { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, null, null); + SSLEngine se = sslContext.createSSLEngine(); + assertNotNull(se); + } + { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, null, null); + SSLEngine se = sslContext.createSSLEngine(null, -1); + assertNotNull(se); + } + } + + @KnownFailure("Should be able to ask SSLContext for SSLSessionContext's before called SSLContext.init") + public void test_SSLContext_getServerSessionContext() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSessionContext sessionContext = sslContext.getServerSessionContext(); + assertNotNull(sessionContext); + + assertNotSame(SSLContext.getInstance("TLS").getServerSessionContext(), + sessionContext); + } + + @KnownFailure("Should be able to ask SSLContext for SSLSessionContext's before called SSLContext.init") + public void test_SSLContext_getClientSessionContext() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSessionContext sessionContext = sslContext.getClientSessionContext(); + assertNotNull(sessionContext); + + assertNotSame(SSLContext.getInstance("TLS").getClientSessionContext(), + sessionContext); + } + + /** + * SSLContextTest.Helper is a convenience class for other tests that + * want a canned SSLContext and related state for testing so they + * don't have to duplicate the logic. + */ + public static final class Helper { + + static { + if (SSLContextTest.IS_RI) { + Security.addProvider(new BouncyCastleProvider()); + } + } + + public final KeyStore keyStore; + public final char[] keyStorePassword; + public final String publicAlias; + public final String privateAlias; + public final SSLContext sslContext; + public final SSLServerSocket serverSocket; + public final InetAddress host; + public final int port; + + private Helper(final KeyStore keyStore, + final char[] keyStorePassword, + final String publicAlias, + final String privateAlias, + final SSLContext sslContext, + final SSLServerSocket serverSocket, + final InetAddress host, + final int port) { + this.keyStore = keyStore; + this.keyStorePassword = keyStorePassword; + this.publicAlias = publicAlias; + this.privateAlias = privateAlias; + this.sslContext = sslContext; + this.serverSocket = serverSocket; + this.host = host; + this.port = port; + } + + public static Helper create() { + try { + final char[] keyStorePassword = null; + final String publicAlias = "public"; + final String privateAlias = "private"; + return create(createKeyStore(keyStorePassword, publicAlias, privateAlias), + null, + publicAlias, + privateAlias); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static Helper create(final KeyStore keyStore, + final char[] keyStorePassword, + final String publicAlias, + final String privateAlias) { + try { + final SSLContext sslContext = createSSLContext(keyStore, keyStorePassword); + + final SSLServerSocket serverSocket = (SSLServerSocket) + sslContext.getServerSocketFactory().createServerSocket(0); + final InetSocketAddress sa = (InetSocketAddress) serverSocket.getLocalSocketAddress(); + final InetAddress host = sa.getAddress(); + final int port = sa.getPort(); + + return new Helper(keyStore, keyStorePassword, publicAlias, privateAlias, + sslContext, serverSocket, host, port); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Create a BKS KeyStore containing an RSAPrivateKey with alias + * "private" and a X509Certificate based on the matching + * RSAPublicKey stored under the alias name publicAlias. + * + * The private key will have a certificate chain including the + * certificate stored under the alias name privateAlias. The + * certificate will be signed by the private key. The certificate + * Subject and Issuer Common-Name will be the local host's + * canonical hostname. The certificate will be valid for one day + * before and one day after the time of creation. + * + * The KeyStore is optionally password protected by the + * keyStorePassword argument, which can be null if a password is + * not desired. + * + * Based on: + * org.bouncycastle.jce.provider.test.SigTest + * org.bouncycastle.jce.provider.test.CertTest + */ + public static KeyStore createKeyStore(final char[] keyStorePassword, + String publicAlias, + String privateAlias) + throws Exception { + + // 1.) we make the keys + final int keysize = 1024; + final KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(keysize, new SecureRandom()); + final KeyPair kp = kpg.generateKeyPair(); + final RSAPrivateKey privateKey = (RSAPrivateKey)kp.getPrivate(); + final RSAPublicKey publicKey = (RSAPublicKey)kp.getPublic(); + + // 2.) use keys to make certficate + + // note that there doesn't seem to be a standard way to make a + // certificate using java.* or javax.*. The CertificateFactory + // interface assumes you want to read in a stream of bytes a + // factory specific format. So here we use Bouncy Castle's + // X509V3CertificateGenerator and related classes. + + final Hashtable attributes = new Hashtable(); + attributes.put(X509Principal.CN, InetAddress.getLocalHost().getCanonicalHostName()); + final X509Principal dn = new X509Principal(attributes); + + final long millisPerDay = 24 * 60 * 60 * 1000; + final long now = System.currentTimeMillis(); + final Date start = new Date(now - millisPerDay); + final Date end = new Date(now + millisPerDay); + final BigInteger serial = BigInteger.valueOf(1); + + final X509V3CertificateGenerator x509cg = new X509V3CertificateGenerator(); + x509cg.setSubjectDN(dn); + x509cg.setIssuerDN(dn); + x509cg.setNotBefore(start); + x509cg.setNotAfter(end); + x509cg.setPublicKey(publicKey); + x509cg.setSignatureAlgorithm("sha1WithRSAEncryption"); + x509cg.setSerialNumber(serial); + final X509Certificate x509c = x509cg.generateX509Certificate(privateKey); + final X509Certificate[] x509cc = new X509Certificate[] { x509c }; + + + // 3.) put certificate and private key to make a key store + final KeyStore ks = KeyStore.getInstance("BKS"); + ks.load(null, null); + ks.setKeyEntry(privateAlias, privateKey, keyStorePassword, x509cc); + ks.setCertificateEntry(publicAlias, x509c); + return ks; + } + + /** + * Create a SSLContext with a KeyManager using the private key and + * certificate chain from the given KeyStore and a TrustManager + * using the certificates authorities from the same KeyStore. + */ + public static final SSLContext createSSLContext(final KeyStore keyStore, final char[] keyStorePassword) + throws Exception { + final String kmfa = KeyManagerFactory.getDefaultAlgorithm(); + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfa); + kmf.init(keyStore, keyStorePassword); + + final String tmfa = TrustManagerFactory.getDefaultAlgorithm(); + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfa); + tmf.init(keyStore); + + final SSLContext context = SSLContext.getInstance("TLS"); + context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom()); + return context; + } + } + + public void test_SSLContextTest_Helper_create() { + Helper helper = Helper.create(); + assertNotNull(helper); + assertNotNull(helper.keyStore); + assertNull(helper.keyStorePassword); + assertNotNull(helper.publicAlias); + assertNotNull(helper.privateAlias); + assertNotNull(helper.sslContext); + assertNotNull(helper.serverSocket); + assertNotNull(helper.host); + assertTrue(helper.port != 0); + } +} diff --git a/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java b/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java new file mode 100644 index 0000000..38848da --- /dev/null +++ b/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2010 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 javax.net.ssl; + +import dalvik.annotation.KnownFailure; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedList; +import junit.framework.TestCase; + +public class SSLSessionContextTest extends TestCase { + + public static final void assertSSLSessionContextSize(int expected, SSLSessionContext s) { + assertEquals(expected, Collections.list(s.getIds()).size()); + } + + public void test_SSLSessionContext_getIds() { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + assertSSLSessionContextSize(0, c.sslContext.getClientSessionContext()); + assertSSLSessionContextSize(0, c.sslContext.getServerSessionContext()); + + final SSLSocketTest.Helper s = SSLSocketTest.Helper.create_workaround(); + assertSSLSessionContextSize(1, s.c.sslContext.getClientSessionContext()); + assertSSLSessionContextSize(1, s.c.sslContext.getServerSessionContext()); + final Enumeration clientIds = s.c.sslContext.getClientSessionContext().getIds(); + final Enumeration serverIds = s.c.sslContext.getServerSessionContext().getIds(); + final byte[] clientId = (byte[]) clientIds.nextElement(); + final byte[] serverId = (byte[]) serverIds.nextElement(); + assertEquals(32, clientId.length); + assertEquals(32, serverId.length); + assertEquals(clientId, serverId); + } + + @KnownFailure("Should throw NullPointerException on getSession(null)") + public void test_SSLSessionContext_getSession() { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + try { + c.sslContext.getClientSessionContext().getSession(null); + fail(); + } catch (NullPointerException e) { + } + assertNull(c.sslContext.getClientSessionContext().getSession(new byte[0])); + assertNull(c.sslContext.getClientSessionContext().getSession(new byte[1])); + + final SSLSocketTest.Helper s = SSLSocketTest.Helper.create_workaround(); + final SSLSessionContext client = s.c.sslContext.getClientSessionContext(); + final SSLSessionContext server = s.c.sslContext.getServerSessionContext(); + final byte[] clientId = (byte[]) client.getIds().nextElement(); + final byte[] serverId = (byte[]) server.getIds().nextElement(); + assertNotNull(client.getSession(clientId)); + assertNotNull(server.getSession(serverId)); + assertEquals(clientId, client.getSession(clientId).getId()); + assertEquals(serverId, server.getSession(serverId).getId()); + } + + @KnownFailure("Should return 0 for unlimited, not 10 entries") + public void test_SSLSessionContext_getSessionCacheSize() { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + assertEquals(0, c.sslContext.getClientSessionContext().getSessionCacheSize()); + assertEquals(0, c.sslContext.getServerSessionContext().getSessionCacheSize()); + + final SSLSocketTest.Helper s = SSLSocketTest.Helper.create_workaround(); + assertEquals(0, s.c.sslContext.getClientSessionContext().getSessionCacheSize()); + assertEquals(0, s.c.sslContext.getServerSessionContext().getSessionCacheSize()); + } + + @KnownFailure("Should return 0 for unlimited, not 10 entries") + public void test_SSLSessionContext_setSessionCacheSize_basic() { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + assertBasicSetSessionCacheSizeBehavior(c.sslContext.getClientSessionContext()); + assertBasicSetSessionCacheSizeBehavior(c.sslContext.getServerSessionContext()); + } + + private static void assertBasicSetSessionCacheSizeBehavior(SSLSessionContext s) { + try { + s.setSessionCacheSize(-1); + fail(); + } catch (IllegalArgumentException e) { + } + assertEquals(0, s.getSessionCacheSize()); + s.setSessionCacheSize(1); + assertEquals(1, s.getSessionCacheSize()); + } + + @KnownFailure("Should return 0 for unlimited, not 10 entries") + public void test_SSLSessionContext_setSessionCacheSize_dynamic() { + + final SSLSocketTest.Helper s = SSLSocketTest.Helper.create_workaround(); + final SSLSessionContext client = s.c.sslContext.getClientSessionContext(); + final SSLSessionContext server = s.c.sslContext.getServerSessionContext(); + assertEquals(0, client.getSessionCacheSize()); + assertEquals(0, server.getSessionCacheSize()); + assertSSLSessionContextSize(1, client); + assertSSLSessionContextSize(1, server); + + final LinkedList<String> uniqueCipherSuites + = new LinkedList(Arrays.asList(s.server.getEnabledCipherSuites())); + uniqueCipherSuites.remove(s.client.getSession().getCipherSuite()); + + // only use RSA cipher suites which will work with our TrustProvider + Iterator<String> i = uniqueCipherSuites.iterator(); + while (i.hasNext()) { + String cipherSuite = i.next(); + if (cipherSuite.startsWith("SSL_RSA_")) { + continue; + } + if (cipherSuite.startsWith("TLS_RSA_")) { + continue; + } + if (cipherSuite.startsWith("TLS_DHE_RSA_")) { + continue; + } + if (cipherSuite.startsWith("SSL_DHE_RSA_")) { + continue; + } + i.remove(); + } + + /* + * having more than 5 uniqueCipherSuites is a test + * requirement, not a requirement of the interface or + * implementation. It simply allows us to make sure that we + * will not get a cached session ID since we'll have to + * renegotiate a new session due to the new cipher suite + * requirement. even this test only really needs three if it + * reused the unique cipher suites every time it resets the + * session cache. + */ + assertTrue(uniqueCipherSuites.size() > 5); + + SSLSocketTest.Helper.connect_workaround(s.c, + new String[] { uniqueCipherSuites.remove() }); // 1 + assertSSLSessionContextSize(2, client); + assertSSLSessionContextSize(2, server); + SSLSocketTest.Helper.connect_workaround(s.c, + new String[] { uniqueCipherSuites.remove() }); // 2 + assertSSLSessionContextSize(3, client); + assertSSLSessionContextSize(3, server); + + client.setSessionCacheSize(1); + server.setSessionCacheSize(1); + assertEquals(1, client.getSessionCacheSize()); + assertEquals(1, server.getSessionCacheSize()); + assertSSLSessionContextSize(1, client); + assertSSLSessionContextSize(1, server); + SSLSocketTest.Helper.connect_workaround(s.c, + new String[] { uniqueCipherSuites.remove() }); // 3 + assertSSLSessionContextSize(1, client); + assertSSLSessionContextSize(1, server); + + client.setSessionCacheSize(2); + server.setSessionCacheSize(2); + SSLSocketTest.Helper.connect_workaround(s.c, + new String[] { uniqueCipherSuites.remove() }); // 4 + assertSSLSessionContextSize(2, client); + assertSSLSessionContextSize(2, server); + SSLSocketTest.Helper.connect_workaround(s.c, + new String[] { uniqueCipherSuites.remove() }); // 5 + assertSSLSessionContextSize(2, client); + assertSSLSessionContextSize(2, server); + } + + @KnownFailure("Should return 86400 seconds (1 day), not 0 for unlimited") + public void test_SSLSessionContext_getSessionTimeout() { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + assertEquals(86400, c.sslContext.getClientSessionContext().getSessionTimeout()); + assertEquals(86400, c.sslContext.getServerSessionContext().getSessionTimeout()); + + final SSLSocketTest.Helper s = SSLSocketTest.Helper.create_workaround(); + assertEquals(86400, s.c.sslContext.getClientSessionContext().getSessionTimeout()); + assertEquals(86400, s.c.sslContext.getServerSessionContext().getSessionTimeout()); + } + + @KnownFailure("Should return 86400 seconds (1 day), not 0 for unlimited") + public void test_SSLSessionContext_setSessionTimeout() throws Exception { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + assertEquals(86400, c.sslContext.getClientSessionContext().getSessionTimeout()); + assertEquals(86400, c.sslContext.getServerSessionContext().getSessionTimeout()); + c.sslContext.getClientSessionContext().setSessionTimeout(0); + c.sslContext.getServerSessionContext().setSessionTimeout(0); + assertEquals(0, c.sslContext.getClientSessionContext().getSessionTimeout()); + assertEquals(0, c.sslContext.getServerSessionContext().getSessionTimeout()); + + try { + c.sslContext.getClientSessionContext().setSessionTimeout(-1); + fail(); + } catch (IllegalArgumentException e) { + } + try { + c.sslContext.getServerSessionContext().setSessionTimeout(-1); + fail(); + } catch (IllegalArgumentException e) { + } + + final SSLSocketTest.Helper s = SSLSocketTest.Helper.create_workaround(); + assertSSLSessionContextSize(1, s.c.sslContext.getClientSessionContext()); + assertSSLSessionContextSize(1, s.c.sslContext.getServerSessionContext()); + Thread.sleep(1 * 1000); + s.c.sslContext.getClientSessionContext().setSessionTimeout(1); + s.c.sslContext.getServerSessionContext().setSessionTimeout(1); + assertSSLSessionContextSize(0, s.c.sslContext.getClientSessionContext()); + assertSSLSessionContextSize(0, s.c.sslContext.getServerSessionContext()); + } +} diff --git a/luni/src/test/java/javax/net/ssl/SSLSessionTest.java b/luni/src/test/java/javax/net/ssl/SSLSessionTest.java new file mode 100644 index 0000000..bf0e4d6 --- /dev/null +++ b/luni/src/test/java/javax/net/ssl/SSLSessionTest.java @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2010 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 javax.net.ssl; + +import dalvik.annotation.KnownFailure; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import junit.framework.TestCase; + +public class SSLSessionTest extends TestCase { + + public static final class Helper { + + /** + * An invalid session that is not connected + */ + public final SSLSession invalid; + + /** + * The server side of a connected session + */ + public final SSLSession server; + + /** + * The client side of a connected session + */ + public final SSLSession client; + + /** + * The associated SSLSocketTest.Helper that is the source of + * the client and server SSLSessions. + */ + public final SSLSocketTest.Helper s; + + private Helper(final SSLSession invalid, + final SSLSession server, + final SSLSession client, + final SSLSocketTest.Helper s) { + this.invalid = invalid; + this.server = server; + this.client = client; + this.s = s; + } + + public static final Helper create() { + try { + final SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + final SSLSocket ssl = (SSLSocket) sf.createSocket(); + final SSLSession invalid = ssl.getSession(); + final SSLSocketTest.Helper s = SSLSocketTest.Helper.create_workaround(); + return new Helper(invalid, s.server.getSession(), s.client.getSession(), s); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + + public void test_SSLSocket_Helper_create() { + final Helper s = Helper.create(); + assertNotNull(s.invalid); + assertFalse(s.invalid.isValid()); + assertTrue(s.server.isValid()); + assertTrue(s.client.isValid()); + } + + public void test_SSLSession_getApplicationBufferSize() { + final Helper s = Helper.create(); + assertTrue(s.invalid.getApplicationBufferSize() > 0); + assertTrue(s.server.getApplicationBufferSize() > 0); + assertTrue(s.client.getApplicationBufferSize() > 0); + } + + @KnownFailure("Expected SSL_NULL_WITH_NULL_NULL but received TLS_NULL_WITH_NULL_NULL") + public void test_SSLSession_getCipherSuite() { + final Helper s = Helper.create(); + assertNotNull(s.invalid.getCipherSuite()); + assertEquals("SSL_NULL_WITH_NULL_NULL", s.invalid.getCipherSuite()); + assertNotNull(s.server.getCipherSuite()); + assertNotNull(s.client.getCipherSuite()); + assertEquals(s.server.getCipherSuite(), + s.client.getCipherSuite()); + } + + public void test_SSLSession_getCreationTime() { + final Helper s = Helper.create(); + assertTrue(s.invalid.getCreationTime() > 0); + assertTrue(s.server.getCreationTime() > 0); + assertTrue(s.client.getCreationTime() > 0); + assertTrue(Math.abs(s.server.getCreationTime() - s.client.getCreationTime()) < 1 * 1000); + } + + public void test_SSLSession_getId() { + final Helper s = Helper.create(); + assertNotNull(s.invalid.getId()); + assertNotNull(s.server.getId()); + assertNotNull(s.client.getId()); + assertEquals(0, s.invalid.getId().length); + assertEquals(32, s.server.getId().length); + assertEquals(32, s.client.getId().length); + assertEquals(s.server.getId(), s.client.getId()); + } + + public void test_SSLSession_getLastAccessedTime() { + final Helper s = Helper.create(); + assertTrue(s.invalid.getLastAccessedTime() > 0); + assertTrue(s.server.getLastAccessedTime() > 0); + assertTrue(s.client.getLastAccessedTime() > 0); + assertTrue(Math.abs(s.server.getLastAccessedTime() - + s.client.getLastAccessedTime()) < 1 * 1000); + assertTrue(s.server.getLastAccessedTime() >= + s.server.getCreationTime()); + assertTrue(s.client.getLastAccessedTime() >= + s.client.getCreationTime()); + } + + public void test_SSLSession_getLocalCertificates() throws Exception { + final Helper s = Helper.create(); + assertNull(s.invalid.getLocalCertificates()); + assertNull(s.client.getLocalCertificates()); + assertNotNull(s.server.getLocalCertificates()); + assertEquals(1, s.server.getLocalCertificates().length); + assertEquals(s.s.c.keyStore.getCertificate(s.s.c.publicAlias), + s.server.getLocalCertificates()[0]); + } + + public void test_SSLSession_getLocalPrincipal() throws Exception { + final Helper s = Helper.create(); + assertNull(s.invalid.getLocalPrincipal()); + assertNull(s.client.getLocalPrincipal()); + assertNotNull(s.server.getLocalPrincipal()); + assertNotNull(s.server.getLocalPrincipal().getName()); + final X509Certificate x509certificate = (X509Certificate) + s.s.c.keyStore.getCertificate(s.s.c.publicAlias); + assertEquals(x509certificate.getSubjectDN().getName(), + s.server.getLocalPrincipal().getName()); + } + + public void test_SSLSession_getPacketBufferSize() { + final Helper s = Helper.create(); + assertTrue(s.invalid.getPacketBufferSize() > 0); + assertTrue(s.server.getPacketBufferSize() > 0); + assertTrue(s.client.getPacketBufferSize() > 0); + } + + public void test_SSLSession_getPeerCertificateChain() throws Exception { + final Helper s = Helper.create(); + try { + s.invalid.getPeerCertificateChain(); + fail(); + } catch (SSLPeerUnverifiedException e) { + } + assertNotNull(s.client.getPeerCertificates()); + assertEquals(1, s.client.getPeerCertificates().length); + assertEquals(s.s.c.keyStore.getCertificate(s.s.c.publicAlias), + s.client.getPeerCertificates()[0]); + try { + assertNull(s.server.getPeerCertificates()); + fail(); + } catch (SSLPeerUnverifiedException e) { + } + } + + public void test_SSLSession_getPeerCertificates() throws Exception { + final Helper s = Helper.create(); + try { + s.invalid.getPeerCertificates(); + fail(); + } catch (SSLPeerUnverifiedException e) { + } + assertNotNull(s.client.getPeerCertificates()); + assertEquals(1, s.client.getPeerCertificates().length); + assertEquals(s.s.c.keyStore.getCertificate(s.s.c.publicAlias), + s.client.getPeerCertificates()[0]); + try { + s.server.getPeerCertificates(); + fail(); + } catch (SSLPeerUnverifiedException e) { + } + } + + public void test_SSLSession_getPeerHost() { + final Helper s = Helper.create(); + assertNull(s.invalid.getPeerHost()); + assertNotNull(s.server.getPeerHost()); + assertNotNull(s.client.getPeerHost()); + } + + public void test_SSLSession_getPeerPort() { + final Helper s = Helper.create(); + assertEquals(-1, s.invalid.getPeerPort()); + assertTrue(s.server.getPeerPort() > 0); + assertEquals(s.s.c.port, s.client.getPeerPort()); + } + + public void test_SSLSession_getPeerPrincipal() throws Exception { + final Helper s = Helper.create(); + try { + s.invalid.getPeerPrincipal(); + fail(); + } catch (SSLPeerUnverifiedException e) { + } + try { + s.server.getPeerPrincipal(); + fail(); + } catch (SSLPeerUnverifiedException e) { + } + assertNotNull(s.client.getPeerPrincipal()); + assertNotNull(s.client.getPeerPrincipal().getName()); + final X509Certificate x509certificate = (X509Certificate) + s.s.c.keyStore.getCertificate(s.s.c.publicAlias); + assertEquals(x509certificate.getSubjectDN().getName(), + s.client.getPeerPrincipal().getName()); + + } + + public void test_SSLSession_getProtocol() { + final Helper s = Helper.create(); + assertNotNull(s.invalid.getProtocol()); + assertEquals("NONE", s.invalid.getProtocol()); + assertNotNull(s.server.getProtocol()); + assertNotNull(s.client.getProtocol()); + assertEquals(s.server.getProtocol(), + s.client.getProtocol()); + } + + public void test_SSLSession_getSessionContext() { + final Helper s = Helper.create(); + assertNull(s.invalid.getSessionContext()); + assertNotNull(s.server.getSessionContext()); + assertNotNull(s.client.getSessionContext()); + assertEquals(s.s.c.sslContext.getServerSessionContext(), + s.server.getSessionContext()); + assertEquals(s.s.c.sslContext.getClientSessionContext(), + s.client.getSessionContext()); + assertNotSame(s.server.getSessionContext(), + s.client.getSessionContext()); + } + + public void test_SSLSession_getValue() { + final Helper s = Helper.create(); + try { + s.invalid.getValue(null); + } catch (IllegalArgumentException e) { + } + assertNull(s.invalid.getValue("BOGUS")); + } + + public void test_SSLSession_getValueNames() { + final Helper s = Helper.create(); + assertNotNull(s.invalid.getValueNames()); + assertEquals(0, s.invalid.getValueNames().length); + } + + public void test_SSLSession_invalidate() { + final Helper s = Helper.create(); + assertFalse(s.invalid.isValid()); + s.invalid.invalidate(); + assertFalse(s.invalid.isValid()); + assertNull(s.invalid.getSessionContext()); + + assertTrue(s.server.isValid()); + s.server.invalidate(); + assertFalse(s.server.isValid()); + assertNull(s.server.getSessionContext()); + + assertTrue(s.client.isValid()); + s.client.invalidate(); + assertFalse(s.client.isValid()); + assertNull(s.client.getSessionContext()); + } + + public void test_SSLSession_isValid() { + final Helper s = Helper.create(); + assertFalse(s.invalid.isValid()); + assertTrue(s.server.isValid()); + assertTrue(s.client.isValid()); + } + + public void test_SSLSession_putValue() { + final Helper s = Helper.create(); + final String key = "KEY"; + final String value = "VALUE"; + assertNull(s.invalid.getValue(key)); + assertEquals(0, s.invalid.getValueNames().length); + s.invalid.putValue(key, value); + assertSame(value, s.invalid.getValue(key)); + assertEquals(1, s.invalid.getValueNames().length); + assertEquals(key, s.invalid.getValueNames()[0]); + } + + public void test_SSLSession_removeValue() { + final Helper s = Helper.create(); + final String key = "KEY"; + final String value = "VALUE"; + s.invalid.putValue(key, value); + assertEquals(1, s.invalid.getValueNames().length); + assertEquals(key, s.invalid.getValueNames()[0]); + s.invalid.removeValue(key); + assertNull(s.invalid.getValue(key)); + assertEquals(0, s.invalid.getValueNames().length); + } +} diff --git a/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java b/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java new file mode 100644 index 0000000..5ccae7f --- /dev/null +++ b/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 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 javax.net.ssl; + +import dalvik.annotation.KnownFailure; +import java.net.Socket; +import java.net.SocketException; +import java.net.ServerSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import javax.net.ServerSocketFactory; +import javax.net.SocketFactory; +import junit.framework.TestCase; + +public class SSLSocketFactoryTest extends TestCase { + public void test_SSLSocketFactory_getDefault() { + SocketFactory sf = SSLSocketFactory.getDefault(); + assertNotNull(sf); + assertTrue(SSLSocketFactory.class.isAssignableFrom(sf.getClass())); + } + + public void test_SSLSocketFactory_getDefaultCipherSuites() { + SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + String[] cs = sf.getDefaultCipherSuites(); + assertNotNull(cs); + assertTrue(cs.length != 0); + } + + public void test_SSLSocketFactory_getSupportedCipherSuites() { + SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + String[] cs = sf.getSupportedCipherSuites(); + assertNotNull(cs); + assertTrue(cs.length != 0); + } + + @KnownFailure("Should not parse bogus port number -1 during createSocket") + public void test_SSLSocketFactory_createSocket() throws Exception { + try { + SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + Socket s = sf.createSocket(null, null, -1, false); + fail(); + } catch (NullPointerException e) { + } + + try { + SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + Socket ssl = sf.createSocket(new Socket(), null, -1, false); + fail(); + } catch (SocketException e) { + } + + ServerSocket ss = ServerSocketFactory.getDefault().createServerSocket(0); + InetSocketAddress sa = (InetSocketAddress) ss.getLocalSocketAddress(); + InetAddress host = sa.getAddress(); + int port = sa.getPort(); + Socket s = new Socket(host, port); + SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + Socket ssl = sf.createSocket(s, null, -1, false); + assertNotNull(ssl); + assertTrue(SSLSocket.class.isAssignableFrom(ssl.getClass())); + } +} diff --git a/luni/src/test/java/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/javax/net/ssl/SSLSocketTest.java new file mode 100644 index 0000000..e5ad54d --- /dev/null +++ b/luni/src/test/java/javax/net/ssl/SSLSocketTest.java @@ -0,0 +1,686 @@ +/* + * Copyright (C) 2010 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 javax.net.ssl; + +import dalvik.annotation.KnownFailure; +import java.math.BigInteger; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.security.Key; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.Principal; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import javax.net.ServerSocketFactory; +import javax.net.SocketFactory; +import junit.framework.TestCase; + +public class SSLSocketTest extends TestCase { + + public void test_SSLSocket_getSupportedCipherSuites() throws Exception { + final SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + final SSLSocket ssl = (SSLSocket) sf.createSocket(); + final String[] cs = ssl.getSupportedCipherSuites(); + assertNotNull(cs); + assertTrue(cs.length != 0); + } + + public void test_SSLSocket_getEnabledCipherSuites() throws Exception { + final SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + final SSLSocket ssl = (SSLSocket) sf.createSocket(); + final String[] cs = ssl.getEnabledCipherSuites(); + assertNotNull(cs); + assertTrue(cs.length != 0); + } + + @KnownFailure("Should support disabling all cipher suites") + public void test_SSLSocket_setEnabledCipherSuites() throws Exception { + final SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + final SSLSocket ssl = (SSLSocket) sf.createSocket(); + + try { + ssl.setEnabledCipherSuites(null); + fail(); + } catch (IllegalArgumentException e) { + } + try { + ssl.setEnabledCipherSuites(new String[1]); + fail(); + } catch (IllegalArgumentException e) { + } + try { + ssl.setEnabledCipherSuites(new String[] { "Bogus" } ); + fail(); + } catch (IllegalArgumentException e) { + } + + ssl.setEnabledCipherSuites(new String[0]); + ssl.setEnabledCipherSuites(ssl.getEnabledCipherSuites()); + ssl.setEnabledCipherSuites(ssl.getSupportedCipherSuites()); + } + + public void test_SSLSocket_getSupportedProtocols() throws Exception { + final SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + final SSLSocket ssl = (SSLSocket) sf.createSocket(); + final String[] p = ssl.getSupportedProtocols(); + assertNotNull(p); + assertTrue(p.length != 0); + } + + public void test_SSLSocket_getEnabledProtocols() throws Exception { + final SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + final SSLSocket ssl = (SSLSocket) sf.createSocket(); + final String[] p = ssl.getEnabledProtocols(); + assertNotNull(p); + assertTrue(p.length != 0); + } + + @KnownFailure("Should thow IllegalArgumentException not NullPointerException on null enabled protocols argument") + public void test_SSLSocket_setEnabledProtocols() throws Exception { + final SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + final SSLSocket ssl = (SSLSocket) sf.createSocket(); + + try { + ssl.setEnabledProtocols(null); + fail(); + } catch (IllegalArgumentException e) { + } + try { + ssl.setEnabledProtocols(new String[1]); + fail(); + } catch (IllegalArgumentException e) { + } + try { + ssl.setEnabledProtocols(new String[] { "Bogus" } ); + fail(); + } catch (IllegalArgumentException e) { + } + ssl.setEnabledProtocols(new String[0]); + ssl.setEnabledProtocols(ssl.getEnabledProtocols()); + ssl.setEnabledProtocols(ssl.getSupportedProtocols()); + } + + @KnownFailure("session of unconnected socket should not be valid") + public void test_SSLSocket_getSession() throws Exception { + final SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); + final SSLSocket ssl = (SSLSocket) sf.createSocket(); + final SSLSession session = ssl.getSession(); + assertNotNull(session); + assertFalse(session.isValid()); + } + + @KnownFailure("Implementation should not start handshake in ServerSocket.accept") + public void test_SSLSocket_startHandshake() throws Exception { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port); + if (!SSLContextTest.IS_RI) { + /* + * The following hangs in accept in the Dalvik + * implementation because accept is also incorrectly + * starting the handhake. + */ + c.serverSocket.setSoTimeout(1 * 1000); + /* + * That workaround doesn't seem to work so... + * + * See test_SSLSocket_startHandshake_workaround for + * redundant version of this test that works around this + * issue. + */ + fail(); + } + final SSLSocket server = (SSLSocket) c.serverSocket.accept(); + final Thread thread = new Thread(new Runnable () { + public void run() { + try { + server.startHandshake(); + assertNotNull(server.getSession()); + try { + server.getSession().getPeerCertificates(); + fail(); + } catch (SSLPeerUnverifiedException e) { + } + Certificate[] localCertificates = server.getSession().getLocalCertificates(); + assertNotNull(localCertificates); + assertEquals(1, localCertificates.length); + assertNotNull(localCertificates[0]); + assertNotNull(localCertificates[0].equals(c.keyStore.getCertificate(c.privateAlias))); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + thread.start(); + client.startHandshake(); + assertNotNull(client.getSession()); + assertNull(client.getSession().getLocalCertificates()); + Certificate[] peerCertificates = client.getSession().getPeerCertificates(); + assertNotNull(peerCertificates); + assertEquals(1, peerCertificates.length); + assertNotNull(peerCertificates[0]); + assertNotNull(peerCertificates[0].equals(c.keyStore.getCertificate(c.publicAlias))); + thread.join(); + } + + @KnownFailure("local certificates should be null as it should not have been requested by server") + public void test_SSLSocket_startHandshake_workaround() throws Exception { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + final Thread thread = new Thread(new Runnable () { + public void run() { + try { + final SSLSocket server = (SSLSocket) c.serverSocket.accept(); + server.startHandshake(); + assertNotNull(server.getSession()); + try { + server.getSession().getPeerCertificates(); + fail(); + } catch (SSLPeerUnverifiedException e) { + } + Certificate[] localCertificates = server.getSession().getLocalCertificates(); + assertNotNull(localCertificates); + assertEquals(1, localCertificates.length); + assertNotNull(localCertificates[0]); + assertNotNull(localCertificates[0].equals(c.keyStore.getCertificate(c.privateAlias))); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + thread.start(); + final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port); + client.startHandshake(); + assertNotNull(client.getSession()); + assertNull(client.getSession().getLocalCertificates()); + Certificate[] peerCertificates = client.getSession().getPeerCertificates(); + assertNotNull(peerCertificates); + assertEquals(1, peerCertificates.length); + assertNotNull(peerCertificates[0]); + assertNotNull(peerCertificates[0].equals(c.keyStore.getCertificate(c.publicAlias))); + thread.join(); + } + + @KnownFailure("Should throw SSLException on server, not IOException on client") + public void test_SSLSocket_startHandshake_noKeyStore_workaround() throws Exception { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(null, null, null, null); + final Thread thread = new Thread(new Runnable () { + public void run() { + try { + c.serverSocket.accept(); + fail(); + } catch (SSLException e) { + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + thread.start(); + final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port); + if (!SSLContextTest.IS_RI) { + client.startHandshake(); + } + thread.join(); + } + + /** + * Marked workaround because it avoid accepting on main thread like test_SSLSocket_startHandshake_workaround + */ + @KnownFailure("local certificates should be null as it should not have been requested by server") + public void test_SSLSocket_HandshakeCompletedListener_workaround() throws Exception { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + final Thread thread = new Thread(new Runnable () { + public void run() { + try { + final SSLSocket server = (SSLSocket) c.serverSocket.accept(); + server.startHandshake(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + thread.start(); + final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port); + client.addHandshakeCompletedListener(new HandshakeCompletedListener() { + public void handshakeCompleted(final HandshakeCompletedEvent event) { + try { + SSLSession session = event.getSession(); + String cipherSuite = event.getCipherSuite(); + Certificate[] localCertificates = event.getLocalCertificates(); + Certificate[] peerCertificates = event.getPeerCertificates(); + javax.security.cert.X509Certificate[] peerCertificateChain = event.getPeerCertificateChain(); + Principal peerPrincipal = event.getPeerPrincipal(); + Principal localPrincipal = event.getLocalPrincipal(); + Socket socket = event.getSocket(); + + if (false) { + System.out.println("Session=" + session); + System.out.println("CipherSuite=" + cipherSuite); + System.out.println("LocalCertificates=" + localCertificates); + System.out.println("PeerCertificates=" + peerCertificates); + System.out.println("PeerCertificateChain=" + peerCertificateChain); + System.out.println("PeerPrincipal=" + peerPrincipal); + System.out.println("LocalPrincipal=" + localPrincipal); + System.out.println("Socket=" + socket); + } + + assertNotNull(session); + byte[] id = session.getId(); + assertNotNull(id); + assertEquals(32, id.length); + assertNotNull(c.sslContext.getClientSessionContext().getSession(id)); + assertNotNull(c.sslContext.getServerSessionContext().getSession(id)); + + assertNotNull(cipherSuite); + assertTrue(Arrays.asList(client.getEnabledCipherSuites()).contains(cipherSuite)); + assertTrue(Arrays.asList(c.serverSocket.getEnabledCipherSuites()).contains(cipherSuite)); + + final Enumeration e = c.keyStore.aliases(); + Certificate certificate = null; + Key key = null; + while (e.hasMoreElements()) { + String alias = (String) e.nextElement(); + if (c.keyStore.isCertificateEntry(alias)) { + assertNull(certificate); + certificate = c.keyStore.getCertificate(alias); + } else if (c.keyStore.isKeyEntry(alias)) { + assertNull(key); + key = c.keyStore.getKey(alias, c.keyStorePassword); + } + else { + fail(); + } + } + assertNotNull(certificate); + assertNotNull(key); + + assertTrue(X509Certificate.class.isAssignableFrom(certificate.getClass())); + final X509Certificate x509certificate = (X509Certificate) certificate; + + assertNull(localCertificates); + + assertNotNull(peerCertificates); + assertEquals(1, peerCertificates.length); + assertNotNull(peerCertificates[0]); + assertEquals(peerCertificates[0], x509certificate); + + assertNotNull(peerCertificateChain); + assertEquals(1, peerCertificateChain.length); + assertNotNull(peerCertificateChain[0]); + assertEquals(x509certificate.getSubjectDN().getName(), + peerCertificateChain[0].getSubjectDN().getName()); + + assertNotNull(peerPrincipal); + assertEquals(x509certificate.getSubjectDN().getName(), + peerPrincipal.getName()); + + assertNull(localPrincipal); + + assertNotNull(socket); + assertSame(client, socket); + + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + client.startHandshake(); + thread.join(); + } + + /** + * Marked workaround because it avoid accepting on main thread like test_SSLSocket_startHandshake_workaround. + * Technically this test shouldn't even need a second thread. + */ + public void test_SSLSocket_getUseClientMode_workaround() throws Exception { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + final Thread thread = new Thread(new Runnable () { + public void run() { + try { + final SSLSocket server = (SSLSocket) c.serverSocket.accept(); + assertFalse(server.getUseClientMode()); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + thread.start(); + final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port); + if (!SSLContextTest.IS_RI) { + client.startHandshake(); + } + assertTrue(client.getUseClientMode()); + thread.join(); + } + + /** + * Marked workaround because it avoid accepting on main thread like test_SSLSocket_startHandshake_workaround. + * Technically this test shouldn't even need a second thread. + */ + @KnownFailure("This test relies on socket timeouts which are not working. It also fails because ServerSocket.accept is handshaking") + public void test_SSLSocket_setUseClientMode_workaround() throws Exception { + // client is client, server is server + test_SSLSocket_setUseClientMode_workaround(true, false); + // client is server, server is client + test_SSLSocket_setUseClientMode_workaround(true, false); + // both are client + try { + test_SSLSocket_setUseClientMode_workaround(true, true); + fail(); + } catch (SSLProtocolException e) { + } + + // both are server + try { + test_SSLSocket_setUseClientMode_workaround(false, false); + fail(); + } catch (SocketTimeoutException e) { + } + } + + private void test_SSLSocket_setUseClientMode_workaround(final boolean clientClientMode, + final boolean serverClientMode) + throws Exception { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + final SSLProtocolException[] sslProtocolException = new SSLProtocolException[1]; + final SocketTimeoutException[] socketTimeoutException = new SocketTimeoutException[1]; + final Thread thread = new Thread(new Runnable () { + public void run() { + try { + final SSLSocket server = (SSLSocket) c.serverSocket.accept(); + if (!serverClientMode) { + server.setSoTimeout(1 * 1000); + if (!SSLContextTest.IS_RI) { + /* as above setSoTimeout isn't working in dalvikvm */ + fail(); + } + } + server.setUseClientMode(serverClientMode); + server.startHandshake(); + } catch (SSLProtocolException e) { + sslProtocolException[0] = e; + } catch (SocketTimeoutException e) { + socketTimeoutException[0] = e; + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + thread.start(); + final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port); + if (!clientClientMode) { + client.setSoTimeout(1 * 1000); + if (!SSLContextTest.IS_RI) { + /* as above setSoTimeout isn't working in dalvikvm */ + fail(); + } + } + client.setUseClientMode(clientClientMode); + client.startHandshake(); + thread.join(); + if (sslProtocolException[0] != null) { + throw sslProtocolException[0]; + } + if (socketTimeoutException[0] != null) { + throw socketTimeoutException[0]; + } + } + + /** + * Marked workaround because it avoid accepting on main thread like test_SSLSocket_startHandshake_workaround + */ + public void test_SSLSocket_clientAuth_workaround() throws Exception { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + final Thread thread = new Thread(new Runnable () { + public void run() { + try { + final SSLSocket server = (SSLSocket) c.serverSocket.accept(); + assertFalse(server.getWantClientAuth()); + assertFalse(server.getNeedClientAuth()); + + // confirm turning one on by itself + server.setWantClientAuth(true); + assertTrue(server.getWantClientAuth()); + assertFalse(server.getNeedClientAuth()); + + // confirm turning setting on toggles the other + server.setNeedClientAuth(true); + assertFalse(server.getWantClientAuth()); + assertTrue(server.getNeedClientAuth()); + + // confirm toggling back + server.setWantClientAuth(true); + assertTrue(server.getWantClientAuth()); + assertFalse(server.getNeedClientAuth()); + + server.startHandshake(); + + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + thread.start(); + final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port); + client.startHandshake(); + assertNotNull(client.getSession().getLocalCertificates()); + assertEquals(1, client.getSession().getLocalCertificates().length); + thread.join(); + } + + /** + * Marked workaround because it avoid accepting on main thread like test_SSLSocket_startHandshake_workaround + * Technically this test shouldn't even need a second thread. + */ + public void test_SSLSocket_getEnableSessionCreation_workaround() throws Exception { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + final Thread thread = new Thread(new Runnable () { + public void run() { + try { + final SSLSocket server = (SSLSocket) c.serverSocket.accept(); + assertTrue(server.getEnableSessionCreation()); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + thread.start(); + final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port); + assertTrue(client.getEnableSessionCreation()); + if (!SSLContextTest.IS_RI) { + client.startHandshake(); + } + thread.join(); + } + + /** + * Marked workaround because it avoid accepting on main thread like test_SSLSocket_startHandshake_workaround + */ + @KnownFailure("Server side session creation disabling does not work, should throw SSLException, not fail") + public void test_SSLSocket_setEnableSessionCreation_server_workaround() throws Exception { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + final Thread thread = new Thread(new Runnable () { + public void run() { + try { + final SSLSocket server = (SSLSocket) c.serverSocket.accept(); + server.setEnableSessionCreation(false); + try { + server.startHandshake(); + fail(); + } catch (SSLException e) { + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + thread.start(); + final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port); + try { + client.startHandshake(); + fail(); + } catch (SSLException e) { + } + thread.join(); + } + + /** + * Marked workaround because it avoid accepting on main thread like test_SSLSocket_startHandshake_workaround + */ + @KnownFailure("Should throw SSLException on server, not IOException") + public void test_SSLSocket_setEnableSessionCreation_client_workaround() throws Exception { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + final Thread thread = new Thread(new Runnable () { + public void run() { + try { + final SSLSocket server = (SSLSocket) c.serverSocket.accept(); + try { + server.startHandshake(); + fail(); + } catch (SSLException e) { + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + thread.start(); + final SSLSocket client = (SSLSocket) c.sslContext.getSocketFactory().createSocket(c.host, c.port); + client.setEnableSessionCreation(false); + try { + client.startHandshake(); + fail(); + } catch (SSLException e) { + if (!SSLContextTest.IS_RI) { + fail(); + } + } + thread.join(); + } + + /** + * SSLSocketTest.Helper is a convenience class for other tests that + * want a pair of connected and handshaked client and server + * SSLSocketsfor testing so they don't have to duplicate the + * logic. + */ + public static final class Helper { + public final SSLContextTest.Helper c; + public final SSLSocket server; + public final SSLSocket client; + + private Helper (final SSLContextTest.Helper c, + final SSLSocket server, + final SSLSocket client) { + this.c = c; + this.server = server; + this.client = client; + } + + /** + * based on test_SSLSocket_startHandshake_workaround, should + * be written to non-workaround form when possible + */ + public static Helper create_workaround () { + final SSLContextTest.Helper c = SSLContextTest.Helper.create(); + final SSLSocket[] sockets = connect_workaround(c, null); + return new Helper(c, sockets[0], sockets[1]); + } + + /** + * Create a new connected server/client socket pair within a + * existing SSLContext. Optional clientCipherSuites allows + * forcing new SSLSession to test SSLSessionContext caching + */ + public static SSLSocket[] connect_workaround (final SSLContextTest.Helper c, + String[] clientCipherSuites) { + try { + final SSLSocket[] server = new SSLSocket[1]; + final Thread thread = new Thread(new Runnable () { + public void run() { + try { + server[0] = (SSLSocket) c.serverSocket.accept(); + server[0].startHandshake(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + thread.start(); + final SSLSocket client = (SSLSocket) + c.sslContext.getSocketFactory().createSocket(c.host, c.port); + if (clientCipherSuites != null) { + client.setEnabledCipherSuites(clientCipherSuites); + } + client.startHandshake(); + thread.join(); + return new SSLSocket[] { server[0], client }; + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + public void test_SSLSocketTest_Test_create() { + Helper test = Helper.create_workaround(); + assertNotNull(test.c); + assertNotNull(test.server); + assertNotNull(test.client); + assertNotNull(test.server.isConnected()); + assertNotNull(test.client.isConnected()); + assertNotNull(test.server.getSession()); + assertNotNull(test.client.getSession()); + } +} diff --git a/luni/src/test/java/tests/AllTests.java b/luni/src/test/java/tests/AllTests.java index 3110026..4b3a484 100644 --- a/luni/src/test/java/tests/AllTests.java +++ b/luni/src/test/java/tests/AllTests.java @@ -65,6 +65,7 @@ public class AllTests suite.addTest(java.text.AllTests.suite()); suite.addTest(java.util.AllTests.suite()); suite.addTest(javax.xml.parsers.AllTests.suite()); + suite.addTest(javax.net.ssl.AllTests.suite()); suite.addTest(org.apache.harmony.luni.platform.AllTests.suite()); suite.addTest(org.json.AllTests.suite()); suite.addTest(tests.api.org.apache.harmony.kernel.dalvik.AllTests.suite()); |