com.sshtools.daemon.forwarding.ForwardingServer.java Source code

Java tutorial

Introduction

Here is the source code for com.sshtools.daemon.forwarding.ForwardingServer.java

Source

/*
 *  SSHTools - Java SSH2 API
 *
 *  Copyright (C) 2002 Lee David Painter.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  You may also distribute it and/or modify it under the terms of the
 *  Apache style J2SSH Software License. A copy of which should have
 *  been provided with the distribution.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  License document supplied with your distribution for more details.
 *
 */

package com.sshtools.daemon.forwarding;

import java.io.IOException;
import java.net.Socket;
import java.net.SocketPermission;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.sshtools.j2ssh.connection.Channel;
import com.sshtools.j2ssh.connection.ChannelFactory;
import com.sshtools.j2ssh.connection.ConnectionProtocol;
import com.sshtools.j2ssh.connection.GlobalRequestHandler;
import com.sshtools.j2ssh.connection.GlobalRequestResponse;
import com.sshtools.j2ssh.connection.InvalidChannelException;
import com.sshtools.j2ssh.forwarding.ForwardingClient;
import com.sshtools.j2ssh.forwarding.ForwardingConfiguration;
import com.sshtools.j2ssh.forwarding.ForwardingConfigurationException;
import com.sshtools.j2ssh.forwarding.ForwardingListener;
import com.sshtools.j2ssh.forwarding.ForwardingSocketChannel;
import com.sshtools.j2ssh.io.ByteArrayReader;

/**
 *
 *
 * @author $author$
 * @version $Revision: 1.1.1.1 $
 */
public class ForwardingServer implements ChannelFactory, GlobalRequestHandler {
    private static Log log = LogFactory.getLog(ForwardingServer.class);
    private ConnectionProtocol connection;
    private List channelTypes = new Vector();
    private List localForwardings = new Vector();
    private List remoteForwardings = new Vector();

    /**
     * Creates a new ForwardingServer object.
     *
     * @param connection
     *
     * @throws IOException
     */
    public ForwardingServer(ConnectionProtocol connection) throws IOException {
        this.connection = connection;
        channelTypes.add(ForwardingSocketChannel.LOCAL_FORWARDING_CHANNEL);
        connection.addChannelFactory(ForwardingSocketChannel.LOCAL_FORWARDING_CHANNEL, this);
        connection.allowGlobalRequest(ForwardingClient.REMOTE_FORWARD_REQUEST, this);
        connection.allowGlobalRequest(ForwardingClient.REMOTE_FORWARD_CANCEL_REQUEST, this);
    }

    /* public List getChannelType() {
     return channelTypes;
      }*/
    public Channel createChannel(String channelType, byte[] requestData) throws InvalidChannelException {
        if (!channelType.equals(ForwardingSocketChannel.LOCAL_FORWARDING_CHANNEL)) {
            throw new InvalidChannelException(
                    "The client can only request the " + "opening of a local forwarding channel");
        }

        try {
            ByteArrayReader bar = new ByteArrayReader(requestData);
            String hostToConnect = bar.readString();
            int portToConnect = (int) bar.readInt();
            String originatingHost = bar.readString();
            int originatingPort = (int) bar.readInt();

            // Get a configuration item for the forwarding
            ForwardingConfiguration config = getLocalForwardingByAddress(originatingHost, originatingPort);
            Socket socket = new Socket(hostToConnect, portToConnect);

            // Create the channel adding it to the active channels
            ForwardingSocketChannel channel = config.createForwardingSocketChannel(channelType, hostToConnect,
                    portToConnect, originatingHost, originatingPort);
            channel.bindSocket(socket);

            return channel;
        } catch (ForwardingConfigurationException fce) {
            throw new InvalidChannelException("No valid forwarding configuration was available for the request");
        } catch (IOException ioe) {
            throw new InvalidChannelException(
                    "The channel request data is " + "invalid/or corrupt for channel type " + channelType);
        }
    }

    /**
     *
     *
     * @param requestName
     * @param requestData
     *
     * @return
     */
    public GlobalRequestResponse processGlobalRequest(String requestName, byte[] requestData) {
        GlobalRequestResponse response = new GlobalRequestResponse(false);
        String addressToBind = null;
        int portToBind = -1;
        log.debug("Processing " + requestName + " global request");

        try {
            ByteArrayReader bar = new ByteArrayReader(requestData);
            addressToBind = bar.readString();
            portToBind = (int) bar.readInt();

            if (requestName.equals(ForwardingClient.REMOTE_FORWARD_REQUEST)) {
                addRemoteForwardingConfiguration(addressToBind, portToBind);
                response = new GlobalRequestResponse(true);
            }

            if (requestName.equals(ForwardingClient.REMOTE_FORWARD_CANCEL_REQUEST)) {
                removeRemoteForwarding(addressToBind, portToBind);
                response = new GlobalRequestResponse(true);
            }
        } catch (IOException ioe) {
            log.warn("The client failed to request " + requestName + " for " + addressToBind + ":"
                    + String.valueOf(portToBind), ioe);
        }

        return response;
    }

