Organized libssh code

This commit is contained in:
Abdelilah El Aissaoui 2022-12-24 03:23:43 +01:00
parent 944f4e9955
commit 193755454e
11 changed files with 193 additions and 175 deletions

View File

@ -1,24 +1,21 @@
package com.jetpackduba.gitnuro.credentials
import com.jetpackduba.gitnuro.credentials.streams.LibSshInputErrStream
import com.jetpackduba.gitnuro.credentials.streams.LibSshInputStream
import com.jetpackduba.gitnuro.credentials.streams.LibSshOutputStream
import com.jetpackduba.gitnuro.credentials.streams.checkValidResult
import com.jetpackduba.gitnuro.ssh.libssh.*
import java.io.InputStream
import java.io.OutputStream
class GProcessLibSsh : Process() {
private lateinit var channel: ssh_channel
private lateinit var session: ssh_session
private lateinit var channel: LibSshChannel
private lateinit var session: LibSshSession
private val outputStream by lazy {
LibSshOutputStream(channel)
channel.outputStream
}
private val inputStream by lazy {
LibSshInputStream(channel)
channel.inputStream
}
private val errorOutputStream by lazy {
LibSshInputErrStream(channel)
channel.errorOutputStream
}
override fun getOutputStream(): OutputStream {
@ -44,27 +41,27 @@ class GProcessLibSsh : Process() {
check(!isRunning())
println("exitValue called")
return sshLib.ssh_channel_close(channel)
return channel.close()
}
override fun destroy() {
if (sshLib.ssh_channel_is_open(channel) == 1) {
checkValidResult(sshLib.ssh_channel_close(channel))
if (channel.isOpen()) {
channel.close()
}
sshLib.ssh_disconnect(session)
session.disconnect()
println("Destroy called")
}
private fun isRunning(): Boolean {
return sshLib.ssh_channel_is_open(channel) == 1
return channel.isOpen()
}
fun setup(session: ssh_session, commandName: String) {
val channel = sshLib.ssh_channel_new(session)
fun setup(session: LibSshSession, commandName: String) {
val channel = session.createChannel()
checkValidResult(sshLib.ssh_channel_open_session(channel))
checkValidResult(sshLib.ssh_channel_request_exec(channel, commandName))
channel.openSession()
channel.requestExec(commandName)
this.session = session
this.channel = channel

View File

@ -1,12 +1,11 @@
package com.jetpackduba.gitnuro.credentials
import com.jetpackduba.gitnuro.ssh.libssh.LibSshOptions
import com.jetpackduba.gitnuro.ssh.libssh.LibSshSession
import org.apache.sshd.client.SshClient
import org.apache.sshd.client.future.ConnectFuture
import org.apache.sshd.client.session.ClientSession
import org.apache.sshd.common.config.keys.FilePasswordProvider
import org.eclipse.jgit.transport.RemoteSession
import org.eclipse.jgit.transport.URIish
import java.time.Duration
import javax.inject.Inject
import javax.inject.Provider
@ -15,33 +14,18 @@ private const val DEFAULT_SSH_PORT = 22
class GRemoteSession @Inject constructor(
private val processProvider: Provider<GProcess>,
private val processSession: Provider<LibSshSession>,
private val credentialsStateManager: CredentialsStateManager,
) : RemoteSession {
private val client = SshClient.setUpDefaultClient()
private var connectFuture: ConnectFuture? = null
private var ssh_session: ssh_session? = null
private var session: LibSshSession? = null
override fun exec(commandName: String, timeout: Int): Process {
println(commandName)
// val session = connectFuture!!.clientSession
//
// val auth = session.auth()
// auth.addListener { arg0 ->
// println("Authentication completed with " + if (arg0.isSuccess) "success" else "failure")
// }
//
// session.waitFor(
// listOf(
// ClientSession.ClientSessionEvent.WAIT_AUTH,
// ClientSession.ClientSessionEvent.CLOSED,
// ClientSession.ClientSessionEvent.AUTHED
// ), Duration.ofHours(2)
// )
// auth.verify()
// val process = processProvider.get()
println("Running command $commandName")
val session = this.ssh_session ?: throw Exception("Session is null")
val session = this.session ?: throw Exception("Session is null")
val process = GProcessLibSsh()
process.setup(session, commandName)
@ -54,46 +38,11 @@ class GRemoteSession @Inject constructor(
}
fun setup(uri: URIish) {
val session = processSession.get()
session.setOptions(LibSshOptions.SSH_OPTIONS_HOST, uri.host)
session.connect()
session.userAuthPublicKeyAuto(uri.user, null)
val session = sshLib.ssh_new()
sshLib.ssh_options_set(session, 0, uri.host)
sshLib.ssh_connect(session)
checkValidResult(sshLib.ssh_userauth_publickey_auto(session, uri.user, null))
this.ssh_session = session
// client.open()
//
// val port = if (uri.port == -1) {
// DEFAULT_SSH_PORT
// } else
// uri.port
//
// val filePasswordProvider =
// FilePasswordProvider { _, _, _ ->
// credentialsStateManager.updateState(CredentialsState.SshCredentialsRequested)
//
// var credentials = credentialsStateManager.currentCredentialsState
// while (credentials is CredentialsState.CredentialsRequested) {
// credentials = credentialsStateManager.currentCredentialsState
// }
//
// if (credentials !is CredentialsState.SshCredentialsAccepted)
// null
// else
// credentials.password
// }
//
// client.filePasswordProvider = filePasswordProvider
//
// val connectFuture = client.connect(uri.user, uri.host, port)
// connectFuture.await()
//
// this.connectFuture = connectFuture
this.session = session
}
}
fun checkValidResult(result: Int) {
if (result != 0)
throw Exception("Result is $result")
}

View File

@ -1,10 +0,0 @@
package com.jetpackduba.gitnuro.credentials.streams
class Convertest {
companion object {
fun printIt(byteArray: ByteArray) {
val intList = byteArray.map { it.toInt() }
println(intList)
}
}
}

View File

@ -1,65 +0,0 @@
package com.jetpackduba.gitnuro.credentials.streams
import com.jetpackduba.gitnuro.credentials.sshLib
import com.jetpackduba.gitnuro.credentials.ssh_channel
import java.io.InputStream
class LibSshInputErrStream(private val sshChannel: ssh_channel) : InputStream() {
private var cancelled = false
private var calls = 0
// override fun read(b: ByteArray, off: Int, len: Int): Int {
// return sshLib.ssh_channel_read(sshChannel, b, len, 1)
// }
override fun read(): Int {
println("Read error")
val buffer = ByteArray(1)
return if (sshLib.ssh_channel_poll(sshChannel, 1) > 0) {
sshLib.ssh_channel_read(sshChannel, buffer, 1, 1)
val first = buffer.first()
println("Read error finished ${first.toInt()}")
print(String(buffer))
first.toInt()
} else
-1
}
// override fun read(b: ByteArray, off: Int, len: Int): Int {
// calls++
//
// println("Read error started, call $calls for len of $len with offset $off")
//
// val byteArray = ByteArray(len)
// val result = sshLib.ssh_channel_read(sshChannel, byteArray, len, 1)
// for(i in 0 until len) {
// b[off + i] = byteArray[i]
// }
//
// println("Read ended ${byteArray.map { it.toInt() }}")
//
// return result
// }
//
// override fun read(): Int {
// val buffer = ByteArray(1)
//
// sshLib.ssh_channel_read(sshChannel, buffer, 1, 1)
//
// val first = buffer.first()
//
// println("Error message is ${String(buffer)}")
//
// return first.toInt()
// }
override fun close() {
println("Closing error")
cancelled = true
}
}

View File

@ -0,0 +1,32 @@
package com.jetpackduba.gitnuro.ssh.libssh
import com.jetpackduba.gitnuro.ssh.libssh.streams.LibSshChannelInputErrStream
import com.jetpackduba.gitnuro.ssh.libssh.streams.LibSshChannelInputStream
import com.jetpackduba.gitnuro.ssh.libssh.streams.LibSshChannelOutputStream
class LibSshChannel internal constructor(sshSession: ssh_session) {
private val sshLib = SSHLibrary.INSTANCE
private var channel: ssh_channel = sshLib.ssh_channel_new(sshSession)
val outputStream = LibSshChannelOutputStream(channel)
val inputStream = LibSshChannelInputStream(channel)
val errorOutputStream = LibSshChannelInputErrStream(channel)
fun openSession() {
sshLib.ssh_channel_open_session(channel)
}
fun requestExec(commandName: String) {
sshLib.ssh_channel_request_exec(channel, commandName)
}
fun isOpen(): Boolean {
return sshLib.ssh_channel_is_open(channel) == 1
}
fun close(): Int {
return sshLib.ssh_channel_close(channel)
}
}

View File

@ -0,0 +1,50 @@
package com.jetpackduba.gitnuro.ssh.libssh
/**
* Enum based on the enum "ssh_options_e" of libssh/libssh.h
*/
enum class LibSshOptions {
SSH_OPTIONS_HOST,
SSH_OPTIONS_PORT,
SSH_OPTIONS_PORT_STR,
SSH_OPTIONS_FD,
SSH_OPTIONS_USER,
SSH_OPTIONS_SSH_DIR,
SSH_OPTIONS_IDENTITY,
SSH_OPTIONS_ADD_IDENTITY,
SSH_OPTIONS_KNOWNHOSTS,
SSH_OPTIONS_TIMEOUT,
SSH_OPTIONS_TIMEOUT_USEC,
SSH_OPTIONS_SSH1,
SSH_OPTIONS_SSH2,
SSH_OPTIONS_LOG_VERBOSITY,
SSH_OPTIONS_LOG_VERBOSITY_STR,
SSH_OPTIONS_CIPHERS_C_S,
SSH_OPTIONS_CIPHERS_S_C,
SSH_OPTIONS_COMPRESSION_C_S,
SSH_OPTIONS_COMPRESSION_S_C,
SSH_OPTIONS_PROXYCOMMAND,
SSH_OPTIONS_BINDADDR,
SSH_OPTIONS_STRICTHOSTKEYCHECK,
SSH_OPTIONS_COMPRESSION,
SSH_OPTIONS_COMPRESSION_LEVEL,
SSH_OPTIONS_KEY_EXCHANGE,
SSH_OPTIONS_HOSTKEYS,
SSH_OPTIONS_GSSAPI_SERVER_IDENTITY,
SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY,
SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS,
SSH_OPTIONS_HMAC_C_S,
SSH_OPTIONS_HMAC_S_C,
SSH_OPTIONS_PASSWORD_AUTH,
SSH_OPTIONS_PUBKEY_AUTH,
SSH_OPTIONS_KBDINT_AUTH,
SSH_OPTIONS_GSSAPI_AUTH,
SSH_OPTIONS_GLOBAL_KNOWNHOSTS,
SSH_OPTIONS_NODELAY,
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
SSH_OPTIONS_PROCESS_CONFIG,
SSH_OPTIONS_REKEY_DATA,
SSH_OPTIONS_REKEY_TIME,
SSH_OPTIONS_RSA_MIN_SIZE,
SSH_OPTIONS_IDENTITY_AGENT
}

View File

@ -0,0 +1,38 @@
package com.jetpackduba.gitnuro.ssh.libssh
import javax.inject.Inject
class LibSshSession @Inject constructor() {
private val sshLib = SSHLibrary.INSTANCE
private var session: ssh_session = sshLib.ssh_new()
private var channel: LibSshChannel? = null
fun setOptions(option: LibSshOptions, value: String) {
sshLib.ssh_options_set(session, option.ordinal, value)
}
fun connect() {
sshLib.ssh_connect(session)
}
fun userAuthPublicKeyAuto(username: String?, password: String?) {
sshLib.ssh_userauth_publickey_auto(session, username, password)
}
fun createChannel(): LibSshChannel {
val newChannel = LibSshChannel(session)
this.channel = newChannel
return newChannel
}
fun disconnect() {
sshLib.ssh_disconnect(session)
}
}

View File

@ -1,4 +1,4 @@
package com.jetpackduba.gitnuro.credentials
package com.jetpackduba.gitnuro.ssh.libssh
import com.sun.jna.Library
import com.sun.jna.Native
@ -7,6 +7,7 @@ import com.sun.jna.PointerType
class ssh_session : PointerType()
class ssh_channel : PointerType()
@Suppress("FunctionName")
interface SSHLibrary : Library {
fun ssh_new(): ssh_session
fun ssh_disconnect(session: ssh_session): ssh_session
@ -43,5 +44,3 @@ interface SSHLibrary : Library {
) as SSHLibrary
}
}
val sshLib = SSHLibrary.INSTANCE

View File

@ -0,0 +1,33 @@
package com.jetpackduba.gitnuro.ssh.libssh.streams
import com.jetpackduba.gitnuro.ssh.libssh.SSHLibrary
import com.jetpackduba.gitnuro.ssh.libssh.ssh_channel
import java.io.InputStream
class LibSshChannelInputErrStream(private val sshChannel: ssh_channel) : InputStream() {
private var cancelled = false
private val sshLib = SSHLibrary.INSTANCE
override fun read(): Int {
println("Read error")
val buffer = ByteArray(1)
return if (sshLib.ssh_channel_poll(sshChannel, 1) > 0) {
sshLib.ssh_channel_read(sshChannel, buffer, 1, 1)
val first = buffer.first()
println("Read error finished ${first.toInt()}")
print(String(buffer))
first.toInt()
} else
-1
}
override fun close() {
println("Closing error")
cancelled = true
}
}

View File

@ -1,26 +1,20 @@
package com.jetpackduba.gitnuro.credentials.streams
package com.jetpackduba.gitnuro.ssh.libssh.streams
import com.jetpackduba.gitnuro.credentials.sshLib
import com.jetpackduba.gitnuro.credentials.ssh_channel
import com.jetpackduba.gitnuro.ssh.libssh.SSHLibrary
import com.jetpackduba.gitnuro.ssh.libssh.ssh_channel
import java.io.InputStream
class LibSshInputStream(private val sshChannel: ssh_channel) : InputStream() {
private var calls = 0
class LibSshChannelInputStream(private val sshChannel: ssh_channel) : InputStream() {
private val sshLib = SSHLibrary.INSTANCE
override fun read(b: ByteArray, off: Int, len: Int): Int {
calls++
println("Read started, call $calls for len of $len with offset $off")
val byteArray = ByteArray(len)
val result = sshLib.ssh_channel_read(sshChannel, byteArray, len, 0)
for(i in 0 until len) {
b[off + i] = byteArray[i]
}
println("Read ended ${byteArray.map { it.toInt() }}")
return result
}

View File

@ -1,11 +1,12 @@
package com.jetpackduba.gitnuro.credentials.streams
package com.jetpackduba.gitnuro.ssh.libssh.streams
import com.jetpackduba.gitnuro.credentials.sshLib
import com.jetpackduba.gitnuro.credentials.ssh_channel
import com.jetpackduba.gitnuro.ssh.libssh.SSHLibrary
import com.jetpackduba.gitnuro.ssh.libssh.ssh_channel
import java.io.OutputStream
import java.nio.ByteBuffer
class LibSshOutputStream(private val sshChannel: ssh_channel) : OutputStream() {
class LibSshChannelOutputStream(private val sshChannel: ssh_channel) : OutputStream() {
private val sshLib = SSHLibrary.INSTANCE
override fun write(b: Int) {
println("write int")