mirror of
https://github.com/corda/corda.git
synced 2025-02-21 17:56:54 +00:00
CORDA-3520, CORDA-3550: SSH memory leak and security (#5873)
* CORDA-3520: Closing RPC connection on SSH disconnect CORDA-3550: Remove support for outdated ciphers and algorithms from SSH * CORDA-3550: Remove support for outdated ciphers and algorithms from SSH
This commit is contained in:
parent
597658c4ab
commit
6a2249e697
@ -104,7 +104,7 @@ buildscript {
|
|||||||
ext.dependency_checker_version = '5.2.0'
|
ext.dependency_checker_version = '5.2.0'
|
||||||
ext.commons_collections_version = '4.3'
|
ext.commons_collections_version = '4.3'
|
||||||
ext.beanutils_version = '1.9.3'
|
ext.beanutils_version = '1.9.3'
|
||||||
ext.crash_version = '1.7.1'
|
ext.crash_version = '1.7.2'
|
||||||
ext.jsr305_version = constants.getProperty("jsr305Version")
|
ext.jsr305_version = constants.getProperty("jsr305Version")
|
||||||
ext.shiro_version = '1.4.1'
|
ext.shiro_version = '1.4.1'
|
||||||
ext.artifactory_plugin_version = constants.getProperty('artifactoryPluginVersion')
|
ext.artifactory_plugin_version = constants.getProperty('artifactoryPluginVersion')
|
||||||
|
@ -103,6 +103,8 @@ Unreleased
|
|||||||
* Environment variables and system properties can now be provided with underscore separators instead of dots. Neither are case sensitive.
|
* Environment variables and system properties can now be provided with underscore separators instead of dots. Neither are case sensitive.
|
||||||
See :ref:`overriding config values <corda_configuration_file_overriding_config>` for more information.
|
See :ref:`overriding config values <corda_configuration_file_overriding_config>` for more information.
|
||||||
|
|
||||||
|
* SSH server in the :doc:`shell` has been updated to remove outdated weak ciphers and algorithms.
|
||||||
|
|
||||||
.. _changelog_v4.1:
|
.. _changelog_v4.1:
|
||||||
|
|
||||||
Version 4.1
|
Version 4.1
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.tools.shell
|
package net.corda.tools.shell
|
||||||
|
|
||||||
|
import net.corda.client.rpc.CordaRPCConnection
|
||||||
import net.corda.core.internal.messaging.InternalCordaRPCOps
|
import net.corda.core.internal.messaging.InternalCordaRPCOps
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException
|
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException
|
||||||
@ -7,7 +8,7 @@ import org.crsh.auth.AuthInfo
|
|||||||
import org.crsh.auth.AuthenticationPlugin
|
import org.crsh.auth.AuthenticationPlugin
|
||||||
import org.crsh.plugin.CRaSHPlugin
|
import org.crsh.plugin.CRaSHPlugin
|
||||||
|
|
||||||
class CordaAuthenticationPlugin(private val rpcOps: (username: String, credential: String) -> InternalCordaRPCOps) : CRaSHPlugin<AuthenticationPlugin<String>>(), AuthenticationPlugin<String> {
|
class CordaAuthenticationPlugin(private val makeRPCConnection: (username: String, credential: String) -> CordaRPCConnection) : CRaSHPlugin<AuthenticationPlugin<String>>(), AuthenticationPlugin<String> {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val logger = loggerFor<CordaAuthenticationPlugin>()
|
private val logger = loggerFor<CordaAuthenticationPlugin>()
|
||||||
@ -23,8 +24,9 @@ class CordaAuthenticationPlugin(private val rpcOps: (username: String, credentia
|
|||||||
return AuthInfo.UNSUCCESSFUL
|
return AuthInfo.UNSUCCESSFUL
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
val ops = rpcOps(username, credential)
|
val connection = makeRPCConnection(username, credential)
|
||||||
return CordaSSHAuthInfo(true, ops, isSsh = true)
|
val ops = connection.proxy as InternalCordaRPCOps
|
||||||
|
return CordaSSHAuthInfo(true, ops, isSsh = true, rpcConn = connection)
|
||||||
} catch (e: ActiveMQSecurityException) {
|
} catch (e: ActiveMQSecurityException) {
|
||||||
logger.warn(e.message)
|
logger.warn(e.message)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package net.corda.tools.shell
|
||||||
|
|
||||||
|
import org.crsh.auth.AuthInfo
|
||||||
|
import org.crsh.auth.DisconnectPlugin
|
||||||
|
import org.crsh.plugin.CRaSHPlugin
|
||||||
|
|
||||||
|
class CordaDisconnectPlugin : CRaSHPlugin<DisconnectPlugin>(), DisconnectPlugin {
|
||||||
|
override fun getImplementation() = this
|
||||||
|
|
||||||
|
override fun onDisconnect(userName: String?, authInfo: AuthInfo?) {
|
||||||
|
(authInfo as? CordaSSHAuthInfo)?.rpcConn?.forceClose()
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,14 @@
|
|||||||
package net.corda.tools.shell
|
package net.corda.tools.shell
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import net.corda.client.rpc.CordaRPCConnection
|
||||||
import net.corda.core.internal.messaging.InternalCordaRPCOps
|
import net.corda.core.internal.messaging.InternalCordaRPCOps
|
||||||
import net.corda.tools.shell.InteractiveShell.createYamlInputMapper
|
import net.corda.tools.shell.InteractiveShell.createYamlInputMapper
|
||||||
import net.corda.tools.shell.utlities.ANSIProgressRenderer
|
import net.corda.tools.shell.utlities.ANSIProgressRenderer
|
||||||
import org.crsh.auth.AuthInfo
|
import org.crsh.auth.AuthInfo
|
||||||
|
|
||||||
class CordaSSHAuthInfo(val successful: Boolean, val rpcOps: InternalCordaRPCOps, val ansiProgressRenderer: ANSIProgressRenderer? = null, val isSsh: Boolean = false) : AuthInfo {
|
class CordaSSHAuthInfo(val successful: Boolean, val rpcOps: InternalCordaRPCOps, val ansiProgressRenderer: ANSIProgressRenderer? = null,
|
||||||
|
val isSsh: Boolean = false, val rpcConn: CordaRPCConnection? = null) : AuthInfo {
|
||||||
override fun isSuccessful(): Boolean = successful
|
override fun isSuccessful(): Boolean = successful
|
||||||
|
|
||||||
val yamlInputMapper: ObjectMapper by lazy {
|
val yamlInputMapper: ObjectMapper by lazy {
|
||||||
|
@ -94,7 +94,7 @@ const val STANDALONE_SHELL_PERMISSION = "ALL"
|
|||||||
@Suppress("MaxLineLength")
|
@Suppress("MaxLineLength")
|
||||||
object InteractiveShell {
|
object InteractiveShell {
|
||||||
private val log = LoggerFactory.getLogger(javaClass)
|
private val log = LoggerFactory.getLogger(javaClass)
|
||||||
private lateinit var rpcOps: (username: String, password: String) -> InternalCordaRPCOps
|
private lateinit var makeRPCConnection: (username: String, password: String) -> CordaRPCConnection
|
||||||
private lateinit var ops: InternalCordaRPCOps
|
private lateinit var ops: InternalCordaRPCOps
|
||||||
private lateinit var rpcConn: CordaRPCConnection
|
private lateinit var rpcConn: CordaRPCConnection
|
||||||
private var shell: Shell? = null
|
private var shell: Shell? = null
|
||||||
@ -112,7 +112,7 @@ object InteractiveShell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun startShell(configuration: ShellConfiguration, classLoader: ClassLoader? = null, standalone: Boolean = false) {
|
fun startShell(configuration: ShellConfiguration, classLoader: ClassLoader? = null, standalone: Boolean = false) {
|
||||||
rpcOps = { username: String, password: String ->
|
makeRPCConnection = { username: String, password: String ->
|
||||||
val connection = if (standalone) {
|
val connection = if (standalone) {
|
||||||
CordaRPCClient(
|
CordaRPCClient(
|
||||||
configuration.hostAndPort,
|
configuration.hostAndPort,
|
||||||
@ -130,7 +130,7 @@ object InteractiveShell {
|
|||||||
).start(username, password)
|
).start(username, password)
|
||||||
}
|
}
|
||||||
rpcConn = connection
|
rpcConn = connection
|
||||||
connection.proxy as InternalCordaRPCOps
|
connection
|
||||||
}
|
}
|
||||||
launchShell(configuration, standalone, classLoader)
|
launchShell(configuration, standalone, classLoader)
|
||||||
}
|
}
|
||||||
@ -252,7 +252,8 @@ object InteractiveShell {
|
|||||||
// Don't use the Java language plugin (we may not have tools.jar available at runtime), this
|
// Don't use the Java language plugin (we may not have tools.jar available at runtime), this
|
||||||
// will cause any commands using JIT Java compilation to be suppressed. In CRaSH upstream that
|
// will cause any commands using JIT Java compilation to be suppressed. In CRaSH upstream that
|
||||||
// is only the 'jmx' command.
|
// is only the 'jmx' command.
|
||||||
return super.getPlugins().filterNot { it is JavaLanguage } + CordaAuthenticationPlugin(rpcOps)
|
return super.getPlugins().filterNot { it is JavaLanguage } + CordaAuthenticationPlugin(makeRPCConnection) +
|
||||||
|
CordaDisconnectPlugin()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val attributes = emptyMap<String, Any>()
|
val attributes = emptyMap<String, Any>()
|
||||||
@ -260,6 +261,7 @@ object InteractiveShell {
|
|||||||
context.refresh()
|
context.refresh()
|
||||||
this.config = config
|
this.config = config
|
||||||
start(context)
|
start(context)
|
||||||
|
val rpcOps = { username: String, password: String -> makeRPCConnection(username, password).proxy as InternalCordaRPCOps }
|
||||||
ops = makeRPCOps(rpcOps, localUserName, localUserPassword)
|
ops = makeRPCOps(rpcOps, localUserName, localUserPassword)
|
||||||
return context.getPlugin(ShellFactory::class.java).create(null, CordaSSHAuthInfo(false, ops,
|
return context.getPlugin(ShellFactory::class.java).create(null, CordaSSHAuthInfo(false, ops,
|
||||||
StdoutANSIProgressRenderer), shellSafety)
|
StdoutANSIProgressRenderer), shellSafety)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user