    /**
     *
     *
     * @param orginatingAddress
     * @param originatingPort
     *
     * @return
     *
     * @throws ForwardingConfigurationException
     */
    protected ForwardingConfiguration getLocalForwardingByAddress(String orginatingAddress, int originatingPort)
            throws ForwardingConfigurationException {
        try {
            Iterator it = localForwardings.iterator();
            ForwardingConfiguration config;

            while (it.hasNext()) {
                config = (ForwardingConfiguration) it.next();

                if (config.getAddressToBind().equals(orginatingAddress)
                        && (config.getPortToBind() == originatingPort)) {
                    return config;
                }
            }

            // No configuration is available so create one
            config = new ForwardingConfiguration(orginatingAddress, originatingPort);

            // We must start this configuration in order to use it
            config.start();
            localForwardings.add(config);

            return config;
        } catch (IOException ex) {
            throw new ForwardingConfigurationException(ex.getMessage());
        }
    }

    /**
     *
     *
     * @param addressToBind
     * @param portToBind
     *
     * @return
     *
     * @throws ForwardingConfigurationException
     */
    protected ForwardingConfiguration getRemoteForwardingByAddress(String addressToBind, int portToBind)
            throws ForwardingConfigurationException {
        Iterator it = remoteForwardings.iterator();
        ForwardingConfiguration config;

        while (it.hasNext()) {
            config = (ForwardingConfiguration) it.next();

            if (config.getAddressToBind().equals(addressToBind) && (config.getPortToBind() == portToBind)) {
                return config;
            }
        }

        throw new ForwardingConfigurationException("The remote forwarding does not exist!");
    }

    /**
     *
     *
     * @param addressToBind
     * @param portToBind
     *
     * @throws ForwardingConfigurationException
     */
    protected void addRemoteForwardingConfiguration(String addressToBind, int portToBind)
            throws ForwardingConfigurationException {
        // Is the server already listening
        Iterator it = remoteForwardings.iterator();
        ForwardingConfiguration config;

        while (it.hasNext()) {
            config = (ForwardingConfiguration) it.next();

            if (config.getAddressToBind().equals(addressToBind) && (config.getPortToBind() == portToBind)) {
                throw new ForwardingConfigurationException("The address and port are already in use!");
            }
        }

        config = new ForwardingConfiguration(addressToBind, portToBind);

        // Check the security mananger
        SecurityManager manager = System.getSecurityManager();

        if (manager != null) {
            try {
                manager.checkPermission(
                        new SocketPermission(addressToBind + ":" + String.valueOf(portToBind), "accept,listen"));
            } catch (SecurityException e) {
                throw new ForwardingConfigurationException("The security manager has denied listen permision on "
                        + addressToBind + ":" + String.valueOf(portToBind));
            }
        }

        try {
            ForwardingListener listener = new ServerForwardingListener(connection, addressToBind, portToBind);
            remoteForwardings.add(listener);
            listener.start();
        } catch (IOException ex) {
            throw new ForwardingConfigurationException(ex.getMessage());
        }
    }

    /**
     *
     *
     * @param addressToBind
     * @param portToBind
     *
     * @throws ForwardingConfigurationException
     */
    protected void removeRemoteForwarding(String addressToBind, int portToBind)
            throws ForwardingConfigurationException {
        ForwardingConfiguration config = getRemoteForwardingByAddress(addressToBind, portToBind);

        // Stop the forwarding
        config.stop();

        // Remove from the remote forwardings list
        remoteForwardings.remove(config);
    }

    class ServerForwardingListener extends ForwardingListener {
        public ServerForwardingListener(ConnectionProtocol connection, String addressToBind, int portToBind) {
            super(connection, addressToBind, portToBind);
        }

        public ForwardingSocketChannel createChannel(String hostToConnect, int portToConnect, Socket socket)
                throws ForwardingConfigurationException {
            try {
                ForwardingSocketChannel channel = createForwardingSocketChannel(
                        ForwardingSocketChannel.REMOTE_FORWARDING_CHANNEL, hostToConnect, portToConnect,
                        /*( (InetSocketAddress) socket.getRemoteSocketAddress()).getAddress()
                          .getHostAddress(),
                          ( (InetSocketAddress) socket.getRemoteSocketAddress())
                          .getPort()*/
                        socket.getInetAddress().getHostAddress(), socket.getPort());
                channel.bindSocket(socket);

                return channel;
            } catch (IOException ex) {
                throw new ForwardingConfigurationException(ex.getMessage());
            }
        }
    }
}