From 5cf088bd12422c2d47d754f4fb670ca98a7a0c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Prante?= Date: Mon, 27 May 2024 22:19:50 +0200 Subject: [PATCH] fix SFTP test --- .../sshd/fs/test/SFTPFileSystemTest.java | 40 ------- .../fs/test/SftpWithPrivateKeyReaderTest.java | 74 ++++++++++++ .../client/auth/pubkey/UserAuthPublicKey.java | 6 - .../sshd/common/util/buffer/Buffer.java | 109 ++++++++---------- .../common/util/security/SecurityUtils.java | 6 +- settings.gradle | 2 +- 6 files changed, 128 insertions(+), 109 deletions(-) delete mode 100644 files-sftp-fs/src/test/java/org/apache/sshd/fs/test/SFTPFileSystemTest.java create mode 100644 files-sftp-fs/src/test/java/org/apache/sshd/fs/test/SftpWithPrivateKeyReaderTest.java diff --git a/files-sftp-fs/src/test/java/org/apache/sshd/fs/test/SFTPFileSystemTest.java b/files-sftp-fs/src/test/java/org/apache/sshd/fs/test/SFTPFileSystemTest.java deleted file mode 100644 index 270a096..0000000 --- a/files-sftp-fs/src/test/java/org/apache/sshd/fs/test/SFTPFileSystemTest.java +++ /dev/null @@ -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 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(); - } -} diff --git a/files-sftp-fs/src/test/java/org/apache/sshd/fs/test/SftpWithPrivateKeyReaderTest.java b/files-sftp-fs/src/test/java/org/apache/sshd/fs/test/SftpWithPrivateKeyReaderTest.java new file mode 100644 index 0000000..ee8cf39 --- /dev/null +++ b/files-sftp-fs/src/test/java/org/apache/sshd/fs/test/SftpWithPrivateKeyReaderTest.java @@ -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 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 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 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 stream = Files.list(fileSystem.getDefaultDir())) { + stream.forEach(p -> logger.log(Level.INFO, "p = " + p)); + } + fileSystem.close(); + sshClient.stop(); + } + } + +} diff --git a/files-sftp/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKey.java b/files-sftp/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKey.java index 004b47a..6886006 100644 --- a/files-sftp/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKey.java +++ b/files-sftp/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKey.java @@ -42,7 +42,6 @@ import org.apache.sshd.common.signature.SignatureFactory; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; -import org.apache.sshd.common.util.buffer.BufferUtils; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; /** @@ -95,18 +94,13 @@ public class UserAuthPublicKey extends AbstractUserAuth implements SignatureFact } catch (Error e) { throw new RuntimeSshException(e); } - PublicKeyAuthenticationReporter reporter = session.getPublicKeyAuthenticationReporter(); if (current == null) { - if (reporter != null) { reporter.signalAuthenticationExhausted(session, service); } - return false; } - - KeyPair keyPair; try { keyPair = current.getKeyIdentity(); diff --git a/files-sftp/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java b/files-sftp/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java index 798d1ae..dfb14a0 100644 --- a/files-sftp/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java +++ b/files-sftp/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java @@ -34,6 +34,7 @@ import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.DSAPublicKey; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; +import java.security.interfaces.EdECPublicKey; import java.security.interfaces.RSAPrivateCrtKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.DSAPrivateKeySpec; @@ -877,68 +878,60 @@ public abstract class Buffer implements Readable { public void putRawPublicKeyBytes(PublicKey key) { Objects.requireNonNull(key, "No key"); - if (key instanceof RSAPublicKey) { - RSAPublicKey rsaPub = (RSAPublicKey) key; - - putMPInt(rsaPub.getPublicExponent()); - 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"); + switch (key) { + case RSAPublicKey rsaPub -> { + putMPInt(rsaPub.getPublicExponent()); + putMPInt(rsaPub.getModulus()); } - - byte[] ecPoint = ECCurves.encodeECPoint(ecKey.getW(), ecParams); - putString(curve.getName()); - putBytes(ecPoint); - } else if (SecurityUtils.EDDSA.equals(key.getAlgorithm())) { - SecurityUtils.putRawEDDSAPublicKey(this, key); - } else if (key instanceof OpenSshCertificate) { - OpenSshCertificate cert = (OpenSshCertificate) key; - - putBytes(cert.getNonce()); - putRawPublicKeyBytes(cert.getServerHostKey()); - putLong(cert.getSerial()); - putInt(cert.getType()); - putString(cert.getId()); - - ByteArrayBuffer tmpBuffer = new ByteArrayBuffer(); - tmpBuffer.putStringList(cert.getPrincipals(), false); - putBytes(tmpBuffer.getCompactData()); - - putLong(cert.getValidAfter()); - 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()); - } else { - throw new BufferException("Unsupported raw public key algorithm: " + key.getAlgorithm()); + case DSAPublicKey dsaPub -> { + DSAParams dsaParams = dsaPub.getParams(); + putMPInt(dsaParams.getP()); + putMPInt(dsaParams.getQ()); + putMPInt(dsaParams.getG()); + putMPInt(dsaPub.getY()); + } + case ECPublicKey ecKey -> { + ECParameterSpec ecParams = ecKey.getParams(); + ECCurves curve = ECCurves.fromCurveParameters(ecParams); + if (curve == null) { + throw new BufferException("Unsupported EC curve parameters"); + } + byte[] ecPoint = ECCurves.encodeECPoint(ecKey.getW(), ecParams); + putString(curve.getName()); + putBytes(ecPoint); + } + case EdECPublicKey edECPublicKey -> { + byte[] b = edECPublicKey.getEncoded(); + putBytes(b); + } + case OpenSshCertificate cert -> { + putBytes(cert.getNonce()); + putRawPublicKeyBytes(cert.getServerHostKey()); + putLong(cert.getSerial()); + putInt(cert.getType()); + putString(cert.getId()); + ByteArrayBuffer tmpBuffer = new ByteArrayBuffer(); + tmpBuffer.putStringList(cert.getPrincipals(), false); + putBytes(tmpBuffer.getCompactData()); + putLong(cert.getValidAfter()); + 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) { PublicKey pubKey = kp.getPublic(); PrivateKey prvKey = kp.getPrivate(); - if (prvKey instanceof RSAPrivateCrtKey) { + if (prvKey instanceof RSAPrivateCrtKey rsaPrv) { RSAPublicKey rsaPub = (RSAPublicKey) pubKey; - RSAPrivateCrtKey rsaPrv = (RSAPrivateCrtKey) prvKey; - putString(KeyPairProvider.SSH_RSA); putMPInt(rsaPub.getPublicExponent()); putMPInt(rsaPub.getModulus()); @@ -946,26 +939,22 @@ public abstract class Buffer implements Readable { putMPInt(rsaPrv.getCrtCoefficient()); putMPInt(rsaPrv.getPrimeQ()); putMPInt(rsaPrv.getPrimeP()); - } else if (pubKey instanceof DSAPublicKey) { - DSAPublicKey dsaPub = (DSAPublicKey) pubKey; + } else if (pubKey instanceof DSAPublicKey dsaPub) { DSAParams dsaParams = dsaPub.getParams(); DSAPrivateKey dsaPrv = (DSAPrivateKey) prvKey; - putString(KeyPairProvider.SSH_DSS); putMPInt(dsaParams.getP()); putMPInt(dsaParams.getQ()); putMPInt(dsaParams.getG()); putMPInt(dsaPub.getY()); putMPInt(dsaPrv.getX()); - } else if (pubKey instanceof ECPublicKey) { - ECPublicKey ecPub = (ECPublicKey) pubKey; + } else if (pubKey instanceof ECPublicKey ecPub) { ECPrivateKey ecPriv = (ECPrivateKey) prvKey; ECParameterSpec ecParams = ecPub.getParams(); ECCurves curve = ECCurves.fromCurveParameters(ecParams); if (curve == null) { throw new BufferException("Unsupported EC curve parameters"); } - byte[] ecPoint = ECCurves.encodeECPoint(ecPub.getW(), ecParams); putString(curve.getKeyType()); putString(curve.getName()); diff --git a/files-sftp/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java b/files-sftp/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java index e6536c0..3ba0c51 100644 --- a/files-sftp/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java +++ b/files-sftp/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java @@ -123,8 +123,10 @@ public final class SecurityUtils { * 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 List DEFAULT_SECURITY_PROVIDER_REGISTRARS = Collections.unmodifiableList( - Arrays.asList("org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderRegistrar")); + + public static final List 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 diff --git a/settings.gradle b/settings.gradle index 9c25d81..754aa85 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,7 +16,7 @@ dependencyResolutionManagement { versionCatalogs { libs { version('gradle', '8.7') - version('net', '4.4.0') + version('net', '4.6.0') library('net-security', 'org.xbib', 'net-security').versionRef('net') library('maverick-synergy-client', 'com.sshtools', 'maverick-synergy-client').version('3.1.1') }