예제 #1
0
  @Override
  public void handleOpenSuccess(int recipient, int rwSize, int packetSize, Buffer buffer) {
    setRecipient(recipient);

    Session session = getSession();
    FactoryManager manager =
        ValidateUtils.checkNotNull(session.getFactoryManager(), "No factory manager");
    this.remoteWindow.init(rwSize, packetSize, manager.getProperties());
    ChannelListener listener = getChannelListenerProxy();
    try {
      doOpen();

      listener.channelOpenSuccess(this);
      this.opened.set(true);
      this.openFuture.setOpened();
    } catch (Throwable t) {
      Throwable e = GenericUtils.peelException(t);
      try {
        listener.channelOpenFailure(this, e);
      } catch (Throwable ignored) {
        log.warn(
            "handleOpenSuccess({}) failed ({}) to inform listener of open failure={}: {}",
            this,
            ignored.getClass().getSimpleName(),
            e.getClass().getSimpleName(),
            ignored.getMessage());
      }

      this.openFuture.setException(e);
      this.closeFuture.setClosed();
      this.doCloseImmediately();
    } finally {
      notifyStateChanged();
    }
  }
예제 #2
0
  @Override
  public synchronized OpenFuture open() throws IOException {
    if (isClosing()) {
      throw new SshException("Session has been closed");
    }

    openFuture = new DefaultOpenFuture(lock);
    if (log.isDebugEnabled()) {
      log.debug("open({}) Send SSH_MSG_CHANNEL_OPEN - type={}", this, type);
    }

    Session session = getSession();
    Buffer buffer =
        session.createBuffer(SshConstants.SSH_MSG_CHANNEL_OPEN, type.length() + Integer.SIZE);
    buffer.putString(type);
    buffer.putInt(getId());
    buffer.putInt(localWindow.getSize());
    buffer.putInt(localWindow.getPacketSize());
    writePacket(buffer);
    return openFuture;
  }
  @Override
  public synchronized SshdSocketAddress startRemotePortForwarding(
      SshdSocketAddress remote, SshdSocketAddress local) throws IOException {
    ValidateUtils.checkNotNull(local, "Local address is null");
    ValidateUtils.checkNotNull(remote, "Remote address is null");

    Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_GLOBAL_REQUEST);
    buffer.putString("tcpip-forward");
    buffer.putBoolean(true);
    buffer.putString(remote.getHostName());
    buffer.putInt(remote.getPort());
    Buffer result = session.request(buffer);
    if (result == null) {
      throw new SshException("Tcpip forwarding request denied by server");
    }
    int port = (remote.getPort() == 0) ? result.getInt() : remote.getPort();
    // TODO: Is it really safe to only store the local address after the request ?
    SshdSocketAddress prev;
    synchronized (remoteToLocal) {
      prev = remoteToLocal.put(port, local);
    }

    if (prev != null) {
      throw new IOException(
          "Multiple remote port forwarding bindings on port="
              + port
              + ": current="
              + remote
              + ", previous="
              + prev);
    }

    SshdSocketAddress bound = new SshdSocketAddress(remote.getHostName(), port);
    if (log.isDebugEnabled()) {
      log.debug("startRemotePortForwarding(" + remote + " -> " + local + "): " + bound);
    }

    return bound;
  }
