CertificateChainValidatorpublic class CertificateChainValidator extends Object Class responsible for all server certificate validation functionality
{@hide} |
Fields Summary |
---|
private static final String | TAG | private X509TrustManager | mTrustManager |
Constructors Summary |
---|
private CertificateChainValidator()Creates a new certificate chain validator. This is a private constructor.
If you need a Certificate chain validator, call getInstance().
try {
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X.509");
tmf.init((KeyStore) null);
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
mTrustManager = (X509TrustManager) tm;
}
}
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("X.509 TrustManagerFactory must be available", e);
} catch (KeyStoreException e) {
throw new RuntimeException("X.509 TrustManagerFactory cannot be initialized", e);
}
if (mTrustManager == null) {
throw new RuntimeException(
"None of the X.509 TrustManagers are X509TrustManager");
}
|
Methods Summary |
---|
private void | closeSocketThrowException(javax.net.ssl.SSLSocket socket, java.lang.String errorMessage, java.lang.String defaultErrorMessage)
closeSocketThrowException(
socket, errorMessage != null ? errorMessage : defaultErrorMessage);
| private void | closeSocketThrowException(javax.net.ssl.SSLSocket socket, java.lang.String errorMessage)
if (HttpLog.LOGV) {
HttpLog.v("validation error: " + errorMessage);
}
if (socket != null) {
SSLSession session = socket.getSession();
if (session != null) {
session.invalidate();
}
socket.close();
}
throw new SSLHandshakeException(errorMessage);
| public SslError | doHandshakeAndValidateServerCertificates(HttpsConnection connection, javax.net.ssl.SSLSocket sslSocket, java.lang.String domain)Performs the handshake and server certificates validation
Notice a new chain will be rebuilt by tracing the issuer and subject
before calling checkServerTrusted().
And if the last traced certificate is self issued and it is expired, it
will be dropped.
// get a valid SSLSession, close the socket if we fail
SSLSession sslSession = sslSocket.getSession();
if (!sslSession.isValid()) {
closeSocketThrowException(sslSocket, "failed to perform SSL handshake");
}
// retrieve the chain of the server peer certificates
Certificate[] peerCertificates =
sslSocket.getSession().getPeerCertificates();
if (peerCertificates == null || peerCertificates.length == 0) {
closeSocketThrowException(
sslSocket, "failed to retrieve peer certificates");
} else {
// update the SSL certificate associated with the connection
if (connection != null) {
if (peerCertificates[0] != null) {
connection.setCertificate(
new SslCertificate((X509Certificate)peerCertificates[0]));
}
}
}
return verifyServerDomainAndCertificates((X509Certificate[]) peerCertificates, domain, "RSA");
| public static android.net.http.CertificateChainValidator | getInstance()
return NoPreloadHolder.sInstance;
| private javax.net.ssl.X509TrustManager | getTrustManager()Returns the platform default {@link X509TrustManager}.
return mTrustManager;
| public static void | handleTrustStorageUpdate()Handles updates to credential storage.
TrustManagerFactory tmf;
try {
tmf = TrustManagerFactory.getInstance("X.509");
tmf.init((KeyStore) null);
} catch (NoSuchAlgorithmException e) {
Slog.w(TAG, "Couldn't find default X.509 TrustManagerFactory");
return;
} catch (KeyStoreException e) {
Slog.w(TAG, "Couldn't initialize default X.509 TrustManagerFactory", e);
return;
}
TrustManager[] tms = tmf.getTrustManagers();
boolean sentUpdate = false;
for (TrustManager tm : tms) {
try {
Method updateMethod = tm.getClass().getDeclaredMethod("handleTrustStorageUpdate");
updateMethod.setAccessible(true);
updateMethod.invoke(tm);
sentUpdate = true;
} catch (Exception e) {
}
}
if (!sentUpdate) {
Slog.w(TAG, "Didn't find a TrustManager to handle CA list update");
}
| public static SslError | verifyServerCertificates(byte[][] certChain, java.lang.String domain, java.lang.String authType)Similar to doHandshakeAndValidateServerCertificates but exposed to JNI for use
by Chromium HTTPS stack to validate the cert chain.
if (certChain == null || certChain.length == 0) {
throw new IllegalArgumentException("bad certificate chain");
}
X509Certificate[] serverCertificates = new X509Certificate[certChain.length];
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
for (int i = 0; i < certChain.length; ++i) {
serverCertificates[i] = (X509Certificate) cf.generateCertificate(
new ByteArrayInputStream(certChain[i]));
}
} catch (CertificateException e) {
throw new IOException("can't read certificate", e);
}
return verifyServerDomainAndCertificates(serverCertificates, domain, authType);
| private static SslError | verifyServerDomainAndCertificates(java.security.cert.X509Certificate[] chain, java.lang.String domain, java.lang.String authType)Common code of doHandshakeAndValidateServerCertificates and verifyServerCertificates.
Calls DomainNamevalidator to verify the domain, and TrustManager to verify the certs.
// check if the first certificate in the chain is for this site
X509Certificate currCertificate = chain[0];
if (currCertificate == null) {
throw new IllegalArgumentException("certificate for this site is null");
}
boolean valid = domain != null
&& !domain.isEmpty()
&& NoPreloadHolder.sVerifier.verify(domain,
new DelegatingSSLSession.CertificateWrap(currCertificate));
if (!valid) {
if (HttpLog.LOGV) {
HttpLog.v("certificate not for this host: " + domain);
}
return new SslError(SslError.SSL_IDMISMATCH, currCertificate);
}
try {
X509TrustManager x509TrustManager = SSLParametersImpl.getDefaultX509TrustManager();
if (x509TrustManager instanceof TrustManagerImpl) {
TrustManagerImpl trustManager = (TrustManagerImpl) x509TrustManager;
trustManager.checkServerTrusted(chain, authType, domain);
} else {
x509TrustManager.checkServerTrusted(chain, authType);
}
return null; // No errors.
} catch (GeneralSecurityException e) {
if (HttpLog.LOGV) {
HttpLog.v("failed to validate the certificate chain, error: " +
e.getMessage());
}
return new SslError(SslError.SSL_UNTRUSTED, currCertificate);
}
|
|