Пример #1
0
  /**
   * Reads the identification string from the SSH server. This is the very first string that is sent
   * upon connection by the server. It takes the form of, e.g. "SSH-2.0-OpenSSH_ver".
   *
   * <p>Several concerns are taken care of here, e.g. verifying protocol version, correct line
   * endings as specified in RFC and such.
   *
   * <p>This is not efficient but is only done once.
   *
   * @param buffer The buffer to read from.
   * @return empty string if full ident string has not yet been received
   * @throws IOException
   */
  private String readIdentification(Buffer.PlainBuffer buffer) throws IOException {
    String ident;

    byte[] data = new byte[256];
    for (; ; ) {
      int savedBufPos = buffer.rpos();
      int pos = 0;
      boolean needLF = false;
      for (; ; ) {
        if (buffer.available() == 0) {
          // Need more data, so undo reading and return null
          buffer.rpos(savedBufPos);
          return "";
        }
        byte b = buffer.readByte();
        if (b == '\r') {
          needLF = true;
          continue;
        }
        if (b == '\n') break;
        if (needLF) throw new TransportException("Incorrect identification: bad line ending");
        if (pos >= data.length)
          throw new TransportException("Incorrect identification: line too long");
        data[pos++] = b;
      }
      ident = new String(data, 0, pos);
      if (ident.startsWith("SSH-")) break;
      if (buffer.rpos() > 16 * 1024)
        throw new TransportException("Incorrect identification: too many header lines");
    }

    if (!ident.startsWith("SSH-2.0-") && !ident.startsWith("SSH-1.99-"))
      throw new TransportException(
          DisconnectReason.PROTOCOL_VERSION_NOT_SUPPORTED,
          "Server does not support SSHv2, identified as: " + ident);

    return ident;
  }