2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-30 21:55:10 +00:00

refactor: make changes to SimpleSftpServer

This commit is contained in:
ShellWen Chen
2024-07-15 08:06:18 +08:00
committed by Albert Vaca Cintora
parent 34a78e635e
commit 405e828683

View File

@@ -44,19 +44,31 @@ import java.security.NoSuchAlgorithmException
import java.security.PublicKey import java.security.PublicKey
internal class SimpleSftpServer { internal class SimpleSftpServer {
var port: Int = -1 private lateinit var sshd: SshServer
private set
var isStarted: Boolean = false val port: Int
private set get() {
if (!::sshd.isInitialized) return -1
return sshd.port
}
val isStarted: Boolean
get() {
if (!::sshd.isInitialized) return false
return sshd.isStarted
}
val isClosed: Boolean
get() {
if (!::sshd.isInitialized) return false
return sshd.isClosed
}
private val passwordAuth = SimplePasswordAuthenticator() private val passwordAuth = SimplePasswordAuthenticator()
private val keyAuth = SimplePublicKeyAuthenticator() private val keyAuth = SimplePublicKeyAuthenticator()
var isInitialized: Boolean = false val isInitialized: Boolean
get() = ::sshd.isInitialized
private lateinit var sshd: SshServer
val isClosed: Boolean
get() = ::sshd.isInitialized && sshd.isClosed
private var safFileSystemFactory: SafFileSystemFactory? = null private var safFileSystemFactory: SafFileSystemFactory? = null
@@ -65,13 +77,13 @@ internal class SimpleSftpServer {
} }
@Throws(GeneralSecurityException::class) @Throws(GeneralSecurityException::class)
fun initialize(context: Context?, device: Device) { fun initialize(context: Context, device: Device) {
val sshd = ServerBuilder.builder().apply { val sshd = ServerBuilder.builder().apply {
fileSystemFactory( fileSystemFactory(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
NativeFileSystemFactory() NativeFileSystemFactory()
} else { } else {
safFileSystemFactory = SafFileSystemFactory(context!!) safFileSystemFactory = SafFileSystemFactory(context)
safFileSystemFactory safFileSystemFactory
} }
) )
@@ -111,38 +123,31 @@ internal class SimpleSftpServer {
sshd.publickeyAuthenticator = keyAuth sshd.publickeyAuthenticator = keyAuth
sshd.passwordAuthenticator = passwordAuth sshd.passwordAuthenticator = passwordAuth
this.isInitialized = true
this.sshd = sshd this.sshd = sshd
} }
fun start(): Boolean { fun start(): Boolean {
if (!isStarted) { if (isStarted) return true
regeneratePassword()
port = STARTPORT regeneratePassword()
while (!isStarted) {
try { PORT_RANGE.forEach { port ->
sshd.port = port try {
sshd.start() sshd.port = port
isStarted = true sshd.start()
} catch (e: IOException) {
port++ return true
if (port >= ENDPORT) { } catch (e: IOException) {
port = -1 Log.w("SftpServer", "Failed to start server on port $port, trying next port", e)
Log.e("SftpServer", "No more ports available")
return false
}
}
} }
} }
return true Log.e("SftpServer", "No more ports available")
return false
} }
fun stop() { fun stop() {
try { try {
isStarted = false
sshd.stop(true) sshd.stop(true)
} catch (e: Exception) { } catch (e: Exception) {
Log.e("SFTP", "Exception while stopping the server", e) Log.e("SFTP", "Exception while stopping the server", e)
@@ -150,30 +155,25 @@ internal class SimpleSftpServer {
} }
fun regeneratePassword(): String { fun regeneratePassword(): String {
val password = RandomHelper.randomString(28) return RandomHelper.randomString(28).also {
passwordAuth.setPassword(password) passwordAuth.setPassword(it)
return password }
} }
internal class SimplePasswordAuthenticator : PasswordAuthenticator { internal class SimplePasswordAuthenticator : PasswordAuthenticator {
private var sha: MessageDigest? = null private val sha: MessageDigest = try {
MessageDigest.getInstance("SHA-256")
init { } catch (e: NoSuchAlgorithmException) {
try { throw RuntimeException(e)
sha = MessageDigest.getInstance("SHA-256")
} catch (e: NoSuchAlgorithmException) {
throw RuntimeException(e)
}
} }
private var passwordHash: ByteArray = byteArrayOf()
fun setPassword(password: String) { fun setPassword(password: String) {
sha!!.digest(password.toByteArray(StandardCharsets.UTF_8)) passwordHash = sha.digest(password.toByteArray(StandardCharsets.UTF_8))
} }
var passwordHash: ByteArray = byteArrayOf()
override fun authenticate(user: String, password: String, session: ServerSession): Boolean { override fun authenticate(user: String, password: String, session: ServerSession): Boolean {
val receivedPasswordHash = sha!!.digest(password.toByteArray(StandardCharsets.UTF_8)) val receivedPasswordHash = sha.digest(password.toByteArray(StandardCharsets.UTF_8))
return user == USER && constantTimeCompare(passwordHash, receivedPasswordHash) return user == USER && constantTimeCompare(passwordHash, receivedPasswordHash)
} }
} }
@@ -182,12 +182,11 @@ internal class SimpleSftpServer {
var deviceKey: PublicKey? = null var deviceKey: PublicKey? = null
override fun authenticate(user: String, key: PublicKey, session: ServerSession): Boolean = override fun authenticate(user: String, key: PublicKey, session: ServerSession): Boolean =
deviceKey == key user == USER && deviceKey == key
} }
companion object { companion object {
private const val STARTPORT = 1739 private val PORT_RANGE = 1739..1764
private const val ENDPORT = 1764
const val USER: String = "kdeconnect" const val USER: String = "kdeconnect"