]> Joshua Wise's Git repositories - dumload.git/blob - src/com/jcraft/jsch/ChannelForwardedTCPIP.java
GPLv3
[dumload.git] / src / com / jcraft / jsch / ChannelForwardedTCPIP.java
1 /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
2 /*
3 Copyright (c) 2002-2010 ymnk, JCraft,Inc. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8   1. Redistributions of source code must retain the above copyright notice,
9      this list of conditions and the following disclaimer.
10
11   2. Redistributions in binary form must reproduce the above copyright 
12      notice, this list of conditions and the following disclaimer in 
13      the documentation and/or other materials provided with the distribution.
14
15   3. The names of the authors may not be used to endorse or promote products
16      derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
19 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
21 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 package com.jcraft.jsch;
31
32 import java.net.*;
33 import java.io.*;
34
35 public class ChannelForwardedTCPIP extends Channel{
36
37   static java.util.Vector pool=new java.util.Vector();
38
39   static private final int LOCAL_WINDOW_SIZE_MAX=0x20000;
40 //static private final int LOCAL_WINDOW_SIZE_MAX=0x100000;
41   static private final int LOCAL_MAXIMUM_PACKET_SIZE=0x4000;
42
43   static private final int TIMEOUT=10*1000;
44
45   SocketFactory factory=null;
46   private Socket socket=null;
47   private ForwardedTCPIPDaemon daemon=null;
48   String target;
49   int lport;
50   int rport;
51
52   ChannelForwardedTCPIP(){
53     super();
54     setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX);
55     setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX);
56     setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE);
57     io=new IO();
58     connected=true;
59   }
60
61   public void run(){
62     try{ 
63       if(lport==-1){
64         Class c=Class.forName(target);
65         daemon=(ForwardedTCPIPDaemon)c.newInstance();
66
67         PipedOutputStream out=new PipedOutputStream();
68         io.setInputStream(new PassiveInputStream(out
69                                                  , 32*1024
70                                                  ), false);
71
72         daemon.setChannel(this, getInputStream(), out);
73         Object[] foo=getPort(getSession(), rport);
74         daemon.setArg((Object[])foo[3]);
75
76         new Thread(daemon).start();
77       }
78       else{
79         socket=(factory==null) ? 
80            Util.createSocket(target, lport, TIMEOUT) : 
81           factory.createSocket(target, lport);
82         socket.setTcpNoDelay(true);
83         io.setInputStream(socket.getInputStream());
84         io.setOutputStream(socket.getOutputStream());
85       }
86       sendOpenConfirmation();
87     }
88     catch(Exception e){
89       sendOpenFailure(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED);
90       close=true;
91       disconnect();
92       return; 
93     }
94
95     thread=Thread.currentThread();
96     Buffer buf=new Buffer(rmpsize);
97     Packet packet=new Packet(buf);
98     int i=0;
99     try{
100       while(thread!=null && 
101             io!=null && 
102             io.in!=null){
103         i=io.in.read(buf.buffer, 
104                      14, 
105                      buf.buffer.length-14
106                      -32 -20 // padding and mac
107                      );
108         if(i<=0){
109           eof();
110           break;
111         }
112         packet.reset();
113         if(close)break;
114         buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA);
115         buf.putInt(recipient);
116         buf.putInt(i);
117         buf.skip(i);
118         getSession().write(packet, this, i);
119       }
120     }
121     catch(Exception e){
122       //System.err.println(e);
123     }
124     //thread=null;
125     //eof();
126     disconnect();
127   }
128
129   void getData(Buffer buf){
130     setRecipient(buf.getInt());
131     setRemoteWindowSize(buf.getUInt());
132     setRemotePacketSize(buf.getInt());
133     byte[] addr=buf.getString();
134     int port=buf.getInt();
135     byte[] orgaddr=buf.getString();
136     int orgport=buf.getInt();
137
138     /*
139     System.err.println("addr: "+Util.byte2str(addr));
140     System.err.println("port: "+port);
141     System.err.println("orgaddr: "+Util.byte2str(orgaddr));
142     System.err.println("orgport: "+orgport);
143     */
144
145     Session _session=null;
146     try{
147       _session=getSession();
148     }
149     catch(JSchException e){
150       // session has been already down.
151     }
152
153     synchronized(pool){
154       for(int i=0; i<pool.size(); i++){
155         Object[] foo=(Object[])(pool.elementAt(i));
156         if(foo[0]!=_session) continue;
157         if(((Integer)foo[1]).intValue()!=port) continue;
158         this.rport=port;
159         this.target=(String)foo[2];
160         if(foo[3]==null || (foo[3] instanceof Object[])){ this.lport=-1; }
161         else{ this.lport=((Integer)foo[3]).intValue(); }
162         if(foo.length>=6){
163           this.factory=((SocketFactory)foo[5]);
164         }
165         break;
166       }
167       if(target==null){
168         //System.err.println("??");
169       }
170     }
171   }
172
173   static Object[] getPort(Session session, int rport){
174     synchronized(pool){
175       for(int i=0; i<pool.size(); i++){
176         Object[] bar=(Object[])(pool.elementAt(i));
177         if(bar[0]!=session) continue;
178         if(((Integer)bar[1]).intValue()!=rport) continue;
179         return bar;
180       }
181       return null;
182     }
183   }
184
185   static String[] getPortForwarding(Session session){
186     java.util.Vector foo=new java.util.Vector();
187     synchronized(pool){
188       for(int i=0; i<pool.size(); i++){
189         Object[] bar=(Object[])(pool.elementAt(i));
190         if(bar[0]!=session) continue;
191         if(bar[3]==null){ foo.addElement(bar[1]+":"+bar[2]+":"); }
192         else{ foo.addElement(bar[1]+":"+bar[2]+":"+bar[3]); }
193       }
194     }
195     String[] bar=new String[foo.size()];
196     for(int i=0; i<foo.size(); i++){
197       bar[i]=(String)(foo.elementAt(i));
198     }
199     return bar;
200   }
201
202   static String normalize(String address){
203     if(address==null){ return "localhost"; }
204     else if(address.length()==0 || address.equals("*")){ return ""; }
205     else{ return address; }
206   }
207
208   static void addPort(Session session, String _address_to_bind, int port, String target, int lport, SocketFactory factory) throws JSchException{
209     String address_to_bind=normalize(_address_to_bind);
210     synchronized(pool){
211       if(getPort(session, port)!=null){
212         throw new JSchException("PortForwardingR: remote port "+port+" is already registered.");
213       }
214       Object[] foo=new Object[6];
215       foo[0]=session; foo[1]=new Integer(port);
216       foo[2]=target; foo[3]=new Integer(lport);
217       foo[4]=address_to_bind;
218       foo[5]=factory;
219       pool.addElement(foo);
220     }
221   }
222   static void addPort(Session session, String _address_to_bind, int port, String daemon, Object[] arg) throws JSchException{
223     String address_to_bind=normalize(_address_to_bind);
224     synchronized(pool){
225       if(getPort(session, port)!=null){
226         throw new JSchException("PortForwardingR: remote port "+port+" is already registered.");
227       }
228       Object[] foo=new Object[5];
229       foo[0]=session; foo[1]=new Integer(port);
230       foo[2]=daemon; foo[3]=arg;
231       foo[4]=address_to_bind; 
232       pool.addElement(foo);
233     }
234   }
235   static void delPort(ChannelForwardedTCPIP c){
236     Session _session=null;
237     try{
238       _session=c.getSession();
239     }
240     catch(JSchException e){
241       // session has been already down.
242     }
243     if(_session!=null)
244       delPort(_session, c.rport);
245   }
246   static void delPort(Session session, int rport){
247     delPort(session, null, rport);
248   }
249   static void delPort(Session session, String address_to_bind, int rport){
250     synchronized(pool){
251       Object[] foo=null;
252       for(int i=0; i<pool.size(); i++){
253         Object[] bar=(Object[])(pool.elementAt(i));
254         if(bar[0]!=session) continue;
255         if(((Integer)bar[1]).intValue()!=rport) continue;
256         foo=bar;
257         break;
258       }
259       if(foo==null)return;
260       pool.removeElement(foo);
261       if(address_to_bind==null){
262         address_to_bind=(String)foo[4];
263       } 
264       if(address_to_bind==null){
265         address_to_bind="0.0.0.0";
266       }
267     }
268
269     Buffer buf=new Buffer(100); // ??
270     Packet packet=new Packet(buf);
271
272     try{
273       // byte SSH_MSG_GLOBAL_REQUEST 80
274       // string "cancel-tcpip-forward"
275       // boolean want_reply
276       // string  address_to_bind (e.g. "127.0.0.1")
277       // uint32  port number to bind
278       packet.reset();
279       buf.putByte((byte) 80/*SSH_MSG_GLOBAL_REQUEST*/);
280       buf.putString(Util.str2byte("cancel-tcpip-forward"));
281       buf.putByte((byte)0);
282       buf.putString(Util.str2byte(address_to_bind));
283       buf.putInt(rport);
284       session.write(packet);
285     }
286     catch(Exception e){
287 //    throw new JSchException(e.toString());
288     }
289   }
290   static void delPort(Session session){
291     int[] rport=null;
292     int count=0;
293     synchronized(pool){
294       rport=new int[pool.size()];
295       for(int i=0; i<pool.size(); i++){
296         Object[] bar=(Object[])(pool.elementAt(i));
297         if(bar[0]==session) {
298           rport[count++]=((Integer)bar[1]).intValue();
299         }
300       }
301     }
302     for(int i=0; i<count; i++){
303       delPort(session, rport[i]);
304     }
305   }
306
307   public int getRemotePort(){return rport;}
308   void setSocketFactory(SocketFactory factory){
309     this.factory=factory;
310   }
311 }
This page took 0.038875 seconds and 4 git commands to generate.