CORDA-2001: added SNI header to TLS connections based on hashed CordaX500 (#3968)

* CORDA-2001: added SNI header to TLS connections based on hashed CordaX500

* CORDA-2001: added newline

* CORDA-2001: truncate hashed x500 to pass IDN validations

* CORDA-2001: convert hostname to lower case

* CORDA-2001: to lower after truncating, use of better suited method

* CORDA-2001: to lower after truncating, use of better suited method

* CORDA-2001: correctly set ssl parameters in the engine
This commit is contained in:
bpaunescu 2018-09-20 16:22:27 +01:00 committed by GitHub
parent 4639f14383
commit 5139ac3d01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 1 deletions

View File

@ -123,7 +123,7 @@ class AMQPClient(val targets: List<NetworkHostAndPort>,
override fun initChannel(ch: SocketChannel) {
val pipeline = ch.pipeline()
val target = parent.currentTarget
val handler = createClientSslHelper(target, keyManagerFactory, trustManagerFactory)
val handler = createClientSslHelper(target, parent.allowedRemoteLegalNames, keyManagerFactory, trustManagerFactory)
pipeline.addLast("sslHandler", handler)
if (conf.trace) pipeline.addLast("logger", LoggingHandler(LogLevel.INFO))
pipeline.addLast(AMQPChannelHandler(false,

View File

@ -1,7 +1,9 @@
package net.corda.nodeapi.internal.protonwrapper.netty
import io.netty.handler.ssl.SslHandler
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.newSecureRandom
import net.corda.core.identity.CordaX500Name
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.toHex
@ -16,6 +18,8 @@ import java.security.cert.*
import java.util.*
import javax.net.ssl.*
private const val HOSTNAME_FORMAT = "%s.corda.net"
internal class LoggingTrustManagerWrapper(val wrapped: X509ExtendedTrustManager) : X509ExtendedTrustManager() {
companion object {
val log = contextLogger()
@ -102,6 +106,7 @@ internal class LoggingTrustManagerWrapper(val wrapped: X509ExtendedTrustManager)
}
internal fun createClientSslHelper(target: NetworkHostAndPort,
expectedRemoteLegalNames: Set<CordaX500Name>,
keyManagerFactory: KeyManagerFactory,
trustManagerFactory: TrustManagerFactory): SslHandler {
val sslContext = SSLContext.getInstance("TLS")
@ -113,6 +118,11 @@ internal fun createClientSslHelper(target: NetworkHostAndPort,
sslEngine.enabledProtocols = ArtemisTcpTransport.TLS_VERSIONS.toTypedArray()
sslEngine.enabledCipherSuites = ArtemisTcpTransport.CIPHER_SUITES.toTypedArray()
sslEngine.enableSessionCreation = true
if (expectedRemoteLegalNames.size == 1) {
val sslParameters = sslEngine.sslParameters
sslParameters.serverNames = listOf(SNIHostName(x500toHostName(expectedRemoteLegalNames.single())))
sslEngine.sslParameters = sslParameters
}
return SslHandler(sslEngine)
}
@ -152,3 +162,10 @@ internal fun initialiseTrustStoreAndEnableCrlChecking(trustStore: CertificateSto
fun KeyManagerFactory.init(keyStore: CertificateStore) = init(keyStore.value.internal, keyStore.password.toCharArray())
fun TrustManagerFactory.init(trustStore: CertificateStore) = init(trustStore.value.internal)
internal fun x500toHostName(x500Name: CordaX500Name): String {
val secureHash = SecureHash.sha256(x500Name.toString())
// RFC 1035 specifies a limit 255 bytes for hostnames with each label being 63 bytes or less. Due to this, the string
// representation of the SHA256 hash is truncated to 32 characters.
return String.format(HOSTNAME_FORMAT, secureHash.toString().substring(0..32).toLowerCase())
}