From 021829e21e76b13fa961eb973339c9ab77e94edc Mon Sep 17 00:00:00 2001 From: ortigali Date: Thu, 16 Feb 2017 00:40:42 +0500 Subject: [PATCH] =str Remove manual hostname verifier support, used to be included only because Java 6 (#22320) * Remove manual hostname verifier support, used to be included only because Java 6 #21854 * Remove manual hostname verifier support, used to be included only because Java 6 #21854 --- .../test/scala/akka/stream/io/TlsSpec.scala | 19 ++++++++++++++ .../stream/impl/ActorMaterializerImpl.scala | 2 +- .../scala/akka/stream/impl/io/TLSActor.scala | 17 +++---------- .../scala/akka/stream/impl/io/TlsModule.scala | 6 ++--- .../main/scala/akka/stream/scaladsl/TLS.scala | 25 ++++++------------- project/MiMa.scala | 3 +++ 6 files changed, 37 insertions(+), 35 deletions(-) diff --git a/akka-stream-tests/src/test/scala/akka/stream/io/TlsSpec.scala b/akka-stream-tests/src/test/scala/akka/stream/io/TlsSpec.scala index 7d50ebab75..2dc1295ff9 100644 --- a/akka-stream-tests/src/test/scala/akka/stream/io/TlsSpec.scala +++ b/akka-stream-tests/src/test/scala/akka/stream/io/TlsSpec.scala @@ -471,6 +471,25 @@ class TlsSpec extends StreamSpec("akka.loglevel=INFO\nakka.actor.debug.receive=o Await.result(f, 8.second).utf8String should be(scenario.output.utf8String) } + "verify hostname" in assertAllStagesStopped { + def run(hostName: String): Future[akka.Done] = { + val rhs = Flow[SslTlsInbound] + .map { + case SessionTruncated ⇒ SendBytes(ByteString.empty) + case SessionBytes(_, b) ⇒ SendBytes(b) + } + val clientTls = TLS(sslContext, None, cipherSuites, Client, EagerClose, Some((hostName, 80))) + val flow = clientTls atop serverTls(EagerClose).reversed join rhs + + Source.single(SendBytes(ByteString.empty)).via(flow).runWith(Sink.ignore) + } + Await.result(run("akka-remote"), 3.seconds) // CN=akka-remote + val cause = intercept[SSLHandshakeException] { + Await.result(run("akka-stream"), 3.seconds) + } + cause.getCause.getCause.getMessage should startWith("No name matching akka-stream found") + } + } "A SslTlsPlacebo" must { diff --git a/akka-stream/src/main/scala/akka/stream/impl/ActorMaterializerImpl.scala b/akka-stream/src/main/scala/akka/stream/impl/ActorMaterializerImpl.scala index 8613a2b07c..857d6568d8 100644 --- a/akka-stream/src/main/scala/akka/stream/impl/ActorMaterializerImpl.scala +++ b/akka-stream/src/main/scala/akka/stream/impl/ActorMaterializerImpl.scala @@ -197,7 +197,7 @@ private[akka] case class ActorMaterializerImpl( case tls: TlsModule ⇒ // TODO solve this so TlsModule doesn't need special treatment here val es = effectiveSettings(effectiveAttributes) val props = - TLSActor.props(es, tls.createSSLEngine, tls.verifySession, tls.closing) + TLSActor.props(es, tls.createSSLEngine, tls.closing) val impl = actorOf(props, stageName(effectiveAttributes), es.dispatcher) def factory(id: Int) = new ActorPublisher[Any](impl) { override val wakeUpMsg = FanOut.SubstreamSubscribePending(id) diff --git a/akka-stream/src/main/scala/akka/stream/impl/io/TLSActor.scala b/akka-stream/src/main/scala/akka/stream/impl/io/TLSActor.scala index 3fa9625290..e732024717 100644 --- a/akka-stream/src/main/scala/akka/stream/impl/io/TLSActor.scala +++ b/akka-stream/src/main/scala/akka/stream/impl/io/TLSActor.scala @@ -30,10 +30,9 @@ private[stream] object TLSActor { def props( settings: ActorMaterializerSettings, createSSLEngine: ActorSystem ⇒ SSLEngine, // ActorSystem is only needed to support the AkkaSSLConfig legacy, see #21753 - verifySession: (ActorSystem, SSLSession) ⇒ Try[Unit], // ActorSystem is only needed to support the AkkaSSLConfig legacy, see #21753 closing: TLSClosing, - tracing: Boolean = false): Props = - Props(new TLSActor(settings, createSSLEngine, verifySession, closing, tracing)).withDeploy(Deploy.local) + tracing: Boolean = false): Props = + Props(new TLSActor(settings, createSSLEngine, closing, tracing)).withDeploy(Deploy.local) final val TransportIn = 0 final val TransportOut = 0 @@ -48,7 +47,6 @@ private[stream] object TLSActor { private[stream] class TLSActor( settings: ActorMaterializerSettings, createSSLEngine: ActorSystem ⇒ SSLEngine, // ActorSystem is only needed to support the AkkaSSLConfig legacy, see #21753 - verifySession: (ActorSystem, SSLSession) ⇒ Try[Unit], // ActorSystem is only needed to support the AkkaSSLConfig legacy, see #21753 closing: TLSClosing, tracing: Boolean) extends Actor with ActorLogging with Pump { @@ -410,15 +408,8 @@ private[stream] class TLSActor( private def handshakeFinished(): Unit = { if (tracing) log.debug("handshake finished") - val session = engine.getSession - - verifySession(context.system, session) match { - case Success(()) ⇒ - currentSession = session - corkUser = false - case Failure(ex) ⇒ - fail(ex, closeTransport = true) - } + currentSession = engine.getSession + corkUser = false } override def receive = inputBunch.subreceive.orElse[Any, Unit](outputBunch.subreceive) diff --git a/akka-stream/src/main/scala/akka/stream/impl/io/TlsModule.scala b/akka-stream/src/main/scala/akka/stream/impl/io/TlsModule.scala index 21d787b4c3..09551e24b1 100644 --- a/akka-stream/src/main/scala/akka/stream/impl/io/TlsModule.scala +++ b/akka-stream/src/main/scala/akka/stream/impl/io/TlsModule.scala @@ -18,11 +18,10 @@ private[stream] final case class TlsModule(plainIn: Inlet[SslTlsOutbound], plain cipherIn: Inlet[ByteString], cipherOut: Outlet[ByteString], shape: Shape, attributes: Attributes, createSSLEngine: ActorSystem ⇒ SSLEngine, // ActorSystem is only needed to support the AkkaSSLConfig legacy, see #21753 - verifySession: (ActorSystem, SSLSession) ⇒ Try[Unit], // ActorSystem is only needed to support the AkkaSSLConfig legacy, see #21753 closing: TLSClosing) extends AtomicModule { override def withAttributes(att: Attributes): TlsModule = copy(attributes = att) - override def carbonCopy: TlsModule = TlsModule(attributes, createSSLEngine, verifySession, closing) + override def carbonCopy: TlsModule = TlsModule(attributes, createSSLEngine, closing) override def replaceShape(s: Shape) = if (s != shape) { @@ -40,7 +39,6 @@ private[stream] object TlsModule { def apply( attributes: Attributes, createSSLEngine: ActorSystem ⇒ SSLEngine, // ActorSystem is only needed to support the AkkaSSLConfig legacy, see #21753 - verifySession: (ActorSystem, SSLSession) ⇒ Try[Unit], // ActorSystem is only needed to support the AkkaSSLConfig legacy, see #21753 closing: TLSClosing): TlsModule = { val name = attributes.nameOrDefault(s"StreamTls()") val cipherIn = Inlet[ByteString](s"$name.cipherIn") @@ -48,6 +46,6 @@ private[stream] object TlsModule { val plainIn = Inlet[SslTlsOutbound](s"$name.transportIn") val plainOut = Outlet[SslTlsInbound](s"$name.transportOut") val shape = new BidiShape(plainIn, cipherOut, cipherIn, plainOut) - TlsModule(plainIn, plainOut, cipherIn, cipherOut, shape, attributes, createSSLEngine, verifySession, closing) + TlsModule(plainIn, plainOut, cipherIn, cipherOut, shape, attributes, createSSLEngine, closing) } } diff --git a/akka-stream/src/main/scala/akka/stream/scaladsl/TLS.scala b/akka-stream/src/main/scala/akka/stream/scaladsl/TLS.scala index cfb35821ca..74de43ca07 100644 --- a/akka-stream/src/main/scala/akka/stream/scaladsl/TLS.scala +++ b/akka-stream/src/main/scala/akka/stream/scaladsl/TLS.scala @@ -84,6 +84,12 @@ object TLS { config.sslEngineConfigurator.configure(engine, sslContext) engine.setUseClientMode(role == Client) + if (!config.config.loose.disableHostnameVerification && engine.getUseClientMode && hostInfo.isDefined) { + val parameters = engine.getSSLParameters + parameters.setEndpointIdentificationAlgorithm("HTTPS") + engine.setSSLParameters(parameters) + } + val finalSessionParameters = if (firstSession.sslParameters.isDefined && hostInfo.isDefined && !config.config.loose.disableSNI) { val newParams = TlsUtils.cloneParameters(firstSession.sslParameters.get) @@ -99,19 +105,8 @@ object TLS { TlsUtils.applySessionParameters(engine, finalSessionParameters) engine } - def verifySession: (ActorSystem, SSLSession) ⇒ Try[Unit] = - hostInfo match { - case Some((hostname, _)) ⇒ { (system, session) ⇒ - val hostnameVerifier = theSslConfig(system).hostnameVerifier - if (!hostnameVerifier.verify(hostname, session)) - Failure(new ConnectionException(s"Hostname verification failed! Expected session to be for $hostname")) - else - Success(()) - } - case None ⇒ (_, _) ⇒ Success(()) - } - new scaladsl.BidiFlow(TlsModule(Attributes.none, createSSLEngine, verifySession, closing)) + new scaladsl.BidiFlow(TlsModule(Attributes.none, createSSLEngine, closing)) } /** @@ -156,17 +151,13 @@ object TLS { * You can specify a constructor to create an SSLEngine that must already be configured for * client and server mode and with all the parameters for the first session. * - * You can specify a verification function that will be called after every successful handshake - * to verify additional session information. - * * For a description of the `closing` parameter please refer to [[TLSClosing]]. */ def apply( createSSLEngine: () ⇒ SSLEngine, // we don't offer the internal `ActorSystem => SSLEngine` API here, see #21753 - verifySession: SSLSession ⇒ Try[Unit], // we don't offer the internal API that provides `ActorSystem` here, see #21753 closing: TLSClosing ): scaladsl.BidiFlow[SslTlsOutbound, ByteString, ByteString, SslTlsInbound, NotUsed] = - new scaladsl.BidiFlow(TlsModule(Attributes.none, _ ⇒ createSSLEngine(), (_, session) ⇒ verifySession(session), closing)) + new scaladsl.BidiFlow(TlsModule(Attributes.none, _ ⇒ createSSLEngine(), closing)) } /** diff --git a/project/MiMa.scala b/project/MiMa.scala index d3ea8bf141..7d5bb2a9c1 100644 --- a/project/MiMa.scala +++ b/project/MiMa.scala @@ -394,6 +394,9 @@ object MiMa extends AutoPlugin { ProblemFilters.exclude[DirectMissingMethodProblem]("akka.cluster.ddata.Replicator#WriteMajority.copy"), ProblemFilters.exclude[DirectMissingMethodProblem]("akka.cluster.ddata.Replicator#WriteMajority.apply"), + // #21854 Remove manual hostname verifier support + ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.stream.scaladsl.TLS.apply"), + // #22277 changes to internal classes ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.transport.netty.TcpServerHandler.this"), ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.transport.netty.TcpClientHandler.this"),