001: /*
002: * SSHTools - Java SSH2 API
003: *
004: * Copyright (C) 2002-2003 Lee David Painter and Contributors.
005: *
006: * Contributions made by:
007: *
008: * Brett Smith
009: * Richard Pernavas
010: * Erwin Bolwidt
011: *
012: * This program is free software; you can redistribute it and/or
013: * modify it under the terms of the GNU General Public License
014: * as published by the Free Software Foundation; either version 2
015: * of the License, or (at your option) any later version.
016: *
017: * This program is distributed in the hope that it will be useful,
018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
020: * GNU General Public License for more details.
021: *
022: * You should have received a copy of the GNU General Public License
023: * along with this program; if not, write to the Free Software
024: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
025: */
026: package com.sshtools.daemon.forwarding;
027:
028: import com.sshtools.j2ssh.connection.Channel;
029: import com.sshtools.j2ssh.connection.ChannelFactory;
030: import com.sshtools.j2ssh.connection.ConnectionProtocol;
031: import com.sshtools.j2ssh.connection.GlobalRequestHandler;
032: import com.sshtools.j2ssh.connection.GlobalRequestResponse;
033: import com.sshtools.j2ssh.connection.InvalidChannelException;
034: import com.sshtools.j2ssh.forwarding.ForwardingClient;
035: import com.sshtools.j2ssh.forwarding.ForwardingConfiguration;
036: import com.sshtools.j2ssh.forwarding.ForwardingConfigurationException;
037: import com.sshtools.j2ssh.forwarding.ForwardingListener;
038: import com.sshtools.j2ssh.forwarding.ForwardingSocketChannel;
039: import com.sshtools.j2ssh.io.ByteArrayReader;
040:
041: import org.apache.commons.logging.Log;
042: import org.apache.commons.logging.LogFactory;
043:
044: import java.io.IOException;
045:
046: import java.net.Socket;
047: import java.net.SocketPermission;
048:
049: import java.util.Iterator;
050: import java.util.List;
051: import java.util.Vector;
052:
053: /**
054: *
055: *
056: * @author $author$
057: * @version $Revision: 1.14 $
058: */
059: public class ForwardingServer implements ChannelFactory,
060: GlobalRequestHandler {
061: private static Log log = LogFactory.getLog(ForwardingServer.class);
062: private ConnectionProtocol connection;
063: private List channelTypes = new Vector();
064: private List localForwardings = new Vector();
065: private List remoteForwardings = new Vector();
066:
067: /**
068: * Creates a new ForwardingServer object.
069: *
070: * @param connection
071: *
072: * @throws IOException
073: */
074: public ForwardingServer(ConnectionProtocol connection)
075: throws IOException {
076: this .connection = connection;
077: channelTypes
078: .add(ForwardingSocketChannel.LOCAL_FORWARDING_CHANNEL);
079: connection.addChannelFactory(
080: ForwardingSocketChannel.LOCAL_FORWARDING_CHANNEL, this );
081: connection.allowGlobalRequest(
082: ForwardingClient.REMOTE_FORWARD_REQUEST, this );
083: connection.allowGlobalRequest(
084: ForwardingClient.REMOTE_FORWARD_CANCEL_REQUEST, this );
085: }
086:
087: /* public List getChannelType() {
088: return channelTypes;
089: }*/
090: public Channel createChannel(String channelType, byte[] requestData)
091: throws InvalidChannelException {
092: if (!channelType
093: .equals(ForwardingSocketChannel.LOCAL_FORWARDING_CHANNEL)) {
094: throw new InvalidChannelException(
095: "The client can only request the "
096: + "opening of a local forwarding channel");
097: }
098:
099: try {
100: ByteArrayReader bar = new ByteArrayReader(requestData);
101: String hostToConnect = bar.readString();
102: int portToConnect = (int) bar.readInt();
103: String originatingHost = bar.readString();
104: int originatingPort = (int) bar.readInt();
105:
106: // Get a configuration item for the forwarding
107: ForwardingConfiguration config = getLocalForwardingByAddress(
108: originatingHost, originatingPort);
109: Socket socket = new Socket(hostToConnect, portToConnect);
110:
111: // Create the channel adding it to the active channels
112: ForwardingSocketChannel channel = config
113: .createForwardingSocketChannel(channelType,
114: hostToConnect, portToConnect,
115: originatingHost, originatingPort);
116: channel.bindSocket(socket);
117:
118: return channel;
119: } catch (ForwardingConfigurationException fce) {
120: throw new InvalidChannelException(
121: "No valid forwarding configuration was available for the request");
122: } catch (IOException ioe) {
123: throw new InvalidChannelException(
124: "The channel request data is "
125: + "invalid/or corrupt for channel type "
126: + channelType);
127: }
128: }
129:
130: /**
131: *
132: *
133: * @param requestName
134: * @param requestData
135: *
136: * @return
137: */
138: public GlobalRequestResponse processGlobalRequest(
139: String requestName, byte[] requestData) {
140: GlobalRequestResponse response = new GlobalRequestResponse(
141: false);
142: String addressToBind = null;
143: int portToBind = -1;
144: log.debug("Processing " + requestName + " global request");
145:
146: try {
147: ByteArrayReader bar = new ByteArrayReader(requestData);
148: addressToBind = bar.readString();
149: portToBind = (int) bar.readInt();
150:
151: if (requestName
152: .equals(ForwardingClient.REMOTE_FORWARD_REQUEST)) {
153: addRemoteForwardingConfiguration(addressToBind,
154: portToBind);
155: response = new GlobalRequestResponse(true);
156: }
157:
158: if (requestName
159: .equals(ForwardingClient.REMOTE_FORWARD_CANCEL_REQUEST)) {
160: removeRemoteForwarding(addressToBind, portToBind);
161: response = new GlobalRequestResponse(true);
162: }
163: } catch (IOException ioe) {
164: log.warn("The client failed to request " + requestName
165: + " for " + addressToBind + ":"
166: + String.valueOf(portToBind), ioe);
167: }
168:
169: return response;
170: }
171:
172: /**
173: *
174: *
175: * @param orginatingAddress
176: * @param originatingPort
177: *
178: * @return
179: *
180: * @throws ForwardingConfigurationException
181: */
182: protected ForwardingConfiguration getLocalForwardingByAddress(
183: String orginatingAddress, int originatingPort)
184: throws ForwardingConfigurationException {
185: try {
186: Iterator it = localForwardings.iterator();
187: ForwardingConfiguration config;
188:
189: while (it.hasNext()) {
190: config = (ForwardingConfiguration) it.next();
191:
192: if (config.getAddressToBind().equals(orginatingAddress)
193: && (config.getPortToBind() == originatingPort)) {
194: return config;
195: }
196: }
197:
198: // No configuration is available so create one
199: config = new ForwardingConfiguration(orginatingAddress,
200: originatingPort);
201:
202: // We must start this configuration in order to use it
203: config.start();
204: localForwardings.add(config);
205:
206: return config;
207: } catch (IOException ex) {
208: throw new ForwardingConfigurationException(ex.getMessage());
209: }
210: }
211:
212: /**
213: *
214: *
215: * @param addressToBind
216: * @param portToBind
217: *
218: * @return
219: *
220: * @throws ForwardingConfigurationException
221: */
222: protected ForwardingConfiguration getRemoteForwardingByAddress(
223: String addressToBind, int portToBind)
224: throws ForwardingConfigurationException {
225: Iterator it = remoteForwardings.iterator();
226: ForwardingConfiguration config;
227:
228: while (it.hasNext()) {
229: config = (ForwardingConfiguration) it.next();
230:
231: if (config.getAddressToBind().equals(addressToBind)
232: && (config.getPortToBind() == portToBind)) {
233: return config;
234: }
235: }
236:
237: throw new ForwardingConfigurationException(
238: "The remote forwarding does not exist!");
239: }
240:
241: /**
242: *
243: *
244: * @param addressToBind
245: * @param portToBind
246: *
247: * @throws ForwardingConfigurationException
248: */
249: protected void addRemoteForwardingConfiguration(
250: String addressToBind, int portToBind)
251: throws ForwardingConfigurationException {
252: // Is the server already listening
253: Iterator it = remoteForwardings.iterator();
254: ForwardingConfiguration config;
255:
256: while (it.hasNext()) {
257: config = (ForwardingConfiguration) it.next();
258:
259: if (config.getAddressToBind().equals(addressToBind)
260: && (config.getPortToBind() == portToBind)) {
261: throw new ForwardingConfigurationException(
262: "The address and port are already in use!");
263: }
264: }
265:
266: config = new ForwardingConfiguration(addressToBind, portToBind);
267:
268: // Check the security mananger
269: SecurityManager manager = System.getSecurityManager();
270:
271: if (manager != null) {
272: try {
273: manager.checkPermission(new SocketPermission(
274: addressToBind + ":"
275: + String.valueOf(portToBind),
276: "accept,listen"));
277: } catch (SecurityException e) {
278: throw new ForwardingConfigurationException(
279: "The security manager has denied listen permision on "
280: + addressToBind + ":"
281: + String.valueOf(portToBind));
282: }
283: }
284:
285: try {
286: ForwardingListener listener = new ServerForwardingListener(
287: connection, addressToBind, portToBind);
288: remoteForwardings.add(listener);
289: listener.start();
290: } catch (IOException ex) {
291: throw new ForwardingConfigurationException(ex.getMessage());
292: }
293: }
294:
295: /**
296: *
297: *
298: * @param addressToBind
299: * @param portToBind
300: *
301: * @throws ForwardingConfigurationException
302: */
303: protected void removeRemoteForwarding(String addressToBind,
304: int portToBind) throws ForwardingConfigurationException {
305: ForwardingConfiguration config = getRemoteForwardingByAddress(
306: addressToBind, portToBind);
307:
308: // Stop the forwarding
309: config.stop();
310:
311: // Remove from the remote forwardings list
312: remoteForwardings.remove(config);
313: }
314:
315: class ServerForwardingListener extends ForwardingListener {
316: public ServerForwardingListener(ConnectionProtocol connection,
317: String addressToBind, int portToBind) {
318: super (connection, addressToBind, portToBind);
319: }
320:
321: public ForwardingSocketChannel createChannel(
322: String hostToConnect, int portToConnect, Socket socket)
323: throws ForwardingConfigurationException {
324: try {
325: ForwardingSocketChannel channel = createForwardingSocketChannel(
326: ForwardingSocketChannel.REMOTE_FORWARDING_CHANNEL,
327: hostToConnect, portToConnect,
328:
329: /*( (InetSocketAddress) socket.getRemoteSocketAddress()).getAddress()
330: .getHostAddress(),
331: ( (InetSocketAddress) socket.getRemoteSocketAddress())
332: .getPort()*/
333: socket.getInetAddress().getHostAddress(),
334: socket.getPort());
335: channel.bindSocket(socket);
336:
337: return channel;
338: } catch (IOException ex) {
339: throw new ForwardingConfigurationException(ex
340: .getMessage());
341: }
342: }
343: }
344: }
|