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

An SSH client receives an echo as a response from the server

    XMLWordPrintableJSON

Details

    • Question
    • Status: Resolved
    • Minor
    • Resolution: Invalid
    • 1.4.0
    • None
    • None

    Description

      I'm trying to integrate my Java application with a device which provides a custom protocol over SSH.

      The whole point of this protocol is about exchanging XML documents back and forth. It can be described with the following steps:

      1. a client connects to the server
      2. the client sends an XML document which contains the request data
      3. the client waits for the XML document which contains a response data from a server
      4. the server receives the XML document that was sent by the client and sends the response XML document back to the client
      5. the client receives the XML response from the server and closes the connection

      The recommended way to send requests to this device is to use `cat` and `ssh` tools. Here's a simple example:

      cat example.xml | ssh <user_id>@<device_ip>
      

      where `example.xml` is a file that contains an XML document with the request data.

      Calling directly 'cat' and 'ssh' via Runtime.exec would be very problematic because this approach has a lot of drawbacks. So, I decided to implement this protocol using MINA SSHD library.

      The problem I've run into is I receive my own request as a response from the server. So there's some kind of echoing stuff going on, I think.

      For example, when I send this XML document as a request to the server:

      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <xg-request>
          <action-request>
              <action-name>test</action-name>
          </action-request>
      </xg-request>
      
      

      I receive the following data as a response:

      Last login: Wed May 3 07:33:43 2017 from ip
      
      Header
      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <xg-request>
          <action-request>
              <action-name>test</action-name>
          </action-request>
      </xg-request>
      
      

      The funny this is when I send the same request via cat and ssh (the example I mentioned above), I receive the correct response from the device.

      Here's an excerpt from my application:

      public class Test {
      
        private static final long AWAIT_TIMEOUT = TimeUnit.SECONDS.toMillis(5);
        private static final String XML_PAYLOAD_HEADER = "<?xml";
      
        public void init() throws IOException, JAXBException {
          try (SshClient client = initSshClient();
               ClientSession session =
                 initClientSession(client, "test", "localhost", 22, "pass")) {
            sendRequest(session);
          }
        }
      
        private static SshClient initSshClient() {
          SshClient client = SshClient.setUpDefaultClient();
          client.start();
      
          return client;
        }
      
        private ClientSession initClientSession(SshClient client, String user, 
                                                String host, int port, 
                                                String password) throws IOException {
          ClientSession session =
            client.connect(user, host, port).verify(AWAIT_TIMEOUT).getSession();
      
          session.addPasswordIdentity(password);
          session.auth().verify(AWAIT_TIMEOUT);
      
          return session;
        }
      
        private void sendRequest(ClientSession session) throws IOException {
          try (PipedOutputStream out = new PipedOutputStream();
               PipedInputStream channelIn = new PipedInputStream(out);
               PipedOutputStream channelOut = new PipedOutputStream();
               PipedInputStream in = new PipedInputStream(channelOut);
               BufferedReader reader = new BufferedReader(new InputStreamReader(in));
               BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
               ClientChannel channel = initClientChannel(session, channelIn, channelOut)) {
            String xmlRequest = ""; // Here goes a real XML document;
      
            writer.write(xmlRequest);
            writer.newLine();
            writer.flush();
      
            String response = readFully(reader);
          }
        }
      
        private static ClientChannel initClientChannel(ClientSession session, InputStream input,
                                                       OutputStream output) throws IOException {
          ClientChannel channel = session.createChannel(Channel.CHANNEL_SHELL);
      
          channel.setIn(input);
          channel.setOut(output);
          channel.setErr(new ByteArrayOutputStream());
          channel.open().verify(AWAIT_TIMEOUT);
      
          return channel;
        }
      
        private static String readFully(BufferedReader reader) throws IOException {
          StringBuilder builder = new StringBuilder();
          String line;
          boolean foundXmlPayload = false;
      
          while ((line = reader.readLine()) != null) {
            if (foundXmlPayload && line.isEmpty()) {
              break;
            }
      
            builder.append(line);
      
            if (!foundXmlPayload && builder.indexOf(XML_PAYLOAD_HEADER) != -1) {
              foundXmlPayload = true;
            }
          }
      
          return builder.toString();
        }
      }
      

      Any suggestions would be greatly appreciated.

      Attachments

        Activity

          People

            Unassigned Unassigned
            maseev Miron Aseev
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: