EVALUATION
(Pawel Veselov, St.Petersburg HotJava team, email: ###@###.###)
This is a bug in sun.net.www.protocol.http.HttpURLConnection class.
The domain query source is there:
HttpURLConnectionCookie.getInputStream() :
InputStream is = null;
try {
Thread.sleep(10000);
System.out.println("super.getInputStream() : "+((new Date())));
is = super.getInputStream();
Thread.sleep(10000);
} catch (InterruptedException e) {
}
>HotJava console:
super.getInputStream() : Tue Jan 19 14:25:12 GMT 1999
>tcpdump results:
17:25:12.433636 druid.53008 > warrior.domain: 28298+ (40) (DF)
17:25:12.541710 druid.53010 > warrior.domain: 18435+ (40) (DF)
17:25:17.456030 druid.53011 > warrior.domain: 28298+ (40) (DF)
The code in jdk reads ( HttpURLConnection.connect() method )
if ("http".equals(url.getProtocol()) && !failedOnce) {
http = HttpClient.New(url);
} else {
// make sure to construct new connection if first attempt failed
http = new HttpClient(url, handler.proxy, handler.proxyPort);
}
This !failedOnce seems to explain why we can connect only from the second try.
So, I believe, this bug should be transferred to java.net cathegory.
======================================================================
I don't really understand the above evaluation.
jeff.nisewanger@Eng 1999-03-09
Name: pvC76716 Date: 03/10/99
Okay, here is a testcase:
---- cut ----
import java.net.*;
import java.io.*;
import java.util.Properties;
public class GetHttp {
GetHttp(String urlString) {
URL url=null;
InputStream io;
try {
URL.setURLStreamHandlerFactory(new MyFactory());
} catch (Exception e) {
System.err.println("Factory is already installed!");
System.exit(0);
}
Properties props = System.getProperties();
props.put("http.proxyHost","guard");
props.put("http.proxyPort","3128");
props.put("trustProxy", "true");
for (int i=0; i<2; i++) {
System.out.println(" ======== TRY NO. "+(i+1));
try {
url = new URL(urlString);
} catch (MalformedURLException e) {
System.err.println("Malformed URL");
continue;
}
try {
URLConnection conn = url.openConnection();
conn.connect();
io = conn.getInputStream();
} catch (Exception e) {
e.printStackTrace();
continue;
}
System.out.println("Everything is OK!");
int b;
do {
try {
b = io.read();
} catch (Exception e) {
e.printStackTrace();
break;
}
if (b>=0) {
System.out.print((char)b);
}
} while (b >= 0);
}
}
public static void main(String arg[]) {
if (arg.length < 1) {
System.err.println("Usage : java GetHttp <url>");
System.exit(0);
}
new GetHttp(arg[0]);
}
class MyFactory implements URLStreamHandlerFactory {
public URLStreamHandler createURLStreamHandler(String protocol) {
System.out.println("Asked for Handler for proto "+protocol);
if (protocol.equalsIgnoreCase("http")) {
return new MyHandler();
} else {
return null;
}
}
}
class MyHandler extends sun.net.www.protocol.http.Handler {
public MyHandler() {
super();
}
public MyHandler(String proxy, int proxyPort) {
super(proxy, proxyPort);
}
protected URLConnection openConnection(URL url) throws IOException {
// return (URLConnection) new
// sun.net.www.protocol.http.HttpURLConnection(url,
// (sun.net.www.protocol.http.Handler)this);
System.out.println("Asked for connection for url "+url);
return (URLConnection) new
MyConnection(url,this);
}
}
class MyConnection extends sun.net.www.protocol.http.HttpURLConnection {
protected MyConnection(URL url, MyHandler hdl) throws IOException {
super(url,hdl);
}
public MyConnection(URL url,String proxy,int proxyPort)
throws IOException {
super(url, proxy, proxyPort);
}
}
}
---- cut ----
When this application run, there is one DNS request for the host:
[vps@druid]~/jprogs$ java GetHttp http://aaa
======== TRY NO. 1
Asked for Handler for proto http
Asked for connection for url http://aaa/
Everything is OK!
======== TRY NO. 2
Asked for connection for url http://aaa/
Everything is OK!
TCPDUMP:
[root@druid]~# tcpdump host warrior
tcpdump: listening on hme0
19:22:54.384804 druid.sparc.spb.su.40026 > warrior.sparc.spb.su.domain: 61525+ (34) (DF)
19:22:54.385737 warrior.sparc.spb.su.domain > druid.sparc.spb.su.40026: 61525 NXDomain* 0/1/0 (94) (DF)
19:22:54.386456 druid.sparc.spb.su.40027 > warrior.sparc.spb.su.domain: 61526+ (28) (DF)
19:22:54.388655 warrior.sparc.spb.su.domain > druid.sparc.spb.su.40027: 61526 0/0/0 (28) (DF)
19:22:54.389239 druid.sparc.spb.su.40028 > warrior.sparc.spb.su.domain: 61527+ A? aaa. (21) (DF)
19:22:54.390082 warrior.sparc.spb.su.domain > druid.sparc.spb.su.40028: 61527 NXDomain* 0/1/0 (81) (DF)
druid is my box and warrior is a DNS server.
This DNS request can produce very long delay, if DNS is disable inside firewall.
You can see : even if proxy is set and we are trying to get the URL via proxy,
JDK tries to find out is URL hostname valid or not.
I hope I am doing this the same way HotJava does.
======================================================================
[mayank.upadhyay@eng 1999-09-15]
As of JDK1.2 the problem of not connecting on the first attempt is fixed. You can connect to the host outside the firewall on the first attempt. But you have to be sure to set the trustProxy property to true.
sun.net.www.http.HttpClient calls InetAddress.getByName() at the start of its constructor which will result in a DNS lookup the first time. When using the security manager the SocketPermission class also does name to address translations which return the cached value from the first lookup. The first DNS lookup is done to prevent various DNS spoofing attacks and will be left in for now.
mayank.upadhyay@eng 2000-02-14
Retaining this bug as a placeholder to possibly do some cleanup in the area of trustproxy and maybe also avoid doing the DNS lookup.
bradford.wetmore@eng 2000-02-16
This "feature" is definately generating customer calls. I'm rethinking
that we may want to expose trustProxy more than in the past.
Anyway, it appears as though we have another problem.
http://java.sun.com/security/signExample12/signedPluginEx.html
If I am behind the firewall, trustProxy is not true, and I have
the following grant statement:
grant {
java.security.AllPermission;
};
Everything works as expected.
However, if you change the line to:
grant signedBy "Duke" {
permission java.security.AllPermission;
};
I get an unexpected access control permission denied.
I'm not doing any codebase stuff, just a signedBy....
java.security.AccessControlException: access denied (java.net.SocketPermission java.sun.com connect,accept,resolve)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java, Compiled Code)
at java.security.AccessController.checkPermission(AccessController.java, Compiled Code)
at java.lang.SecurityManager.checkPermission(SecurityManager.java, Compiled Code)
at java.net.URLClassLoader$3.run(URLClassLoader.java, Compiled Code)
at java.security.AccessController.doPrivileged(Native Method)
....rest deleted....
This code is definately signed by Duke...
Name: pvC76716 Date: 02/17/2000
It would also nice if this bug can be fixed in 1.1.next, since
HotJava works with JDK 1.1.x only for now...
======================================================================
bradford.wetmore@eng 2000-03-07
The RM for this bug does not expect a JDK 1.1.next.
From: merlund Tue, 7 Mar 2000
The last I heard, there's not going to be a 1.1.9. The customer
will need to escalate to get a fix on 1.1.x.
###@###.### 2004-01-16
Filed another bug 4975882 to track the issues related to SocketPermission class. This bug will now only refers to the original issues about DNS lookup attempted when proxy is present even without a security manager presence, i.e. related to the "sprint bug" fix.
|