United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 4107059 ftp protocol fails when the client machine has multiple IP adresses
4107059 : ftp protocol fails when the client machine has multiple IP adresses

Details
Type:
Bug
Submit Date:
1998-01-27
Status:
Resolved
Updated Date:
2001-09-20
Project Name:
JDK
Resolved Date:
2000-06-29
Component:
core-libs
OS:
generic,windows_98
Sub-Component:
java.net
CPU:
x86,generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.1.5,1.2.1,1.3.0
Fixed Versions:
1.4.0

Related Reports
Duplicate:
Duplicate:

Sub Tasks

Description

Name: dgC58589			Date: 01/27/98


[the text from the user is reformatted and more explanations
are added after exchanging e-mail (###@###.###

The problem appears when a machine that has more than one
IP addresses tries to use a ftp URL to get something. The two
IP addresses are not routable one to another - this situation
is normal for a machine connected to an internal LAN with some
unroutable addresses (example 10.1.1.1) and with a dial up
connection.

When the ftp protocol binds a server socket for receiving data
from the server it send the socj`ket IP and port to the server
so that the server can connect to it. The address sent to the server
is the one returned by InetAddress.getLocalHost().getAddress(). 
When the host has multiple addresses there is no way to reliably
tell which one should be returned  - the internal one will not
wrok when connecting to an external host and the external one
will not work when connecting to an internal host.

A possible suggested fix is to use the local address from the
client socket already connected to the server - if the server can
talk to it and the server socket is bound with inAddrAny then
this should work. The question is wether the getLocalAddress()
[acctually getsockname() in the C library] will return the good
address for a connected socket in the case of multiple IP addresses.

Here is the test case sent by the user:

import java.io.*;
import java.net.*;

/**
 *
 * Program to snarf files from a random website.
 *
 */
public class Snarf {
  public static void main(String[] args) {
    InputStream inStream = null;
    OutputStream outStream = null;

    try {
      // Check args.
      if (args.length < 2) {
	throw new IllegalArgumentException("Wrong number of arguments.");
      } else {
	String urlRoot = args[0];
	for (int i = 1; i < args.length; i++) {
	  URL turl = new URL(urlRoot + args[i]);
	  System.out.println("Snarfing " + turl + " via " +
			     turl.getProtocol() + " on port " +
			     turl.getPort() + ".");
	  String protocol = turl.getProtocol();
	  int port = turl.getPort();
	  String host = turl.getHost();
	  String file = turl.getFile();
	  turl = null;
	  URL url = new URL(protocol, host, port, file);
	  URLConnection urlConnection = url.openConnection();
	  inStream = urlConnection.getInputStream();
	  outStream = new FileOutputStream(args[i]);
	  byte[] buffer = new byte[1096];
	  int bytes_read = 0;
	  while((bytes_read = inStream.read(buffer)) != -1) {
	    outStream.write(buffer, 0, bytes_read);
	    System.out.print(".");
	  }
	  System.out.println("\nDone with " + url);
	  inStream = null; outStream = null; buffer = null; url = null;
	}
      }	// Args were OK.
    } catch(Exception e) {
      // Bail informatively.
      System.err.println(e);
      System.err.println("Usage: java Snarf URL files ...");
    } finally {			// Always close streams!
      try {
	inStream.close();
	outStream.close();
      } catch(Exception e) {
	/* NOTHING */
      }
    }
  }
}
(Review ID: 22303)
======================================================================

                                    

Comments
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
merlin
merlin-beta

FIXED IN:
merlin
merlin-beta

INTEGRATED IN:
merlin-beta


                                     
2004-06-14
SUGGESTED FIX



> The problem could be fixed in sun\net\ftp\FtpClient.java
> in method openDataConnection by setting myAddress=serverSocket.getInetAddress()
> (rather than InetAddress.getLocalHost()) to get the ip address of the original
> connection.
> 
> serverSocket is the actual socket we used to connect to the ftp client,
> so does have the right address to tell the ftp host to connect back to.
> 
> The code change has been tested and it does work.
> 
> FtpClient.java:
> 
>     protected Socket openDataConnection(String cmd) throws IOException {
>         ServerSocket portSocket;
>         String      portCmd;
> //      InetAddress myAddress = InetAddress.getLocalHost();        /*xxx.7813*/
>         InetAddress myAddress = serverSocket.getInetAddress();     /*xxx.7813*/
>         byte        addr[] = myAddress.getAddress();
>         int         shift;
>         IOException e;
> 
> //      portSocket = new ServerSocket(0, 1);                       /*xxx.7813*/
>         portSocket = new ServerSocket(0, 1, myAddress);            /*xxx.7813*/
>         portCmd = "PORT ";
> 
> The other line isn't strictly needed, but if we are telling the ftp host to
> connect back to a specific address of ours, is there any point on listening
> on all the local addresss?  Shouldn't we just listen on the one we are
> interested in.  This may be better for security reasons as well.

mick.fleming@Ireland 1998-11-30
                                     
1998-11-30
EVALUATION

The suggested fix of obtaining the local address of the connected
socket seems like a good one. We should also implement PASV mode
(bugid 4191863) which will eliminate the need to use the PORT command
most of the time and thereby avoid this issue entirely.

jeff.nisewanger@Eng 1998-11-25
                                     
1998-11-25



Hardware and Software, Engineered to Work Together