Uploaded image for project: 'MINA SSHD'
  1. MINA SSHD
  2. SSHD-1188

OpenMode and CopyMode is not honored as expected in version > 4 of SFTP api

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • 2.5.1, 2.7.0
    • 2.8.0
    • None

    Description

      When calling 

      sftpClient.write(remoteFileName, OpenMode.Create, OpenMode.Write, OpenMode.Exclusive);

      I expect the operation to succeed if no file with that name exists and fail if a file with that name exists. This works as expected when using a SftpVersionSelector to force version 3 or 4. Version 5 or 6 will overwrite the existing file.

       

      Similarly I expect the line below to fail when newName already exists.

      sftpClient.rename(oldName, newName);
      

      This works as expected in version 3 or 4. In version 5 or 6 the existing file is overwritten.

      I expect the following line which is not supported in version 3 or 4 to fail when the newName file already exists when using 5 or 6 but it still overwrites any existing file:

      sftpClient.rename(oldName, newName, CopyMode.Atomic);
      

       

      I'm using 2.5 but issue seems to be the same in 2.7.

       

      I have tested this using apache mina server & client, including a quick and dirty test to demonstrate the OpenMode issue:

      import static org.junit.Assert.assertEquals;
      import static org.junit.Assert.assertFalse;
      
      import java.io.IOException;
      import java.time.Duration;
      import java.util.Collections;
      import java.util.HashMap;
      import java.util.Map;
      
      import org.apache.sshd.client.SshClient;
      import org.apache.sshd.client.session.ClientSession;
      import org.apache.sshd.client.subsystem.sftp.SftpClient;
      import org.apache.sshd.client.subsystem.sftp.SftpClientFactory;
      import org.apache.sshd.client.subsystem.sftp.SftpVersionSelector;
      import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
      import org.apache.sshd.server.SshServer;
      import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
      import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
      import org.junit.Before;
      import org.junit.Rule;
      import org.junit.Test;
      import org.junit.rules.TemporaryFolder;
      
      public class BugMVP {
      
         @Rule
         public TemporaryFolder testFolder = new TemporaryFolder();
      
         private static final String USERNAME = "username";
      
         private static final String PASSWORD = "password";
      
         private SshServer sshd;
      
         @Before
         public void prepare() throws IOException {
            Map<String, String> roots = new HashMap<>();
            roots.put(USERNAME, testFolder.getRoot().getAbsolutePath());
      
            sshd = SshServer.setUpDefaultServer();
            sshd.setFileSystemFactory(new VirtualFileSystemFactory(testFolder.getRoot().toPath()));
            sshd.setPort(42414);
            sshd.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory()));
            sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(testFolder.newFile("hostkey.ser").toPath()));
            sshd.setPasswordAuthenticator((username, password, session) -> username.equals(USERNAME) && password.equals(PASSWORD));
            sshd.start();
      
            testFolder.newFolder("somefolder");
            testFolder.newFile("somefolder/foo.bar");
         }
      
         @Test
         public void testUploadingFileUsingDefaultVersion6_shouldFail() throws IOException {
            SshClient client = SshClient.setUpDefaultClient();
            client.start();
      
            ClientSession clientSession = client.connect(USERNAME, "localhost", 42414)
                  .verify(Duration.ofSeconds(10))
                  .getSession();
      
            clientSession.addPasswordIdentity(PASSWORD);
            clientSession.auth().verify(Duration.ofSeconds(10));
      
            SftpClientFactory factory = SftpClientFactory.instance();
            SftpClient sftpClient = factory.createSftpClient(clientSession);
      
            try (sftpClient; clientSession) {
               sftpClient.write("somefolder/foo.bar", SftpClient.OpenMode.Write, SftpClient.OpenMode.Create, SftpClient.OpenMode.Exclusive);
               assertFalse(true);
            } catch (IOException e){
               assertEquals("File/Directory already exists",e.getMessage());
            }
         }
      
         @Test
         public void testUploadingFileUsingV4_shouldFail() throws IOException {
            SshClient client = SshClient.setUpDefaultClient();
            client.start();
      
            ClientSession clientSession = client.connect(USERNAME, "localhost", 42414)
                  .verify(Duration.ofSeconds(10))
                  .getSession();
      
            clientSession.addPasswordIdentity(PASSWORD);
            clientSession.auth().verify(Duration.ofSeconds(10));
      
            SftpVersionSelector versionSelector = (session, initial, current, available) -> {
               return 4;
            };
            SftpClientFactory factory = SftpClientFactory.instance();
            SftpClient sftpClient = factory.createSftpClient(clientSession, versionSelector);
      
            try (sftpClient; clientSession) {
               sftpClient.write("somefolder/foo.bar", SftpClient.OpenMode.Write, SftpClient.OpenMode.Create, SftpClient.OpenMode.Exclusive);
               assertFalse(true);
            } catch (IOException e){
               assertEquals("File/Directory already exists",e.getMessage());
            }
         }
      
      }
      

       

      Attachments

        Activity

          People

            twolf Thomas Wolf
            martin.peters Martin Peters
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: