mirror of
git://f0xx.org/android_cast
synced 2026-07-29 08:57:44 +03:00
some rssh stuff
This commit is contained in:
@@ -119,6 +119,7 @@ android {
|
||||
excludes += '/META-INF/LICENSE.txt'
|
||||
excludes += '/META-INF/NOTICE'
|
||||
excludes += '/META-INF/NOTICE.txt'
|
||||
excludes += '/META-INF/versions/**'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +147,8 @@ dependencies {
|
||||
implementation 'com.github.mwiede:jsch:0.2.21'
|
||||
|
||||
implementation 'org.apache.sshd:sshd-core:2.14.0'
|
||||
implementation 'org.apache.sshd:sshd-sftp:2.14.0'
|
||||
implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1'
|
||||
implementation 'org.slf4j:slf4j-android:1.7.36'
|
||||
|
||||
implementation project(':tunnel')
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
<li><b>Google Play In-App Review</b> — Google Play SDK terms</li>
|
||||
<li><b>Eclipse Paho MQTT client</b> — Eclipse Public License 1.0 and Eclipse Distribution License 1.0 (dual-licensed)</li>
|
||||
<li><b>JSch (mwiede fork)</b> — BSD 3-Clause License (reverse SSH remote access)</li>
|
||||
<li><b>Apache MINA SSHD</b> — Apache License 2.0 (embedded local SSH on device for RSSH alpha)</li>
|
||||
<li><b>Apache MINA SSHD</b> — Apache License 2.0 (embedded local SSH/SFTP for RSSH alpha)</li>
|
||||
<li><b>Bouncy Castle</b> — MIT-style license (SSHD crypto on Android)</li>
|
||||
</ul>
|
||||
|
||||
<h2>JUnit 4</h2>
|
||||
|
||||
@@ -42,7 +42,7 @@ public final class ReverseSshTunnelBridge {
|
||||
Log.w(TAG, "incomplete RSSH credentials");
|
||||
return false;
|
||||
}
|
||||
if (!RsshLocalSshServer.start(user, pass, localPort)) {
|
||||
if (!RsshLocalSshServer.start(context, user, pass, localPort)) {
|
||||
Log.w(TAG, "local SSH on :" + localPort + " failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
package com.foxx.androidcast.remoteaccess;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.sshd.server.SshServer;
|
||||
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
|
||||
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
|
||||
import org.apache.sshd.server.shell.ProcessShellFactory;
|
||||
import org.apache.sshd.sftp.server.SftpSubsystemFactory;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Embedded SSH on {@code 127.0.0.1:8022} for RSSH reverse forward target.
|
||||
* Embedded SSH/SFTP on {@code 127.0.0.1:8022} for RSSH reverse forward target.
|
||||
* Operator reaches this via bastion forwarded port (same username/password).
|
||||
*/
|
||||
public final class RsshLocalSshServer {
|
||||
@@ -24,9 +25,10 @@ public final class RsshLocalSshServer {
|
||||
|
||||
private RsshLocalSshServer() {}
|
||||
|
||||
public static boolean start(String username, String password, int port) {
|
||||
public static boolean start(Context context, String username, String password, int port) {
|
||||
stop();
|
||||
if (username == null || username.isEmpty() || password == null || password.isEmpty()) {
|
||||
if (context == null || username == null || username.isEmpty()
|
||||
|| password == null || password.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (port <= 0 || port > 65535) {
|
||||
@@ -36,8 +38,8 @@ public final class RsshLocalSshServer {
|
||||
final String pass = password;
|
||||
final int listenPort = port;
|
||||
try {
|
||||
Path hostKey = Files.createTempFile("rssh_host", ".key");
|
||||
hostKey.toFile().deleteOnExit();
|
||||
RsshSecuritySetup.ensureReady(context);
|
||||
java.nio.file.Path hostKey = context.getCacheDir().toPath().resolve("rssh_host.key");
|
||||
SshServer sshd = SshServer.setUpDefaultServer();
|
||||
sshd.setHost("127.0.0.1");
|
||||
sshd.setPort(listenPort);
|
||||
@@ -45,14 +47,15 @@ public final class RsshLocalSshServer {
|
||||
sshd.setPasswordAuthenticator((PasswordAuthenticator) (u, p, session) ->
|
||||
user.equals(u) && pass.equals(p));
|
||||
sshd.setShellFactory(new ProcessShellFactory("/system/bin/sh", "-"));
|
||||
sshd.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory()));
|
||||
sshd.start();
|
||||
server = sshd;
|
||||
activeUser = user;
|
||||
running.set(true);
|
||||
Log.i(TAG, "local SSH listening 127.0.0.1:" + listenPort + " user=" + user);
|
||||
Log.i(TAG, "local SSH/SFTP listening 127.0.0.1:" + listenPort + " user=" + user);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "local SSH start failed: " + e.getMessage());
|
||||
} catch (Throwable e) {
|
||||
Log.e(TAG, "local SSH start failed: " + e.getMessage(), e);
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.foxx.androidcast.remoteaccess;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.sshd.common.util.OsUtils;
|
||||
import org.apache.sshd.common.util.io.PathUtils;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.security.Security;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/** One-time MINA SSHD + BouncyCastle setup for Android (see mina-sshd docs/android.md). */
|
||||
final class RsshSecuritySetup {
|
||||
private static final String TAG = "RsshSecurity";
|
||||
private static final AtomicBoolean READY = new AtomicBoolean(false);
|
||||
|
||||
private RsshSecuritySetup() {}
|
||||
|
||||
static void ensureReady(Context context) {
|
||||
if (!READY.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
Context app = context.getApplicationContext();
|
||||
try {
|
||||
try {
|
||||
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
Path home = app.getFilesDir().toPath();
|
||||
System.setProperty("user.home", home.toString());
|
||||
PathUtils.setUserHomeFolderResolver(() -> home);
|
||||
OsUtils.setCurrentUser(app.getPackageName());
|
||||
Log.i(TAG, "SSHD security providers ready; user.home=" + home);
|
||||
} catch (Exception e) {
|
||||
READY.set(false);
|
||||
Log.e(TAG, "SSHD security setup failed: " + e.getMessage(), e);
|
||||
throw new IllegalStateException("RSSH security setup failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user