Skip to content

Commit

Permalink
[OkHttp]Add hostname verification.
Browse files Browse the repository at this point in the history
  • Loading branch information
Xudong Ma committed Dec 21, 2015
1 parent 663a4f4 commit d948330
Show file tree
Hide file tree
Showing 5 changed files with 712 additions and 7 deletions.
Expand Up @@ -31,6 +31,12 @@

package io.grpc.testing.integration;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.google.common.base.Throwables;
import com.google.protobuf.EmptyProtos.Empty;

import com.squareup.okhttp.ConnectionSpec;
import com.squareup.okhttp.TlsVersion;

Expand All @@ -52,6 +58,8 @@

import java.io.IOException;

import javax.net.ssl.SSLPeerUnverifiedException;

/**
* Integration tests for GRPC over Http2 using the OkHttp framework.
*/
Expand Down Expand Up @@ -117,4 +125,29 @@ public void receivedDataForFinishedStream() throws Exception {
recorder.awaitCompletion();
emptyUnary();
}

@Test(timeout = 10000)
public void wrongHostNameFailHostnameVerification() throws Exception {
OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("127.0.0.1", serverPort)
.connectionSpec(new ConnectionSpec.Builder(OkHttpChannelBuilder.DEFAULT_CONNECTION_SPEC)
.cipherSuites(TestUtils.preferredTestCiphers().toArray(new String[0]))
.tlsVersions(ConnectionSpec.MODERN_TLS.tlsVersions().toArray(new TlsVersion[0]))
.build())
.overrideAuthority(GrpcUtil.authorityFromHostAndPort(
"I.am.a.bad.hostname", serverPort));
ManagedChannel channel = builder.sslSocketFactory(
TestUtils.newSslSocketFactoryForCa(TestUtils.loadCert("ca.pem"))).build();
TestServiceGrpc.TestServiceBlockingStub blockingStub =
TestServiceGrpc.newBlockingStub(channel);

try {
blockingStub.emptyCall(Empty.getDefaultInstance());
fail("The rpc should have been failed due to hostname verification");
} catch (Throwable t) {
Throwable cause = Throwables.getRootCause(t);
assertTrue("Failed by unexpected exception: " + cause,
cause instanceof SSLPeerUnverifiedException);
}
channel.shutdown();
}
}
Expand Up @@ -46,6 +46,7 @@
import java.security.Security;
import java.util.List;

import javax.annotation.Nullable;
import javax.net.ssl.SSLSocket;

/**
Expand Down Expand Up @@ -96,8 +97,10 @@ static OkHttpProtocolNegotiator createNegotiator(ClassLoader loader) {
* @throws RuntimeException if the negotiation completed, but no protocol was selected.
*/
public String negotiate(
SSLSocket sslSocket, String hostname, List<Protocol> protocols) throws IOException {
configureTlsExtensions(sslSocket, hostname, protocols);
SSLSocket sslSocket, String hostname, @Nullable List<Protocol> protocols) throws IOException {
if (protocols != null) {
configureTlsExtensions(sslSocket, hostname, protocols);
}
try {
// Force handshake.
sslSocket.startHandshake();
Expand Down
14 changes: 9 additions & 5 deletions okhttp/src/main/java/io/grpc/okhttp/OkHttpTlsUpgrader.java
Expand Up @@ -34,6 +34,7 @@
import com.google.common.base.Preconditions;

import io.grpc.okhttp.internal.ConnectionSpec;
import io.grpc.okhttp.internal.OkHostnameVerifier;
import io.grpc.okhttp.internal.Protocol;

import java.io.IOException;
Expand All @@ -42,6 +43,7 @@
import java.util.Collections;
import java.util.List;

import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

Expand Down Expand Up @@ -69,11 +71,13 @@ public static SSLSocket upgrade(SSLSocketFactory sslSocketFactory,
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(
socket, host, port, true /* auto close */);
spec.apply(sslSocket, false);
if (spec.supportsTlsExtensions()) {
String negotiatedProtocol =
OkHttpProtocolNegotiator.get().negotiate(sslSocket, host, TLS_PROTOCOLS);
Preconditions.checkState(HTTP2_PROTOCOL_NAME.equals(negotiatedProtocol),
"Only \"h2\" is supported, but negotiated protocol is %s", negotiatedProtocol);
String negotiatedProtocol = OkHttpProtocolNegotiator.get().negotiate(
sslSocket, host, spec.supportsTlsExtensions() ? TLS_PROTOCOLS : null);
Preconditions.checkState(HTTP2_PROTOCOL_NAME.equals(negotiatedProtocol),
"Only \"h2\" is supported, but negotiated protocol is %s", negotiatedProtocol);

if (!OkHostnameVerifier.INSTANCE.verify(host, sslSocket.getSession())) {
throw new SSLPeerUnverifiedException("Cannot verify hostname: " + host);
}
return sslSocket;
}
Expand Down

0 comments on commit d948330

Please sign in to comment.