001: /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
002: /*
003: Copyright (c) 2002-2008 ymnk, JCraft,Inc. All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions are met:
007:
008: 1. Redistributions of source code must retain the above copyright notice,
009: this list of conditions and the following disclaimer.
010:
011: 2. Redistributions in binary form must reproduce the above copyright
012: notice, this list of conditions and the following disclaimer in
013: the documentation and/or other materials provided with the distribution.
014:
015: 3. The names of the authors may not be used to endorse or promote products
016: derived from this software without specific prior written permission.
017:
018: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
019: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
020: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
021: INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
022: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
024: OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
027: EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package com.jcraft.jsch;
031:
032: import java.net.*;
033: import java.io.*;
034:
035: public class ChannelForwardedTCPIP extends Channel {
036:
037: static java.util.Vector pool = new java.util.Vector();
038:
039: static private final int LOCAL_WINDOW_SIZE_MAX = 0x20000;
040: //static private final int LOCAL_WINDOW_SIZE_MAX=0x100000;
041: static private final int LOCAL_MAXIMUM_PACKET_SIZE = 0x4000;
042:
043: static private final int TIMEOUT = 10 * 1000;
044:
045: SocketFactory factory = null;
046: private Socket socket = null;
047: private ForwardedTCPIPDaemon daemon = null;
048: String target;
049: int lport;
050: int rport;
051:
052: ChannelForwardedTCPIP() {
053: super ();
054: setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX);
055: setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX);
056: setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE);
057: io = new IO();
058: connected = true;
059: }
060:
061: public void run() {
062: try {
063: if (lport == -1) {
064: Class c = Class.forName(target);
065: daemon = (ForwardedTCPIPDaemon) c.newInstance();
066:
067: PipedOutputStream out = new PipedOutputStream();
068: io.setInputStream(
069: new PassiveInputStream(out, 32 * 1024), false);
070:
071: daemon.setChannel(this , getInputStream(), out);
072: Object[] foo = getPort(session, rport);
073: daemon.setArg((Object[]) foo[3]);
074:
075: new Thread(daemon).start();
076: } else {
077: socket = (factory == null) ? Util.createSocket(target,
078: lport, TIMEOUT) : factory.createSocket(target,
079: lport);
080: socket.setTcpNoDelay(true);
081: io.setInputStream(socket.getInputStream());
082: io.setOutputStream(socket.getOutputStream());
083: }
084: sendOpenConfirmation();
085: } catch (Exception e) {
086: sendOpenFailure(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED);
087: close = true;
088: disconnect();
089: return;
090: }
091:
092: thread = Thread.currentThread();
093: Buffer buf = new Buffer(rmpsize);
094: Packet packet = new Packet(buf);
095: int i = 0;
096: try {
097: while (thread != null && io != null && io.in != null) {
098: i = io.in.read(buf.buffer, 14,
099: buf.buffer.length - 14 - 32 - 20 // padding and mac
100: );
101: if (i <= 0) {
102: eof();
103: break;
104: }
105: packet.reset();
106: if (close)
107: break;
108: buf.putByte((byte) Session.SSH_MSG_CHANNEL_DATA);
109: buf.putInt(recipient);
110: buf.putInt(i);
111: buf.skip(i);
112: session.write(packet, this , i);
113: }
114: } catch (Exception e) {
115: //System.err.println(e);
116: }
117: //thread=null;
118: //eof();
119: disconnect();
120: }
121:
122: void getData(Buffer buf) {
123: setRecipient(buf.getInt());
124: setRemoteWindowSize(buf.getInt());
125: setRemotePacketSize(buf.getInt());
126: byte[] addr = buf.getString();
127: int port = buf.getInt();
128: byte[] orgaddr = buf.getString();
129: int orgport = buf.getInt();
130:
131: /*
132: System.err.println("addr: "+new String(addr));
133: System.err.println("port: "+port);
134: System.err.println("orgaddr: "+new String(orgaddr));
135: System.err.println("orgport: "+orgport);
136: */
137:
138: synchronized (pool) {
139: for (int i = 0; i < pool.size(); i++) {
140: Object[] foo = (Object[]) (pool.elementAt(i));
141: if (foo[0] != session)
142: continue;
143: if (((Integer) foo[1]).intValue() != port)
144: continue;
145: this .rport = port;
146: this .target = (String) foo[2];
147: if (foo[3] == null || (foo[3] instanceof Object[])) {
148: this .lport = -1;
149: } else {
150: this .lport = ((Integer) foo[3]).intValue();
151: }
152: if (foo.length >= 5) {
153: this .factory = ((SocketFactory) foo[4]);
154: }
155: break;
156: }
157: if (target == null) {
158: System.err.println("??");
159: }
160: }
161: }
162:
163: static Object[] getPort(Session session, int rport) {
164: synchronized (pool) {
165: for (int i = 0; i < pool.size(); i++) {
166: Object[] bar = (Object[]) (pool.elementAt(i));
167: if (bar[0] != session)
168: continue;
169: if (((Integer) bar[1]).intValue() != rport)
170: continue;
171: return bar;
172: }
173: return null;
174: }
175: }
176:
177: static String[] getPortForwarding(Session session) {
178: java.util.Vector foo = new java.util.Vector();
179: synchronized (pool) {
180: for (int i = 0; i < pool.size(); i++) {
181: Object[] bar = (Object[]) (pool.elementAt(i));
182: if (bar[0] != session)
183: continue;
184: if (bar[3] == null) {
185: foo.addElement(bar[1] + ":" + bar[2] + ":");
186: } else {
187: foo
188: .addElement(bar[1] + ":" + bar[2] + ":"
189: + bar[3]);
190: }
191: }
192: }
193: String[] bar = new String[foo.size()];
194: for (int i = 0; i < foo.size(); i++) {
195: bar[i] = (String) (foo.elementAt(i));
196: }
197: return bar;
198: }
199:
200: static void addPort(Session session, int port, String target,
201: int lport, SocketFactory factory) throws JSchException {
202: synchronized (pool) {
203: if (getPort(session, port) != null) {
204: throw new JSchException("PortForwardingR: remote port "
205: + port + " is already registered.");
206: }
207: Object[] foo = new Object[5];
208: foo[0] = session;
209: foo[1] = new Integer(port);
210: foo[2] = target;
211: foo[3] = new Integer(lport);
212: foo[4] = factory;
213: pool.addElement(foo);
214: }
215: }
216:
217: static void addPort(Session session, int port, String daemon,
218: Object[] arg) throws JSchException {
219: synchronized (pool) {
220: if (getPort(session, port) != null) {
221: throw new JSchException("PortForwardingR: remote port "
222: + port + " is already registered.");
223: }
224: Object[] foo = new Object[4];
225: foo[0] = session;
226: foo[1] = new Integer(port);
227: foo[2] = daemon;
228: foo[3] = arg;
229: pool.addElement(foo);
230: }
231: }
232:
233: static void delPort(ChannelForwardedTCPIP c) {
234: delPort(c.session, c.rport);
235: }
236:
237: static void delPort(Session session, int rport) {
238: synchronized (pool) {
239: Object[] foo = null;
240: for (int i = 0; i < pool.size(); i++) {
241: Object[] bar = (Object[]) (pool.elementAt(i));
242: if (bar[0] != session)
243: continue;
244: if (((Integer) bar[1]).intValue() != rport)
245: continue;
246: foo = bar;
247: break;
248: }
249: if (foo == null)
250: return;
251: pool.removeElement(foo);
252: }
253:
254: Buffer buf = new Buffer(100); // ??
255: Packet packet = new Packet(buf);
256:
257: try {
258: // byte SSH_MSG_GLOBAL_REQUEST 80
259: // string "cancel-tcpip-forward"
260: // boolean want_reply
261: // string address_to_bind (e.g. "127.0.0.1")
262: // uint32 port number to bind
263: packet.reset();
264: buf.putByte((byte) 80/*SSH_MSG_GLOBAL_REQUEST*/);
265: buf.putString("cancel-tcpip-forward".getBytes());
266: buf.putByte((byte) 0);
267: buf.putString("0.0.0.0".getBytes());
268: buf.putInt(rport);
269: session.write(packet);
270: } catch (Exception e) {
271: // throw new JSchException(e.toString());
272: }
273: }
274:
275: static void delPort(Session session) {
276: int[] rport = null;
277: int count = 0;
278: synchronized (pool) {
279: rport = new int[pool.size()];
280: for (int i = 0; i < pool.size(); i++) {
281: Object[] bar = (Object[]) (pool.elementAt(i));
282: if (bar[0] == session) {
283: rport[count++] = ((Integer) bar[1]).intValue();
284: }
285: }
286: }
287: for (int i = 0; i < count; i++) {
288: delPort(session, rport[i]);
289: }
290: }
291:
292: public int getRemotePort() {
293: return rport;
294: }
295:
296: void setSocketFactory(SocketFactory factory) {
297: this.factory = factory;
298: }
299: }
|