Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: mindbright/ssh/SSHFtpTunnel.java


1   /******************************************************************************
2    *
3    * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
4    *                 www.mindbright.se, info@mindbright.se
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation; either version 2 of the License, or
9    * (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   *****************************************************************************
17   * $Author: nallen $
18   * $Date: 2001/11/12 16:31:18 $
19   * $Name:  $
20   *****************************************************************************/
21  package mindbright.ssh;
22  
23  import java.net.*;
24  import java.io.*;
25  
26  public class SSHFtpTunnel extends SSHTunnel {
27  
28    public final static String TUNNEL_NAME       = "#FTP";
29    public final static int    MAX_REMOTE_LISTEN = 10;
30  
31    boolean havePORT;
32  
33    boolean     waitingPASVResponse;
34    String      localAddrPASVStr;
35    InetAddress localAddr;
36  
37    byte[][] newPortMsg;
38  
39    static int timeWaitKludgeToggler;
40    static Object timeWaitKludgeCrit = new Object();
41  
42    public SSHFtpTunnel(Socket ioSocket, int channelId, int remoteChannelId,
43            SSHChannelController controller)
44      throws IOException {
45      super(ioSocket, channelId, remoteChannelId, controller);
46  
47      int a1, a2, a3, a4;
48  
49      havePORT = controller.sshAsClient().havePORTFtp;
50  
51      if(havePORT) {
52        int firstPort = controller.sshAsClient().firstFTPPort;
53        byte[] serverAddr = controller.sshAsClient().getServerRealAddr().getAddress();
54        a1 = serverAddr[0] & 0xff;
55        a2 = serverAddr[1] & 0xff;
56        a3 = serverAddr[2] & 0xff;
57        a4 = serverAddr[3] & 0xff;
58        String msg;
59        newPortMsg = new byte[MAX_REMOTE_LISTEN][1];
60        for(int i = 0; i < MAX_REMOTE_LISTEN; i++) {
61      int p1 = ((firstPort + i) >>> 8) & 0xff;
62      int p2 = (firstPort + i) & 0xff;
63      msg = "PORT " + a1 + "," + a2 + "," + a3 + "," + a4 + "," + p1 + "," + p2 + "\n";
64      newPortMsg[i] = msg.getBytes();
65        }
66      }
67  
68      localAddr = controller.sshAsClient().getLocalAddr();
69  
70      byte[] localAddrArr = controller.sshAsClient().getLocalAddr().getAddress();
71  
72      if(localAddrArr[0] == 0) {
73        localAddrArr = InetAddress.getLocalHost().getAddress();
74      }
75  
76      a1 = localAddrArr[0] & 0xff;
77      a2 = localAddrArr[1] & 0xff;
78      a3 = localAddrArr[2] & 0xff;
79      a4 = localAddrArr[3] & 0xff;
80      localAddrPASVStr = a1 + "," + a2 + "," + a3 + "," + a4;
81    }
82  
83    boolean parseHostAndPort(String msg, int[] d) {
84      boolean ok = true;
85      int   cl   = 0;
86      int   cn   = 0;
87      try {
88        for(int i = 0; i < 6; i++) {
89    String num;
90    if(i == 5) {
91      cn = msg.indexOf(')', cl);
92      if(cn == -1)
93        cn = msg.indexOf('\r', cl);
94      else if(cn == -1)
95        cn = msg.indexOf('\n', cl);
96    } else
97      cn = msg.indexOf(',', cl);
98    num = msg.substring(cl, cn);
99    cl = cn + 1;
100   d[i] = Integer.parseInt(num);
101       }
102     } catch (Exception e) {
103       ok = false;
104     }
105     return ok;
106   }
107 
108   public void receive(SSHPdu pdu) {
109     String msg = new String(pdu.rawData(), pdu.rawOffset(), pdu.rawSize());
110 
111     if(msg.startsWith("PASV") || msg.startsWith("pasv")) {
112       waitingPASVResponse = true;
113     } else if(msg.startsWith("PORT ") || msg.startsWith("port ")) {
114       if(!havePORT) {
115   controller.alert("Ftp-client is using PORT commands, either \n" +
116        "enable 'passive mode' in the ftp-client or \n" +
117        "enable 'ftp PORT' in 'SSH Settings' and reconnect.");
118       } else {
119   msg = msg.substring(5);
120   int[] d = new int[6];
121 
122   if(parseHostAndPort(msg, d)) {
123     byte[] dst = pdu.rawData();
124     byte[] newmsg;
125     String mapName;
126   
127     synchronized(timeWaitKludgeCrit) {
128       newmsg  = newPortMsg[timeWaitKludgeToggler];
129       mapName = TUNNEL_NAME + timeWaitKludgeToggler;
130       timeWaitKludgeToggler = (timeWaitKludgeToggler + 1) % MAX_REMOTE_LISTEN;
131     }
132 
133     int len    = newmsg.length;
134     int off    = pdu.rawOffset() - 4;
135     dst[off++] = (byte)((len >>> 24) & 0xff);
136     dst[off++] = (byte)((len >>> 16) & 0xff);
137     dst[off++] = (byte)((len >>> 8)  & 0xff);
138     dst[off++] = (byte)(len & 0xff);
139     System.arraycopy(newmsg, 0, dst, off, len);
140     pdu.rawAdjustSize(off + len);
141 
142     String toHost = d[0] + "." + d[1] + "." + d[2] + "." + d[3];
143     int    toPort = (d[4] << 8) | d[5];
144     controller.addHostMapTemporary(mapName, toHost, toPort);
145   } else {
146     controller.alert("Bug in SSHFtpTunnel (PORT), please report: " + msg);
147   }
148       }
149     }
150 
151     super.receive(pdu);
152   }
153 
154   public void transmit(SSHPdu pdu) {
155     SSHListenChannel listenChan = null;
156     String           msg        = new String(pdu.rawData(), pdu.rawOffset(), pdu.rawSize());
157 
158     if(waitingPASVResponse && msg.startsWith("227 ")) {
159       byte[] newmsg;
160       waitingPASVResponse = false;
161       msg = msg.substring(27);
162       int[] d = new int[6];
163       if(parseHostAndPort(msg, d)) {
164   String toHost = d[0] + "." + d[1] + "." + d[2] + "." + d[3];
165   int    toPort = (d[4] << 8) | d[5];
166   int    localPort;
167   try {
168     listenChan = controller.newListenChannel(localAddr.getHostAddress(), 0,
169                toHost, toPort, "general");
170   } catch(IOException e) {
171     controller.alert("Error in FtpTunnel: " + e.toString());
172   }
173   listenChan.setTemporaryListener(true); // Go away after next accept...
174   localPort = listenChan.getListenPort();
175   int p1 = (localPort >>> 8) & 0xff;
176   int p2 = localPort & 0xff;
177         msg = "227 Entering Passive Mode (" + localAddrPASVStr + "," + p1 + "," + p2 + ")\n";
178   newmsg = msg.getBytes();
179   pdu.rawSetData(newmsg);
180       } else {
181   controller.alert("Bug in SSHFtpTunnel (PASV), please report: " + msg);
182       }
183     }
184 
185     super.transmit(pdu);
186   }
187 
188   public String getDescription() {
189     if(ioSocket != null)
190       return ioSocket.getInetAddress().getHostAddress() + ":" + ioSocket.getPort() + " <-ftp-> " +
191   getLocalHost() + ":" + ioSocket.getLocalPort() + " <-ssh-> " + remoteDesc;
192     else
193       return "< N/A >";
194   }
195 
196 }