-
Bug
-
Resolution: Not an Issue
-
P3
-
None
-
8u172
-
x86_64
-
os_x
FULL PRODUCT VERSION :
java version "1.8.0_172-ea"
Java(TM) SE Runtime Environment (build 1.8.0_172-ea-b03)
Java HotSpot(TM) 64-Bit Server VM (build 25.172-b03, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Darwin hostname 17.4.0 Darwin Kernel Version 17.4.0: Sun Dec 17 09:19:54 PST 2017; root:xnu-4570.41.2~1/RELEASE_X86_64 x86_64
EXTRA RELEVANT SYSTEM CONFIGURATION :
running squid proxy in local docker instance
A DESCRIPTION OF THE PROBLEM :
Tunneling a HTTPS request through a proxy that uses authorization fails unless a http request is performed first.
using a HTTP backend works fine. It also seems to populate a cache that is used for HTTPS, so performing a HTTP request first seems to enable HTTPS.
REGRESSION. Last worked in version 8u151
ADDITIONAL REGRESSION INFORMATION:
last working version:
java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) start a docker container with a local squid proxy w/ auth
docker run -e SQUID_USERNAME=foo -e SQUID_PASSWORD=bar -p 3128:3128 robhaswell/squid-authenticated
2) execute the provided java program
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
the output should look like this (the first request should be successful and the password should be requested in the initial https call)
=== BEGIN https ===
>>> requesting password
{
"headers": {
"Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Java/1.8.0_102"
}
}
=== END https ===
=== BEGIN http ===
{
"headers": {
"Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
"Cache-Control": "max-age=259200",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Java/1.8.0_102"
}
}
=== END http ===
=== BEGIN https ===
{
"headers": {
"Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Java/1.8.0_102"
}
}
=== END https ===
ACTUAL -
the initial HTTPS request fails and does call the Authenticator
=== BEGIN https ===
ERROR: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required"
=== END https ===
=== BEGIN http ===
>>> requesting password
{
"headers": {
"Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
"Cache-Control": "max-age=259200",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Java/1.8.0_172-ea"
}
}
=== END http ===
=== BEGIN https ===
{
"headers": {
"Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Java/1.8.0_172-ea"
}
}
=== END https ===
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import static java.util.Arrays.asList;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URI;
import java.util.Scanner;
public class Sample
{
public static void main( String[] args )
{
for ( String protocol : asList( "http", "https" ) )
{
System.setProperty( protocol + ".proxyHost", "localhost" );
System.setProperty( protocol + ".proxyPort", "3128" );
}
Authenticator.setDefault( new Authenticator()
{
@Override
protected PasswordAuthentication getPasswordAuthentication()
{
System.out.println( ">>> requesting password" );
return new PasswordAuthentication( "foo", "bar".toCharArray() );
}
} );
for ( String protocol : asList( "https", "http", "https" ) )
{
System.out.println( "=== BEGIN " + protocol + " ===" );
try ( InputStream in = new URI( protocol, "httpbin.org", "/headers", null ).toURL().openStream() )
{
System.out.println( asString( in ) );
}
catch ( Exception e )
{
System.out.println( "ERROR: " + e.getMessage() );
}
System.out.println( "=== END " + protocol + " ===" );
}
}
private static String asString( InputStream in )
{
try ( Scanner scanner = new Scanner( in ) )
{
scanner.useDelimiter( "\0" );
return scanner.hasNext() ? scanner.next() : "";
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
performing a HTTP request beforehand seems to create a state where subsequent request succeed but this requires code changes in existing applications and has other negative implications as well.
java version "1.8.0_172-ea"
Java(TM) SE Runtime Environment (build 1.8.0_172-ea-b03)
Java HotSpot(TM) 64-Bit Server VM (build 25.172-b03, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Darwin hostname 17.4.0 Darwin Kernel Version 17.4.0: Sun Dec 17 09:19:54 PST 2017; root:xnu-4570.41.2~1/RELEASE_X86_64 x86_64
EXTRA RELEVANT SYSTEM CONFIGURATION :
running squid proxy in local docker instance
A DESCRIPTION OF THE PROBLEM :
Tunneling a HTTPS request through a proxy that uses authorization fails unless a http request is performed first.
using a HTTP backend works fine. It also seems to populate a cache that is used for HTTPS, so performing a HTTP request first seems to enable HTTPS.
REGRESSION. Last worked in version 8u151
ADDITIONAL REGRESSION INFORMATION:
last working version:
java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) start a docker container with a local squid proxy w/ auth
docker run -e SQUID_USERNAME=foo -e SQUID_PASSWORD=bar -p 3128:3128 robhaswell/squid-authenticated
2) execute the provided java program
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
the output should look like this (the first request should be successful and the password should be requested in the initial https call)
=== BEGIN https ===
>>> requesting password
{
"headers": {
"Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Java/1.8.0_102"
}
}
=== END https ===
=== BEGIN http ===
{
"headers": {
"Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
"Cache-Control": "max-age=259200",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Java/1.8.0_102"
}
}
=== END http ===
=== BEGIN https ===
{
"headers": {
"Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Java/1.8.0_102"
}
}
=== END https ===
ACTUAL -
the initial HTTPS request fails and does call the Authenticator
=== BEGIN https ===
ERROR: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required"
=== END https ===
=== BEGIN http ===
>>> requesting password
{
"headers": {
"Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
"Cache-Control": "max-age=259200",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Java/1.8.0_172-ea"
}
}
=== END http ===
=== BEGIN https ===
{
"headers": {
"Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Java/1.8.0_172-ea"
}
}
=== END https ===
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import static java.util.Arrays.asList;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URI;
import java.util.Scanner;
public class Sample
{
public static void main( String[] args )
{
for ( String protocol : asList( "http", "https" ) )
{
System.setProperty( protocol + ".proxyHost", "localhost" );
System.setProperty( protocol + ".proxyPort", "3128" );
}
Authenticator.setDefault( new Authenticator()
{
@Override
protected PasswordAuthentication getPasswordAuthentication()
{
System.out.println( ">>> requesting password" );
return new PasswordAuthentication( "foo", "bar".toCharArray() );
}
} );
for ( String protocol : asList( "https", "http", "https" ) )
{
System.out.println( "=== BEGIN " + protocol + " ===" );
try ( InputStream in = new URI( protocol, "httpbin.org", "/headers", null ).toURL().openStream() )
{
System.out.println( asString( in ) );
}
catch ( Exception e )
{
System.out.println( "ERROR: " + e.getMessage() );
}
System.out.println( "=== END " + protocol + " ===" );
}
}
private static String asString( InputStream in )
{
try ( Scanner scanner = new Scanner( in ) )
{
scanner.useDelimiter( "\0" );
return scanner.hasNext() ? scanner.next() : "";
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
performing a HTTP request beforehand seems to create a state where subsequent request succeed but this requires code changes in existing applications and has other negative implications as well.