1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 /* 3 * Copyright (C) 2011 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.org.conscrypt; 19 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertTrue; 22 import static org.junit.Assert.fail; 23 24 import java.io.IOException; 25 import java.security.KeyStore; 26 import java.security.Principal; 27 import java.security.cert.Certificate; 28 import java.security.cert.CertificateException; 29 import java.security.cert.X509Certificate; 30 import java.util.Arrays; 31 import java.util.List; 32 import javax.net.ssl.HandshakeCompletedListener; 33 import javax.net.ssl.HttpsURLConnection; 34 import javax.net.ssl.SSLParameters; 35 import javax.net.ssl.SSLPeerUnverifiedException; 36 import javax.net.ssl.SSLSession; 37 import javax.net.ssl.SSLSessionContext; 38 import javax.net.ssl.SSLSocket; 39 import javax.net.ssl.X509TrustManager; 40 import com.android.org.conscrypt.java.security.TestKeyStore; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.junit.runners.JUnit4; 44 45 /** 46 * @hide This class is not part of the Android public SDK API 47 */ 48 @RunWith(JUnit4.class) 49 public class TrustManagerImplTest { 50 51 /** 52 * Ensure that our non-standard behavior of learning to trust new 53 * intermediate CAs does not regress. http://b/3404902 54 */ 55 @Test 56 public void testLearnIntermediate() throws Exception { 57 TestUtils.assumeExtendedTrustManagerAvailable(); 58 // chain3 should be server/intermediate/root 59 KeyStore.PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA"); 60 X509Certificate[] chain3 = (X509Certificate[])pke.getCertificateChain(); 61 X509Certificate root = chain3[2]; 62 X509Certificate intermediate = chain3[1]; 63 X509Certificate server = chain3[0]; 64 X509Certificate[] chain2 = new X509Certificate[] { server, intermediate }; 65 X509Certificate[] chain1 = new X509Certificate[] { server }; 66 67 // Normal behavior 68 assertValid(chain3, trustManager(root)); 69 assertValid(chain2, trustManager(root)); 70 assertInvalid(chain1, trustManager(root)); 71 assertValid(chain3, trustManager(intermediate)); 72 assertValid(chain2, trustManager(intermediate)); 73 assertValid(chain1, trustManager(intermediate)); 74 assertValid(chain3, trustManager(server)); 75 assertValid(chain2, trustManager(server)); 76 assertValid(chain1, trustManager(server)); 77 78 // non-standard behavior 79 X509TrustManager tm = trustManager(root); 80 // fail on short chain with only root trusted 81 assertInvalid(chain1, tm); 82 // succeed on longer chain, learn intermediate 83 assertValid(chain2, tm); 84 // now we can validate the short chain 85 assertValid(chain1, tm); 86 } 87 88 // We should ignore duplicate cruft in the certificate chain 89 // See https://code.google.com/p/android/issues/detail?id=52295 http://b/8313312 90 @Test 91 public void testDuplicateInChain() throws Exception { 92 TestUtils.assumeExtendedTrustManagerAvailable(); 93 // chain3 should be server/intermediate/root 94 KeyStore.PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA"); 95 X509Certificate[] chain3 = (X509Certificate[])pke.getCertificateChain(); 96 X509Certificate root = chain3[2]; 97 X509Certificate intermediate = chain3[1]; 98 X509Certificate server = chain3[0]; 99 100 X509Certificate[] chain4 = new X509Certificate[] { server, intermediate, 101 server, intermediate 102 }; 103 assertValid(chain4, trustManager(root)); 104 } 105 106 @Test 107 public void testGetFullChain() throws Exception { 108 TestUtils.assumeExtendedTrustManagerAvailable(); 109 // build the trust manager 110 KeyStore.PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA"); 111 X509Certificate[] chain3 = (X509Certificate[]) pke.getCertificateChain(); 112 X509Certificate root = chain3[2]; 113 X509TrustManager tm = trustManager(root); 114 115 // build the chains we'll use for testing 116 X509Certificate intermediate = chain3[1]; 117 X509Certificate server = chain3[0]; 118 X509Certificate[] chain2 = new X509Certificate[] { server, intermediate }; 119 X509Certificate[] chain1 = new X509Certificate[] { server }; 120 121 assertTrue(tm instanceof TrustManagerImpl); 122 TrustManagerImpl tmi = (TrustManagerImpl) tm; 123 List<X509Certificate> certs = 124 tmi.checkServerTrusted(chain2, "RSA", new FakeSSLSession("purple.com")); 125 assertEquals(Arrays.asList(chain3), certs); 126 certs = tmi.checkServerTrusted(chain1, "RSA", new FakeSSLSession("purple.com")); 127 assertEquals(Arrays.asList(chain3), certs); 128 } 129 130 @Test 131 public void testHttpsEndpointIdentification() throws Exception { 132 TestUtils.assumeExtendedTrustManagerAvailable(); 133 134 KeyStore.PrivateKeyEntry pke = TestKeyStore.getServerHostname().getPrivateKey("RSA", "RSA"); 135 X509Certificate[] chain = (X509Certificate[]) pke.getCertificateChain(); 136 X509Certificate root = chain[2]; 137 TrustManagerImpl tmi = (TrustManagerImpl) trustManager(root); 138 139 String goodHostname = TestKeyStore.CERT_HOSTNAME; 140 String badHostname = "definitelywrong.nopenopenope"; 141 142 // The default hostname verifier on OpenJDK rejects all hostnames, so use our own 143 javax.net.ssl.HostnameVerifier oldDefault = HttpsURLConnection.getDefaultHostnameVerifier(); 144 try { 145 HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier()); 146 147 SSLParameters params = new SSLParameters(); 148 149 // Without endpoint identification this should pass despite the mismatched hostname 150 params.setEndpointIdentificationAlgorithm(null); 151 152 List<X509Certificate> certs = tmi.getTrustedChainForServer(chain, "RSA", 153 new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params)); 154 assertEquals(Arrays.asList(chain), certs); 155 156 // Turn on endpoint identification 157 params.setEndpointIdentificationAlgorithm("HTTPS"); 158 159 try { 160 tmi.getTrustedChainForServer(chain, "RSA", 161 new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params)); 162 } catch (CertificateException expected) { 163 } 164 165 certs = tmi.getTrustedChainForServer(chain, "RSA", 166 new FakeSSLSocket(new FakeSSLSession(goodHostname, chain), params)); 167 assertEquals(Arrays.asList(chain), certs); 168 169 // Override the global default hostname verifier with a Conscrypt-specific one that 170 // always passes. Both scenarios should pass. 171 Conscrypt.setDefaultHostnameVerifier(new ConscryptHostnameVerifier() { 172 @Override 173 public boolean verify(String s, SSLSession sslSession) { 174 return true; 175 } 176 }); 177 178 certs = tmi.getTrustedChainForServer(chain, "RSA", 179 new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params)); 180 assertEquals(Arrays.asList(chain), certs); 181 182 certs = tmi.getTrustedChainForServer(chain, "RSA", 183 new FakeSSLSocket(new FakeSSLSession(goodHostname, chain), params)); 184 assertEquals(Arrays.asList(chain), certs); 185 186 // Now set an instance-specific verifier on the trust manager. The bad hostname should 187 // fail again. 188 Conscrypt.setHostnameVerifier(tmi, new TestHostnameVerifier()); 189 190 try { 191 tmi.getTrustedChainForServer(chain, "RSA", 192 new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params)); 193 } catch (CertificateException expected) { 194 } 195 196 certs = tmi.getTrustedChainForServer(chain, "RSA", 197 new FakeSSLSocket(new FakeSSLSession(goodHostname, chain), params)); 198 assertEquals(Arrays.asList(chain), certs); 199 200 // Remove the instance-specific verifier, and both should pass again. 201 Conscrypt.setHostnameVerifier(tmi, null); 202 203 certs = tmi.getTrustedChainForServer(chain, "RSA", 204 new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params)); 205 assertEquals(Arrays.asList(chain), certs); 206 207 certs = tmi.getTrustedChainForServer(chain, "RSA", 208 new FakeSSLSocket(new FakeSSLSession(goodHostname, chain), params)); 209 assertEquals(Arrays.asList(chain), certs); 210 } finally { 211 Conscrypt.setDefaultHostnameVerifier(null); 212 HttpsURLConnection.setDefaultHostnameVerifier(oldDefault); 213 } 214 } 215 216 private X509TrustManager trustManager(X509Certificate ca) throws Exception { 217 KeyStore keyStore = TestKeyStore.createKeyStore(); 218 keyStore.setCertificateEntry("alias", ca); 219 220 return new TrustManagerImpl(keyStore); 221 } 222 223 private void assertValid(X509Certificate[] chain, X509TrustManager tm) throws Exception { 224 if (tm instanceof TrustManagerImpl) { 225 TrustManagerImpl tmi = (TrustManagerImpl) tm; 226 tmi.checkServerTrusted(chain, "RSA"); 227 } 228 tm.checkServerTrusted(chain, "RSA"); 229 } 230 231 private void assertInvalid(X509Certificate[] chain, X509TrustManager tm) { 232 try { 233 tm.checkClientTrusted(chain, "RSA"); 234 fail(); 235 } catch (CertificateException expected) { 236 // Expected. 237 } 238 try { 239 tm.checkServerTrusted(chain, "RSA"); 240 fail(); 241 } catch (CertificateException expected) { 242 // Expected. 243 } 244 } 245 246 private static class FakeSSLSession implements SSLSession { 247 private final String hostname; 248 private final X509Certificate[] peerCerts; 249 250 FakeSSLSession(String hostname) { 251 this.hostname = hostname; 252 peerCerts = null; 253 } 254 255 FakeSSLSession(String hostname, X509Certificate[] peerCerts) { 256 this.hostname = hostname; 257 this.peerCerts = peerCerts.clone(); 258 } 259 260 @Override 261 public int getApplicationBufferSize() { 262 throw new UnsupportedOperationException(); 263 } 264 265 @Override 266 public String getCipherSuite() { 267 throw new UnsupportedOperationException(); 268 } 269 270 @Override 271 public long getCreationTime() { 272 throw new UnsupportedOperationException(); 273 } 274 275 @Override 276 public byte[] getId() { 277 throw new UnsupportedOperationException(); 278 } 279 280 @Override 281 public long getLastAccessedTime() { 282 throw new UnsupportedOperationException(); 283 } 284 285 @Override 286 public Certificate[] getLocalCertificates() { 287 throw new UnsupportedOperationException(); 288 } 289 290 @Override 291 public Principal getLocalPrincipal() { 292 throw new UnsupportedOperationException(); 293 } 294 295 @Override 296 public int getPacketBufferSize() { 297 throw new UnsupportedOperationException(); 298 } 299 300 @Override 301 public javax.security.cert.X509Certificate[] getPeerCertificateChain() 302 throws SSLPeerUnverifiedException { 303 throw new UnsupportedOperationException(); 304 } 305 306 @Override 307 public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { 308 if (peerCerts == null) { 309 throw new SSLPeerUnverifiedException("Null peerCerts"); 310 } else { 311 return peerCerts.clone(); 312 } 313 } 314 315 @Override 316 public String getPeerHost() { 317 return hostname; 318 } 319 320 @Override 321 public int getPeerPort() { 322 throw new UnsupportedOperationException(); 323 } 324 325 @Override 326 public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { 327 throw new UnsupportedOperationException(); 328 } 329 330 @Override 331 public String getProtocol() { 332 throw new UnsupportedOperationException(); 333 } 334 335 @Override 336 public SSLSessionContext getSessionContext() { 337 throw new UnsupportedOperationException(); 338 } 339 340 @Override 341 public Object getValue(String name) { 342 throw new UnsupportedOperationException(); 343 } 344 345 @Override 346 public String[] getValueNames() { 347 throw new UnsupportedOperationException(); 348 } 349 350 @Override 351 public void invalidate() { 352 throw new UnsupportedOperationException(); 353 } 354 355 @Override 356 public boolean isValid() { 357 throw new UnsupportedOperationException(); 358 } 359 360 @Override 361 public void putValue(String name, Object value) { 362 throw new UnsupportedOperationException(); 363 } 364 365 @Override 366 public void removeValue(String name) { 367 throw new UnsupportedOperationException(); 368 } 369 } 370 371 private static class FakeSSLSocket extends SSLSocket { 372 private final SSLSession session; 373 private final SSLParameters parameters; 374 375 public FakeSSLSocket(SSLSession session, SSLParameters parameters) { 376 this.session = session; 377 this.parameters = parameters; 378 } 379 380 @Override 381 public SSLParameters getSSLParameters() { 382 return parameters; 383 } 384 385 @Override 386 public String[] getSupportedCipherSuites() { 387 throw new UnsupportedOperationException(); 388 } 389 390 @Override 391 public String[] getEnabledCipherSuites() { 392 throw new UnsupportedOperationException(); 393 } 394 395 @Override 396 public void setEnabledCipherSuites(String[] strings) { 397 throw new UnsupportedOperationException(); 398 } 399 400 @Override 401 public String[] getSupportedProtocols() { 402 throw new UnsupportedOperationException(); 403 } 404 405 @Override 406 public String[] getEnabledProtocols() { 407 throw new UnsupportedOperationException(); 408 } 409 410 @Override 411 public void setEnabledProtocols(String[] strings) { 412 throw new UnsupportedOperationException(); 413 } 414 415 @Override 416 public SSLSession getSession() { 417 return session; 418 } 419 420 @Override 421 public SSLSession getHandshakeSession() { 422 return session; 423 } 424 425 @Override 426 public void addHandshakeCompletedListener( 427 HandshakeCompletedListener handshakeCompletedListener) { 428 throw new UnsupportedOperationException(); 429 } 430 431 @Override 432 public void removeHandshakeCompletedListener( 433 HandshakeCompletedListener handshakeCompletedListener) { 434 throw new UnsupportedOperationException(); 435 } 436 437 @Override 438 public void startHandshake() throws IOException { 439 throw new UnsupportedOperationException(); 440 } 441 442 @Override 443 public void setUseClientMode(boolean b) { 444 throw new UnsupportedOperationException(); 445 } 446 447 @Override 448 public boolean getUseClientMode() { 449 throw new UnsupportedOperationException(); 450 } 451 452 @Override 453 public void setNeedClientAuth(boolean b) { 454 throw new UnsupportedOperationException(); 455 } 456 457 @Override 458 public boolean getNeedClientAuth() { 459 throw new UnsupportedOperationException(); 460 } 461 462 @Override 463 public void setWantClientAuth(boolean b) { 464 throw new UnsupportedOperationException(); 465 } 466 467 @Override 468 public boolean getWantClientAuth() { 469 throw new UnsupportedOperationException(); 470 } 471 472 @Override 473 public void setEnableSessionCreation(boolean b) { 474 throw new UnsupportedOperationException(); 475 } 476 477 @Override 478 public boolean getEnableSessionCreation() { 479 throw new UnsupportedOperationException(); 480 } 481 } 482 483 private static class TestHostnameVerifier 484 extends com.android.org.conscrypt.javax.net.ssl.TestHostnameVerifier 485 implements ConscryptHostnameVerifier {} 486 } 487