fix SFTP test

This commit is contained in:
Jörg Prante 2024-05-27 22:19:50 +02:00
parent be26f3e231
commit 5cf088bd12
6 changed files with 128 additions and 109 deletions

View file

@ -1,40 +0,0 @@
package org.apache.sshd.fs.test;
import java.nio.file.Files;
import org.apache.sshd.client.ClientBuilder;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.fs.SftpFileSystem;
import org.apache.sshd.fs.SftpFileSystemProvider;
import org.junit.jupiter.api.Test;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.xbib.net.security.PrivateKeyReader;
public class SFTPFileSystemTest {
private static final Logger logger = Logger.getLogger(SFTPFileSystemTest.class.getName());
@Test
public void testXbib() throws Exception {
Map<String, String> env = new HashMap<>();
env.put("username", "joerg");
URI uri = URI.create("sftp://xbib.org");
SshClient sshClient = ClientBuilder.builder().build();
Path privateKeyPath = Paths.get(System.getProperty("user.home") + "/.ssh/id_ed25519");
PrivateKeyReader privateKeyReader = new PrivateKeyReader();
KeyPair keyPair = privateKeyReader.generateFrom(Files.newInputStream(privateKeyPath), null);
sshClient.addPublicKeyIdentity(keyPair);
sshClient.setNioWorkers(1);
sshClient.start();
SftpFileSystem fileSystem = new SftpFileSystemProvider(sshClient).newFileSystem(uri, env);
fileSystem.close();
// ...
sshClient.stop();
sshClient.close();
}
}

View file

@ -0,0 +1,74 @@
package org.apache.sshd.fs.test;
import java.io.InputStream;
import java.nio.file.Files;
import org.apache.sshd.client.ClientBuilder;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.fs.SftpFileSystem;
import org.apache.sshd.fs.SftpFileSystemProvider;
import org.junit.jupiter.api.Test;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
import org.xbib.net.security.PrivateKeyReader;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class SftpWithPrivateKeyReaderTest {
private static final Logger logger = Logger.getLogger(SftpWithPrivateKeyReaderTest.class.getName());
@Test
public void testXbib() throws Exception {
Map<String, String> env = new HashMap<>();
env.put("username", "joerg");
URI uri = URI.create("sftp://xbib.org");
Path privateKeyPath = Paths.get(System.getProperty("user.home") + "/.ssh/id_ed25519");
PrivateKeyReader privateKeyReader = new PrivateKeyReader();
try (InputStream inputStream = Files.newInputStream(privateKeyPath);
SshClient sshClient = ClientBuilder.builder().build()) {
KeyPair keyPair = privateKeyReader.readKeyPair(inputStream, null);
sshClient.addPublicKeyIdentity(keyPair);
sshClient.setNioWorkers(1);
sshClient.start();
SftpFileSystem fileSystem = new SftpFileSystemProvider(sshClient).newFileSystem(uri, env);
assertTrue(Files.exists(fileSystem.getDefaultDir()));
try (Stream<Path> stream = Files.list(fileSystem.getDefaultDir())) {
stream.forEach(p -> logger.log(Level.INFO, "p = " + p));
}
fileSystem.close();
sshClient.stop();
}
}
@Test
public void testDionysos() throws Exception {
Map<String, String> env = new HashMap<>();
env.put("username", "joerg");
URI uri = URI.create("sftp://dionysos");
Path privateKeyPath = Paths.get(System.getProperty("user.home") + "/.ssh/id_ed25519");
PrivateKeyReader privateKeyReader = new PrivateKeyReader();
try (InputStream inputStream = Files.newInputStream(privateKeyPath);
SshClient sshClient = ClientBuilder.builder().build()) {
KeyPair keyPair = privateKeyReader.readKeyPair(inputStream, null);
sshClient.addPublicKeyIdentity(keyPair);
sshClient.setNioWorkers(1);
sshClient.start();
SftpFileSystem fileSystem = new SftpFileSystemProvider(sshClient).newFileSystem(uri, env);
assertTrue(Files.exists(fileSystem.getDefaultDir()));
try (Stream<Path> stream = Files.list(fileSystem.getDefaultDir())) {
stream.forEach(p -> logger.log(Level.INFO, "p = " + p));
}
fileSystem.close();
sshClient.stop();
}
}
}

View file

