mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-16 02:12:58 +08:00
chore: improve x11
This commit is contained in:
@@ -3,7 +3,6 @@ package app.termora
|
||||
import app.termora.keyboardinteractive.TerminalUserInteraction
|
||||
import app.termora.keymgr.OhKeyPairKeyPairProvider
|
||||
import app.termora.terminal.TerminalSize
|
||||
import app.termora.x11.ChannelX11
|
||||
import app.termora.x11.X11ChannelFactory
|
||||
import com.formdev.flatlaf.FlatLaf
|
||||
import com.formdev.flatlaf.util.FontUtils
|
||||
@@ -80,7 +79,6 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import javax.swing.*
|
||||
import kotlin.math.max
|
||||
import kotlin.random.Random
|
||||
|
||||
@Suppress("CascadeIf")
|
||||
object SshClients {
|
||||
@@ -111,6 +109,12 @@ object SshClients {
|
||||
env.putAll(host.options.envs())
|
||||
|
||||
val channel = session.createShellChannel(configuration, env)
|
||||
if (host.options.enableX11Forwarding) {
|
||||
if (channel is app.termora.x11.ChannelShell) {
|
||||
channel.xForwarding = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!channel.open().verify(timeout).await()) {
|
||||
throw SshException("Failed to open Shell")
|
||||
}
|
||||
@@ -563,7 +567,7 @@ object SshClients {
|
||||
): ChannelShell {
|
||||
if (inCipher is CipherNone || outCipher is CipherNone)
|
||||
throw IllegalStateException("Interactive channels are not supported with none cipher")
|
||||
val channel = MyChannelShell(ptyConfig, env)
|
||||
val channel = app.termora.x11.ChannelShell(ptyConfig, env)
|
||||
val id = connectionService.registerChannel(channel)
|
||||
if (log.isDebugEnabled) {
|
||||
log.debug("createShellChannel({}) created id={} - PTY={}", this, id, ptyConfig)
|
||||
@@ -580,63 +584,6 @@ object SshClients {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
private class MyChannelShell(
|
||||
configHolder: PtyChannelConfigurationHolder?,
|
||||
env: MutableMap<String, *>?
|
||||
) : ChannelShell(configHolder, env) {
|
||||
|
||||
override fun doOpenPty() {
|
||||
val session = super.getSession()
|
||||
val x11Host = CoreModuleProperties.X11_BIND_HOST.getOrNull(session)
|
||||
val x11Port = CoreModuleProperties.X11_BASE_PORT.getOrNull(session)
|
||||
|
||||
if (x11Port == null || x11Host == null) {
|
||||
super.doOpenPty()
|
||||
return
|
||||
}
|
||||
|
||||
val buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST)
|
||||
buffer.putInt(super.getRecipient())
|
||||
buffer.putString("x11-req")
|
||||
buffer.putBoolean(false) // want-reply
|
||||
buffer.putBoolean(false)
|
||||
buffer.putString("MIT-MAGIC-COOKIE-1")
|
||||
buffer.putBytes(getFakedCookie())
|
||||
buffer.putInt(0)
|
||||
|
||||
writePacket(buffer)
|
||||
|
||||
super.doOpenPty()
|
||||
}
|
||||
|
||||
private fun getFakedCookie(): ByteArray {
|
||||
val session = super.getSession()
|
||||
var cookie = ChannelX11.X11_COOKIE_HEX.getOrNull(session)
|
||||
if (cookie != null) {
|
||||
return cookie as ByteArray
|
||||
}
|
||||
|
||||
synchronized(session) {
|
||||
cookie = ChannelX11.X11_COOKIE_HEX.getOrNull(session)
|
||||
if (cookie != null) {
|
||||
return cookie as ByteArray
|
||||
}
|
||||
|
||||
val foo = Random.nextBytes(16)
|
||||
ChannelX11.X11_COOKIE.set(session, foo)
|
||||
|
||||
val bar = foo.copyOf(32)
|
||||
for (i in 0..15) {
|
||||
bar[2 * i] = ChannelX11.COOKIE_TABLE[(foo[i].toInt() ushr 4) and 0xf]
|
||||
bar[2 * i + 1] = ChannelX11.COOKIE_TABLE[foo[i].toInt() and 0xf]
|
||||
}
|
||||
ChannelX11.X11_COOKIE_HEX.set(session, bar)
|
||||
|
||||
return bar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyIoConnector(private val sshClient: MyJGitSshClient, private val ioConnector: IoConnector) :
|
||||
IoConnector {
|
||||
override fun close(immediately: Boolean): CloseFuture {
|
||||
|
||||
59
src/main/kotlin/app/termora/x11/ChannelShell.kt
Normal file
59
src/main/kotlin/app/termora/x11/ChannelShell.kt
Normal file
@@ -0,0 +1,59 @@
|
||||
package app.termora.x11
|
||||
|
||||
import org.apache.sshd.client.channel.ChannelShell
|
||||
import org.apache.sshd.common.SshConstants
|
||||
import org.apache.sshd.common.channel.PtyChannelConfigurationHolder
|
||||
import kotlin.random.Random
|
||||
|
||||
class ChannelShell(
|
||||
configHolder: PtyChannelConfigurationHolder?,
|
||||
env: MutableMap<String, *>?
|
||||
) : ChannelShell(configHolder, env) {
|
||||
|
||||
var xForwarding = false
|
||||
|
||||
override fun doOpenPty() {
|
||||
val session = super.getSession()
|
||||
|
||||
if (xForwarding) {
|
||||
val buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST)
|
||||
buffer.putInt(super.getRecipient())
|
||||
buffer.putString("x11-req")
|
||||
buffer.putBoolean(false) // want-reply
|
||||
buffer.putBoolean(false)
|
||||
buffer.putString("MIT-MAGIC-COOKIE-1")
|
||||
buffer.putBytes(getFakedCookie())
|
||||
buffer.putInt(0)
|
||||
writePacket(buffer)
|
||||
}
|
||||
|
||||
super.doOpenPty()
|
||||
}
|
||||
|
||||
private fun getFakedCookie(): ByteArray {
|
||||
val session = super.getSession()
|
||||
var cookie = ChannelX11.X11_COOKIE_HEX.getOrNull(session)
|
||||
if (cookie != null) {
|
||||
return cookie as ByteArray
|
||||
}
|
||||
|
||||
synchronized(session) {
|
||||
cookie = ChannelX11.X11_COOKIE_HEX.getOrNull(session)
|
||||
if (cookie != null) {
|
||||
return cookie as ByteArray
|
||||
}
|
||||
|
||||
val foo = Random.nextBytes(16)
|
||||
ChannelX11.X11_COOKIE.set(session, foo)
|
||||
|
||||
val bar = foo.copyOf(32)
|
||||
for (i in 0..15) {
|
||||
bar[2 * i] = ChannelX11.COOKIE_TABLE[(foo[i].toInt() ushr 4) and 0xf]
|
||||
bar[2 * i + 1] = ChannelX11.COOKIE_TABLE[foo[i].toInt() and 0xf]
|
||||
}
|
||||
ChannelX11.X11_COOKIE_HEX.set(session, bar)
|
||||
|
||||
return bar
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user