mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-04 20:18:49 +00:00
6980004: limit HTTP request cookie headers in HttpURLConnection
6961084: limit setting of some request headers in HttpURLConnection Reviewed-by: chegar
This commit is contained in:
parent
4dff2e9974
commit
a5da7a1b31
@ -196,6 +196,10 @@ class MessageHeader {
|
||||
}
|
||||
|
||||
public synchronized Map<String, List<String>> getHeaders(String[] excludeList) {
|
||||
return filterAndAddHeaders(excludeList, null);
|
||||
}
|
||||
|
||||
public synchronized Map<String, List<String>> filterAndAddHeaders(String[] excludeList, Map<String, List<String>> include) {
|
||||
boolean skipIt = false;
|
||||
Map<String, List<String>> m = new HashMap<String, List<String>>();
|
||||
for (int i = nkeys; --i >= 0;) {
|
||||
@ -223,6 +227,19 @@ class MessageHeader {
|
||||
}
|
||||
}
|
||||
|
||||
if (include != null) {
|
||||
Iterator entries = include.entrySet().iterator();
|
||||
while (entries.hasNext()) {
|
||||
Map.Entry entry = (Map.Entry)entries.next();
|
||||
List l = (List)m.get(entry.getKey());
|
||||
if (l == null) {
|
||||
l = new ArrayList();
|
||||
m.put((String)entry.getKey(), l);
|
||||
}
|
||||
l.add(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
for (String key : m.keySet()) {
|
||||
m.put(key, Collections.unmodifiableList(m.get(key)));
|
||||
}
|
||||
|
||||
@ -51,6 +51,9 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import sun.net.*;
|
||||
import sun.net.www.*;
|
||||
import sun.net.www.http.HttpClient;
|
||||
@ -140,6 +143,54 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
*/
|
||||
private static int bufSize4ES = 0;
|
||||
|
||||
/*
|
||||
* Restrict setting of request headers through the public api
|
||||
* consistent with JavaScript XMLHttpRequest2 with a few
|
||||
* exceptions. Disallowed headers are silently ignored for
|
||||
* backwards compatibility reasons rather than throwing a
|
||||
* SecurityException. For example, some applets set the
|
||||
* Host header since old JREs did not implement HTTP 1.1.
|
||||
* Additionally, any header starting with Sec- is
|
||||
* disallowed.
|
||||
*
|
||||
* The following headers are allowed for historical reasons:
|
||||
*
|
||||
* Accept-Charset, Accept-Encoding, Cookie, Cookie2, Date,
|
||||
* Referer, TE, User-Agent, headers beginning with Proxy-.
|
||||
*
|
||||
* The following headers are allowed in a limited form:
|
||||
*
|
||||
* Connection: close
|
||||
*
|
||||
* See http://www.w3.org/TR/XMLHttpRequest2.
|
||||
*/
|
||||
private static final boolean allowRestrictedHeaders;
|
||||
private static final Set<String> restrictedHeaderSet;
|
||||
private static final String[] restrictedHeaders = {
|
||||
/* Restricted by XMLHttpRequest2 */
|
||||
//"Accept-Charset",
|
||||
//"Accept-Encoding",
|
||||
"Access-Control-Request-Headers",
|
||||
"Access-Control-Request-Method",
|
||||
"Connection", /* close is allowed */
|
||||
"Content-Length",
|
||||
//"Cookie",
|
||||
//"Cookie2",
|
||||
"Content-Transfer-Encoding",
|
||||
//"Date",
|
||||
//"Expect",
|
||||
"Host",
|
||||
"Keep-Alive",
|
||||
"Origin",
|
||||
// "Referer",
|
||||
// "TE",
|
||||
"Trailer",
|
||||
"Transfer-Encoding",
|
||||
"Upgrade",
|
||||
//"User-Agent",
|
||||
"Via"
|
||||
};
|
||||
|
||||
static {
|
||||
maxRedirects = java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetIntegerAction(
|
||||
@ -178,7 +229,17 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
bufSize4ES = 4096; // use the default
|
||||
}
|
||||
|
||||
|
||||
allowRestrictedHeaders = ((Boolean)java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetBooleanAction(
|
||||
"sun.net.http.allowRestrictedHeaders"))).booleanValue();
|
||||
if (!allowRestrictedHeaders) {
|
||||
restrictedHeaderSet = new HashSet<String>(restrictedHeaders.length);
|
||||
for (int i=0; i < restrictedHeaders.length; i++) {
|
||||
restrictedHeaderSet.add(restrictedHeaders[i].toLowerCase());
|
||||
}
|
||||
} else {
|
||||
restrictedHeaderSet = null;
|
||||
}
|
||||
}
|
||||
|
||||
static final String httpVersion = "HTTP/1.1";
|
||||
@ -191,6 +252,15 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
"Proxy-Authorization",
|
||||
"Authorization"
|
||||
};
|
||||
|
||||
// also exclude system cookies when any might be set
|
||||
private static final String[] EXCLUDE_HEADERS2= {
|
||||
"Proxy-Authorization",
|
||||
"Authorization",
|
||||
"Cookie",
|
||||
"Cookie2"
|
||||
};
|
||||
|
||||
protected HttpClient http;
|
||||
protected Handler handler;
|
||||
protected Proxy instProxy;
|
||||
@ -213,6 +283,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
/* User set Cookies */
|
||||
private boolean setUserCookies = true;
|
||||
private String userCookies = null;
|
||||
private String userCookies2 = null;
|
||||
|
||||
/* We only have a single static authenticator for now.
|
||||
* REMIND: backwards compatibility with JDK 1.1. Should be
|
||||
@ -329,6 +400,41 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isRestrictedHeader(String key, String value) {
|
||||
if (allowRestrictedHeaders) {
|
||||
return false;
|
||||
}
|
||||
|
||||
key = key.toLowerCase();
|
||||
if (restrictedHeaderSet.contains(key)) {
|
||||
/*
|
||||
* Exceptions to restricted headers:
|
||||
*
|
||||
* Allow "Connection: close".
|
||||
*/
|
||||
if (key.equals("connection") && value.equalsIgnoreCase("close")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else if (key.startsWith("sec-")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks the validity of http message header and whether the header
|
||||
* is restricted and throws IllegalArgumentException if invalid or
|
||||
* restricted.
|
||||
*/
|
||||
private boolean isExternalMessageHeaderAllowed(String key, String value) {
|
||||
checkMessageHeader(key, value);
|
||||
if (!isRestrictedHeader(key, value)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Logging support */
|
||||
public static PlatformLogger getHttpLogger() {
|
||||
return logger;
|
||||
@ -1047,15 +1153,21 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
// we only want to capture the user defined Cookies once, as
|
||||
// they cannot be changed by user code after we are connected,
|
||||
// only internally.
|
||||
if (setUserCookies) {
|
||||
int k = requests.getKey("Cookie");
|
||||
if ( k != -1)
|
||||
userCookies = requests.getValue(k);
|
||||
setUserCookies = false;
|
||||
synchronized (this) {
|
||||
if (setUserCookies) {
|
||||
int k = requests.getKey("Cookie");
|
||||
if ( k != -1)
|
||||
userCookies = requests.getValue(k);
|
||||
k = requests.getKey("Cookie2");
|
||||
if ( k != -1)
|
||||
userCookies2 = requests.getValue(k);
|
||||
setUserCookies = false;
|
||||
}
|
||||
}
|
||||
|
||||
// remove old Cookie header before setting new one.
|
||||
requests.remove("Cookie");
|
||||
requests.remove("Cookie2");
|
||||
|
||||
URI uri = ParseUtil.toURI(url);
|
||||
if (uri != null) {
|
||||
@ -1101,6 +1213,13 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
else
|
||||
requests.set("Cookie", userCookies);
|
||||
}
|
||||
if (userCookies2 != null) {
|
||||
int k;
|
||||
if ((k = requests.getKey("Cookie")) != -1)
|
||||
requests.set("Cookie2", requests.getValue(k) + ";" + userCookies2);
|
||||
else
|
||||
requests.set("Cookie2", userCookies2);
|
||||
}
|
||||
|
||||
} // end of getting cookies
|
||||
}
|
||||
@ -2539,8 +2658,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
if (key == null)
|
||||
throw new NullPointerException ("key is null");
|
||||
|
||||
checkMessageHeader(key, value);
|
||||
requests.set(key, value);
|
||||
if (isExternalMessageHeaderAllowed(key, value)) {
|
||||
requests.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2561,8 +2681,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
if (key == null)
|
||||
throw new NullPointerException ("key is null");
|
||||
|
||||
checkMessageHeader(key, value);
|
||||
requests.add(key, value);
|
||||
if (isExternalMessageHeaderAllowed(key, value)) {
|
||||
requests.add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -2575,13 +2696,23 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestProperty (String key) {
|
||||
public synchronized String getRequestProperty (String key) {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// don't return headers containing security sensitive information
|
||||
if (key != null) {
|
||||
for (int i=0; i < EXCLUDE_HEADERS.length; i++) {
|
||||
if (key.equalsIgnoreCase(EXCLUDE_HEADERS[i])) {
|
||||
return null;
|
||||
}
|
||||
for (int i=0; i < EXCLUDE_HEADERS.length; i++) {
|
||||
if (key.equalsIgnoreCase(EXCLUDE_HEADERS[i])) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (!setUserCookies) {
|
||||
if (key.equalsIgnoreCase("Cookie")) {
|
||||
return userCookies;
|
||||
}
|
||||
if (key.equalsIgnoreCase("Cookie2")) {
|
||||
return userCookies2;
|
||||
}
|
||||
}
|
||||
return requests.findValue(key);
|
||||
@ -2600,12 +2731,29 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
* @since 1.4
|
||||
*/
|
||||
@Override
|
||||
public Map<String, List<String>> getRequestProperties() {
|
||||
public synchronized Map<String, List<String>> getRequestProperties() {
|
||||
if (connected)
|
||||
throw new IllegalStateException("Already connected");
|
||||
|
||||
// exclude headers containing security-sensitive info
|
||||
return requests.getHeaders(EXCLUDE_HEADERS);
|
||||
if (setUserCookies) {
|
||||
return requests.getHeaders(EXCLUDE_HEADERS);
|
||||
}
|
||||
/*
|
||||
* The cookies in the requests message headers may have
|
||||
* been modified. Use the saved user cookies instead.
|
||||
*/
|
||||
Map userCookiesMap = null;
|
||||
if (userCookies != null || userCookies2 != null) {
|
||||
userCookiesMap = new HashMap();
|
||||
if (userCookies != null) {
|
||||
userCookiesMap.put("Cookie", userCookies);
|
||||
}
|
||||
if (userCookies2 != null) {
|
||||
userCookiesMap.put("Cookie2", userCookies2);
|
||||
}
|
||||
}
|
||||
return requests.filterAndAddHeaders(EXCLUDE_HEADERS2, userCookiesMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user