Apache MINA SSHD session echoes characters twice when using ProcessShellFactory, control characters don't work

Viewed 661

I'm running OpenJDK 14 on macOS 10.15.7. I'm doing some proof-of-concept code establishing an SSH server with Apache Mina SSHD and then connecting to it. Here's what I have:

import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;

import org.apache.sshd.common.cipher.BuiltinCiphers;
import org.apache.sshd.common.util.logging.AbstractLoggingBean;
import org.apache.sshd.server.ServerBuilder;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.auth.AsyncAuthException;
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
import org.apache.sshd.server.auth.password.PasswordChangeRequiredException;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.shell.InteractiveProcessShellFactory;
import org.apache.sshd.server.shell.ProcessShellFactory;

public class FunctionalTest
{
    private static class TestAuthenticator
        extends AbstractLoggingBean
        implements PasswordAuthenticator
    {
        @Override
        public boolean authenticate(String username, String password, ServerSession session)
            throws PasswordChangeRequiredException, AsyncAuthException
        {
            if ("test".equals(username) && "foobar".equals(password))
            {
                this.log.info("authenticate({}[{}]: accepted", username, session);
                return true;
            }

            this.log.warn("authenticate({}[{}]: rejected", username, session);
            return false;
        }
    }

    public static void main(String... args) throws IOException
    {
        SshServer sshd = SshServer.setUpDefaultServer();
        sshd.setHost("0.0.0.0");
        sshd.setPort(1022);
        sshd.setShellFactory(InteractiveProcessShellFactory.INSTANCE);
        sshd.setPasswordAuthenticator(new TestAuthenticator());
        sshd.setCipherFactories(Arrays.asList(BuiltinCiphers.aes256ctr, BuiltinCiphers.aes192ctr));
        sshd.setKeyExchangeFactories(ServerBuilder.setUpDefaultKeyExchanges(false));
        sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(Paths.get("key.ser")));
        sshd.start();

        try
        {
            Thread.sleep(3_600_000);
        }
        catch(InterruptedException e)
        {
            System.out.println("Caught interrupt ... stopping server.");
            sshd.stop(true);
        }
    }
}

When I start this, I can ssh -p 1022 test@localhost with the password foobar and it works. After successful authentication, I first see this:

sh: no job control in this shell

Then at the prompt, characters I type (including newlines) are echoed twice instead of once, resulting in everything being dduupplliiccaatteedd:

williamsn:mina-test williamsn$ llss  --aall

total 24
... (list of files)
williamsn:mina-test williamsn$ eecchhoo  hheelllloo
hello

williamsn:mina-test williamsn$

Additionally, if I run an interactive command like top, it doesn't recognize my inputs, and control characters don't work. ttoopp starts (though its output is ugly and additive instead of replacing the screen), but if I type q to exit (q is not echoed twice in this case), top does not exit in response to the q. It just keeps going. ctrl+c also does not work—top just keeps going. The only way to exit top is to kill my ssh process or shut down the MINA server.

I feel like I must be doing something terribly wrong here. Thoughts?

1 Answers

The "no job control" message indicates that the spawned shell Is not in a full interactive mode, and the double letters show that you have a mismatch between local and remote character echo. I can only assume that the default shell on mac-os (/usr/bin/sh ) is not a bash implementation like it is on Linux. Try changing the shell factory to new ProcessShellFactory("/usr/bin/bash","-i")

Sorry I don't have a mac to try this out.

Paul

Related