Merge "Revert "Revert "Assert SNI type is SNI_HOST_NAME"""
diff --git a/luni/src/test/java/libcore/java/io/FileInputStreamTest.java b/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
index b6650ff..398adbc 100644
--- a/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
+++ b/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
@@ -22,6 +22,11 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import android.system.ErrnoException;
+import android.system.OsConstants;
import junit.framework.TestCase;
import libcore.io.IoUtils;
@@ -204,4 +209,36 @@
FileInputStream input = new FileInputStream(file);
assertTrue(input.available() == 0);
}
+
+ // http://b/25695227
+ public void testFdLeakWhenOpeningDirectory() throws Exception {
+ File phile = IoUtils.createTemporaryDirectory("test_bug_25695227");
+
+ try {
+ new FileInputStream(phile);
+ fail();
+ } catch (FileNotFoundException expected) {
+ }
+
+ assertTrue(getOpenFdsForPrefix("test_bug_25695227").isEmpty());
+ }
+
+ private static List<Integer> getOpenFdsForPrefix(String path) throws Exception {
+ File[] fds = new File("/proc/self/fd").listFiles();
+ List<Integer> list = new ArrayList<>();
+ for (File fd : fds) {
+ try {
+ File fdPath = new File(android.system.Os.readlink(fd.getAbsolutePath()));
+ if (fdPath.getName().startsWith(path)) {
+ list.add(Integer.valueOf(fd.getName()));
+ }
+ } catch (ErrnoException e) {
+ if (e.errno != OsConstants.ENOENT) {
+ throw e.rethrowAsIOException();
+ }
+ }
+ }
+
+ return list;
+ }
}
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
index 5e3a3d5..d50a170 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
@@ -661,6 +661,20 @@
}
}
+ public void test_SSLEngine_endpointVerification_Success() throws Exception {
+ TestSSLContext c = TestSSLContext.create();
+ TestSSLEnginePair p = TestSSLEnginePair.create(c, new TestSSLEnginePair.Hooks() {
+ @Override
+ void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
+ SSLParameters p = client.getSSLParameters();
+ p.setEndpointIdentificationAlgorithm("HTTPS");
+ client.setSSLParameters(p);
+ }
+ });
+ assertConnected(p);
+ c.close();
+ }
+
public void test_SSLEngine_getEnableSessionCreation() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index 451fd66..d44cda9 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -334,6 +334,13 @@
assertFalse(session.isValid());
}
+ public void test_SSLSocket_getHandshakeSession() throws Exception {
+ SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
+ SSLSocket ssl = (SSLSocket) sf.createSocket();
+ SSLSession session = ssl.getHandshakeSession();
+ assertNull(session);
+ }
+
public void test_SSLSocket_startHandshake() throws Exception {
final TestSSLContext c = TestSSLContext.create();
SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
@@ -344,6 +351,7 @@
@Override public Void call() throws Exception {
server.startHandshake();
assertNotNull(server.getSession());
+ assertNull(server.getHandshakeSession());
try {
server.getSession().getPeerCertificates();
fail();
@@ -394,8 +402,8 @@
final TestSSLContext c = TestSSLContext.create();
final ExecutorService executor = Executors.newSingleThreadExecutor();
- final SSLSocket client1 = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
- c.port);
+ final SSLSocket client1 = (SSLSocket) c.clientContext.getSocketFactory()
+ .createSocket(c.host.getHostName(), c.port);
final SSLSocket server1 = (SSLSocket) c.serverSocket.accept();
final Future<byte[]> future1 = executor.submit(new SSLServerSessionIdCallable(server1));
client1.startHandshake();
@@ -407,8 +415,8 @@
client1.close();
server1.close();
- final SSLSocket client2 = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
- c.port);
+ final SSLSocket client2 = (SSLSocket) c.clientContext.getSocketFactory()
+ .createSocket(c.host.getHostName(), c.port);
final SSLSocket server2 = (SSLSocket) c.serverSocket.accept();
final Future<byte[]> future2 = executor.submit(new SSLServerSessionIdCallable(server2));
client2.startHandshake();
@@ -586,6 +594,7 @@
assertSame(client, socket);
assertTrue(socket instanceof SSLSocket);
+ assertNull(((SSLSocket) socket).getHandshakeSession());
synchronized (handshakeCompletedListenerCalled) {
handshakeCompletedListenerCalled[0] = true;
@@ -1016,6 +1025,14 @@
assertEquals(p.getWantClientAuth(), ssl.getWantClientAuth());
assertEquals(p.getNeedClientAuth(), ssl.getNeedClientAuth());
+
+ assertNull(p.getEndpointIdentificationAlgorithm());
+ p.setEndpointIdentificationAlgorithm(null);
+ assertNull(p.getEndpointIdentificationAlgorithm());
+ p.setEndpointIdentificationAlgorithm("HTTPS");
+ assertEquals("HTTPS", p.getEndpointIdentificationAlgorithm());
+ p.setEndpointIdentificationAlgorithm("FOO");
+ assertEquals("FOO", p.getEndpointIdentificationAlgorithm());
}
public void test_SSLSocket_setSSLParameters() throws Exception {
@@ -1199,6 +1216,83 @@
server.close();
}
+ public void test_SSLSocket_endpointIdentification_Success() throws Exception {
+ final TestSSLContext c = TestSSLContext.create();
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
+ SSLParameters p = client.getSSLParameters();
+ p.setEndpointIdentificationAlgorithm("HTTPS");
+ client.connect(new InetSocketAddress(c.host, c.port));
+ final SSLSocket server = (SSLSocket) c.serverSocket.accept();
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Future<Void> future = executor.submit(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ server.startHandshake();
+ assertNotNull(server.getSession());
+ try {
+ server.getSession().getPeerCertificates();
+ fail();
+ } catch (SSLPeerUnverifiedException expected) {
+ }
+ Certificate[] localCertificates = server.getSession().getLocalCertificates();
+ assertNotNull(localCertificates);
+ TestKeyStore.assertChainLength(localCertificates);
+ assertNotNull(localCertificates[0]);
+ TestSSLContext.assertCertificateInKeyStore(localCertificates[0],
+ c.serverKeyStore);
+ return null;
+ }
+ });
+ executor.shutdown();
+ client.startHandshake();
+ assertNotNull(client.getSession());
+ assertNull(client.getSession().getLocalCertificates());
+ Certificate[] peerCertificates = client.getSession().getPeerCertificates();
+ assertNotNull(peerCertificates);
+ TestKeyStore.assertChainLength(peerCertificates);
+ assertNotNull(peerCertificates[0]);
+ TestSSLContext.assertCertificateInKeyStore(peerCertificates[0], c.serverKeyStore);
+ future.get();
+ client.close();
+ server.close();
+ c.close();
+ }
+
+ public void test_SSLSocket_endpointIdentification_Failure() throws Exception {
+ final TestSSLContext c = TestSSLContext.create();
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(
+ InetAddress.getByName("127.0.0.2"), c.port);
+ SSLParameters p = client.getSSLParameters();
+ p.setEndpointIdentificationAlgorithm("HTTPS");
+ client.setSSLParameters(p);
+ // client.connect(new InetSocketAddress(c.host, c.port));
+ final SSLSocket server = (SSLSocket) c.serverSocket.accept();
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Future<Void> future = executor.submit(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ try {
+ server.startHandshake();
+ fail("Should receive SSLHandshakeException as server");
+ } catch (SSLHandshakeException expected) {
+ }
+ return null;
+ }
+ });
+ executor.shutdown();
+ try {
+ client.startHandshake();
+ fail("Should throw when hostname does not match expected");
+ } catch (SSLHandshakeException expected) {
+ } finally {
+ try {
+ future.get();
+ } finally {
+ client.close();
+ server.close();
+ c.close();
+ }
+ }
+ }
+
public void test_SSLSocket_setSoTimeout_basic() throws Exception {
ServerSocket listening = new ServerSocket(0);
diff --git a/ojluni/src/main/java/java/util/WeakHashMap.java b/ojluni/src/main/java/java/util/WeakHashMap.java
index a8ca523..652b053 100755
--- a/ojluni/src/main/java/java/util/WeakHashMap.java
+++ b/ojluni/src/main/java/java/util/WeakHashMap.java
@@ -243,9 +243,10 @@
/**
* A randomizing value associated with this instance that is applied to
* hash code of keys to make hash collisions harder to find.
+ *
+ * This hash seed is only used if {@code useAltHashing} is true.
*/
transient int hashSeed;
- volatile boolean seedSet = false;
@SuppressWarnings("unchecked")
private Entry<K,V>[] newTable(int n) {
@@ -279,6 +280,11 @@
threshold = (int)(capacity * loadFactor);
useAltHashing = sun.misc.VM.isBooted() &&
(capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
+ if (useAltHashing) {
+ hashSeed = sun.misc.Hashing.randomHashSeed(this);
+ } else {
+ hashSeed = 0;
+ }
}
/**
@@ -357,14 +363,6 @@
int h;
if (useAltHashing) {
- if (!seedSet) {
- synchronized(this) {
- if (!seedSet) {
- hashSeed = sun.misc.Hashing.randomHashSeed(this);
- seedSet = true;
- }
- }
- }
h = hashSeed;
if (k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
@@ -572,6 +570,9 @@
useAltHashing |= sun.misc.VM.isBooted() &&
(newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
boolean rehash = oldAltHashing ^ useAltHashing;
+ if (rehash) {
+ hashSeed = sun.misc.Hashing.randomHashSeed(this);
+ }
transfer(oldTable, newTable, rehash);
table = newTable;
diff --git a/ojluni/src/main/native/io_util_md.c b/ojluni/src/main/native/io_util_md.c
index 1df4b9d..4b1de48 100755
--- a/ojluni/src/main/native/io_util_md.c
+++ b/ojluni/src/main/native/io_util_md.c
@@ -83,6 +83,7 @@
fstat(fd, &stat);
if (S_ISDIR(stat.st_mode)) {
+ close(fd);
errno = EISDIR; // For Exception message
throwFileNotFoundException(env, path);
return;
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index f7b8337..9eb9e6c 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -758,6 +758,8 @@
addBoth( "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384");
addOpenSsl("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
addOpenSsl("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
+ addOpenSsl("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256");
+ addOpenSsl("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256");
// Pre-Shared Key (PSK) cipher suites
addOpenSsl("TLS_PSK_WITH_RC4_128_SHA");
@@ -765,6 +767,7 @@
addOpenSsl("TLS_PSK_WITH_AES_256_CBC_SHA");
addOpenSsl("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA");
addOpenSsl("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA");
+ addOpenSsl("TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256");
// RFC 5746's Signaling Cipher Suite Value to indicate a request for secure renegotiation
addBoth(CIPHER_SUITE_SECURE_RENEGOTIATION);
@@ -924,8 +927,10 @@
"SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
"SSL_RSA_WITH_RC4_128_MD5",
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV")
- : Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ : Arrays.asList("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
@@ -948,6 +953,7 @@
// NOTE: This list needs to be kept in sync with Javadoc of javax.net.ssl.SSLSocket and
// javax.net.ssl.SSLEngine.
public static final List<String> CIPHER_SUITES_DEFAULT_PSK = Arrays.asList(
+ "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
"TLS_PSK_WITH_AES_128_CBC_SHA",
@@ -966,7 +972,8 @@
"AES_128_CBC",
"AES_256_CBC",
"AES_128_GCM",
- "AES_256_GCM"));
+ "AES_256_GCM",
+ "CHACHA20_POLY1305"));
private static final Set<String> PERMITTED_DEFAULT_MACS =
new HashSet<String>(Arrays.asList("SHA",
diff --git a/support/src/test/java/libcore/javax/net/ssl/TestSSLContext.java b/support/src/test/java/libcore/javax/net/ssl/TestSSLContext.java
index 8173e9d..1daa2a1 100644
--- a/support/src/test/java/libcore/javax/net/ssl/TestSSLContext.java
+++ b/support/src/test/java/libcore/javax/net/ssl/TestSSLContext.java
@@ -33,6 +33,7 @@
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;
import junit.framework.Assert;
import libcore.java.security.StandardNames;
@@ -83,8 +84,8 @@
public final char[] serverStorePassword;
public final KeyManager[] clientKeyManagers;
public final KeyManager[] serverKeyManagers;
- public final X509TrustManager clientTrustManager;
- public final X509TrustManager serverTrustManager;
+ public final X509ExtendedTrustManager clientTrustManager;
+ public final X509ExtendedTrustManager serverTrustManager;
public final SSLContext clientContext;
public final SSLContext serverContext;
public final SSLServerSocket serverSocket;
@@ -97,8 +98,8 @@
char[] serverStorePassword,
KeyManager[] clientKeyManagers,
KeyManager[] serverKeyManagers,
- X509TrustManager clientTrustManager,
- X509TrustManager serverTrustManager,
+ X509ExtendedTrustManager clientTrustManager,
+ X509ExtendedTrustManager serverTrustManager,
SSLContext clientContext,
SSLContext serverContext,
SSLServerSocket serverSocket,
@@ -189,8 +190,8 @@
serverKeyStore, serverStorePassword,
clientKeyManagers,
serverKeyManagers,
- (X509TrustManager) clientTrustManagers,
- (X509TrustManager) serverTrustManagers,
+ (X509ExtendedTrustManager) clientTrustManagers,
+ (X509ExtendedTrustManager) serverTrustManagers,
clientContext, serverContext,
serverSocket, host, port);
} catch (RuntimeException e) {
diff --git a/support/src/test/java/libcore/javax/net/ssl/TestTrustManager.java b/support/src/test/java/libcore/javax/net/ssl/TestTrustManager.java
index dc4bb28..b703984 100644
--- a/support/src/test/java/libcore/javax/net/ssl/TestTrustManager.java
+++ b/support/src/test/java/libcore/javax/net/ssl/TestTrustManager.java
@@ -20,6 +20,7 @@
import java.net.Socket;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
@@ -28,15 +29,16 @@
/**
* TestTrustManager is a simple proxy class that wraps an existing
- * X509TrustManager to provide debug logging and recording of
+ * X509ExtendedTrustManager to provide debug logging and recording of
* values.
*/
-public final class TestTrustManager implements X509TrustManager {
+public final class TestTrustManager extends X509ExtendedTrustManager {
private static final boolean LOG = false;
private static final PrintStream out = LOG ? System.out : new NullPrintStream();
private final X509TrustManager trustManager;
+ private final X509ExtendedTrustManager extendedTrustManager;
public static TrustManager[] wrap(TrustManager[] trustManagers) {
TrustManager[] result = trustManagers.clone();
@@ -47,14 +49,23 @@
}
public static TrustManager wrap(TrustManager trustManager) {
- if (trustManager instanceof X509TrustManager) {
+ if (trustManager instanceof X509ExtendedTrustManager) {
+ return new TestTrustManager((X509ExtendedTrustManager) trustManager);
+ } else if (trustManager instanceof X509TrustManager) {
return new TestTrustManager((X509TrustManager) trustManager);
}
return trustManager;
}
+ public TestTrustManager(X509ExtendedTrustManager trustManager) {
+ out.println("TestTrustManager.<init> extendedTrustManager=" + trustManager);
+ this.extendedTrustManager = trustManager;
+ this.trustManager = trustManager;
+ }
+
public TestTrustManager(X509TrustManager trustManager) {
out.println("TestTrustManager.<init> trustManager=" + trustManager);
+ this.extendedTrustManager = null;
this.trustManager = trustManager;
}
@@ -73,6 +84,50 @@
}
}
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket)
+ throws CertificateException {
+ if (extendedTrustManager == null) {
+ out.print("(fallback to X509TrustManager) ");
+ checkClientTrusted(chain, authType);
+ return;
+ }
+ out.print("TestTrustManager.checkClientTrusted "
+ + "chain=" + chain.length + " "
+ + "authType=" + authType + " "
+ + "socket=" + socket + " ");
+ try {
+ assertClientAuthType(authType);
+ extendedTrustManager.checkClientTrusted(chain, authType, socket);
+ out.println("OK");
+ } catch (CertificateException e) {
+ e.printStackTrace(out);
+ throw e;
+ }
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine)
+ throws CertificateException {
+ if (extendedTrustManager == null) {
+ out.print("(fallback to X509TrustManager) ");
+ checkClientTrusted(chain, authType);
+ return;
+ }
+ out.print("TestTrustManager.checkClientTrusted "
+ + "chain=" + chain.length + " "
+ + "authType=" + authType + " "
+ + "engine=" + engine + " ");
+ try {
+ assertClientAuthType(authType);
+ extendedTrustManager.checkClientTrusted(chain, authType, engine);
+ out.println("OK");
+ } catch (CertificateException e) {
+ e.printStackTrace(out);
+ throw e;
+ }
+ }
+
private void assertClientAuthType(String authType) {
if (!StandardNames.CLIENT_AUTH_TYPES.contains(authType)) {
throw new AssertionError("Unexpected client auth type " + authType);
@@ -94,6 +149,50 @@
}
}
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket)
+ throws CertificateException {
+ if (extendedTrustManager == null) {
+ out.print("(fallback to X509TrustManager) ");
+ checkServerTrusted(chain, authType);
+ return;
+ }
+ out.print("TestTrustManager.checkServerTrusted "
+ + "chain=" + chain.length + " "
+ + "authType=" + authType + " "
+ + "socket=" + socket.toString() + " ");
+ try {
+ assertServerAuthType(authType);
+ extendedTrustManager.checkServerTrusted(chain, authType, socket);
+ out.println("OK");
+ } catch (CertificateException e) {
+ e.printStackTrace(out);
+ throw e;
+ }
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine)
+ throws CertificateException {
+ if (extendedTrustManager == null) {
+ out.print("(fallback to X509TrustManager) ");
+ checkServerTrusted(chain, authType);
+ return;
+ }
+ out.print("TestTrustManager.checkServerTrusted "
+ + "chain=" + chain.length + " "
+ + "authType=" + authType + " "
+ + "engine=" + engine.toString() + " ");
+ try {
+ assertServerAuthType(authType);
+ extendedTrustManager.checkServerTrusted(chain, authType, engine);
+ out.println("OK");
+ } catch (CertificateException e) {
+ e.printStackTrace(out);
+ throw e;
+ }
+ }
+
private void assertServerAuthType(String authType) {
if (!StandardNames.SERVER_AUTH_TYPES.contains(authType)) {
throw new AssertionError("Unexpected server auth type " + authType);