perbaikan dari gemini

This commit is contained in:
2026-08-31 00:10:34 +07:00
parent 0d3038f9a9
commit 1040b19448
8 changed files with 388 additions and 13 deletions

View File

@@ -33,7 +33,10 @@ android {
}
kotlinOptions { jvmTarget = "17" }
packaging {
resources.excludes += "META-INF/{AL2.0,LGPL2.1}"
resources {
excludes += "META-INF/{AL2.0,LGPL2.1}"
excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
}
}
lint { abortOnError = false }
buildFeatures { viewBinding = true }
@@ -50,6 +53,8 @@ dependencies {
// SSH
implementation("com.hierynomus:sshj:0.38.0")
implementation("org.bouncycastle:bcprov-jdk18on:1.78.1")
implementation("org.bouncycastle:bcpkix-jdk18on:1.78.1")
// Secure credential storage (EncryptedSharedPreferences via Tink)
implementation("androidx.security:security-crypto:1.1.0-alpha06")

View File

@@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name=".KosSSHApplication"
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"

View File

@@ -0,0 +1,19 @@
package com.kosbarokah.sshclient
import android.app.Application
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.Security
class KosSSHApplication : Application() {
override fun onCreate() {
super.onCreate()
setupBouncyCastle()
}
private fun setupBouncyCastle() {
// Remove the restricted system Bouncy Castle provider
Security.removeProvider("BC")
// Insert the full Bouncy Castle provider at the first position to ensure it's used
Security.insertProviderAt(BouncyCastleProvider(), 1)
}
}

View File

@@ -143,22 +143,24 @@ class SshEngine(
private fun newClient(): SSHClient {
val config: Config = DefaultConfig()
val c = SSHClient(config)
c.useCompression()
// Catatan: tidak memanggil loadKnownHosts() — di Android tidak ada file
// known_hosts di path default JVM, jadi sshj hanya akan melempar peringatan
// "could not load known_host". Host-key pinning (known_hosts) direncanakan
// di backlog; untuk v1 kita terima host key (PromiscuousVerifier).
// Validate host keys: in this v1 we accept any host key but warn.
// TODO: real known-host pinning (store fingerprint per profile).
// Disable compression for better stability on unstable mobile networks
// c.useCompression()
c.addHostKeyVerifier(PromiscuousVerifier())
val p = if (profile.port > 0) profile.port else 22
// Set connection timeout explicitly to 10 seconds
c.connectTimeout = 10000
c.connect(profile.host, p)
c.timeout = 20000
// Enable SSH keep-alive (client-side ping every 60s) so NAT/lazy routers
// don't drop the session during idle.
// Set read timeout to 0 (infinite) for interactive shell stability
c.timeout = 0
// Enable SSH keep-alive (client-side ping every 30s) to keep NAT sessions alive
try {
c.connection.keepAlive.setKeepAliveInterval(60)
} catch (_: Exception) {
c.connection.keepAlive.setKeepAliveInterval(30)
} catch (e: Exception) {
Log.w(TAG, "Gagal mengatur keep-alive: ${e.message}")
}
return c
}