Apache Mina SSHD SFTP server fails to list some directories on Android

2.3k views Asked by At

Using Apache Mina SSHD I've implemented an SSH and SFTP server in an Android app I'm working on, and I can log in through SSH fine, ls the root directory, cd to 'mnt/sdcard' and ls - all of this is working fine. I can also get su and do whatever else I want.

However when I connect through SFTP I am unable to list the contents of most directories (including '/', '/mnt/sdcard'). I can, however, list the contents of '/mnt/sdcard/Download' - as well as download and upload to and from that directory.

It seems that certain files are halting the directory listing in it's tracks - for example, in '/mnt/sdcard' it seems that 'TWRP' is the cause of the problem. Here's what I get in WinSCP:

General failure (server should provide error description).

Error code: 4 Error message from server: /mnt/sdcard/TWRP

Here's what I get from FileZilla (much less descriptive):

Command: cd "/mnt/sdcard" Response: New directory is: "/mnt/sdcard"

Command: ls Status: Listing directory /mnt/sdcard

Error: Reading directory .: failure Status: Directory listing successful

When trying to list the directories in '/' in WinSCP:

General failure (server should provide error description).

Error code: 4 Error message from server: /charger

I've implemented a custom FileSystemFactory in order to default incoming SFTP connections to '/mnt/sdcard/Download', but I would like to be able to SFTP to any directory (I don't mind using su if needed)

Here's the relevant code to set up the Android SSH/SFTP server and set the custom FileSystemFactory:

//Initialize the server:
final Logger log = LoggerFactory.getLogger(server_service.class);
final SshServer sshd = SshServer.setUpDefaultServer();
final SimplePasswordAuthenticator passwordAuth = new SimplePasswordAuthenticator();
final SimplePublicKeyAuthenticator publicKeyAuth = new SimplePublicKeyAuthenticator();

passwordAuth.setUser(username_string);
passwordAuth.setPassword(password_string);
sshd.setPort(port);
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(server_info.getAppContext().getFilesDir().getPath() + "/key.ser"));
sshd.setShellFactory(new PseudoTerminalFactory("/system/bin/sh", "-i"));
sshd.setPasswordAuthenticator(passwordAuth);
sshd.setPublickeyAuthenticator(publicKeyAuth);
sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystem.Factory()));
sshd.setFileSystemFactory(getModifiedNativeFileSystemFactory());

try {
    sshd.start();
    Log.i("SUCCESS: Server listening on port",Integer.toString(port));
    server_info.sshd = sshd;
    server_info.log = log;
} catch (Exception ex) {
    Log.e("FAILURE: Server start failed", ex.toString());
    ex.printStackTrace();
}


}

//Custom FileSystemFactory to change initial root directory on SFTP connection
NativeFileSystemFactory getModifiedNativeFileSystemFactory() {
    return new NativeFileSystemFactory() {

    @Override
    public FileSystemView createFileSystemView(Session session) {
        String userName = getUsername(session);
        NativeFileSystemView nfsv = new ModifiedNativeFileSystemView(
                userName, isCaseInsensitive());
        Log.d("Creating a modified NativeFileSystemView for user", nfsv.getUserName());
        return nfsv;
    }

};
}
//Hook for testing without valid session
String getUsername(Session session) {
    return session.getUsername();
}
//Class to return the altered FileSystemView with changed initial directory
class ModifiedNativeFileSystemView extends NativeFileSystemView {
    String modifiedRootDir;

public ModifiedNativeFileSystemView(String userName,boolean caseInsensitive) {
    super(userName, caseInsensitive);
    modifiedRootDir = System.getProperty("user.dir") + File.separator + TARGET_DIR_NAME;
    Log.d("Modified NativeFileSystemView created with root directory", modifiedRootDir);
}

@Override
public SshFile getFile(String file) {
    return getFile(modifiedRootDir, file);
}
}

EDIT: Fixed SD card access with "su restorecon -FR /data/media/0". It turns out that the TWRP folder had bad permissions after my upgrade to Lollipop (even with "su ls -l" it wouldn't return the permissions, just said access denied). After fixing those permissions, I am able to list the sdcard directories with SFTP just fine.
However, I'm still unable to list the root directories ('/') with SFTP, but there are no problems doing it with "su ls -l" while SSH'd in (it does not work without su). I don't believe it to be the same issue - I think it's just that my SFTP access is not su.
Can anyone tell me how would I make SFTP run as su?

0

There are 0 answers