Пример #1
0
  @Override
  public void init(String remoteHost, int remotePort, InputStream in, OutputStream out)
      throws TransportException {
    connInfo = new ConnInfo(remoteHost, remotePort, in, out);

    try {

      log.info("Client identity string: {}", clientID);
      connInfo.out.write((clientID + "\r\n").getBytes(IOUtils.UTF8));
      connInfo.out.flush();

      // Read server's ID
      final Buffer.PlainBuffer buf = new Buffer.PlainBuffer();
      while ((serverID = readIdentification(buf)).isEmpty()) {
        int b = connInfo.in.read();
        if (b == -1)
          throw new TransportException("Server closed connection during identification exchange");
        buf.putByte((byte) b);
      }

      log.info("Server identity string: {}", serverID);

    } catch (IOException e) {
      throw new TransportException(e);
    }

    reader.start();
  }
Пример #2
0
  @Override
  public boolean next(Message msg, SSHPacket packet)
      throws GeneralSecurityException, TransportException {
    if (msg != Message.KEXDH_31)
      throw new TransportException(
          DisconnectReason.KEY_EXCHANGE_FAILED, "Unexpected packet: " + msg);

    log.debug("Received SSH_MSG_KEXDH_REPLY");
    final byte[] K_S;
    final BigInteger f;
    final byte[] sig; // signature sent by server
    try {
      K_S = packet.readBytes();
      f = packet.readMPInt();
      sig = packet.readBytes();
      hostKey = new Buffer.PlainBuffer(K_S).readPublicKey();
    } catch (Buffer.BufferException be) {
      throw new TransportException(be);
    }

    dh.computeK(f);

    final Buffer.PlainBuffer buf =
        new Buffer.PlainBuffer()
            .putString(V_C)
            .putString(V_S)
            .putString(I_C)
            .putString(I_S)
            .putString(K_S)
            .putMPInt(dh.getE())
            .putMPInt(f)
            .putMPInt(dh.getK());
    sha1.update(buf.array(), buf.rpos(), buf.available());
    H = sha1.digest();

    Signature signature =
        Factory.Named.Util.create(
            trans.getConfig().getSignatureFactories(), KeyType.fromKey(hostKey).toString());
    signature.init(hostKey, null);
    signature.update(H, 0, H.length);
    if (!signature.verify(sig))
      throw new TransportException(
          DisconnectReason.KEY_EXCHANGE_FAILED, "KeyExchange signature verification failed");
    return true;
  }
Пример #3
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;
  }