@Override public void connect(final HttpClientConnection conn, final HttpRoute route, final int connectTimeout, final HttpContext context) throws IOException { try { super.connect(conn, route, connectTimeout, context); } catch (SSLProtocolException e) { Boolean enableSniValue = (Boolean) context.getAttribute(SniSSLConnectionSocketFactory.ENABLE_SNI); boolean enableSni = enableSniValue == null || enableSniValue; if (enableSni && e.getMessage() != null && e.getMessage().equals("handshake alert: unrecognized_name")) { logger.warn("Server saw wrong SNI host, retrying without SNI"); context.setAttribute(SniSSLConnectionSocketFactory.ENABLE_SNI, false); super.connect(conn, route, connectTimeout, context); } else { throw e; } } }
SignatureAlgorithmsExtension(HandshakeInStream s, int len) throws IOException { super(ExtensionType.EXT_SIGNATURE_ALGORITHMS); algorithmsLen = s.getInt16(); if (algorithmsLen == 0 || algorithmsLen + 2 != len) { throw new SSLProtocolException("Invalid " + type + " extension"); } algorithms = new ArrayList<SignatureAndHashAlgorithm>(); int remains = algorithmsLen; int sequence = 0; while (remains > 1) { // needs at least two bytes int hash = s.getInt8(); // hash algorithm int signature = s.getInt8(); // signature algorithm SignatureAndHashAlgorithm algorithm = SignatureAndHashAlgorithm.valueOf(hash, signature, ++sequence); algorithms.add(algorithm); remains -= 2; // one byte for hash, one byte for signature } if (remains != 0) { throw new SSLProtocolException("Invalid server_name extension"); } }
RenegotiationInfoExtension(HandshakeInStream s, int len) throws IOException { super(ExtensionType.EXT_RENEGOTIATION_INFO); // check the extension length if (len < 1) { throw new SSLProtocolException("Invalid " + type + " extension"); } int renegoInfoDataLen = s.getInt8(); if (renegoInfoDataLen + 1 != len) { // + 1 = the byte we just read throw new SSLProtocolException("Invalid " + type + " extension"); } renegotiated_connection = new byte[renegoInfoDataLen]; if (renegoInfoDataLen != 0) { s.read(renegotiated_connection, 0, renegoInfoDataLen); } }
SupportedEllipticPointFormatsExtension(HandshakeInStream s, int len) throws IOException { super(ExtensionType.EXT_EC_POINT_FORMATS); formats = s.getBytes8(); // RFC 4492 says uncompressed points must always be supported. // Check just to make sure. boolean uncompressed = false; for (int format : formats) { if (format == FMT_UNCOMPRESSED) { uncompressed = true; break; } } if (uncompressed == false) { throw new SSLProtocolException ("Peer does not support uncompressed points"); } }
EllipticPointFormatsExtension(HandshakeInStream s, int len) throws IOException { super(ExtensionType.EXT_EC_POINT_FORMATS); formats = s.getBytes8(); // RFC 4492 says uncompressed points must always be supported. // Check just to make sure. boolean uncompressed = false; for (int format : formats) { if (format == FMT_UNCOMPRESSED) { uncompressed = true; break; } } if (uncompressed == false) { throw new SSLProtocolException ("Peer does not support uncompressed points"); } }
static void checkCookie(ProtocolVersion protocolVersion, byte[] cookie) throws IOException { if (cookie != null && cookie.length != 0) { int limit = COOKIE_MAX_LENGTH_DTLS12; if (protocolVersion.v == ProtocolVersion.DTLS10.v) { limit = COOKIE_MAX_LENGTH_DTLS10; } if (cookie.length > COOKIE_MAX_LENGTH_DTLS10) { throw new SSLProtocolException( "Invalid HelloVerifyRequest.cookie (length = " + cookie.length + " bytes)"); } } // Otherwise, no cookie exchange. }
@Test public void test_SSL_do_handshake_with_psk_key_mismatch() throws Exception { final ServerSocket listener = newServerSocket(); ClientHooks cHooks = new ClientHooks(); ServerHooks sHooks = new ServerHooks(); cHooks.pskEnabled = true; sHooks.pskEnabled = true; cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8"); sHooks.pskKey = "1, 2, 3, 3, Testing...".getBytes("UTF-8"); Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null); Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null); try { client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SSLProtocolException.class, expected.getCause().getClass()); } }
@Test public void test_SSL_do_handshake_with_psk_with_no_client_key() throws Exception { final ServerSocket listener = newServerSocket(); ClientHooks cHooks = new ClientHooks(); ServerHooks sHooks = new ServerHooks(); cHooks.pskEnabled = true; sHooks.pskEnabled = true; cHooks.pskKey = null; sHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8"); Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null); Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null); try { client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SSLProtocolException.class, expected.getCause().getClass()); } }
@Test public void test_SSL_do_handshake_with_psk_with_no_server_key() throws Exception { final ServerSocket listener = newServerSocket(); ClientHooks cHooks = new ClientHooks(); ServerHooks sHooks = new ServerHooks(); cHooks.pskEnabled = true; sHooks.pskEnabled = true; cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8"); sHooks.pskKey = null; Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null); Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null); try { client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SSLProtocolException.class, expected.getCause().getClass()); } }
public final void connectFailed(Connection paramConnection, IOException paramIOException) { if (Internal.instance.recycleCount(paramConnection) > 0) {} for (;;) { return; Route localRoute1 = paramConnection.route; if ((localRoute1.proxy.type() != Proxy.Type.DIRECT) && (this.address.proxySelector != null)) { this.address.proxySelector.connectFailed(this.uri, localRoute1.proxy.address(), paramIOException); } this.routeDatabase.failed(localRoute1); if ((!(paramIOException instanceof SSLHandshakeException)) && (!(paramIOException instanceof SSLProtocolException))) { while (this.nextSpecIndex < this.connectionSpecs.size()) { List localList = this.connectionSpecs; int i = this.nextSpecIndex; this.nextSpecIndex = (i + 1); ConnectionSpec localConnectionSpec = (ConnectionSpec)localList.get(i); boolean bool = shouldSendTlsFallbackIndicator(localConnectionSpec); Route localRoute2 = new Route(this.address, this.lastProxy, this.lastInetSocketAddress, localConnectionSpec, bool); this.routeDatabase.failed(localRoute2); } } } }
@Test public void testTruncatedPacket() throws Exception { SSLEngine engine = SSLContext.getDefault().createSSLEngine(); engine.setUseClientMode(false); EmbeddedChannel ch = new EmbeddedChannel(new SslHandler(engine)); // Push the first part of a 5-byte handshake message. ch.writeInbound(Unpooled.wrappedBuffer(new byte[]{22, 3, 1, 0, 5})); // Should decode nothing yet. assertThat(ch.readInbound(), is(nullValue())); try { // Push the second part of the 5-byte handshake message. ch.writeInbound(Unpooled.wrappedBuffer(new byte[]{2, 0, 0, 1, 0})); fail(); } catch (DecoderException e) { // The pushed message is invalid, so it should raise an exception if it decoded the message correctly. assertThat(e.getCause(), is(instanceOf(SSLProtocolException.class))); } }
@Override public void connect( final ManagedHttpClientConnection conn, final HttpHost host, final InetSocketAddress localAddress, final int connectTimeout, final SocketConfig socketConfig, final HttpContext context) throws IOException { try { super.connect(conn, host, localAddress, connectTimeout, socketConfig, context); } catch (SSLProtocolException e) { Boolean enableSniValue = (Boolean) context.getAttribute(SSLConnectionSocketFactoryImpl.ENABLE_SNI); boolean enableSni = enableSniValue == null || enableSniValue; if (enableSni && e.getMessage() != null && e.getMessage().equals("handshake alert: unrecognized_name")) { //print.e("Server received saw wrong SNI host, retrying without SNI"); context.setAttribute(SSLConnectionSocketFactoryImpl.ENABLE_SNI, false); super.connect(conn, host, localAddress, connectTimeout, socketConfig, context); } else throw e; } }
public void test_SSL_do_handshake_missing_required_certificate() throws Exception { // required client certificate negative case final ServerSocket listener = new ServerSocket(0); try { Hooks cHooks = new Hooks(); Hooks sHooks = new ServerHooks(SERVER_PRIVATE_KEY, SERVER_CERTIFICATES) { @Override public int beforeHandshake(int c) throws SSLException { int s = super.beforeHandshake(c); NativeCrypto.SSL_set_client_CA_list(s, CA_PRINCIPALS); NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); return s; } }; Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); fail(); } catch (ExecutionException expected) { assertEquals(SSLProtocolException.class, expected.getCause().getClass()); } }
/** * Clients should invoke this method when they encounter a connectivity * failure on a connection returned by this route selector. */ public void connectFailed(Connection connection, IOException failure) { // If this is a recycled connection, don't count its failure against the route. if (Internal.instance.recycleCount(connection) > 0) return; Route failedRoute = connection.getRoute(); if (failedRoute.getProxy().type() != Proxy.Type.DIRECT && proxySelector != null) { // Tell the proxy selector when we fail to connect on a fresh connection. proxySelector.connectFailed(uri, failedRoute.getProxy().address(), failure); } routeDatabase.failed(failedRoute); // If the previously returned route's problem was not related to TLS, and // the next route only changes the TLS mode, we shouldn't even attempt it. // This suppresses it in both this selector and also in the route database. if (!(failure instanceof SSLHandshakeException) && !(failure instanceof SSLProtocolException)) { while (hasNextTlsVersion()) { Route toSuppress = new Route(address, lastProxy, lastInetSocketAddress, nextTlsVersion()); routeDatabase.failed(toSuppress); } } }