コード例 #1
0
  public void msgChannelOpenConfirmation(byte[] msg, int msglen) throws IOException {
    PacketChannelOpenConfirmation sm = new PacketChannelOpenConfirmation(msg, 0, msglen);

    Channel c = getChannel(sm.recipientChannelID);

    if (c == null)
      throw new IOException(
          "Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for non-existent channel "
              + sm.recipientChannelID);

    synchronized (c) {
      if (c.state != Channel.STATE_OPENING)
        throw new IOException(
            "Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for channel "
                + sm.recipientChannelID);

      c.remoteID = sm.senderChannelID;
      c.remoteWindow = sm.initialWindowSize & 0xFFFFffffL; /* convert UINT32 to long */
      c.remoteMaxPacketSize = sm.maxPacketSize;
      c.state = Channel.STATE_OPEN;
      c.notifyAll();
    }

    log.debug(
        "Got SSH_MSG_CHANNEL_OPEN_CONFIRMATION (channel "
            + sm.recipientChannelID
            + " / remote: "
            + sm.senderChannelID
            + ")");
  }
コード例 #2
0
  public void msgChannelWindowAdjust(byte[] msg, int msglen) throws IOException {
    if (msglen != 9)
      throw new IOException(
          "SSH_MSG_CHANNEL_WINDOW_ADJUST message has wrong size (" + msglen + ")");

    int id =
        ((msg[1] & 0xff) << 24)
            | ((msg[2] & 0xff) << 16)
            | ((msg[3] & 0xff) << 8)
            | (msg[4] & 0xff);
    int windowChange =
        ((msg[5] & 0xff) << 24)
            | ((msg[6] & 0xff) << 16)
            | ((msg[7] & 0xff) << 8)
            | (msg[8] & 0xff);

    Channel c = getChannel(id);

    if (c == null)
      throw new IOException(
          "Unexpected SSH_MSG_CHANNEL_WINDOW_ADJUST message for non-existent channel " + id);

    synchronized (c) {
      final long huge = 0xFFFFffffL; /* 2^32 - 1 */

      c.remoteWindow += (windowChange & huge); /* avoid sign extension */

      /* TODO - is this a good heuristic? */

      if ((c.remoteWindow > huge)) c.remoteWindow = huge;

      c.notifyAll();
    }

    log.debug("Got SSH_MSG_CHANNEL_WINDOW_ADJUST (channel " + id + ", " + windowChange + ")");
  }
コード例 #3
0
  public void sendData(Channel c, byte[] buffer, int pos, int len) throws IOException {
    boolean wasInterrupted = false;

    try {
      while (len > 0) {
        int thislen = 0;
        byte[] msg;

        synchronized (c) {
          while (true) {
            if (c.state == Channel.STATE_CLOSED)
              throw new ChannelClosedException(
                  "SSH channel is closed. (" + c.getReasonClosed() + ")");

            if (c.state != Channel.STATE_OPEN)
              throw new ChannelClosedException("SSH channel in strange state. (" + c.state + ")");

            if (c.remoteWindow != 0) break;

            try {
              c.wait();
            } catch (InterruptedException ignore) {
              wasInterrupted = true;
            }
          }

          /* len > 0, no sign extension can happen when comparing */

          thislen = (c.remoteWindow >= len) ? len : (int) c.remoteWindow;

          int estimatedMaxDataLen = c.remoteMaxPacketSize - (tm.getPacketOverheadEstimate() + 9);

          /* The worst case scenario =) a true bottleneck */

          if (estimatedMaxDataLen <= 0) {
            estimatedMaxDataLen = 1;
          }

          if (thislen > estimatedMaxDataLen) thislen = estimatedMaxDataLen;

          c.remoteWindow -= thislen;

          msg = new byte[1 + 8 + thislen];

          msg[0] = Packets.SSH_MSG_CHANNEL_DATA;
          msg[1] = (byte) (c.remoteID >> 24);
          msg[2] = (byte) (c.remoteID >> 16);
          msg[3] = (byte) (c.remoteID >> 8);
          msg[4] = (byte) (c.remoteID);
          msg[5] = (byte) (thislen >> 24);
          msg[6] = (byte) (thislen >> 16);
          msg[7] = (byte) (thislen >> 8);
          msg[8] = (byte) (thislen);

          System.arraycopy(buffer, pos, msg, 9, thislen);
        }

        synchronized (c.channelSendLock) {
          if (c.closeMessageSent == true)
            throw new ChannelClosedException(
                "SSH channel is closed. (" + c.getReasonClosed() + ")");

          tm.sendMessage(msg);
        }

        pos += thislen;
        len -= thislen;
      }
    } finally {
      if (wasInterrupted) Thread.currentThread().interrupt();
    }
  }
