8218863: Better endpoint checks

Reviewed-by: ahgross, jnimeh, mullan, rhalade
This commit is contained in:
Xue-Lei Andrew Fan 2019-02-27 13:58:04 -08:00
parent 44b9ab02fe
commit e06d193456
2 changed files with 62 additions and 66 deletions

View file

@ -145,7 +145,7 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
private Validator checkTrustedInit(X509Certificate[] chain,
String authType, boolean isClient) {
String authType, boolean checkClientTrusted) {
if (chain == null || chain.length == 0) {
throw new IllegalArgumentException(
"null or zero-length certificate chain");
@ -157,7 +157,7 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
Validator v = null;
if (isClient) {
if (checkClientTrusted) {
v = clientValidator;
if (v == null) {
validatorLock.lock();
@ -192,9 +192,10 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
return v;
}
private void checkTrusted(X509Certificate[] chain, String authType,
Socket socket, boolean isClient) throws CertificateException {
Validator v = checkTrustedInit(chain, authType, isClient);
private void checkTrusted(X509Certificate[] chain,
String authType, Socket socket,
boolean checkClientTrusted) throws CertificateException {
Validator v = checkTrustedInit(chain, authType, checkClientTrusted);
X509Certificate[] trustedChain = null;
if ((socket != null) && socket.isConnected() &&
@ -223,28 +224,23 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
// Grab any stapled OCSP responses for use in validation
List<byte[]> responseList = Collections.emptyList();
if (!isClient && isExtSession) {
if (!checkClientTrusted && isExtSession) {
responseList =
((ExtendedSSLSession)session).getStatusResponses();
}
trustedChain = v.validate(chain, null, responseList,
constraints, isClient ? null : authType);
// check if EE certificate chains to a public root CA (as
// pre-installed in cacerts)
boolean chainsToPublicCA = AnchorCertificates.contains(
trustedChain[trustedChain.length-1]);
constraints, checkClientTrusted ? null : authType);
// check endpoint identity
String identityAlg = sslSocket.getSSLParameters().
getEndpointIdentificationAlgorithm();
if (identityAlg != null && !identityAlg.isEmpty()) {
checkIdentity(session, trustedChain[0], identityAlg, isClient,
getRequestedServerNames(socket), chainsToPublicCA);
checkIdentity(session,
trustedChain, identityAlg, checkClientTrusted);
}
} else {
trustedChain = v.validate(chain, null, Collections.emptyList(),
null, isClient ? null : authType);
null, checkClientTrusted ? null : authType);
}
if (SSLLogger.isOn && SSLLogger.isOn("ssl,trustmanager")) {
@ -253,9 +249,10 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
}
private void checkTrusted(X509Certificate[] chain, String authType,
SSLEngine engine, boolean isClient) throws CertificateException {
Validator v = checkTrustedInit(chain, authType, isClient);
private void checkTrusted(X509Certificate[] chain,
String authType, SSLEngine engine,
boolean checkClientTrusted) throws CertificateException {
Validator v = checkTrustedInit(chain, authType, checkClientTrusted);
X509Certificate[] trustedChain = null;
if (engine != null) {
@ -281,28 +278,23 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
// Grab any stapled OCSP responses for use in validation
List<byte[]> responseList = Collections.emptyList();
if (!isClient && isExtSession) {
if (!checkClientTrusted && isExtSession) {
responseList =
((ExtendedSSLSession)session).getStatusResponses();
}
trustedChain = v.validate(chain, null, responseList,
constraints, isClient ? null : authType);
// check if EE certificate chains to a public root CA (as
// pre-installed in cacerts)
boolean chainsToPublicCA = AnchorCertificates.contains(
trustedChain[trustedChain.length-1]);
constraints, checkClientTrusted ? null : authType);
// check endpoint identity
String identityAlg = engine.getSSLParameters().
getEndpointIdentificationAlgorithm();
if (identityAlg != null && !identityAlg.isEmpty()) {
checkIdentity(session, trustedChain[0], identityAlg, isClient,
getRequestedServerNames(engine), chainsToPublicCA);
checkIdentity(session, trustedChain,
identityAlg, checkClientTrusted);
}
} else {
trustedChain = v.validate(chain, null, Collections.emptyList(),
null, isClient ? null : authType);
null, checkClientTrusted ? null : authType);
}
if (SSLLogger.isOn && SSLLogger.isOn("ssl,trustmanager")) {
@ -360,14 +352,8 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
static List<SNIServerName> getRequestedServerNames(Socket socket) {
if (socket != null && socket.isConnected() &&
socket instanceof SSLSocket) {
SSLSocket sslSocket = (SSLSocket)socket;
SSLSession session = sslSocket.getHandshakeSession();
if (session != null && (session instanceof ExtendedSSLSession)) {
ExtendedSSLSession extSession = (ExtendedSSLSession)session;
return extSession.getRequestedServerNames();
}
return getRequestedServerNames(
((SSLSocket)socket).getHandshakeSession());
}
return Collections.<SNIServerName>emptyList();
@ -376,12 +362,16 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
// Also used by X509KeyManagerImpl
static List<SNIServerName> getRequestedServerNames(SSLEngine engine) {
if (engine != null) {
SSLSession session = engine.getHandshakeSession();
return getRequestedServerNames(engine.getHandshakeSession());
}
if (session != null && (session instanceof ExtendedSSLSession)) {
ExtendedSSLSession extSession = (ExtendedSSLSession)session;
return extSession.getRequestedServerNames();
}
return Collections.<SNIServerName>emptyList();
}
private static List<SNIServerName> getRequestedServerNames(
SSLSession session) {
if (session != null && (session instanceof ExtendedSSLSession)) {
return ((ExtendedSSLSession)session).getRequestedServerNames();
}
return Collections.<SNIServerName>emptyList();
@ -402,23 +392,28 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
* the identity checking aginst the server_name extension if present, and
* may failove to peer host checking.
*/
private static void checkIdentity(SSLSession session,
X509Certificate cert,
static void checkIdentity(SSLSession session,
X509Certificate[] trustedChain,
String algorithm,
boolean isClient,
List<SNIServerName> sniNames,
boolean chainsToPublicCA) throws CertificateException {
boolean checkClientTrusted) throws CertificateException {
// check if EE certificate chains to a public root CA (as
// pre-installed in cacerts)
boolean chainsToPublicCA = AnchorCertificates.contains(
trustedChain[trustedChain.length - 1]);
boolean identifiable = false;
String peerHost = session.getPeerHost();
if (isClient) {
String hostname = getHostNameInSNI(sniNames);
if (hostname != null) {
if (!checkClientTrusted) {
List<SNIServerName> sniNames = getRequestedServerNames(session);
String sniHostName = getHostNameInSNI(sniNames);
if (sniHostName != null) {
try {
checkIdentity(hostname, cert, algorithm, chainsToPublicCA);
checkIdentity(sniHostName,
trustedChain[0], algorithm, chainsToPublicCA);
identifiable = true;
} catch (CertificateException ce) {
if (hostname.equalsIgnoreCase(peerHost)) {
if (sniHostName.equalsIgnoreCase(peerHost)) {
throw ce;
}
@ -428,7 +423,8 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
if (!identifiable) {
checkIdentity(peerHost, cert, algorithm, chainsToPublicCA);
checkIdentity(peerHost,
trustedChain[0], algorithm, chainsToPublicCA);
}
}