diff --git a/play-ahc-ws-standalone/src/main/scala/play/api/libs/ws/ahc/AhcConfig.scala b/play-ahc-ws-standalone/src/main/scala/play/api/libs/ws/ahc/AhcConfig.scala index 438b51216..f902358d4 100644 --- a/play-ahc-ws-standalone/src/main/scala/play/api/libs/ws/ahc/AhcConfig.scala +++ b/play-ahc-ws-standalone/src/main/scala/play/api/libs/ws/ahc/AhcConfig.scala @@ -4,8 +4,6 @@ package play.api.libs.ws.ahc -import java.security.KeyStore -import java.security.cert.CertPathValidatorException import javax.inject.{ Inject, Provider, Singleton } import javax.net.ssl._ @@ -229,14 +227,6 @@ class AhcConfigBuilder(ahcConfig: AhcWSClientConfig = AhcWSClientConfig()) { Protocols.recommendedProtocols.filter(existingProtocols.contains).toArray } - if (!sslConfig.loose.allowWeakProtocols) { - val deprecatedProtocols = Protocols.deprecatedProtocols - for (deprecatedProtocol <- deprecatedProtocols) { - if (definedProtocols.contains(deprecatedProtocol)) { - throw new IllegalStateException(s"Weak protocol $deprecatedProtocol found in ws.ssl.protocols!") - } - } - } definedProtocols } @@ -247,17 +237,9 @@ class AhcConfigBuilder(ahcConfig: AhcWSClientConfig = AhcWSClientConfig()) { configuredCiphers.filter(existingCiphers.contains(_)).toArray case None => - Ciphers.recommendedCiphers.filter(existingCiphers.contains(_)).toArray + existingCiphers } - if (!sslConfig.loose.allowWeakCiphers) { - val deprecatedCiphers = Ciphers.deprecatedCiphers - for (deprecatedCipher <- deprecatedCiphers) { - if (definedCiphers.contains(deprecatedCipher)) { - throw new IllegalStateException(s"Weak cipher $deprecatedCipher found in ws.ssl.ciphers!") - } - } - } definedCiphers } @@ -269,7 +251,6 @@ class AhcConfigBuilder(ahcConfig: AhcWSClientConfig = AhcWSClientConfig()) { // context! val sslContext = if (sslConfig.default) { logger.info("buildSSLContext: play.ws.ssl.default is true, using default SSLContext") - validateDefaultTrustManager(sslConfig) SSLContext.getDefault } else { // break out the static methods as much as we can... @@ -311,31 +292,7 @@ class AhcConfigBuilder(ahcConfig: AhcWSClientConfig = AhcWSClientConfig()) { } def validateDefaultTrustManager(sslConfig: SSLConfigSettings): Unit = { - // If we are using a default SSL context, we can't filter out certificates with weak algorithms - // We ALSO don't have access to the trust manager from the SSLContext without doing horrible things - // with reflection. - // - // However, given that the default SSLContextImpl will call out to the TrustManagerFactory and any - // configuration with system properties will also apply with the factory, we can use the factory - // method to recreate the trust manager and validate the trust certificates that way. - // - // This is really a last ditch attempt to satisfy https://wiki.mozilla.org/CA:MD5and1024 on root certificates. - // - // http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/sun/security/ssl/SSLContextImpl.java#79 - - val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm) - tmf.init(null.asInstanceOf[KeyStore]) - val trustManager: X509TrustManager = tmf.getTrustManagers()(0).asInstanceOf[X509TrustManager] - - val constraints = sslConfig.disabledKeyAlgorithms.map(a => AlgorithmConstraintsParser.parseAll(AlgorithmConstraintsParser.expression, a).get).toSet - val algorithmChecker = new AlgorithmChecker(loggerFactory, Set(), constraints) - for (cert <- trustManager.getAcceptedIssuers) { - try { - algorithmChecker.checkKeyAlgorithms(cert) - } catch { - case e: CertPathValidatorException => - logger.warn("You are using play.ws.ssl.default=true and have a weak certificate in your default trust store! (You can modify play.ws.ssl.disabledKeyAlgorithms to remove this message.)", e) - } - } + logger.warn( + "validateDefaultTrustManager is not doing anything since play-ws 2.1.8, it was useful only in Java 7 and below"); } } diff --git a/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala b/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala index b18db05fa..d672d8670 100644 --- a/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala +++ b/play-ahc-ws-standalone/src/test/scala/play/api/libs/ws/ahc/AhcConfigBuilderSpec.scala @@ -5,13 +5,12 @@ package play.api.libs.ws.ahc import com.typesafe.config.{ Config, ConfigFactory } -import com.typesafe.sslconfig.ssl.{ Ciphers, Protocols, SSLConfigFactory, SSLConfigSettings } +import com.typesafe.sslconfig.ssl.{ Protocols, SSLConfigFactory, SSLConfigSettings } import org.specs2.mock.Mockito import org.specs2.mutable.Specification import play.api.libs.ws.WSClientConfig import play.shaded.ahc.org.asynchttpclient.proxy.ProxyServerSelector import play.shaded.ahc.org.asynchttpclient.util.ProxyUtils -import uk.org.lidalia.slf4jtest.TestLoggerFactory import scala.concurrent.duration._ @@ -53,7 +52,6 @@ class AhcConfigBuilderSpec extends Specification with Mockito { actual.isFollowRedirect must_== defaultWsConfig.followRedirects actual.getCookieStore must_== null - actual.getEnabledCipherSuites.toSeq must not contain Ciphers.deprecatedCiphers actual.getEnabledProtocols.toSeq must not contain Protocols.deprecatedProtocols } @@ -184,47 +182,6 @@ class AhcConfigBuilderSpec extends Specification with Mockito { asyncClientConfig.getSslEngineFactory must not(beNull) } - "use the default with a current certificate" in { - // You can't get the value of SSLContext out from the JSSE SSL engine factory, so - // checking SSLContext.getDefault from a default = true is hard. - // Unless we can mock this, it doesn't seem like it's easy to unit test. - pending("AHC 2.0 does not provide a reference to a configured SSLContext") - - //val tmc = TrustManagerConfig() - //val wsConfig = defaultWsConfig.copy(ssl = SSLConfig(default = true, trustManagerConfig = tmc)) - //val config = defaultConfig.copy(wsClientConfig = wsConfig) - //val builder = new AhcConfigBuilder(config) - // - //val asyncClientConfig = builder.build() - //val sslEngineFactory = asyncClientConfig.getSslEngineFactory - } - - "log a warning if sslConfig.default is passed in with an weak certificate" in { - import scala.collection.JavaConverters._ - // Pass in a configuration which is guaranteed to fail, by banning RSA, DSA and EC certificates - val underlyingConfig = parseSSLConfig( - """ - |play.ws.ssl.default=true - |play.ws.ssl.disabledKeyAlgorithms=["RSA", "DSA", "EC"] - """.stripMargin) - val sslConfigSettings = SSLConfigFactory.parse(underlyingConfig) - - val wsConfig = defaultWsConfig.copy(ssl = sslConfigSettings) - val config = defaultConfig.copy(wsClientConfig = wsConfig) - - // clear the logger of any messages... - TestLoggerFactory.clear() - val builder = new AhcConfigBuilder(config) - - // Run method that will trigger the logger warning - builder.configureSSL(sslConfig = sslConfigSettings) - - val loggerFactory = TestLoggerFactory.getInstance() - val logger = loggerFactory.getLogger(builder.getClass) - val messages = logger.getLoggingEvents.asList().asScala.map(_.getMessage) - messages must contain("You are using play.ws.ssl.default=true and have a weak certificate in your default trust store! (You can modify play.ws.ssl.disabledKeyAlgorithms to remove this message.)") - } - "should validate certificates" in { val sslConfig = SSLConfigSettings() val wsConfig = defaultWsConfig.copy(ssl = sslConfig) @@ -273,47 +230,6 @@ class AhcConfigBuilderSpec extends Specification with Mockito { actual.toSeq must containTheSameElementsAs(Seq("derp", "baz", "quux")) } - - "throw exception on deprecated protocols from explicit list" in { - val deprecatedProtocol = Protocols.deprecatedProtocols.head - - // the enabled protocol list has a deprecated protocol in it. - val underlyingConfig = parseSSLConfig(s"""play.ws.ssl.enabledProtocols=["$deprecatedProtocol", "goodOne", "goodTwo"]""") - val sslConfig = SSLConfigFactory.parse(underlyingConfig) - val wsConfig = defaultWsConfig.copy(ssl = sslConfig) - val config = defaultConfig.copy(wsClientConfig = wsConfig) - - val builder = new AhcConfigBuilder(config) - - // The existing protocols is larger than the enabled list, and out of order. - val existingProtocols = Array("goodTwo", "badOne", "badTwo", deprecatedProtocol, "goodOne") - - builder.configureProtocols(existingProtocols, sslConfig).must(throwAn[IllegalStateException]) - } - - "not throw exception on deprecated protocols from list if allowWeakProtocols is enabled" in { - val deprecatedProtocol = Protocols.deprecatedProtocols.head - - // the enabled protocol list has a deprecated protocol in it. - val underlyingConfig = parseSSLConfig( - s""" - |play.ws.ssl.enabledProtocols=["$deprecatedProtocol", "goodOne", "goodTwo"] - |play.ws.ssl.loose.allowWeakProtocols=true - """.stripMargin) - val sslConfig = SSLConfigFactory.parse(underlyingConfig) - val wsConfig = defaultWsConfig.copy(ssl = sslConfig) - val config = defaultConfig.copy(wsClientConfig = wsConfig) - - val builder = new AhcConfigBuilder(config) - - // The existing protocols is larger than the enabled list, and out of order. - val existingProtocols = Array("goodTwo", "badOne", "badTwo", deprecatedProtocol, "goodOne") - - val actual = builder.configureProtocols(existingProtocols, sslConfig) - - // We should only have the list in order, including the deprecated protocol. - actual.toSeq must containTheSameElementsAs(Seq(deprecatedProtocol, "goodOne", "goodTwo")) - } } "with ciphers" should { @@ -330,38 +246,6 @@ class AhcConfigBuilderSpec extends Specification with Mockito { actual.toSeq must containTheSameElementsAs(Seq("goodone", "goodtwo")) } - - "throw exception on deprecated ciphers from the explicit cipher list" in { - val underlyingConfig = parseSSLConfig(s"""play.ws.ssl.enabledCipherSuites=[${Ciphers.deprecatedCiphers.head}, "goodone", "goodtwo"]""") - val enabledCiphers = Seq(Ciphers.deprecatedCiphers.head, "goodone", "goodtwo") - val sslConfig = SSLConfigFactory.parse(underlyingConfig) - val wsConfig = defaultWsConfig.copy(ssl = sslConfig) - val config = defaultConfig.copy(wsClientConfig = wsConfig) - val builder = new AhcConfigBuilder(config) - val existingCiphers = enabledCiphers.toArray - - builder.configureCipherSuites(existingCiphers, sslConfig).must(throwAn[IllegalStateException]) - } - - "not throw exception on deprecated ciphers if allowWeakCiphers is enabled" in { - // User specifies list with deprecated ciphers... - val underlyingConfig = parseSSLConfig( - """ - |play.ws.ssl.enabledCipherSuites=[badone, "goodone", "goodtwo"] - |play.ws.ssl.loose.allowWeakCiphers=true - """.stripMargin) - - val sslConfig = SSLConfigFactory.parse(underlyingConfig) - val wsConfig = defaultWsConfig.copy(ssl = sslConfig) - val config = defaultConfig.copy(wsClientConfig = wsConfig) - val builder = new AhcConfigBuilder(config) - val existingCiphers = Array("badone", "goodone", "goodtwo") - - val actual = builder.configureCipherSuites(existingCiphers, sslConfig) - - actual.toSeq must containTheSameElementsAs(Seq("badone", "goodone", "goodtwo")) - } - } } } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 5fa68d189..ee5a46129 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -33,7 +33,7 @@ object Dependencies { val javaxInject = Seq("javax.inject" % "javax.inject" % "1") - val sslConfigVersion = "0.4.1" + val sslConfigVersion = "0.6.0" val sslConfigCore = Seq("com.typesafe" %% "ssl-config-core" % sslConfigVersion) val scalaXmlVersion = "1.2.0"