コード例 #4
0
  public void msgChannelOpen(byte[] msg, int msglen) throws IOException {
    TypesReader tr = new TypesReader(msg, 0, msglen);

    tr.readByte(); // skip packet type
    String channelType = tr.readString();
    int remoteID = tr.readUINT32(); /* sender channel */
    int remoteWindow = tr.readUINT32(); /* initial window size */
    int remoteMaxPacketSize = tr.readUINT32(); /* maximum packet size */

    if ("x11".equals(channelType)) {
      synchronized (x11_magic_cookies) {
        /* If we did not request X11 forwarding, then simply ignore this bogus request. */

        if (x11_magic_cookies.size() == 0) {
          PacketChannelOpenFailure pcof =
              new PacketChannelOpenFailure(
                  remoteID,
                  Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
                  "X11 forwarding not activated",
                  "");

          tm.sendAsynchronousMessage(pcof.getPayload());

          log.warning("Unexpected X11 request, denying it!");

          return;
        }
      }

      String remoteOriginatorAddress = tr.readString();
      int remoteOriginatorPort = tr.readUINT32();

      Channel c = new Channel(this);

      synchronized (c) {
        c.remoteID = remoteID;
        c.remoteWindow = remoteWindow & 0xFFFFffffL; /* properly convert UINT32 to long */
        c.remoteMaxPacketSize = remoteMaxPacketSize;
        c.localID = addChannel(c);
      }

      /*
       * The open confirmation message will be sent from another thread
       */

      RemoteX11AcceptThread rxat =
          new RemoteX11AcceptThread(c, remoteOriginatorAddress, remoteOriginatorPort);
      rxat.setDaemon(true);
      rxat.start();

      return;
    }

    if ("forwarded-tcpip".equals(channelType)) {
      String remoteConnectedAddress = tr.readString(); /* address that was connected */
      int remoteConnectedPort = tr.readUINT32(); /* port that was connected */
      String remoteOriginatorAddress = tr.readString(); /* originator IP address */
      int remoteOriginatorPort = tr.readUINT32(); /* originator port */

      RemoteForwardingData rfd = null;

      synchronized (remoteForwardings) {
        rfd = remoteForwardings.get(new Integer(remoteConnectedPort));
      }

      if (rfd == null) {
        PacketChannelOpenFailure pcof =
            new PacketChannelOpenFailure(
                remoteID,
                Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
                "No thanks, unknown port in forwarded-tcpip request",
                "");

        /* Always try to be polite. */

        tm.sendAsynchronousMessage(pcof.getPayload());

        log.debug("Unexpected forwarded-tcpip request, denying it!");

        return;
      }

      Channel c = new Channel(this);

      synchronized (c) {
        c.remoteID = remoteID;
        c.remoteWindow = remoteWindow & 0xFFFFffffL; /* convert UINT32 to long */
        c.remoteMaxPacketSize = remoteMaxPacketSize;
        c.localID = addChannel(c);
      }

      /*
       * The open confirmation message will be sent from another thread.
       */

      RemoteAcceptThread rat =
          new RemoteAcceptThread(
              c,
              remoteConnectedAddress,
              remoteConnectedPort,
              remoteOriginatorAddress,
              remoteOriginatorPort,
              rfd.targetAddress,
              rfd.targetPort);

      rat.setDaemon(true);
      rat.start();

      return;
    }

    if ((server_state != null) && ("session".equals(channelType))) {
      ServerConnectionCallback cb = null;

      synchronized (server_state) {
        cb = server_state.cb_conn;
      }

      if (cb == null) {
        tm.sendAsynchronousMessage(
            new PacketChannelOpenFailure(
                    remoteID,
                    Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
                    "Sessions are currently not enabled",
                    "en")
                .getPayload());

        return;
      }

      final Channel c = new Channel(this);

      synchronized (c) {
        c.remoteID = remoteID;
        c.remoteWindow = remoteWindow & 0xFFFFffffL; /* convert UINT32 to long */
        c.remoteMaxPacketSize = remoteMaxPacketSize;
        c.localID = addChannel(c);
        c.state = Channel.STATE_OPEN;
        c.ss = new ServerSessionImpl(c);
      }

      PacketChannelOpenConfirmation pcoc =
          new PacketChannelOpenConfirmation(
              c.remoteID, c.localID, c.localWindow, c.localMaxPacketSize);

      tm.sendAsynchronousMessage(pcoc.getPayload());

      c.ss.sscb = cb.acceptSession(c.ss);

      return;
    }

    /* Tell the server that we have no idea what it is talking about */

    PacketChannelOpenFailure pcof =
        new PacketChannelOpenFailure(
            remoteID, Packets.SSH_OPEN_UNKNOWN_CHANNEL_TYPE, "Unknown channel type", "");

    tm.sendAsynchronousMessage(pcof.getPayload());

    log.warning("The peer tried to open an unsupported channel type (" + channelType + ")");
  }