예제 #4
0
  @Override
  public Result process(
      ConnectionService connectionService, String request, boolean wantReply, Buffer buffer)
      throws Exception {
    if (!REQUEST.equals(request)) {
      return super.process(connectionService, request, wantReply, buffer);
    }

    String address = buffer.getString();
    int port = buffer.getInt();
    SshdSocketAddress socketAddress = new SshdSocketAddress(address, port);
    TcpipForwarder forwarder =
        Objects.requireNonNull(connectionService.getTcpipForwarder(), "No TCP/IP forwarder");
    SshdSocketAddress bound = forwarder.localPortForwardingRequested(socketAddress);
    if (log.isDebugEnabled()) {
      log.debug(
          "process({})[{}][want-reply-{}] {} => {}",
          connectionService,
          request,
          wantReply,
          socketAddress,
          bound);
    }

    if (bound == null) {
      return Result.ReplyFailure;
    }

    port = bound.getPort();
    if (wantReply) {
      Session session = connectionService.getSession();
      buffer = session.createBuffer(SshConstants.SSH_MSG_REQUEST_SUCCESS, Integer.BYTES);
      buffer.putInt(port);
      session.writePacket(buffer);
    }

    return Result.Replied;
  }
  @Override
  public synchronized void stopRemotePortForwarding(SshdSocketAddress remote) throws IOException {
    SshdSocketAddress bound;
    synchronized (remoteToLocal) {
      bound = remoteToLocal.remove(remote.getPort());
    }

    if (bound != null) {
      if (log.isDebugEnabled()) {
        log.debug("stopRemotePortForwarding(" + remote + ") cancel forwarding to " + bound);
      }

      Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_GLOBAL_REQUEST);
      buffer.putString("cancel-tcpip-forward");
      buffer.putBoolean(false);
      buffer.putString(remote.getHostName());
      buffer.putInt(remote.getPort());
      session.writePacket(buffer);
    } else {
      if (log.isDebugEnabled()) {
        log.debug("stopRemotePortForwarding(" + remote + ") no binding found");
      }
    }
  }
  @Override
  public synchronized SshdSocketAddress localPortForwardingRequested(SshdSocketAddress local)
      throws IOException {
    ValidateUtils.checkNotNull(local, "Local address is null");
    ValidateUtils.checkTrue(local.getPort() >= 0, "Invalid local port: %s", local);

    FactoryManager manager = session.getFactoryManager();
    ForwardingFilter filter = manager.getTcpipForwardingFilter();
    if ((filter == null) || (!filter.canListen(local, session))) {
      if (log.isDebugEnabled()) {
        log.debug(
            "localPortForwardingRequested("
                + session
                + ")["
                + local
                + "][haveFilter="
                + (filter != null)
                + "] rejected");
      }
      throw new IOException("Rejected address: " + local);
    }
    InetSocketAddress bound = doBind(local, staticIoHandlerFactory);
    SshdSocketAddress result = new SshdSocketAddress(bound.getHostString(), bound.getPort());
    if (log.isDebugEnabled()) {
      log.debug("localPortForwardingRequested(" + local + "): " + result);
    }

    boolean added;
    synchronized (localForwards) {
      // NOTE !!! it is crucial to use the bound address host name first
      added =
          localForwards.add(
              new LocalForwardingEntry(
                  result.getHostName(), local.getHostName(), result.getPort()));
    }

    if (!added) {
      throw new IOException(
          "Failed to add local port forwarding entry for " + local + " -> " + result);
    }
    return result;
  }
  @Override
  public FileSystem createFileSystem(Session session) {
    String userName = session.getUsername();
    // create home if does not exist
    if (createHome) {
      String homeDirStr = "/home/" + userName;
      File homeDir = new File(homeDirStr);
      if (homeDir.isFile()) {
        log.warn("Not a directory :: " + homeDirStr);
        //                    throw new FtpException("Not a directory :: " + homeDirStr);
      }
      if ((!homeDir.exists()) && (!homeDir.mkdirs())) {
        log.warn("Cannot create user home :: " + homeDirStr);
        //                    throw new FtpException("Cannot create user home :: "
        //                            + homeDirStr);
      }
    }

    return FileSystems.getDefault();
  }
  /**
   * @param address The request bind address
   * @param handlerFactory A {@link Factory} to create an {@link IoHandler} if necessary
   * @return The {@link InetSocketAddress} to which the binding occurred
   * @throws IOException If failed to bind
   */
  private InetSocketAddress doBind(
      SshdSocketAddress address, Factory<? extends IoHandler> handlerFactory) throws IOException {
    if (acceptor == null) {
      FactoryManager manager = session.getFactoryManager();
      IoServiceFactory factory = manager.getIoServiceFactory();
      IoHandler handler = handlerFactory.create();
      acceptor = factory.createAcceptor(handler);
    }

    // TODO find a better way to determine the resulting bind address - what if multi-threaded
    // calls...
    Set<SocketAddress> before = acceptor.getBoundAddresses();
    try {
      InetSocketAddress bindAddress = address.toInetSocketAddress();
      acceptor.bind(bindAddress);

      Set<SocketAddress> after = acceptor.getBoundAddresses();
      if (GenericUtils.size(after) > 0) {
        after.removeAll(before);
      }
      if (GenericUtils.isEmpty(after)) {
        throw new IOException(
            "Error binding to " + address + "[" + bindAddress + "]: no local addresses bound");
      }

      if (after.size() > 1) {
        throw new IOException(
            "Multiple local addresses have been bound for " + address + "[" + bindAddress + "]");
      }
      return (InetSocketAddress) after.iterator().next();
    } catch (IOException bindErr) {
      Set<SocketAddress> after = acceptor.getBoundAddresses();
      if (GenericUtils.isEmpty(after)) {
        close();
      }
      throw bindErr;
    }
  }