From 46a6259140ec9ba60b2745ecd9899684500fa392 Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Mon, 28 Jul 2014 11:45:38 -0400 Subject: [PATCH] Add Sftp Server Tests Using Apache Mina --- .../sftp/session/SftpServerTests.java | 204 ++++++++++++++++++ .../src/test/resources/id_rsa | 27 +++ .../src/test/resources/id_rsa.pub | 1 + 3 files changed, 232 insertions(+) create mode 100644 spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpServerTests.java create mode 100644 spring-integration-sftp/src/test/resources/id_rsa create mode 100644 spring-integration-sftp/src/test/resources/id_rsa.pub diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpServerTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpServerTests.java new file mode 100644 index 0000000000..a8e6d7f50b --- /dev/null +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpServerTests.java @@ -0,0 +1,204 @@ +/* + * Copyright 2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.sftp.session; + +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.spec.RSAPublicKeySpec; +import java.util.Arrays; + +import org.apache.sshd.SshServer; +import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.file.FileSystemView; +import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory; +import org.apache.sshd.common.file.nativefs.NativeFileSystemView; +import org.apache.sshd.server.Command; +import org.apache.sshd.server.PasswordAuthenticator; +import org.apache.sshd.server.PublickeyAuthenticator; +import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; +import org.apache.sshd.server.session.ServerSession; +import org.apache.sshd.server.sftp.SftpSubsystem; +import org.junit.Test; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.integration.file.remote.session.Session; +import org.springframework.integration.test.util.SocketUtils; + +import sun.misc.BASE64Decoder; + +import com.jcraft.jsch.ChannelSftp.LsEntry; + +/** + * @author Gary Russell + * @since 3.0.2 + * + */ +public class SftpServerTests { + + @SuppressWarnings("unchecked") + @Test + public void testUcPw() throws Exception { + final int port = SocketUtils.findAvailableServerSocket(); + SshServer server = SshServer.setUpDefaultServer(); + try { + server.setPasswordAuthenticator(new PasswordAuthenticator() { + + @Override + public boolean authenticate(String arg0, String arg1, ServerSession arg2) { + return true; + } + }); + server.setPort(port); + server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser")); + SftpSubsystem.Factory sftp = new SftpSubsystem.Factory(); + server.setSubsystemFactories(Arrays.>asList(sftp)); + server.setFileSystemFactory(new NativeFileSystemFactory() { + + @Override + public FileSystemView createFileSystemView(org.apache.sshd.common.Session session) { + final String pathname = System.getProperty("java.io.tmpdir") + File.separator + "sftptest" + + File.separator; + File f = new File(pathname); + f.mkdirs(); + return new NativeFileSystemView(session.getUsername(), false) { + + @Override + public String getVirtualUserDir() { + return pathname; + } + }; + } + + }); + server.start(); + + DefaultSftpSessionFactory f = new DefaultSftpSessionFactory(); + f.setHost("localhost"); + f.setPort(port); + f.setUser("user"); + f.setPassword("pass"); + Session session = f.getSession(); + doTest(server, session); + } + finally { + server.stop(true); + } + } + + @Test + @SuppressWarnings("unchecked") + public void testPubPrivKey() throws Exception { + final int port = SocketUtils.findAvailableServerSocket(); + SshServer server = SshServer.setUpDefaultServer(); + final PublicKey allowedKey = decodePublicKey(); + try { + server.setPublickeyAuthenticator(new PublickeyAuthenticator() { + + @Override + public boolean authenticate(String username, PublicKey key, ServerSession session) { + return key.equals(allowedKey); + } + + }); + server.setPort(port); + server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser")); + SftpSubsystem.Factory sftp = new SftpSubsystem.Factory(); + server.setSubsystemFactories(Arrays.>asList(sftp)); + server.setFileSystemFactory(new NativeFileSystemFactory() { + + @Override + public FileSystemView createFileSystemView(org.apache.sshd.common.Session session) { + final String pathname = System.getProperty("java.io.tmpdir") + File.separator + "sftptest" + + File.separator; + File f = new File(pathname); + f.mkdirs(); + return new NativeFileSystemView(session.getUsername(), false) { + + @Override + public String getVirtualUserDir() { + return pathname; + } + }; + } + + }); + server.start(); + + DefaultSftpSessionFactory f = new DefaultSftpSessionFactory(); + f.setHost("localhost"); + f.setPort(port); + f.setUser("user"); + f.setPrivateKey(new ClassPathResource("id_rsa")); + Session session = f.getSession(); + doTest(server, session); + } + finally { + server.stop(true); + } + } + + private PublicKey decodePublicKey() throws Exception { + InputStream stream = new ClassPathResource("id_rsa.pub").getInputStream(); + byte[] decodeBuffer = new BASE64Decoder().decodeBuffer(stream); + ByteBuffer bb = ByteBuffer.wrap(decodeBuffer); + int len = bb.getInt(); + byte[] type = new byte[len]; + bb.get(type); + if ("ssh-rsa".equals(new String(type))) { + BigInteger e = decodeBigInt(bb); + BigInteger m = decodeBigInt(bb); + RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e); + return KeyFactory.getInstance("RSA").generatePublic(spec); + + } + else { + throw new IllegalArgumentException("Only supports RSA"); + } + } + + private BigInteger decodeBigInt(ByteBuffer bb) { + int len = bb.getInt(); + byte[] bytes = new byte[len]; + bb.get(bytes); + return new BigInteger(bytes); + } + + protected void doTest(SshServer server, Session session) throws IOException { + assertEquals(1, server.getActiveSessions().size()); + LsEntry[] list = session.list("."); + if (list.length > 0) { + session.remove("*"); + } + session.write(new ByteArrayInputStream("foo".getBytes()), "bar"); + list = session.list("."); + assertEquals("bar", list[0].getFilename()); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + session.read("bar", outputStream); + assertEquals("foo", new String(outputStream.toByteArray())); + session.remove("bar"); + session.close(); + } + +} diff --git a/spring-integration-sftp/src/test/resources/id_rsa b/spring-integration-sftp/src/test/resources/id_rsa new file mode 100644 index 0000000000..59c7bab7e3 --- /dev/null +++ b/spring-integration-sftp/src/test/resources/id_rsa @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAzEAf70wmOkBBfvz+92UGc4I+SwVBvICj2wF3VnBP19IN44LD +6cW+/jRoqjaT/qFSELC/UO0wbL9f1+8XOrHekpjP1Ez/CxdM5X9BkrxHoQtgU/fB +gog6iPASqWYxujvPqTxAWPDOYhji7Q1Es5Yc8le5D3AA2Cx5f89X7LFPsdlDC+wa +EpoIdFz3Nrvhr+vufElZNoqQGTpmlmQ8s1gHN7HM8/w5EHkf3KY9OOx1XNWW/zOW +uGo2CNfCmvplYSnokJx3NzSsBOmcXMJWnG1Sv33sqX6Xqx0DpY+hHun+oboZ1cfc +eNlddQONU6IffFiNhFQ3qruBHE8RxyZ7SYaW3QIDAQABAoIBAQCclFgm+eigZVwQ +fuDzRTZR3Lnmhywi1zdGEHStBkKfP/+3typ7j0Xg2MqYGmkQHhmsg+LWpk6mP3u5 +LShQrcTj+1Pv++rVVNJ1aT4awE3lLrR1Co0FhWviSLD1vktG6s1CftcRl+GPoGZu +tepCBkVAn3FWXVW4YzftfEV6RV/EBVzZLySXeaQyKl8ln3yEBpOPkevy8uLC20O9 +OKDGa30gEP215Kvx1rkvs6jXeMdeH+reEfvyYD8+SMcE60lyY8ntwKhrd/OiZP48 +Fqp4kVEBf/u5DSeQbABLCW2uteHAMFzm/weOHDIIBm2aQzmrokw8IYuYiAyTpnDd +yqlJN+99AoGBAOegXlfK/6aVxpeygRatSRD+JI9p/7Hi9ShQ/VCANyc1RTKvDHIA +j5On1Hnwm1czFMr3CPs78MQa8uDlZEa19HbUAEgSp9X6nIPYi5Fo0Q3Fyp1O122S +QAA0mthGiEsneWMgRDordHgGFVoWcDbTWCH61bkisNufK90b/90TXVoPAoGBAOG+ +SyW5aJTGHw01vHyNnnMWyloNMwd55vGp7Zhb7m1qUIci8WixJ3Jr1exLhhnc8Bpl +DU2sA4x2r6c1yozNozAw/KkLoa0JFISUg8eqprO0kMg6W9SP57xW2ooUMwEOJbkC +pjlgVcw3AXPfBZwCmujNG0wxc5TVVulgjQk0y1xTAoGBAK9RdjdTYp/vfAq0RPsq +HETtaDTZEX3OgKuMacA13AkkTAUp8+ySOhqUDMJjeODOvC1IQJcQ7pMwpqfNWVIg +RTJwEup6nGjdMPymujVMtfeLv2nEFFFOQn0lVBLhiCYCceGyuZGh9J0oVZ8DntoQ +rAPEPWLNPDpvxx6sI8Vs89rHAoGATLypQuuh92DZ0V3A8v4ZLLpEkxQFkrcHoILJ +N4+Yny0Srr1cHuCJrkWl9Ks/rK8EF5TeTtb4Zdk6oLaSYgbNQGaGnNhNX0rE5MSv +f0ItZM0uokHkUX+RoN5Nb76qD+PFQvz5kGuE/uR74+2eNIhWLGj8rIvq5F8ZKkAd +8VE3B+0CgYEAnrh436/L4s9RI9kbKfd99PEl87DFOYB3/v4g4n4Xoi9843dYDjgX +bl1JLbD2jv5HYMs55sHK9Rz/aWiTTDCoONkHL5b84ZDrPJnKzzzwMAND4RivJBYK +ORr+P2OrWEIt57CvLxTYB2RjHQdJ7+r8fxjyRGkkkxJScdsDhCBYisk= +-----END RSA PRIVATE KEY----- diff --git a/spring-integration-sftp/src/test/resources/id_rsa.pub b/spring-integration-sftp/src/test/resources/id_rsa.pub new file mode 100644 index 0000000000..e790fbc53d --- /dev/null +++ b/spring-integration-sftp/src/test/resources/id_rsa.pub @@ -0,0 +1 @@ +AAAAB3NzaC1yc2EAAAADAQABAAABAQDMQB/vTCY6QEF+/P73ZQZzgj5LBUG8gKPbAXdWcE/X0g3jgsPpxb7+NGiqNpP+oVIQsL9Q7TBsv1/X7xc6sd6SmM/UTP8LF0zlf0GSvEehC2BT98GCiDqI8BKpZjG6O8+pPEBY8M5iGOLtDUSzlhzyV7kPcADYLHl/z1fssU+x2UML7BoSmgh0XPc2u+Gv6+58SVk2ipAZOmaWZDyzWAc3sczz/DkQeR/cpj047HVc1Zb/M5a4ajYI18Ka+mVhKeiQnHc3NKwE6ZxcwlacbVK/feypfperHQOlj6Ee6f6huhnVx9x42V11A41Toh98WI2EVDequ4EcTxHHJntJhpbd