@ -42,7 +42,6 @@ import org.apache.sshd.common.signature.SignatureFactory;
import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.BufferUtils;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer; import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
/** /**
@ -95,18 +94,13 @@ public class UserAuthPublicKey extends AbstractUserAuth implements SignatureFact
} catch (Error e) { } catch (Error e) {
throw new RuntimeSshException(e); throw new RuntimeSshException(e);
} }
PublicKeyAuthenticationReporter reporter = session.getPublicKeyAuthenticationReporter(); PublicKeyAuthenticationReporter reporter = session.getPublicKeyAuthenticationReporter();
if (current == null) { if (current == null) {
if (reporter != null) { if (reporter != null) {
reporter.signalAuthenticationExhausted(session, service); reporter.signalAuthenticationExhausted(session, service);
} }
return false; return false;
} }
KeyPair keyPair; KeyPair keyPair;
try { try {
keyPair = current.getKeyIdentity(); keyPair = current.getKeyIdentity();

View file

@ -34,6 +34,7 @@ import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey; import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey; import java.security.interfaces.ECPublicKey;
import java.security.interfaces.EdECPublicKey;
import java.security.interfaces.RSAPrivateCrtKey; import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.security.spec.DSAPrivateKeySpec; import java.security.spec.DSAPrivateKeySpec;
@ -877,68 +878,60 @@ public abstract class Buffer implements Readable {
public void putRawPublicKeyBytes(PublicKey key) { public void putRawPublicKeyBytes(PublicKey key) {
Objects.requireNonNull(key, "No key"); Objects.requireNonNull(key, "No key");
if (key instanceof RSAPublicKey) { switch (key) {
RSAPublicKey rsaPub = (RSAPublicKey) key; case RSAPublicKey rsaPub -> {
putMPInt(rsaPub.getPublicExponent());
putMPInt(rsaPub.getPublicExponent()); putMPInt(rsaPub.getModulus());
putMPInt(rsaPub.getModulus());
} else if (key instanceof DSAPublicKey) {
DSAPublicKey dsaPub = (DSAPublicKey) key;
DSAParams dsaParams = dsaPub.getParams();
putMPInt(dsaParams.getP());
putMPInt(dsaParams.getQ());
putMPInt(dsaParams.getG());
putMPInt(dsaPub.getY());
} else if (key instanceof ECPublicKey) {
ECPublicKey ecKey = (ECPublicKey) key;
ECParameterSpec ecParams = ecKey.getParams();
ECCurves curve = ECCurves.fromCurveParameters(ecParams);
if (curve == null) {
throw new BufferException("Unsupported EC curve parameters");
} }
case DSAPublicKey dsaPub -> {
byte[] ecPoint = ECCurves.encodeECPoint(ecKey.getW(), ecParams); DSAParams dsaParams = dsaPub.getParams();
putString(curve.getName()); putMPInt(dsaParams.getP());
putBytes(ecPoint); putMPInt(dsaParams.getQ());
} else if (SecurityUtils.EDDSA.equals(key.getAlgorithm())) { putMPInt(dsaParams.getG());
SecurityUtils.putRawEDDSAPublicKey(this, key); putMPInt(dsaPub.getY());
} else if (key instanceof OpenSshCertificate) { }
OpenSshCertificate cert = (OpenSshCertificate) key; case ECPublicKey ecKey -> {
ECParameterSpec ecParams = ecKey.getParams();
putBytes(cert.getNonce()); ECCurves curve = ECCurves.fromCurveParameters(ecParams);
putRawPublicKeyBytes(cert.getServerHostKey()); if (curve == null) {
putLong(cert.getSerial()); throw new BufferException("Unsupported EC curve parameters");
putInt(cert.getType()); }
putString(cert.getId()); byte[] ecPoint = ECCurves.encodeECPoint(ecKey.getW(), ecParams);
putString(curve.getName());
ByteArrayBuffer tmpBuffer = new ByteArrayBuffer(); putBytes(ecPoint);
tmpBuffer.putStringList(cert.getPrincipals(), false); }
putBytes(tmpBuffer.getCompactData()); case EdECPublicKey edECPublicKey -> {
byte[] b = edECPublicKey.getEncoded();
putLong(cert.getValidAfter()); putBytes(b);
putLong(cert.getValidBefore()); }
putNameList(cert.getCriticalOptions()); case OpenSshCertificate cert -> {
putNameList(cert.getExtensions()); putBytes(cert.getNonce());
putString(cert.getReserved()); putRawPublicKeyBytes(cert.getServerHostKey());
putLong(cert.getSerial());
tmpBuffer = new ByteArrayBuffer(); // TODO tmpBuffer.clear() instead of allocate new buffer putInt(cert.getType());
tmpBuffer.putRawPublicKey(cert.getCaPubKey()); putString(cert.getId());
putBytes(tmpBuffer.getCompactData()); ByteArrayBuffer tmpBuffer = new ByteArrayBuffer();
tmpBuffer.putStringList(cert.getPrincipals(), false);
putBytes(cert.getSignature()); putBytes(tmpBuffer.getCompactData());
} else { putLong(cert.getValidAfter());
throw new BufferException("Unsupported raw public key algorithm: " + key.getAlgorithm()); putLong(cert.getValidBefore());
putNameList(cert.getCriticalOptions());
putNameList(cert.getExtensions());
putString(cert.getReserved());
tmpBuffer = new ByteArrayBuffer(); // TODO tmpBuffer.clear() instead of allocate new buffer
tmpBuffer.putRawPublicKey(cert.getCaPubKey());
putBytes(tmpBuffer.getCompactData());
putBytes(cert.getSignature());
}
default -> throw new BufferException("Unsupported raw public key algorithm: " + key.getAlgorithm());
} }
} }
public void putKeyPair(KeyPair kp) { public void putKeyPair(KeyPair kp) {
PublicKey pubKey = kp.getPublic(); PublicKey pubKey = kp.getPublic();
PrivateKey prvKey = kp.getPrivate(); PrivateKey prvKey = kp.getPrivate();
if (prvKey instanceof RSAPrivateCrtKey) { if (prvKey instanceof RSAPrivateCrtKey rsaPrv) {
RSAPublicKey rsaPub = (RSAPublicKey) pubKey; RSAPublicKey rsaPub = (RSAPublicKey) pubKey;
RSAPrivateCrtKey rsaPrv = (RSAPrivateCrtKey) prvKey;
putString(KeyPairProvider.SSH_RSA); putString(KeyPairProvider.SSH_RSA);
putMPInt(rsaPub.getPublicExponent()); putMPInt(rsaPub.getPublicExponent());
putMPInt(rsaPub.getModulus()); putMPInt(rsaPub.getModulus());
@ -946,26 +939,22 @@ public abstract class Buffer implements Readable {
putMPInt(rsaPrv.getCrtCoefficient()); putMPInt(rsaPrv.getCrtCoefficient());
putMPInt(rsaPrv.getPrimeQ()); putMPInt(rsaPrv.getPrimeQ());
putMPInt(rsaPrv.getPrimeP()); putMPInt(rsaPrv.getPrimeP());
} else if (pubKey instanceof DSAPublicKey) { } else if (pubKey instanceof DSAPublicKey dsaPub) {
DSAPublicKey dsaPub = (DSAPublicKey) pubKey;
DSAParams dsaParams = dsaPub.getParams(); DSAParams dsaParams = dsaPub.getParams();
DSAPrivateKey dsaPrv = (DSAPrivateKey) prvKey; DSAPrivateKey dsaPrv = (DSAPrivateKey) prvKey;
putString(KeyPairProvider.SSH_DSS); putString(KeyPairProvider.SSH_DSS);
putMPInt(dsaParams.getP()); putMPInt(dsaParams.getP());
putMPInt(dsaParams.getQ()); putMPInt(dsaParams.getQ());
putMPInt(dsaParams.getG()); putMPInt(dsaParams.getG());
putMPInt(dsaPub.getY()); putMPInt(dsaPub.getY());
putMPInt(dsaPrv.getX()); putMPInt(dsaPrv.getX());
} else if (pubKey instanceof ECPublicKey) { } else if (pubKey instanceof ECPublicKey ecPub) {
ECPublicKey ecPub = (ECPublicKey) pubKey;
ECPrivateKey ecPriv = (ECPrivateKey) prvKey; ECPrivateKey ecPriv = (ECPrivateKey) prvKey;
ECParameterSpec ecParams = ecPub.getParams(); ECParameterSpec ecParams = ecPub.getParams();
ECCurves curve = ECCurves.fromCurveParameters(ecParams); ECCurves curve = ECCurves.fromCurveParameters(ecParams);
if (curve == null) { if (curve == null) {
throw new BufferException("Unsupported EC curve parameters"); throw new BufferException("Unsupported EC curve parameters");
} }
byte[] ecPoint = ECCurves.encodeECPoint(ecPub.getW(), ecParams); byte[] ecPoint = ECCurves.encodeECPoint(ecPub.getW(), ecParams);
putString(curve.getKeyType()); putString(curve.getKeyType());
putString(curve.getName()); putString(curve.getName());

View file

@ -123,8 +123,10 @@ public final class SecurityUtils {
* Comma separated list of fully qualified {@link SecurityProviderRegistrar}s to automatically register * Comma separated list of fully qualified {@link SecurityProviderRegistrar}s to automatically register
*/ */
public static final String SECURITY_PROVIDER_REGISTRARS = "org.apache.sshd.security.registrars"; public static final String SECURITY_PROVIDER_REGISTRARS = "org.apache.sshd.security.registrars";
public static final List<String> DEFAULT_SECURITY_PROVIDER_REGISTRARS = Collections.unmodifiableList(
Arrays.asList("org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderRegistrar")); public static final List<String> DEFAULT_SECURITY_PROVIDER_REGISTRARS =
List.of("org.apache.sshd.common.util.security.edec.EdECSecurityProviderRegistrar");
//Collections.unmodifiableList(Arrays.asList("org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderRegistrar"));
/** /**
* System property used to control whether Elliptic Curves are supported or not. If not set then the support is * System property used to control whether Elliptic Curves are supported or not. If not set then the support is

View file

@ -16,7 +16,7 @@ dependencyResolutionManagement {
versionCatalogs { versionCatalogs {
libs { libs {
version('gradle', '8.7') version('gradle', '8.7')
version('net', '4.4.0') version('net', '4.6.0')
library('net-security', 'org.xbib', 'net-security').versionRef('net') library('net-security', 'org.xbib', 'net-security').versionRef('net')
library('maverick-synergy-client', 'com.sshtools', 'maverick-synergy-client').version('3.1.1') library('maverick-synergy-client', 'com.sshtools', 'maverick-synergy-client').version('3.1.1')
} }