Added basic error and port handling
This commit is contained in:
parent
6dee4fbc93
commit
865109d8d4
12 changed files with 135 additions and 121 deletions
|
@ -19,12 +19,20 @@ interface WatcherInitError {
|
|||
MaxFilesWatch();
|
||||
};
|
||||
|
||||
enum AuthStatus {
|
||||
"Success",
|
||||
"Denied",
|
||||
"Partial",
|
||||
"Info",
|
||||
"Again",
|
||||
};
|
||||
|
||||
|
||||
interface Session {
|
||||
constructor();
|
||||
void setup(string host, string? user, i32 port);
|
||||
void public_key_auth();
|
||||
void password_auth(string password);
|
||||
void setup(string host, string? user, u16? port);
|
||||
AuthStatus public_key_auth(string password);
|
||||
AuthStatus password_auth(string password);
|
||||
void disconnect();
|
||||
};
|
||||
|
||||
|
|
|
@ -7,9 +7,10 @@ use std::sync::mpsc::{channel, RecvTimeoutError};
|
|||
use std::sync::{Arc, RwLock};
|
||||
use std::time::Duration;
|
||||
|
||||
use libssh_rs::{PollStatus, SshOption};
|
||||
use libssh_rs::{AuthStatus, PollStatus, SshOption};
|
||||
use notify::{Config, Error, ErrorKind, Event, RecommendedWatcher, RecursiveMode, Watcher};
|
||||
|
||||
|
||||
uniffi::include_scaffolding!("gitnuro");
|
||||
|
||||
const ACCEPTED_SSH_TYPES: &str = "ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ssh-dss";
|
||||
|
@ -133,7 +134,7 @@ impl Session {
|
|||
}
|
||||
}
|
||||
|
||||
fn setup(&self, host: String, user: Option<String>, port: i32) {
|
||||
fn setup(&self, host: String, user: Option<String>, port: Option<u16>) {
|
||||
let session = self.session.write().unwrap();
|
||||
session.set_option(SshOption::Hostname(host)).unwrap();
|
||||
|
||||
|
@ -141,7 +142,7 @@ impl Session {
|
|||
session.set_option(SshOption::User(Some(user))).unwrap();
|
||||
}
|
||||
|
||||
if let Ok(port) = port.try_into() {
|
||||
if let Some(port) = port {
|
||||
session.set_option(SshOption::Port(port)).unwrap();
|
||||
}
|
||||
|
||||
|
@ -150,14 +151,21 @@ impl Session {
|
|||
session.connect().unwrap();
|
||||
}
|
||||
|
||||
fn public_key_auth(&self) {
|
||||
fn public_key_auth(&self, password: String) -> AuthStatus {
|
||||
println!("Public key auth");
|
||||
|
||||
let session = self.session.write().unwrap();
|
||||
session.userauth_public_key_auto(None, Some("")).unwrap();
|
||||
|
||||
let status = session.userauth_public_key_auto(None, Some(&password)).unwrap();
|
||||
|
||||
println!("Status is {status:?}");
|
||||
|
||||
status
|
||||
}
|
||||
|
||||
fn password_auth(&self, password: String) {
|
||||
fn password_auth(&self, password: String) -> AuthStatus {
|
||||
let session = self.session.write().unwrap();
|
||||
session.userauth_password(None, Some(&password)).unwrap();
|
||||
session.userauth_password(None, Some(&password)).unwrap()
|
||||
}
|
||||
|
||||
fn disconnect(&self) {
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
package com.jetpackduba.gitnuro.credentials
|
||||
|
||||
import org.eclipse.jgit.transport.RemoteSession
|
||||
import org.eclipse.jgit.transport.URIish
|
||||
import uniffi.gitnuro.Session
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
private const val DEFAULT_SSH_PORT = 22
|
||||
|
||||
class GRemoteSession @Inject constructor(
|
||||
private val credentialsStateManager: CredentialsStateManager,
|
||||
) : RemoteSession {
|
||||
private var session: Session? = null
|
||||
|
||||
override fun exec(commandName: String, timeout: Int): Process {
|
||||
println("Running command $commandName")
|
||||
|
||||
val session = this.session ?: throw Exception("Session is null")
|
||||
val process = GProcessLibSsh()
|
||||
|
||||
process.setup(session, commandName)
|
||||
return process
|
||||
}
|
||||
|
||||
override fun disconnect() {
|
||||
session?.disconnect()
|
||||
}
|
||||
|
||||
fun setup(uri: URIish) {
|
||||
val session = Session()
|
||||
session.setup(uri.host, uri.user, uri.port)
|
||||
|
||||
var result = session.publicKeyAuth()
|
||||
|
||||
// if (result == 1) {
|
||||
// credentialsStateManager.updateState(CredentialsRequested.SshCredentialsRequested)
|
||||
//
|
||||
// var credentials = credentialsStateManager.currentCredentialsState
|
||||
// while (credentials is CredentialsRequested) {
|
||||
// credentials = credentialsStateManager.currentCredentialsState
|
||||
// }
|
||||
//
|
||||
// val password = if (credentials !is CredentialsAccepted.SshCredentialsAccepted)
|
||||
// throw CancellationException("Credentials cancelled")
|
||||
// else
|
||||
// credentials.password
|
||||
//
|
||||
// result = session.userAuthPublicKeyAuto(null, password)
|
||||
//
|
||||
// if (result != 0) {
|
||||
// result = session.userAuthPassword(password)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (result != 0)
|
||||
// throw Exception("Something went wrong with authentication. Code $result")
|
||||
|
||||
this.session = session
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ class GSessionManager @Inject constructor(
|
|||
}
|
||||
|
||||
class MySessionFactory @Inject constructor(
|
||||
private val sessionProvider: Provider<GRemoteSession>
|
||||
private val sessionProvider: Provider<SshRemoteSession>
|
||||
) : SshSessionFactory(), CredentialsCache {
|
||||
override fun getSession(
|
||||
uri: URIish,
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package com.jetpackduba.gitnuro.credentials
|
||||
|
||||
import com.jetpackduba.gitnuro.ssh.libssh.LibSshChannel
|
||||
import uniffi.gitnuro.Channel
|
||||
import com.jetpackduba.gitnuro.ssh.libssh.ChannelWrapper
|
||||
import uniffi.gitnuro.Session
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
class GProcessLibSsh : Process() {
|
||||
private lateinit var channel: LibSshChannel
|
||||
class SshProcess : Process() {
|
||||
private lateinit var channel: ChannelWrapper
|
||||
private lateinit var session: Session
|
||||
|
||||
private val outputStream by lazy {
|
||||
|
@ -61,7 +60,7 @@ class GProcessLibSsh : Process() {
|
|||
}
|
||||
|
||||
fun setup(session: Session, commandName: String) {
|
||||
val channel = LibSshChannel(session)
|
||||
val channel = ChannelWrapper(session)
|
||||
|
||||
channel.openSession()
|
||||
channel.requestExec(commandName)
|
|
@ -0,0 +1,70 @@
|
|||
package com.jetpackduba.gitnuro.credentials
|
||||
|
||||
import org.eclipse.jgit.transport.RemoteSession
|
||||
import org.eclipse.jgit.transport.URIish
|
||||
import uniffi.gitnuro.AuthStatus
|
||||
import uniffi.gitnuro.Session
|
||||
import java.util.concurrent.CancellationException
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
private const val DEFAULT_SSH_PORT = 22
|
||||
private const val NOT_EXPLICIT_PORT = -1
|
||||
|
||||
class SshRemoteSession @Inject constructor(
|
||||
private val credentialsStateManager: CredentialsStateManager,
|
||||
) : RemoteSession {
|
||||
private var session: Session? = null
|
||||
|
||||
override fun exec(commandName: String, timeout: Int): Process {
|
||||
println("Running command $commandName")
|
||||
|
||||
val session = this.session ?: throw Exception("Session is null")
|
||||
val process = SshProcess()
|
||||
|
||||
process.setup(session, commandName)
|
||||
return process
|
||||
}
|
||||
|
||||
override fun disconnect() {
|
||||
session?.disconnect()
|
||||
}
|
||||
|
||||
fun setup(uri: URIish) {
|
||||
val session = Session()
|
||||
|
||||
val port = if (uri.port == NOT_EXPLICIT_PORT) {
|
||||
null
|
||||
} else
|
||||
uri.port
|
||||
|
||||
session.setup(uri.host, uri.user, port?.toUShort())
|
||||
|
||||
var result = session.publicKeyAuth("")
|
||||
|
||||
if (result == AuthStatus.DENIED) {
|
||||
credentialsStateManager.updateState(CredentialsRequested.SshCredentialsRequested)
|
||||
|
||||
var credentials = credentialsStateManager.currentCredentialsState
|
||||
while (credentials is CredentialsRequested) {
|
||||
credentials = credentialsStateManager.currentCredentialsState
|
||||
}
|
||||
|
||||
val password = if (credentials !is CredentialsAccepted.SshCredentialsAccepted)
|
||||
throw CancellationException("Credentials cancelled")
|
||||
else
|
||||
credentials.password
|
||||
|
||||
result = session.publicKeyAuth(password)
|
||||
|
||||
if (result != AuthStatus.SUCCESS) {
|
||||
result = session.passwordAuth(password)
|
||||
}
|
||||
}
|
||||
|
||||
if (result != AuthStatus.SUCCESS)
|
||||
throw Exception("Something went wrong with authentication. Code $result")
|
||||
|
||||
this.session = session
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.jetpackduba.gitnuro.ssh.libssh
|
||||
|
||||
import com.jetpackduba.gitnuro.ssh.libssh.streams.SshChannelInputErrStream
|
||||
import com.jetpackduba.gitnuro.ssh.libssh.streams.SshChannelInputStream
|
||||
import com.jetpackduba.gitnuro.ssh.libssh.streams.SshChannelOutputStream
|
||||
import uniffi.gitnuro.Channel
|
||||
import uniffi.gitnuro.Session
|
||||
|
||||
class ChannelWrapper internal constructor(sshSession: Session) {
|
||||
private var channel = Channel(sshSession)
|
||||
|
||||
val outputStream = SshChannelOutputStream(channel)
|
||||
val inputStream = SshChannelInputStream(channel)
|
||||
val errorOutputStream = SshChannelInputErrStream(channel)
|
||||
|
||||
fun openSession() {
|
||||
channel.openSession()
|
||||
}
|
||||
|
||||
fun requestExec(commandName: String) {
|
||||
channel.requestExec(commandName)
|
||||
}
|
||||
|
||||
fun isOpen(): Boolean {
|
||||
return channel.isOpen()
|
||||
}
|
||||
|
||||
fun close() {
|
||||
channel.close()
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package com.jetpackduba.gitnuro.ssh.libssh
|
||||
|
||||
enum class sshAuthE(val value: Int) {
|
||||
SSH_AUTH_SUCCESS(0),
|
||||
SSH_AUTH_DENIED(1),
|
||||
SSH_AUTH_PARTIAL(2),
|
||||
SSH_AUTH_INFO(3),
|
||||
SSH_AUTH_AGAIN(4),
|
||||
SSH_AUTH_ERROR(-1)
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
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
|
||||
import uniffi.gitnuro.Channel
|
||||
import uniffi.gitnuro.Session
|
||||
|
||||
class LibSshChannel internal constructor(sshSession: Session) {
|
||||
private var channel = Channel(sshSession)
|
||||
|
||||
val outputStream = LibSshChannelOutputStream(channel)
|
||||
val inputStream = LibSshChannelInputStream(channel)
|
||||
val errorOutputStream = LibSshChannelInputErrStream(channel)
|
||||
|
||||
fun openSession() {
|
||||
channel.openSession()
|
||||
}
|
||||
|
||||
fun requestExec(commandName: String) {
|
||||
channel.requestExec(commandName)
|
||||
}
|
||||
|
||||
fun isOpen(): Boolean {
|
||||
return channel.isOpen()
|
||||
}
|
||||
|
||||
fun close() {
|
||||
channel.close()
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ package com.jetpackduba.gitnuro.ssh.libssh.streams
|
|||
import uniffi.gitnuro.Channel
|
||||
import java.io.InputStream
|
||||
|
||||
class LibSshChannelInputErrStream(private val sshChannel: Channel) : InputStream() {
|
||||
class SshChannelInputErrStream(private val sshChannel: Channel) : InputStream() {
|
||||
private var cancelled = false
|
||||
|
||||
override fun read(): Int {
|
|
@ -3,7 +3,7 @@ package com.jetpackduba.gitnuro.ssh.libssh.streams
|
|||
import uniffi.gitnuro.Channel
|
||||
import java.io.InputStream
|
||||
|
||||
class LibSshChannelInputStream(private val sshChannel: Channel) : InputStream() {
|
||||
class SshChannelInputStream(private val sshChannel: Channel) : InputStream() {
|
||||
override fun read(b: ByteArray, off: Int, len: Int): Int {
|
||||
val result = sshChannel.read(false, len.toULong())
|
||||
val byteArray = result.data
|
|
@ -3,7 +3,7 @@ package com.jetpackduba.gitnuro.ssh.libssh.streams
|
|||
import uniffi.gitnuro.Channel
|
||||
import java.io.OutputStream
|
||||
|
||||
class LibSshChannelOutputStream(private val sshChannel: Channel) : OutputStream() {
|
||||
class SshChannelOutputStream(private val sshChannel: Channel) : OutputStream() {
|
||||
override fun write(b: Int) {
|
||||
val byteArrayData = byteArrayOf(b.toByte())
|
||||
write(byteArrayData)
|
Loading…
Reference in a new issue