Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable echo when sending a terminal command using apache-commons-net TelnetClient

So, I have this class that uses the org.apache.commons.net.telnet.TelnetClient class. It attempts to send commands and read the response.

public class AutomatedTelnetClient
{
    private TelnetClient telnet = new TelnetClient();
    private InputStream in;
    private PrintStream out;
    private String prompt = "$";

    public AutomatedTelnetClient(String server, String user, String password)
    {
        try
        {
            EchoOptionHandler echoopt = new EchoOptionHandler(false, false, false, false);
            telnet.addOptionHandler(echoopt);

            // Connect to the specified server
            telnet.connect(server, 23);

            // Get input and output stream references
            in = telnet.getInputStream();
            out = new PrintStream(telnet.getOutputStream());

            // Log the user on
            readUntil("login: ");
            write(user);
            readUntil("Password: ");
            write(password);

            // Advance to a prompt
            readUntil(prompt + " ");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void su(String password)
    {
        try
        {
            write("su");
            readUntil("Password: ");
            write(password);
            prompt = "#";
            readUntil(prompt + " ");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public String readUntil(String pattern)
    {
        try
        {
            char lastChar = pattern.charAt(pattern.length() - 1);
            StringBuffer sb = new StringBuffer();
            boolean found = false;
            char ch = (char) in.read();
            while (true)
            {
                System.out.print(ch);
                sb.append(ch);
                if (ch == lastChar)
                {
                    if (sb.toString().endsWith(pattern))
                    {
                        return sb.toString();
                    }
                }
                ch = (char) in.read();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    public void write(String value)
    {
        try
        {
            out.println(value);
            out.flush();
            System.out.println(value);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public String sendCommand(String command)
    {
        try
        {
            write(command);
            return readUntil(prompt + " ");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    public void disconnect()
    {
        try
        {
            telnet.disconnect();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        try
        {
            AutomatedTelnetClient telnet = new AutomatedTelnetClient(
                    "...", "...", "...");

            System.out.println("Got Connection...");

            System.out.println("run command");
            telnet.sendCommand("ls ");
            telnet.sendCommand("cd netConf");
            telnet.sendCommand("ls ");
            telnet.sendCommand("cd lanSetup");
            telnet.sendCommand("ls ");
            telnet.sendCommand("cd dhcpd");
            telnet.sendCommand("show interface 2");

            telnet.disconnect();
            System.out.println("DONE");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

Trouble is, when I send a command, the response is prefaced with an echo of sorts. For instance, when I send the ls command, this is the response I read

[mls 
....

I've tried searching on how to disable echo, but no one seems to have the answer. So, I've decided to ask this community. Does anyone know how to disable this echo?

EDIT

Looking at the source code of EchoOptionHandler is confusing me. Why are the sub-negotiation methods only returning null?

like image 492
mre Avatar asked Jun 20 '11 11:06

mre


People also ask

What is Telnet echo?

Telnet sends each character the user types to the remote computer. It also displays whatever characters the remote computer sends back. Since SMTP does not send back (echo) the characters typed by the user, you would not see them displayed.

How do I turn on local echo?

Some times you may want to enable local echo if it's turned off. To enable local echo in a terminal, first connect to the host, then enter: "stty echo" command. To disable it, enter: "stty -echo".

How do I enable local echo in Telnet?

To set a control-key combination, hold down the CTRL key while you type the character that you want to assign. Turns on local echo. Logs the current telnet session to the local file. Logging begins automatically when you set this option.


2 Answers

Interesting problem. To summarize my effort: I didn't get it working properly But here are some of my findings:

You cannot write IAC DON'T ECHO directly to the data channel, this is done with commands and options like this example

int[] msg = {TelnetCommand.DONT,TelnetOption.ECHO};
telnet.sendSubnegotiation(msg);

You can register telnet.registerNotifHandler(new MyNotificationHandler()); to debug the commands during connection setup

public class MyNotificationHandler implements TelnetNotificationHandler
{
  @Override
  public void receivedNegotiation(int negotiation_code, int option_code)
  {
    System.out.println("--->"+get(negotiation_code)+" "
                             +TelnetOption.getOption(option_code));
  }

  private String get(int i)
  {
    if(i==TelnetNotificationHandler.RECEIVED_DO){return "RECEIVED_DO";}
    else if(i==TelnetNotificationHandler.RECEIVED_DONT){return "RECEIVED_DONT";}
    else if(i==TelnetNotificationHandler.RECEIVED_WILL){return "RECEIVED_WILL";}
    else if(i==TelnetNotificationHandler.RECEIVED_WONT){return "RECEIVED_WONT";}
    else if(i==TelnetNotificationHandler.RECEIVED_COMMAND)
                                                    {return "RECEIVED_COMMAND";}
    return "UNKNOWN";
    }
}
like image 193
Thor Avatar answered Oct 14 '22 02:10

Thor


By default, TelnetClient indicates to the remote system that it is a "vt100" terminal. The [m is part of a VT100 escape sequence. When constructing the TelnetClient pass "dumb" as the first argument to indicate the terminal does not support escape sequences. So

TelnetClient telnet = new TelnetClient("dumb");

Update:

It may be the shell prompt on the remote is set to display in color. If you run "echo $PS1" you'll see what the prompt is set to and it might be something like:

\[\e]2;\u@\h : \w\007\]\[\e[39m\e[0;49m\][\[\e[1;34m\]\u\[\e[0;37m\]@\[\e[0;32m\]\h\[\e[0;36m\] \[\e[0;33m\]\w\[\e[39m\e[0;49m\]]$ 

That displays on my terminal as "[user@host directory]$ " with the brackets and dollar sign in white, the user in blue, the host in green and the directory in yellow. All very nice for people, but bad for machines.

As soon as you log in, send "PS1='$ '\n". That will set the prompt to exactly a dollar sign followed by a space without any extra sequences.

like image 25
Devon_C_Miller Avatar answered Oct 14 '22 03:10

Devon_C_Miller