--- a/jdk/src/share/classes/com/sun/jndi/dns/DnsContextFactory.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/dns/DnsContextFactory.java Fri Oct 08 11:27:55 2010 +0100
@@ -54,6 +54,7 @@
public class DnsContextFactory implements InitialContextFactory {
private static final String DEFAULT_URL = "dns:";
+ private static final int DEFAULT_PORT = 53;
public Context getInitialContext(Hashtable<?,?> env) throws NamingException {
@@ -89,7 +90,9 @@
* Public for use by product test suite.
*/
public static boolean platformServersAvailable() {
- return !ResolverConfiguration.open().nameservers().isEmpty();
+ return !filterNameServers(
+ ResolverConfiguration.open().nameservers(), true
+ ).isEmpty();
}
private static Context urlToContext(String url, Hashtable env)
@@ -142,8 +145,8 @@
// No server or port given, so look to underlying platform.
// ResolverConfiguration does some limited caching, so the
// following is reasonably efficient even if called rapid-fire.
- List<String> platformServers =
- ResolverConfiguration.open().nameservers();
+ List<String> platformServers = filterNameServers(
+ ResolverConfiguration.open().nameservers(), false);
if (!platformServers.isEmpty()) {
servers.addAll(platformServers);
continue; // on to next URL (if any, which is unlikely)
@@ -213,4 +216,44 @@
String url = (String) env.get(Context.PROVIDER_URL);
return ((url != null) ? url : DEFAULT_URL);
}
+
+ /**
+ * Removes any DNS server that's not permitted to access
+ * @param input the input server[:port] list, must not be null
+ * @param oneIsEnough return output once there exists one ok
+ * @return the filtered list, all non-permitted input removed
+ */
+ private static List filterNameServers(List input, boolean oneIsEnough) {
+ SecurityManager security = System.getSecurityManager();
+ if (security == null || input == null || input.isEmpty()) {
+ return input;
+ } else {
+ List output = new ArrayList();
+ for (Object o: input) {
+ if (o instanceof String) {
+ String platformServer = (String)o;
+ int colon = platformServer.indexOf(':',
+ platformServer.indexOf(']') + 1);
+
+ int p = (colon < 0)
+ ? DEFAULT_PORT
+ : Integer.parseInt(
+ platformServer.substring(colon + 1));
+ String s = (colon < 0)
+ ? platformServer
+ : platformServer.substring(0, colon);
+ try {
+ security.checkConnect(s, p);
+ output.add(platformServer);
+ if (oneIsEnough) {
+ return output;
+ }
+ } catch (SecurityException se) {
+ continue;
+ }
+ }
+ }
+ return output;
+ }
+ }
}
--- a/jdk/src/share/classes/java/awt/image/IndexColorModel.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/java/awt/image/IndexColorModel.java Fri Oct 08 11:27:55 2010 +0100
@@ -129,6 +129,8 @@
private boolean allgrayopaque;
private BigInteger validBits;
+ private sun.awt.image.BufImgSurfaceData.ICMColorData colorData = null;
+
private static int[] opaqueBits = {8, 8, 8};
private static int[] alphaBits = {8, 8, 8, 8};
@@ -1511,7 +1513,6 @@
* longer referenced.
*/
public void finalize() {
- sun.awt.image.BufImgSurfaceData.freeNativeICMData(this);
}
/**
--- a/jdk/src/share/classes/java/net/HttpURLConnection.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/java/net/HttpURLConnection.java Fri Oct 08 11:27:55 2010 +0100
@@ -399,6 +399,8 @@
* @param method the HTTP method
* @exception ProtocolException if the method cannot be reset or if
* the requested method isn't valid for HTTP.
+ * @exception SecurityException if a security manager is set and the
+ * "allowHttpTrace" NetPermission is not granted.
* @see #getRequestMethod()
*/
public void setRequestMethod(String method) throws ProtocolException {
@@ -412,6 +414,12 @@
for (int i = 0; i < methods.length; i++) {
if (methods[i].equals(method)) {
+ if (method.equals("TRACE")) {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null) {
+ s.checkPermission(new NetPermission("allowHttpTrace"));
+ }
+ }
this.method = method;
return;
}
--- a/jdk/src/share/classes/java/net/NetPermission.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/java/net/NetPermission.java Fri Oct 08 11:27:55 2010 +0100
@@ -54,44 +54,23 @@
* <th>What the Permission Allows</th>
* <th>Risks of Allowing this Permission</th>
* </tr>
- *
* <tr>
- * <td>setDefaultAuthenticator</td>
- * <td>The ability to set the
- * way authentication information is retrieved when
- * a proxy or HTTP server asks for authentication</td>
- * <td>Malicious
- * code can set an authenticator that monitors and steals user
- * authentication input as it retrieves the input from the user.</td>
- * </tr>
+ * <td>allowHttpTrace</td>
+ * <td>The ability to use the HTTP TRACE method in HttpURLConnection.</td>
+ * <td>Malicious code using HTTP TRACE could get access to security sensitive
+ * information in the HTTP headers (such as cookies) that it might not
+ * otherwise have access to.</td>
+ * </tr>
*
* <tr>
- * <td>requestPasswordAuthentication</td>
- * <td>The ability
- * to ask the authenticator registered with the system for
- * a password</td>
- * <td>Malicious code may steal this password.</td>
- * </tr>
- *
- * <tr>
- * <td>specifyStreamHandler</td>
- * <td>The ability
- * to specify a stream handler when constructing a URL</td>
- * <td>Malicious code may create a URL with resources that it would
-normally not have access to (like file:/foo/fum/), specifying a
-stream handler that gets the actual bytes from someplace it does
-have access to. Thus it might be able to trick the system into
-creating a ProtectionDomain/CodeSource for a class even though
-that class really didn't come from that location.</td>
- * </tr>
- *
- * <tr>
- * <td>setProxySelector</td>
- * <td>The ability to set the proxy selector used to make decisions
- * on which proxies to use when making network connections.</td>
- * <td>Malicious code can set a ProxySelector that directs network
- * traffic to an arbitrary network host.</td>
- * </tr>
+ * <td>getCookieHandler</td>
+ * <td>The ability to get the cookie handler that processes highly
+ * security sensitive cookie information for an Http session.</td>
+ * <td>Malicious code can get a cookie handler to obtain access to
+ * highly security sensitive cookie information. Some web servers
+ * use cookies to save user private information such as access
+ * control information, or to track user browsing habit.</td>
+ * </tr>
*
* <tr>
* <td>getProxySelector</td>
@@ -103,6 +82,22 @@
* </tr>
*
* <tr>
+ * <td>getResponseCache</td>
+ * <td>The ability to get the response cache that provides
+ * access to a local response cache.</td>
+ * <td>Malicious code getting access to the local response cache
+ * could access security sensitive information.</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>requestPasswordAuthentication</td>
+ * <td>The ability
+ * to ask the authenticator registered with the system for
+ * a password</td>
+ * <td>Malicious code may steal this password.</td>
+ * </tr>
+ *
+ * <tr>
* <td>setCookieHandler</td>
* <td>The ability to set the cookie handler that processes highly
* security sensitive cookie information for an Http session.</td>
@@ -113,14 +108,22 @@
* </tr>
*
* <tr>
- * <td>getCookieHandler</td>
- * <td>The ability to get the cookie handler that processes highly
- * security sensitive cookie information for an Http session.</td>
- * <td>Malicious code can get a cookie handler to obtain access to
- * highly security sensitive cookie information. Some web servers
- * use cookies to save user private information such as access
- * control information, or to track user browsing habit.</td>
- * </tr>
+ * <td>setDefaultAuthenticator</td>
+ * <td>The ability to set the
+ * way authentication information is retrieved when
+ * a proxy or HTTP server asks for authentication</td>
+ * <td>Malicious
+ * code can set an authenticator that monitors and steals user
+ * authentication input as it retrieves the input from the user.</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>setProxySelector</td>
+ * <td>The ability to set the proxy selector used to make decisions
+ * on which proxies to use when making network connections.</td>
+ * <td>Malicious code can set a ProxySelector that directs network
+ * traffic to an arbitrary network host.</td>
+ * </tr>
*
* <tr>
* <td>setResponseCache</td>
@@ -132,13 +135,16 @@
* </tr>
*
* <tr>
- * <td>getResponseCache</td>
- * <td>The ability to get the response cache that provides
- * access to a local response cache.</td>
- * <td>Malicious code getting access to the local response cache
- * could access security sensitive information.</td>
- * </tr>
- *
+ * <td>specifyStreamHandler</td>
+ * <td>The ability
+ * to specify a stream handler when constructing a URL</td>
+ * <td>Malicious code may create a URL with resources that it would
+normally not have access to (like file:/foo/fum/), specifying a
+stream handler that gets the actual bytes from someplace it does
+have access to. Thus it might be able to trick the system into
+creating a ProtectionDomain/CodeSource for a class even though
+that class really didn't come from that location.</td>
+ * </tr>
* </table>
*
* @see java.security.BasicPermission
--- a/jdk/src/share/classes/java/net/NetworkInterface.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/java/net/NetworkInterface.java Fri Oct 08 11:27:55 2010 +0100
@@ -86,7 +86,9 @@
* If there is a security manager, its <code>checkConnect</code>
* method is called for each InetAddress. Only InetAddresses where
* the <code>checkConnect</code> doesn't throw a SecurityException
- * will be returned in the Enumeration.
+ * will be returned in the Enumeration. However, if the caller has the
+ * {@link NetPermission}("getNetworkInformation") permission, then all
+ * InetAddresses are returned.
* @return an Enumeration object with all or a subset of the InetAddresses
* bound to this network interface
*/
@@ -99,11 +101,19 @@
checkedAddresses() {
local_addrs = new InetAddress[addrs.length];
+ boolean trusted = true;
SecurityManager sec = System.getSecurityManager();
+ if (sec != null) {
+ try {
+ sec.checkPermission(new NetPermission("getNetworkInformation"));
+ } catch (SecurityException e) {
+ trusted = false;
+ }
+ }
for (int j=0; j<addrs.length; j++) {
try {
- if (sec != null) {
+ if (sec != null && !trusted) {
sec.checkConnect(addrs[j].getHostAddress(), -1);
}
local_addrs[count++] = addrs[j];
@@ -402,13 +412,29 @@
/**
* Returns the hardware address (usually MAC) of the interface if it
* has one and if it can be accessed given the current privileges.
+ * If a security manager is set, then the caller must have
+ * the permission {@link NetPermission}("getNetworkInformation").
*
- * @return a byte array containing the address or <code>null</code> if
- * the address doesn't exist or is not accessible.
+ * @return a byte array containing the address, or <code>null</code> if
+ * the address doesn't exist, is not accessible or a security
+ * manager is set and the caller does not have the permission
+ * NetPermission("getNetworkInformation")
+ *
* @exception SocketException if an I/O error occurs.
* @since 1.6
*/
public byte[] getHardwareAddress() throws SocketException {
+ SecurityManager sec = System.getSecurityManager();
+ if (sec != null) {
+ try {
+ sec.checkPermission(new NetPermission("getNetworkInformation"));
+ } catch (SecurityException e) {
+ if (!getInetAddresses().hasMoreElements()) {
+ // don't have connect permission to any local address
+ return null;
+ }
+ }
+ }
for (InetAddress addr : addrs) {
if (addr instanceof Inet4Address) {
return getMacAddr0(((Inet4Address)addr).getAddress(), name, index);
@@ -523,11 +549,10 @@
}
public int hashCode() {
- int count = 0;
- if (addrs != null) {
- for (int i = 0; i < addrs.length; i++) {
- count += addrs[i].hashCode();
- }
+ int count = name == null? 0: name.hashCode();
+ Enumeration<InetAddress> addrs = getInetAddresses();
+ while (addrs.hasMoreElements()) {
+ count += addrs.nextElement().hashCode();
}
return count;
}
--- a/jdk/src/share/classes/javax/swing/UIDefaults.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/UIDefaults.java Fri Oct 08 11:27:55 2010 +0100
@@ -52,6 +52,7 @@
import java.security.PrivilegedAction;
import sun.reflect.misc.MethodUtil;
+import sun.reflect.misc.ReflectUtil;
import sun.util.CoreResourceBundleControl;
/**
@@ -1078,6 +1079,9 @@
// In order to pick up the security policy in effect at the
// time of creation we use a doPrivileged with the
// AccessControlContext that was in place when this was created.
+ if (acc == null && System.getSecurityManager() != null) {
+ throw new SecurityException("null AccessControlContext");
+ }
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
try {
@@ -1093,7 +1097,9 @@
cl = ClassLoader.getSystemClassLoader();
}
}
+ ReflectUtil.checkPackageAccess(className);
c = Class.forName(className, true, (ClassLoader)cl);
+ checkAccess(c.getModifiers());
if (methodName != null) {
Class[] types = getClassArray(args);
Method m = c.getMethod(methodName, types);
@@ -1101,6 +1107,7 @@
} else {
Class[] types = getClassArray(args);
Constructor constructor = c.getConstructor(types);
+ checkAccess(constructor.getModifiers());
return constructor.newInstance(args);
}
} catch(Exception e) {
@@ -1115,6 +1122,13 @@
}, acc);
}
+ private void checkAccess(int modifiers) {
+ if(System.getSecurityManager() != null &&
+ !Modifier.isPublic(modifiers)) {
+ throw new SecurityException("Resource is not accessible");
+ }
+ }
+
/*
* Coerce the array of class types provided into one which
* looks the way the Reflection APIs expect. This is done
--- a/jdk/src/share/classes/javax/swing/text/html/HTMLEditorKit.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/text/html/HTMLEditorKit.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,8 @@
*/
package javax.swing.text.html;
+import sun.awt.AppContext;
+
import java.lang.reflect.Method;
import java.awt.*;
import java.awt.event.*;
@@ -369,7 +371,11 @@
* if desired.
*/
public void setStyleSheet(StyleSheet s) {
- defaultStyles = s;
+ if (s == null) {
+ AppContext.getAppContext().remove(DEFAULT_STYLES_KEY);
+ } else {
+ AppContext.getAppContext().put(DEFAULT_STYLES_KEY, s);
+ }
}
/**
@@ -379,8 +385,12 @@
* instances.
*/
public StyleSheet getStyleSheet() {
+ AppContext appContext = AppContext.getAppContext();
+ StyleSheet defaultStyles = (StyleSheet) appContext.get(DEFAULT_STYLES_KEY);
+
if (defaultStyles == null) {
defaultStyles = new StyleSheet();
+ appContext.put(DEFAULT_STYLES_KEY, defaultStyles);
try {
InputStream is = HTMLEditorKit.getResourceAsStream(DEFAULT_CSS);
Reader r = new BufferedReader(
@@ -620,7 +630,7 @@
private static final ViewFactory defaultFactory = new HTMLFactory();
MutableAttributeSet input;
- private static StyleSheet defaultStyles = null;
+ private static final Object DEFAULT_STYLES_KEY = new Object();
private LinkController linkHandler = new LinkController();
private static Parser defaultParser = null;
private Cursor defaultCursor = DefaultCursor;
--- a/jdk/src/share/classes/javax/swing/text/html/parser/DTD.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/text/html/parser/DTD.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
package javax.swing.text.html.parser;
+import sun.awt.AppContext;
+
import java.io.PrintStream;
import java.io.File;
import java.io.FileInputStream;
@@ -314,13 +316,14 @@
}
/**
- * The hashtable of DTDs.
+ * The hashtable key of DTDs in AppContext.
*/
- static Hashtable<String, DTD> dtdHash = new Hashtable<String, DTD>();
+ private static final Object DTD_HASH_KEY = new Object();
- public static void putDTDHash(String name, DTD dtd) {
- dtdHash.put(name, dtd);
- }
+ public static void putDTDHash(String name, DTD dtd) {
+ getDtdHash().put(name, dtd);
+ }
+
/**
* Returns a DTD with the specified <code>name</code>. If
* a DTD with that name doesn't exist, one is created
@@ -332,13 +335,27 @@
*/
public static DTD getDTD(String name) throws IOException {
name = name.toLowerCase();
- DTD dtd = dtdHash.get(name);
+ DTD dtd = getDtdHash().get(name);
if (dtd == null)
dtd = new DTD(name);
return dtd;
}
+ private static Hashtable<String, DTD> getDtdHash() {
+ AppContext appContext = AppContext.getAppContext();
+
+ Hashtable<String, DTD> result = (Hashtable<String, DTD>) appContext.get(DTD_HASH_KEY);
+
+ if (result == null) {
+ result = new Hashtable<String, DTD>();
+
+ appContext.put(DTD_HASH_KEY, result);
+ }
+
+ return result;
+ }
+
/**
* Recreates a DTD from an archived format.
* @param in the <code>DataInputStream</code> to read from
--- a/jdk/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
package javax.swing.text.html.parser;
+import sun.awt.AppContext;
+
import javax.swing.text.html.HTMLEditorKit;
import java.io.BufferedInputStream;
import java.io.IOException;
@@ -33,7 +35,6 @@
import java.io.ObjectInputStream;
import java.io.Reader;
import java.io.Serializable;
-import java.lang.reflect.Method;
/**
* Responsible for starting up a new DocumentParser
@@ -45,9 +46,13 @@
public class ParserDelegator extends HTMLEditorKit.Parser implements Serializable {
- private static DTD dtd = null;
+ private static final Object DTD_KEY = new Object();
protected static synchronized void setDefaultDTD() {
+ AppContext appContext = AppContext.getAppContext();
+
+ DTD dtd = (DTD) appContext.get(DTD_KEY);
+
if (dtd == null) {
DTD _dtd = null;
// (PENDING) Hate having to hard code!
@@ -59,6 +64,8 @@
System.out.println("Throw an exception: could not get default dtd: " + nm);
}
dtd = createDTD(_dtd, nm);
+
+ appContext.put(DTD_KEY, dtd);
}
}
@@ -81,13 +88,11 @@
public ParserDelegator() {
- if (dtd == null) {
- setDefaultDTD();
- }
+ setDefaultDTD();
}
public void parse(Reader r, HTMLEditorKit.ParserCallback cb, boolean ignoreCharSet) throws IOException {
- new DocumentParser(dtd).parse(r, cb, ignoreCharSet);
+ new DocumentParser((DTD) AppContext.getAppContext().get(DTD_KEY)).parse(r, cb, ignoreCharSet);
}
/**
@@ -113,8 +118,6 @@
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException {
s.defaultReadObject();
- if (dtd == null) {
- setDefaultDTD();
- }
+ setDefaultDTD();
}
}
--- a/jdk/src/share/classes/sun/awt/image/BufImgSurfaceData.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/awt/image/BufImgSurfaceData.java Fri Oct 08 11:27:55 2010 +0100
@@ -49,7 +49,7 @@
private BufferedImageGraphicsConfig graphicsConfig;
RenderLoops solidloops;
- private static native void initIDs(Class ICM);
+ private static native void initIDs(Class ICM, Class ICMColorData);
private static final int DCM_RGBX_RED_MASK = 0xff000000;
private static final int DCM_RGBX_GREEN_MASK = 0x00ff0000;
@@ -67,7 +67,7 @@
private static final int DCM_ARGBBM_BLUE_MASK = 0x000000ff;
static {
- initIDs(IndexColorModel.class);
+ initIDs(IndexColorModel.class, ICMColorData.class);
}
public static SurfaceData createData(BufferedImage bufImg) {
@@ -403,7 +403,7 @@
// their pixels are immediately retrievable anyway.
}
- public static native void freeNativeICMData(IndexColorModel icm);
+ private static native void freeNativeICMData(long pData);
/**
* Returns destination Image associated with this SurfaceData.
@@ -411,4 +411,19 @@
public Object getDestination() {
return bufImg;
}
+
+ public static final class ICMColorData {
+ private long pData = 0L;
+
+ private ICMColorData(long pData) {
+ this.pData = pData;
+ }
+
+ public void finalize() {
+ if (pData != 0L) {
+ BufImgSurfaceData.freeNativeICMData(pData);
+ pData = 0L;
+ }
+ }
+ }
}
--- a/jdk/src/share/classes/sun/net/www/MessageHeader.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/net/www/MessageHeader.java Fri Oct 08 11:27:55 2010 +0100
@@ -196,6 +196,10 @@
}
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 @@
}
}
+ 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)));
}
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Fri Oct 08 11:27:55 2010 +0100
@@ -51,6 +51,9 @@
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 @@
*/
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 @@
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 @@
"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 @@
/* 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 @@
});
}
+ 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;
@@ -463,9 +569,12 @@
"application/x-www-form-urlencoded");
}
+ boolean chunked = false;
+
if (streaming()) {
if (chunkLength != -1) {
requests.set ("Transfer-Encoding", "chunked");
+ chunked = true;
} else { /* fixed content length */
if (fixedContentLengthLong != -1) {
requests.set ("Content-Length",
@@ -485,6 +594,16 @@
}
}
+ if (!chunked) {
+ if (requests.findValue("Transfer-Encoding") != null) {
+ requests.remove("Transfer-Encoding");
+ if (logger.isLoggable(PlatformLogger.WARNING)) {
+ logger.warning(
+ "use streaming mode for chunked encoding");
+ }
+ }
+ }
+
// get applicable cookies based on the uri and request headers
// add them to the existing request headers
setCookieHeader();
@@ -1034,15 +1153,21 @@
// 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) {
@@ -1088,6 +1213,13 @@
else
requests.set("Cookie", userCookies);
}
+ if (userCookies2 != null) {
+ int k;
+ if ((k = requests.getKey("Cookie2")) != -1)
+ requests.set("Cookie2", requests.getValue(k) + ";" + userCookies2);
+ else
+ requests.set("Cookie2", userCookies2);
+ }
} // end of getting cookies
}
@@ -2530,8 +2662,9 @@
if (key == null)
throw new NullPointerException ("key is null");
- checkMessageHeader(key, value);
- requests.set(key, value);
+ if (isExternalMessageHeaderAllowed(key, value)) {
+ requests.set(key, value);
+ }
}
/**
@@ -2552,8 +2685,9 @@
if (key == null)
throw new NullPointerException ("key is null");
- checkMessageHeader(key, value);
- requests.add(key, value);
+ if (isExternalMessageHeaderAllowed(key, value)) {
+ requests.add(key, value);
+ }
}
//
@@ -2566,13 +2700,23 @@
}
@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);
@@ -2591,12 +2735,29 @@
* @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
--- a/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java Fri Oct 08 11:27:55 2010 +0100
@@ -35,7 +35,6 @@
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import sun.security.krb5.*;
-import sun.security.jgss.HttpCaller;
import sun.security.krb5.internal.Krb5;
abstract class InitialToken extends Krb5Token {
@@ -217,6 +216,12 @@
int pos = 0;
+ if (checksum == null) {
+ GSSException ge = new GSSException(GSSException.FAILURE, -1,
+ "No cksum in AP_REQ's authenticator");
+ ge.initCause(new KrbException(Krb5.KRB_AP_ERR_INAPP_CKSUM));
+ throw ge;
+ }
checksumBytes = checksum.getBytes();
if ((checksumBytes[0] != CHECKSUM_FIRST_BYTES[0]) ||
--- a/jdk/src/share/classes/sun/security/ssl/Alerts.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/Alerts.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -74,7 +74,7 @@
static final byte alert_insufficient_security = 71;
static final byte alert_internal_error = 80;
static final byte alert_user_canceled = 90;
- static final byte alert_no_negotiation = 100;
+ static final byte alert_no_renegotiation = 100;
// from RFC 3546 (TLS Extensions)
static final byte alert_unsupported_extension = 110;
@@ -132,8 +132,8 @@
return "internal_error";
case alert_user_canceled:
return "user_canceled";
- case alert_no_negotiation:
- return "no_negotiation";
+ case alert_no_renegotiation:
+ return "no_renegotiation";
case alert_unsupported_extension:
return "unsupported_extension";
case alert_certificate_unobtainable:
@@ -203,7 +203,7 @@
case alert_protocol_version:
case alert_internal_error:
case alert_user_canceled:
- case alert_no_negotiation:
+ case alert_no_renegotiation:
default:
e = new SSLException(reason);
break;
--- a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -126,6 +126,8 @@
macAlg = M_SHA;
} else if (name.endsWith("_NULL")) {
macAlg = M_NULL;
+ } else if (name.endsWith("_SCSV")) {
+ macAlg = M_NULL;
} else {
throw new IllegalArgumentException
("Unknown MAC algorithm for ciphersuite " + name);
@@ -160,6 +162,10 @@
return allowed && keyExchange.isAvailable() && cipher.isAvailable();
}
+ boolean isNegotiable() {
+ return this != C_SCSV && isAvailable();
+ }
+
/**
* Compares CipherSuites based on their priority. Has the effect of
* sorting CipherSuites when put in a sorted collection, which is
@@ -268,7 +274,10 @@
// Kerberos cipher suites
K_KRB5 ("KRB5", true),
- K_KRB5_EXPORT("KRB5_EXPORT", true);
+ K_KRB5_EXPORT("KRB5_EXPORT", true),
+
+ // renegotiation protection request signaling cipher suite
+ K_SCSV ("SCSV", true);
// name of the key exchange algorithm, e.g. DHE_DSS
final String name;
@@ -352,7 +361,8 @@
this.exportable = true;
}
- BulkCipher(String transformation, int keySize, int ivSize, boolean allowed) {
+ BulkCipher(String transformation, int keySize,
+ int ivSize, boolean allowed) {
this.transformation = transformation;
this.algorithm = transformation.split("/")[0];
this.description = this.algorithm + "/" + (keySize << 3);
@@ -370,7 +380,8 @@
*
* @exception NoSuchAlgorithmException if anything goes wrong
*/
- CipherBox newCipher(ProtocolVersion version, SecretKey key, IvParameterSpec iv,
+ CipherBox newCipher(ProtocolVersion version,
+ SecretKey key, IvParameterSpec iv,
boolean encrypt) throws NoSuchAlgorithmException {
return CipherBox.newCipherBox(version, this, key, iv, encrypt);
}
@@ -407,8 +418,9 @@
if (b == null) {
try {
SecretKey key = new SecretKeySpec
- (new byte[cipher.expandedKeySize], cipher.algorithm);
- IvParameterSpec iv = new IvParameterSpec(new byte[cipher.ivSize]);
+ (new byte[cipher.expandedKeySize], cipher.algorithm);
+ IvParameterSpec iv =
+ new IvParameterSpec(new byte[cipher.ivSize]);
cipher.newCipher(ProtocolVersion.DEFAULT, key, iv, true);
b = Boolean.TRUE;
} catch (NoSuchAlgorithmException e) {
@@ -460,18 +472,28 @@
}
// export strength ciphers
- final static BulkCipher B_NULL = new BulkCipher("NULL", 0, 0, 0, true);
- final static BulkCipher B_RC4_40 = new BulkCipher(CIPHER_RC4, 5, 16, 0, true);
- final static BulkCipher B_RC2_40 = new BulkCipher("RC2", 5, 16, 8, false);
- final static BulkCipher B_DES_40 = new BulkCipher(CIPHER_DES, 5, 8, 8, true);
+ final static BulkCipher B_NULL =
+ new BulkCipher("NULL", 0, 0, 0, true);
+ final static BulkCipher B_RC4_40 =
+ new BulkCipher(CIPHER_RC4, 5, 16, 0, true);
+ final static BulkCipher B_RC2_40 =
+ new BulkCipher("RC2", 5, 16, 8, false);
+ final static BulkCipher B_DES_40 =
+ new BulkCipher(CIPHER_DES, 5, 8, 8, true);
// domestic strength ciphers
- final static BulkCipher B_RC4_128 = new BulkCipher(CIPHER_RC4, 16, 0, true);
- final static BulkCipher B_DES = new BulkCipher(CIPHER_DES, 8, 8, true);
- final static BulkCipher B_3DES = new BulkCipher(CIPHER_3DES, 24, 8, true);
- final static BulkCipher B_IDEA = new BulkCipher("IDEA", 16, 8, false);
- final static BulkCipher B_AES_128 = new BulkCipher(CIPHER_AES, 16, 16, true);
- final static BulkCipher B_AES_256 = new BulkCipher(CIPHER_AES, 32, 16, true);
+ final static BulkCipher B_RC4_128 =
+ new BulkCipher(CIPHER_RC4, 16, 0, true);
+ final static BulkCipher B_DES =
+ new BulkCipher(CIPHER_DES, 8, 8, true);
+ final static BulkCipher B_3DES =
+ new BulkCipher(CIPHER_3DES, 24, 8, true);
+ final static BulkCipher B_IDEA =
+ new BulkCipher("IDEA", 16, 8, false);
+ final static BulkCipher B_AES_128 =
+ new BulkCipher(CIPHER_AES, 16, 16, true);
+ final static BulkCipher B_AES_256 =
+ new BulkCipher(CIPHER_AES, 32, 16, true);
// MACs
final static MacAlg M_NULL = new MacAlg("NULL", 0);
@@ -487,93 +509,159 @@
// N: ciphersuites only allowed if we are not in FIPS mode
final boolean N = (SunJSSE.isFIPS() == false);
-add("SSL_NULL_WITH_NULL_NULL", 0x0000, 1, K_NULL, B_NULL, F);
+ add("SSL_NULL_WITH_NULL_NULL",
+ 0x0000, 1, K_NULL, B_NULL, F);
// Definition of the CipherSuites that are enabled by default.
// They are listed in preference order, most preferred first.
int p = DEFAULT_SUITES_PRIORITY * 2;
-add("SSL_RSA_WITH_RC4_128_MD5", 0x0004, --p, K_RSA, B_RC4_128, N);
-add("SSL_RSA_WITH_RC4_128_SHA", 0x0005, --p, K_RSA, B_RC4_128, N);
-add("TLS_RSA_WITH_AES_128_CBC_SHA", 0x002f, --p, K_RSA, B_AES_128, T);
-add("TLS_RSA_WITH_AES_256_CBC_SHA", 0x0035, --p, K_RSA, B_AES_256, T);
+ add("SSL_RSA_WITH_RC4_128_MD5",
+ 0x0004, --p, K_RSA, B_RC4_128, N);
+ add("SSL_RSA_WITH_RC4_128_SHA",
+ 0x0005, --p, K_RSA, B_RC4_128, N);
+ add("TLS_RSA_WITH_AES_128_CBC_SHA",
+ 0x002f, --p, K_RSA, B_AES_128, T);
+ add("TLS_RSA_WITH_AES_256_CBC_SHA",
+ 0x0035, --p, K_RSA, B_AES_256, T);
-add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA", 0xC002, --p, K_ECDH_ECDSA, B_RC4_128, N);
-add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", 0xC004, --p, K_ECDH_ECDSA, B_AES_128, T);
-add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", 0xC005, --p, K_ECDH_ECDSA, B_AES_256, T);
-add("TLS_ECDH_RSA_WITH_RC4_128_SHA", 0xC00C, --p, K_ECDH_RSA, B_RC4_128, N);
-add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", 0xC00E, --p, K_ECDH_RSA, B_AES_128, T);
-add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", 0xC00F, --p, K_ECDH_RSA, B_AES_256, T);
+ add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+ 0xC002, --p, K_ECDH_ECDSA, B_RC4_128, N);
+ add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+ 0xC004, --p, K_ECDH_ECDSA, B_AES_128, T);
+ add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+ 0xC005, --p, K_ECDH_ECDSA, B_AES_256, T);
+ add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
+ 0xC00C, --p, K_ECDH_RSA, B_RC4_128, N);
+ add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
+ 0xC00E, --p, K_ECDH_RSA, B_AES_128, T);
+ add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+ 0xC00F, --p, K_ECDH_RSA, B_AES_256, T);
-add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", 0xC007, --p, K_ECDHE_ECDSA,B_RC4_128, N);
-add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 0xC009, --p, K_ECDHE_ECDSA,B_AES_128, T);
-add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 0xC00A, --p, K_ECDHE_ECDSA,B_AES_256, T);
-add("TLS_ECDHE_RSA_WITH_RC4_128_SHA", 0xC011, --p, K_ECDHE_RSA, B_RC4_128, N);
-add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 0xC013, --p, K_ECDHE_RSA, B_AES_128, T);
-add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 0xC014, --p, K_ECDHE_RSA, B_AES_256, T);
+ add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+ 0xC007, --p, K_ECDHE_ECDSA,B_RC4_128, N);
+ add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ 0xC009, --p, K_ECDHE_ECDSA,B_AES_128, T);
+ add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+ 0xC00A, --p, K_ECDHE_ECDSA,B_AES_256, T);
+ add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+ 0xC011, --p, K_ECDHE_RSA, B_RC4_128, N);
+ add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+ 0xC013, --p, K_ECDHE_RSA, B_AES_128, T);
+ add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+ 0xC014, --p, K_ECDHE_RSA, B_AES_256, T);
-add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA", 0x0033, --p, K_DHE_RSA, B_AES_128, T);
-add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA", 0x0039, --p, K_DHE_RSA, B_AES_256, T);
-add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA", 0x0032, --p, K_DHE_DSS, B_AES_128, T);
-add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA", 0x0038, --p, K_DHE_DSS, B_AES_256, T);
+ add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ 0x0033, --p, K_DHE_RSA, B_AES_128, T);
+ add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+ 0x0039, --p, K_DHE_RSA, B_AES_256, T);
+ add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+ 0x0032, --p, K_DHE_DSS, B_AES_128, T);
+ add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
+ 0x0038, --p, K_DHE_DSS, B_AES_256, T);
-add("SSL_RSA_WITH_3DES_EDE_CBC_SHA", 0x000a, --p, K_RSA, B_3DES, T);
-add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", 0xC003, --p, K_ECDH_ECDSA, B_3DES, T);
-add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", 0xC00D, --p, K_ECDH_RSA, B_3DES, T);
-add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", 0xC008, --p, K_ECDHE_ECDSA,B_3DES, T);
-add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", 0xC012, --p, K_ECDHE_RSA, B_3DES, T);
-add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", 0x0016, --p, K_DHE_RSA, B_3DES, T);
-add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", 0x0013, --p, K_DHE_DSS, B_3DES, N);
+ add("SSL_RSA_WITH_3DES_EDE_CBC_SHA",
+ 0x000a, --p, K_RSA, B_3DES, T);
+ add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ 0xC003, --p, K_ECDH_ECDSA, B_3DES, T);
+ add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
+ 0xC00D, --p, K_ECDH_RSA, B_3DES, T);
+ add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ 0xC008, --p, K_ECDHE_ECDSA,B_3DES, T);
+ add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ 0xC012, --p, K_ECDHE_RSA, B_3DES, T);
+ add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ 0x0016, --p, K_DHE_RSA, B_3DES, T);
+ add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+ 0x0013, --p, K_DHE_DSS, B_3DES, N);
-add("SSL_RSA_WITH_DES_CBC_SHA", 0x0009, --p, K_RSA, B_DES, N);
-add("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0015, --p, K_DHE_RSA, B_DES, N);
-add("SSL_DHE_DSS_WITH_DES_CBC_SHA", 0x0012, --p, K_DHE_DSS, B_DES, N);
-add("SSL_RSA_EXPORT_WITH_RC4_40_MD5", 0x0003, --p, K_RSA_EXPORT, B_RC4_40, N);
-add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x0008, --p, K_RSA_EXPORT, B_DES_40, N);
-add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x0014, --p, K_DHE_RSA, B_DES_40, N);
-add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x0011, --p, K_DHE_DSS, B_DES_40, N);
+ add("SSL_RSA_WITH_DES_CBC_SHA",
+ 0x0009, --p, K_RSA, B_DES, N);
+ add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
+ 0x0015, --p, K_DHE_RSA, B_DES, N);
+ add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
+ 0x0012, --p, K_DHE_DSS, B_DES, N);
+ add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+ 0x0003, --p, K_RSA_EXPORT, B_RC4_40, N);
+ add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ 0x0008, --p, K_RSA_EXPORT, B_DES_40, N);
+ add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ 0x0014, --p, K_DHE_RSA, B_DES_40, N);
+ add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ 0x0011, --p, K_DHE_DSS, B_DES_40, N);
+
+ // Renegotiation protection request Signalling Cipher Suite Value (SCSV)
+ add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
+ 0x00ff, --p, K_SCSV, B_NULL, T);
// Definition of the CipherSuites that are supported but not enabled
// by default.
// They are listed in preference order, preferred first.
p = DEFAULT_SUITES_PRIORITY;
-// Anonymous key exchange and the NULL ciphers
-add("SSL_RSA_WITH_NULL_MD5", 0x0001, --p, K_RSA, B_NULL, N);
-add("SSL_RSA_WITH_NULL_SHA", 0x0002, --p, K_RSA, B_NULL, N);
-add("TLS_ECDH_ECDSA_WITH_NULL_SHA", 0xC001, --p, K_ECDH_ECDSA, B_NULL, N);
-add("TLS_ECDH_RSA_WITH_NULL_SHA", 0xC00B, --p, K_ECDH_RSA, B_NULL, N);
-add("TLS_ECDHE_ECDSA_WITH_NULL_SHA", 0xC006, --p, K_ECDHE_ECDSA,B_NULL, N);
-add("TLS_ECDHE_RSA_WITH_NULL_SHA", 0xC010, --p, K_ECDHE_RSA, B_NULL, N);
+ // Anonymous key exchange and the NULL ciphers
+ add("SSL_RSA_WITH_NULL_MD5",
+ 0x0001, --p, K_RSA, B_NULL, N);
+ add("SSL_RSA_WITH_NULL_SHA",
+ 0x0002, --p, K_RSA, B_NULL, N);
+ add("TLS_ECDH_ECDSA_WITH_NULL_SHA",
+ 0xC001, --p, K_ECDH_ECDSA, B_NULL, N);
+ add("TLS_ECDH_RSA_WITH_NULL_SHA",
+ 0xC00B, --p, K_ECDH_RSA, B_NULL, N);
+ add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
+ 0xC006, --p, K_ECDHE_ECDSA,B_NULL, N);
+ add("TLS_ECDHE_RSA_WITH_NULL_SHA",
+ 0xC010, --p, K_ECDHE_RSA, B_NULL, N);
-add("SSL_DH_anon_WITH_RC4_128_MD5", 0x0018, --p, K_DH_ANON, B_RC4_128, N);
-add("TLS_DH_anon_WITH_AES_128_CBC_SHA", 0x0034, --p, K_DH_ANON, B_AES_128, N);
-add("TLS_DH_anon_WITH_AES_256_CBC_SHA", 0x003a, --p, K_DH_ANON, B_AES_256, N);
-add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", 0x001b, --p, K_DH_ANON, B_3DES, N);
-add("SSL_DH_anon_WITH_DES_CBC_SHA", 0x001a, --p, K_DH_ANON, B_DES, N);
+ add("SSL_DH_anon_WITH_RC4_128_MD5",
+ 0x0018, --p, K_DH_ANON, B_RC4_128, N);
+ add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
+ 0x0034, --p, K_DH_ANON, B_AES_128, N);
+ add("TLS_DH_anon_WITH_AES_256_CBC_SHA",
+ 0x003a, --p, K_DH_ANON, B_AES_256, N);
+ add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
+ 0x001b, --p, K_DH_ANON, B_3DES, N);
+ add("SSL_DH_anon_WITH_DES_CBC_SHA",
+ 0x001a, --p, K_DH_ANON, B_DES, N);
-add("TLS_ECDH_anon_WITH_RC4_128_SHA", 0xC016, --p, K_ECDH_ANON, B_RC4_128, N);
-add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA", 0xC018, --p, K_ECDH_ANON, B_AES_128, T);
-add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA", 0xC019, --p, K_ECDH_ANON, B_AES_256, T);
-add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", 0xC017, --p, K_ECDH_ANON, B_3DES, T);
+ add("TLS_ECDH_anon_WITH_RC4_128_SHA",
+ 0xC016, --p, K_ECDH_ANON, B_RC4_128, N);
+ add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
+ 0xC018, --p, K_ECDH_ANON, B_AES_128, T);
+ add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
+ 0xC019, --p, K_ECDH_ANON, B_AES_256, T);
+ add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
+ 0xC017, --p, K_ECDH_ANON, B_3DES, T);
-add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", 0x0017, --p, K_DH_ANON, B_RC4_40, N);
-add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", 0x0019, --p, K_DH_ANON, B_DES_40, N);
+ add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
+ 0x0017, --p, K_DH_ANON, B_RC4_40, N);
+ add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+ 0x0019, --p, K_DH_ANON, B_DES_40, N);
-add("TLS_ECDH_anon_WITH_NULL_SHA", 0xC015, --p, K_ECDH_ANON, B_NULL, N);
+ add("TLS_ECDH_anon_WITH_NULL_SHA",
+ 0xC015, --p, K_ECDH_ANON, B_NULL, N);
-// Supported Kerberos ciphersuites from RFC2712
-add("TLS_KRB5_WITH_RC4_128_SHA", 0x0020, --p, K_KRB5, B_RC4_128, N);
-add("TLS_KRB5_WITH_RC4_128_MD5", 0x0024, --p, K_KRB5, B_RC4_128, N);
-add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA", 0x001f, --p, K_KRB5, B_3DES, N);
-add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5", 0x0023, --p, K_KRB5, B_3DES, N);
-add("TLS_KRB5_WITH_DES_CBC_SHA", 0x001e, --p, K_KRB5, B_DES, N);
-add("TLS_KRB5_WITH_DES_CBC_MD5", 0x0022, --p, K_KRB5, B_DES, N);
-add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA", 0x0028, --p, K_KRB5_EXPORT, B_RC4_40, N);
-add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5", 0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N);
-add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", 0x0026, --p, K_KRB5_EXPORT, B_DES_40, N);
-add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", 0x0029, --p, K_KRB5_EXPORT, B_DES_40, N);
-
+ // Supported Kerberos ciphersuites from RFC2712
+ add("TLS_KRB5_WITH_RC4_128_SHA",
+ 0x0020, --p, K_KRB5, B_RC4_128, N);
+ add("TLS_KRB5_WITH_RC4_128_MD5",
+ 0x0024, --p, K_KRB5, B_RC4_128, N);
+ add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
+ 0x001f, --p, K_KRB5, B_3DES, N);
+ add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
+ 0x0023, --p, K_KRB5, B_3DES, N);
+ add("TLS_KRB5_WITH_DES_CBC_SHA",
+ 0x001e, --p, K_KRB5, B_DES, N);
+ add("TLS_KRB5_WITH_DES_CBC_MD5",
+ 0x0022, --p, K_KRB5, B_DES, N);
+ add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
+ 0x0028, --p, K_KRB5_EXPORT, B_RC4_40, N);
+ add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
+ 0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N);
+ add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
+ 0x0026, --p, K_KRB5_EXPORT, B_DES_40, N);
+ add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
+ 0x0029, --p, K_KRB5_EXPORT, B_DES_40, N);
// Register the names of a few additional CipherSuites.
// Makes them show up as names instead of numbers in
@@ -618,4 +706,6 @@
// ciphersuite SSL_NULL_WITH_NULL_NULL
final static CipherSuite C_NULL = CipherSuite.valueOf(0, 0);
+ // ciphersuite TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+ final static CipherSuite C_SCSV = CipherSuite.valueOf(0x00, 0xff);
}
--- a/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,8 +51,9 @@
// null if not yet checked.
private volatile Boolean containsEC;
- // for use by buildAvailableCache() only
- private CipherSuiteList(Collection<CipherSuite> cipherSuites) {
+ // for use by buildAvailableCache() and
+ // Handshaker.getKickstartMessage() only
+ CipherSuiteList(Collection<CipherSuite> cipherSuites) {
this.cipherSuites = cipherSuites;
}
@@ -221,15 +222,18 @@
// SortedSet automatically arranges ciphersuites in default
// preference order
Set<CipherSuite> cipherSuites = new TreeSet<CipherSuite>();
- Collection<CipherSuite> allowedCipherSuites = CipherSuite.allowedCipherSuites();
+ Collection<CipherSuite> allowedCipherSuites =
+ CipherSuite.allowedCipherSuites();
for (CipherSuite c : allowedCipherSuites) {
if ((c.allowed == false) || (c.priority < minPriority)) {
continue;
}
+
if (c.isAvailable()) {
cipherSuites.add(c);
}
}
+
return new CipherSuiteList(cipherSuites);
}
--- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -94,16 +94,24 @@
*/
ClientHandshaker(SSLSocketImpl socket, SSLContextImpl context,
ProtocolList enabledProtocols,
- ProtocolVersion activeProtocolVersion) {
- super(socket, context, enabledProtocols, true, true);
- this.activeProtocolVersion = activeProtocolVersion;
+ ProtocolVersion activeProtocolVersion,
+ boolean isInitialHandshake, boolean secureRenegotiation,
+ byte[] clientVerifyData, byte[] serverVerifyData) {
+
+ super(socket, context, enabledProtocols, true, true,
+ activeProtocolVersion, isInitialHandshake, secureRenegotiation,
+ clientVerifyData, serverVerifyData);
}
ClientHandshaker(SSLEngineImpl engine, SSLContextImpl context,
ProtocolList enabledProtocols,
- ProtocolVersion activeProtocolVersion) {
- super(engine, context, enabledProtocols, true, true);
- this.activeProtocolVersion = activeProtocolVersion;
+ ProtocolVersion activeProtocolVersion,
+ boolean isInitialHandshake, boolean secureRenegotiation,
+ byte[] clientVerifyData, byte[] serverVerifyData) {
+
+ super(engine, context, enabledProtocols, true, true,
+ activeProtocolVersion, isInitialHandshake, secureRenegotiation,
+ clientVerifyData, serverVerifyData);
}
/*
@@ -279,10 +287,11 @@
// sent the "client hello" but the server's not seen it.
//
if (state < HandshakeMessage.ht_client_hello) {
- if (!renegotiable) { // renegotiation is not allowed.
+ if (!secureRenegotiation && !allowUnsafeRenegotiation) {
+ // renegotiation is not allowed.
if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
- // response with a no_negotiation warning,
- warningSE(Alerts.alert_no_negotiation);
+ // response with a no_renegotiation warning,
+ warningSE(Alerts.alert_no_renegotiation);
// invalidate the handshake so that the caller can
// dispose this object.
@@ -293,26 +302,24 @@
// and the next handshake message will become incomplete.
//
// However, according to SSL/TLS specifications, no more
- // handshake message could immediately follow ClientHello
- // or HelloRequest. But in case of any improper messages,
- // we'd better check to ensure there is no remaining bytes
- // in the handshake input stream.
- if (input.available() > 0) {
- fatalSE(Alerts.alert_unexpected_message,
- "HelloRequest followed by an unexpected " +
- "handshake message");
- }
-
+ // handshake message should immediately follow ClientHello
+ // or HelloRequest. So just let it be.
} else {
// For SSLv3, send the handshake_failure fatal error.
- // Note that SSLv3 does not define a no_negotiation alert
- // like TLSv1. However we cannot ignore the message
+ // Note that SSLv3 does not define a no_renegotiation
+ // alert like TLSv1. However we cannot ignore the message
// simply, otherwise the other side was waiting for a
// response that would never come.
fatalSE(Alerts.alert_handshake_failure,
- "renegotiation is not allowed");
+ "Renegotiation is not allowed");
}
} else {
+ if (!secureRenegotiation) {
+ if (debug != null && Debug.isOn("handshake")) {
+ System.out.println(
+ "Warning: continue with insecure renegotiation");
+ }
+ }
kickstart();
}
}
@@ -347,6 +354,68 @@
// Handshake streams
setVersion(mesgVersion);
+ // check the "renegotiation_info" extension
+ RenegotiationInfoExtension serverHelloRI = (RenegotiationInfoExtension)
+ mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
+ if (serverHelloRI != null) {
+ if (isInitialHandshake) {
+ // verify the length of the "renegotiated_connection" field
+ if (!serverHelloRI.isEmpty()) {
+ // abort the handshake with a fatal handshake_failure alert
+ fatalSE(Alerts.alert_handshake_failure,
+ "The renegotiation_info field is not empty");
+ }
+
+ secureRenegotiation = true;
+ } else {
+ // For a legacy renegotiation, the client MUST verify that
+ // it does not contain the "renegotiation_info" extension.
+ if (!secureRenegotiation) {
+ fatalSE(Alerts.alert_handshake_failure,
+ "Unexpected renegotiation indication extension");
+ }
+
+ // verify the client_verify_data and server_verify_data values
+ byte[] verifyData =
+ new byte[clientVerifyData.length + serverVerifyData.length];
+ System.arraycopy(clientVerifyData, 0, verifyData,
+ 0, clientVerifyData.length);
+ System.arraycopy(serverVerifyData, 0, verifyData,
+ clientVerifyData.length, serverVerifyData.length);
+ if (!Arrays.equals(verifyData,
+ serverHelloRI.getRenegotiatedConnection())) {
+ fatalSE(Alerts.alert_handshake_failure,
+ "Incorrect verify data in ServerHello " +
+ "renegotiation_info message");
+ }
+ }
+ } else {
+ // no renegotiation indication extension
+ if (isInitialHandshake) {
+ if (!allowLegacyHelloMessages) {
+ // abort the handshake with a fatal handshake_failure alert
+ fatalSE(Alerts.alert_handshake_failure,
+ "Failed to negotiate the use of secure renegotiation");
+ }
+
+ secureRenegotiation = false;
+ if (debug != null && Debug.isOn("handshake")) {
+ System.out.println("Warning: No renegotiation " +
+ "indication extension in ServerHello");
+ }
+ } else {
+ // For a secure renegotiation, the client must abort the
+ // handshake if no "renegotiation_info" extension is present.
+ if (secureRenegotiation) {
+ fatalSE(Alerts.alert_handshake_failure,
+ "No renegotiation indication extension");
+ }
+
+ // we have already allowed unsafe renegotation before request
+ // the renegotiation.
+ }
+ }
+
//
// Save server nonce, we always use it to compute connection
// keys and it's also used to create the master secret if we're
@@ -354,10 +423,11 @@
//
svr_random = mesg.svr_random;
- if (isEnabled(mesg.cipherSuite) == false) {
+ if (isNegotiable(mesg.cipherSuite) == false) {
fatalSE(Alerts.alert_illegal_parameter,
- "Server selected disabled ciphersuite " + cipherSuite);
+ "Server selected improper ciphersuite " + cipherSuite);
}
+
setCipherSuite(mesg.cipherSuite);
if (mesg.compression_method != 0) {
@@ -452,7 +522,8 @@
for (HelloExtension ext : mesg.extensions.list()) {
ExtensionType type = ext.type;
if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
- && (type != ExtensionType.EXT_EC_POINT_FORMATS)) {
+ && (type != ExtensionType.EXT_EC_POINT_FORMATS)
+ && (type != ExtensionType.EXT_RENEGOTIATION_INFO)) {
fatalSE(Alerts.alert_unsupported_extension,
"Server sent an unsupported extension: " + type);
}
@@ -869,6 +940,13 @@
}
/*
+ * save server verify data for secure renegotiation
+ */
+ if (secureRenegotiation) {
+ serverVerifyData = mesg.getVerifyData();
+ }
+
+ /*
* OK, it verified. If we're doing the fast handshake, add that
* "Finished" message to the hash of handshake messages, then send
* our own change_cipher_spec and Finished message for the server
@@ -921,6 +999,13 @@
sendChangeCipherSpec(mesg, finishedTag);
/*
+ * save client verify data for secure renegotiation
+ */
+ if (secureRenegotiation) {
+ clientVerifyData = mesg.getVerifyData();
+ }
+
+ /*
* Update state machine so server MUST send 'finished' next.
* (In "long" handshake case; in short case, we're responding
* to its message.)
@@ -933,12 +1018,15 @@
* Returns a ClientHello message to kickstart renegotiations
*/
HandshakeMessage getKickstartMessage() throws SSLException {
- ClientHello mesg = new ClientHello(sslContext.getSecureRandom(),
- protocolVersion);
+ // session ID of the ClientHello message
+ SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
+
+ // a list of cipher suites sent by the client
+ CipherSuiteList cipherSuites = enabledCipherSuites;
+
+ // set the max protocol version this client is supporting.
maxProtocolVersion = protocolVersion;
- clnt_random = mesg.clnt_random;
-
//
// Try to resume an existing session. This might be mandatory,
// given certain API options.
@@ -962,9 +1050,9 @@
if (session != null) {
CipherSuite sessionSuite = session.getSuite();
ProtocolVersion sessionVersion = session.getProtocolVersion();
- if (isEnabled(sessionSuite) == false) {
+ if (isNegotiable(sessionSuite) == false) {
if (debug != null && Debug.isOn("session")) {
- System.out.println("%% can't resume, cipher disabled");
+ System.out.println("%% can't resume, unavailable cipher");
}
session = null;
}
@@ -984,9 +1072,8 @@
+ " from port " + getLocalPortSE());
}
}
- mesg.sessionId = session.getSessionId();
- mesg.protocolVersion = sessionVersion;
+ sessionId = session.getSessionId();
maxProtocolVersion = sessionVersion;
// Update SSL version number in underlying SSL socket and
@@ -995,33 +1082,78 @@
setVersion(sessionVersion);
}
- //
- // don't say much beyond the obvious if we _must_ resume.
- //
+ /*
+ * Force use of the previous session ciphersuite, and
+ * add the SCSV if enabled.
+ */
if (!enableNewSession) {
if (session == null) {
throw new SSLException(
"Can't reuse existing SSL client session");
}
- mesg.setCipherSuites(new CipherSuiteList(sessionSuite));
- return mesg;
- }
- }
- if (session == null) {
- if (enableNewSession) {
- mesg.sessionId = SSLSessionImpl.nullSession.getSessionId();
- } else {
- throw new SSLException("No existing session to resume.");
+
+ Collection<CipherSuite> cipherList =
+ new ArrayList<CipherSuite>(2);
+ cipherList.add(sessionSuite);
+ if (!secureRenegotiation &&
+ cipherSuites.contains(CipherSuite.C_SCSV)) {
+ cipherList.add(CipherSuite.C_SCSV);
+ } // otherwise, renegotiation_info extension will be used
+
+ cipherSuites = new CipherSuiteList(cipherList);
}
}
- //
- // All we have left to do is fill out the cipher suites.
- // (If this changes, change the 'return' above!)
- //
- mesg.setCipherSuites(enabledCipherSuites);
+ if (session == null && !enableNewSession) {
+ throw new SSLException("No existing session to resume");
+ }
+
+ // exclude SCSV for secure renegotiation
+ if (secureRenegotiation && cipherSuites.contains(CipherSuite.C_SCSV)) {
+ Collection<CipherSuite> cipherList =
+ new ArrayList<CipherSuite>(cipherSuites.size() - 1);
+ for (CipherSuite suite : cipherSuites.collection()) {
+ if (suite != CipherSuite.C_SCSV) {
+ cipherList.add(suite);
+ }
+ }
+
+ cipherSuites = new CipherSuiteList(cipherList);
+ }
- return mesg;
+ // make sure there is a negotiable cipher suite.
+ boolean negotiable = false;
+ for (CipherSuite suite : cipherSuites.collection()) {
+ if (isNegotiable(suite)) {
+ negotiable = true;
+ break;
+ }
+ }
+
+ if (!negotiable) {
+ throw new SSLException("No negotiable cipher suite");
+ }
+
+ // create the ClientHello message
+ ClientHello clientHelloMessage = new ClientHello(
+ sslContext.getSecureRandom(), maxProtocolVersion,
+ sessionId, cipherSuites);
+
+ // reset the client random cookie
+ clnt_random = clientHelloMessage.clnt_random;
+
+ /*
+ * need to set the renegotiation_info extension for:
+ * 1: secure renegotiation
+ * 2: initial handshake and no SCSV in the ClientHello
+ * 3: insecure renegotiation and no SCSV in the ClientHello
+ */
+ if (secureRenegotiation ||
+ !cipherSuites.contains(CipherSuite.C_SCSV)) {
+ clientHelloMessage.addRenegotiationInfoExtension(clientVerifyData);
+ }
+
+ return clientHelloMessage;
}
/*
--- a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -172,9 +172,7 @@
* Server can ask the client to initiate a new handshake, e.g. to change
* session parameters after a connection has been (re)established.
*/
-static final
-class HelloRequest extends HandshakeMessage
-{
+static final class HelloRequest extends HandshakeMessage {
int messageType() { return ht_hello_request; }
HelloRequest() { }
@@ -210,10 +208,7 @@
* Until we know how to parse it, we will just read what we know
* about, and let our caller handle the jumps over unknown data.
*/
-static final
-class ClientHello extends HandshakeMessage
-{
- int messageType() { return ht_client_hello; }
+static final class ClientHello extends HandshakeMessage {
ProtocolVersion protocolVersion;
RandomCookie clnt_random;
@@ -225,37 +220,20 @@
private final static byte[] NULL_COMPRESSION = new byte[] {0};
- ClientHello(SecureRandom generator, ProtocolVersion protocolVersion) {
- this.protocolVersion = protocolVersion;
- clnt_random = new RandomCookie(generator);
- compression_methods = NULL_COMPRESSION;
- // sessionId, cipher_suites TBS later
- }
+ ClientHello(SecureRandom generator, ProtocolVersion protocolVersion,
+ SessionId sessionId, CipherSuiteList cipherSuites) {
- CipherSuiteList getCipherSuites() {
- return cipherSuites;
- }
+ this.protocolVersion = protocolVersion;
+ this.sessionId = sessionId;
+ this.cipherSuites = cipherSuites;
- // Set the ciphersuites.
- // This method may only be called once.
- void setCipherSuites(CipherSuiteList cipherSuites) {
- this.cipherSuites = cipherSuites;
if (cipherSuites.containsEC()) {
extensions.add(SupportedEllipticCurvesExtension.DEFAULT);
extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
}
- }
- int messageLength() {
- /*
- * Add fixed size parts of each field...
- * version + random + session + cipher + compress
- */
- return (2 + 32 + 1 + 2 + 1
- + sessionId.length() /* ... + variable parts */
- + (cipherSuites.size() * 2)
- + compression_methods.length)
- + extensions.length();
+ clnt_random = new RandomCookie(generator);
+ compression_methods = NULL_COMPRESSION;
}
ClientHello(HandshakeInStream s, int messageLength) throws IOException {
@@ -269,6 +247,34 @@
}
}
+ CipherSuiteList getCipherSuites() {
+ return cipherSuites;
+ }
+
+ // add renegotiation_info extension
+ void addRenegotiationInfoExtension(byte[] clientVerifyData) {
+ HelloExtension renegotiationInfo = new RenegotiationInfoExtension(
+ clientVerifyData, new byte[0]);
+ extensions.add(renegotiationInfo);
+ }
+
+ @Override
+ int messageType() { return ht_client_hello; }
+
+ @Override
+ int messageLength() {
+ /*
+ * Add fixed size parts of each field...
+ * version + random + session + cipher + compress
+ */
+ return (2 + 32 + 1 + 2 + 1
+ + sessionId.length() /* ... + variable parts */
+ + (cipherSuites.size() * 2)
+ + compression_methods.length)
+ + extensions.length();
+ }
+
+ @Override
void send(HandshakeOutStream s) throws IOException {
s.putInt8(protocolVersion.major);
s.putInt8(protocolVersion.minor);
@@ -279,6 +285,7 @@
extensions.send(s);
}
+ @Override
void print(PrintStream s) throws IOException {
s.println("*** ClientHello, " + protocolVersion);
@@ -315,7 +322,6 @@
CipherSuite cipherSuite;
byte compression_method;
HelloExtensions extensions = new HelloExtensions();
- int extensionLength;
ServerHello() {
// empty
@@ -1425,8 +1431,6 @@
*/
static final class Finished extends HandshakeMessage {
- int messageType() { return ht_finished; }
-
// constant for a Finished message sent by the client
final static int CLIENT = 1;
@@ -1468,7 +1472,7 @@
* both client and server are fully in sync, and that the handshake
* computations have been successful.
*/
- boolean verify(ProtocolVersion protocolVersion,
+ boolean verify(ProtocolVersion protocolVersion,
HandshakeHash handshakeHash, int sender, SecretKey master) {
byte[] myFinished = getFinished(protocolVersion, handshakeHash,
sender, master);
@@ -1542,14 +1546,25 @@
CertificateVerify.updateDigest(md, pad1, pad2, masterSecret);
}
+ // get the verify_data of the finished message
+ byte[] getVerifyData() {
+ return verifyData;
+ }
+
+ @Override
+ int messageType() { return ht_finished; }
+
+ @Override
int messageLength() {
return verifyData.length;
}
+ @Override
void send(HandshakeOutStream out) throws IOException {
out.write(verifyData);
}
+ @Override
void print(PrintStream s) throws IOException {
s.println("*** Finished");
if (debug != null && Debug.isOn("verbose")) {
@@ -1557,7 +1572,6 @@
s.println("***");
}
}
-
}
//
--- a/jdk/src/share/classes/sun/security/ssl/Handshaker.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/Handshaker.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -66,6 +66,14 @@
// the currently active protocol version during a renegotiation
ProtocolVersion activeProtocolVersion;
+ // security parameters for secure renegotiation.
+ boolean secureRenegotiation;
+ byte[] clientVerifyData;
+ byte[] serverVerifyData;
+
+ // is it an initial negotiation or a renegotiation?
+ boolean isInitialHandshake;
+
// list of enabled protocols
ProtocolList enabledProtocols;
@@ -128,31 +136,66 @@
static final Debug debug = Debug.getInstance("ssl");
// By default, disable the unsafe legacy session renegotiation
- static final boolean renegotiable = Debug.getBooleanProperty(
+ static final boolean allowUnsafeRenegotiation = Debug.getBooleanProperty(
"sun.security.ssl.allowUnsafeRenegotiation", false);
+ // For maximum interoperability and backward compatibility, RFC 5746
+ // allows server (or client) to accept ClientHello (or ServerHello)
+ // message without the secure renegotiation_info extension or SCSV.
+ //
+ // For maximum security, RFC 5746 also allows server (or client) to
+ // reject such message with a fatal "handshake_failure" alert.
+ //
+ // By default, allow such legacy hello messages.
+ static final boolean allowLegacyHelloMessages = Debug.getBooleanProperty(
+ "sun.security.ssl.allowLegacyHelloMessages", true);
+
// need to dispose the object when it is invalidated
boolean invalidated;
Handshaker(SSLSocketImpl c, SSLContextImpl context,
ProtocolList enabledProtocols, boolean needCertVerify,
- boolean isClient) {
+ boolean isClient, ProtocolVersion activeProtocolVersion,
+ boolean isInitialHandshake, boolean secureRenegotiation,
+ byte[] clientVerifyData, byte[] serverVerifyData) {
this.conn = c;
- init(context, enabledProtocols, needCertVerify, isClient);
+ init(context, enabledProtocols, needCertVerify, isClient,
+ activeProtocolVersion, isInitialHandshake, secureRenegotiation,
+ clientVerifyData, serverVerifyData);
}
Handshaker(SSLEngineImpl engine, SSLContextImpl context,
ProtocolList enabledProtocols, boolean needCertVerify,
- boolean isClient) {
+ boolean isClient, ProtocolVersion activeProtocolVersion,
+ boolean isInitialHandshake, boolean secureRenegotiation,
+ byte[] clientVerifyData, byte[] serverVerifyData) {
this.engine = engine;
- init(context, enabledProtocols, needCertVerify, isClient);
+ init(context, enabledProtocols, needCertVerify, isClient,
+ activeProtocolVersion, isInitialHandshake, secureRenegotiation,
+ clientVerifyData, serverVerifyData);
}
private void init(SSLContextImpl context, ProtocolList enabledProtocols,
- boolean needCertVerify, boolean isClient) {
+ boolean needCertVerify, boolean isClient,
+ ProtocolVersion activeProtocolVersion,
+ boolean isInitialHandshake, boolean secureRenegotiation,
+ byte[] clientVerifyData, byte[] serverVerifyData) {
+
+ if (debug != null && Debug.isOn("handshake")) {
+ System.out.println(
+ "Allow unsafe renegotiation: " + allowUnsafeRenegotiation +
+ "\nAllow legacy hello messages: " + allowLegacyHelloMessages +
+ "\nIs initial handshake: " + isInitialHandshake +
+ "\nIs secure renegotiation: " + secureRenegotiation);
+ }
this.sslContext = context;
this.isClient = isClient;
+ this.activeProtocolVersion = activeProtocolVersion;
+ this.isInitialHandshake = isInitialHandshake;
+ this.secureRenegotiation = secureRenegotiation;
+ this.clientVerifyData = clientVerifyData;
+ this.serverVerifyData = serverVerifyData;
enableNewSession = true;
invalidated = false;
@@ -353,8 +396,8 @@
* changed due to change in JCE providers since it was enabled).
* Does not check if the required server certificates are available.
*/
- boolean isEnabled(CipherSuite s) {
- return enabledCipherSuites.contains(s) && s.isAvailable();
+ boolean isNegotiable(CipherSuite s) {
+ return enabledCipherSuites.contains(s) && s.isNegotiable();
}
/**
@@ -459,6 +502,27 @@
}
/*
+ * Returns true if renegotiation is in use for this connection.
+ */
+ boolean isSecureRenegotiation() {
+ return secureRenegotiation;
+ }
+
+ /*
+ * Returns the verify_data from the Finished message sent by the client.
+ */
+ byte[] getClientVerifyData() {
+ return clientVerifyData;
+ }
+
+ /*
+ * Returns the verify_data from the Finished message sent by the server.
+ */
+ byte[] getServerVerifyData() {
+ return serverVerifyData;
+ }
+
+ /*
* This routine is fed SSL handshake records when they become available,
* and processes messages found therein.
*/
--- a/jdk/src/share/classes/sun/security/ssl/HelloExtensions.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/HelloExtensions.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -81,7 +81,10 @@
} else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) {
extension = new SupportedEllipticCurvesExtension(s, extlen);
} else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
- extension = new SupportedEllipticPointFormatsExtension(s, extlen);
+ extension =
+ new SupportedEllipticPointFormatsExtension(s, extlen);
+ } else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) {
+ extension = new RenegotiationInfoExtension(s, extlen);
} else {
extension = new UnknownExtension(s, extlen, extType);
}
@@ -89,7 +92,8 @@
len -= extlen + 4;
}
if (len != 0) {
- throw new SSLProtocolException("Error parsing extensions: extra data");
+ throw new SSLProtocolException(
+ "Error parsing extensions: extra data");
}
}
@@ -162,7 +166,8 @@
return name;
}
- static List<ExtensionType> knownExtensions = new ArrayList<ExtensionType>(8);
+ static List<ExtensionType> knownExtensions =
+ new ArrayList<ExtensionType>(9);
static ExtensionType get(int id) {
for (ExtensionType ext : knownExtensions) {
@@ -180,17 +185,44 @@
}
// extensions defined in RFC 3546
- final static ExtensionType EXT_SERVER_NAME = e( 0, "server_name");
- final static ExtensionType EXT_MAX_FRAGMENT_LENGTH = e( 1, "max_fragment_length");
- final static ExtensionType EXT_CLIENT_CERTIFICATE_URL = e( 2, "client_certificate_url");
- final static ExtensionType EXT_TRUSTED_CA_KEYS = e( 3, "trusted_ca_keys");
- final static ExtensionType EXT_TRUNCATED_HMAC = e( 4, "truncated_hmac");
- final static ExtensionType EXT_STATUS_REQUEST = e( 5, "status_request");
+ final static ExtensionType EXT_SERVER_NAME =
+ e(0x0000, "server_name"); // IANA registry value: 0
+ final static ExtensionType EXT_MAX_FRAGMENT_LENGTH =
+ e(0x0001, "max_fragment_length"); // IANA registry value: 1
+ final static ExtensionType EXT_CLIENT_CERTIFICATE_URL =
+ e(0x0002, "client_certificate_url"); // IANA registry value: 2
+ final static ExtensionType EXT_TRUSTED_CA_KEYS =
+ e(0x0003, "trusted_ca_keys"); // IANA registry value: 3
+ final static ExtensionType EXT_TRUNCATED_HMAC =
+ e(0x0004, "truncated_hmac"); // IANA registry value: 4
+ final static ExtensionType EXT_STATUS_REQUEST =
+ e(0x0005, "status_request"); // IANA registry value: 5
+
+ // extensions defined in RFC 4681
+ final static ExtensionType EXT_USER_MAPPING =
+ e(0x0006, "user_mapping"); // IANA registry value: 6
+
+ // extensions defined in RFC 5081
+ final static ExtensionType EXT_CERT_TYPE =
+ e(0x0009, "cert_type"); // IANA registry value: 9
// extensions defined in RFC 4492 (ECC)
- final static ExtensionType EXT_ELLIPTIC_CURVES = e(10, "elliptic_curves");
- final static ExtensionType EXT_EC_POINT_FORMATS = e(11, "ec_point_formats");
+ final static ExtensionType EXT_ELLIPTIC_CURVES =
+ e(0x000A, "elliptic_curves"); // IANA registry value: 10
+ final static ExtensionType EXT_EC_POINT_FORMATS =
+ e(0x000B, "ec_point_formats"); // IANA registry value: 11
+ // extensions defined in RFC 5054
+ final static ExtensionType EXT_SRP =
+ e(0x000C, "srp"); // IANA registry value: 12
+
+ // extensions defined in RFC 5246
+ final static ExtensionType EXT_SIGNATURE_ALGORITHMS =
+ e(0x000D, "signature_algorithms"); // IANA registry value: 13
+
+ // extensions defined in RFC 5746
+ final static ExtensionType EXT_RENEGOTIATION_INFO =
+ e(0xff01, "renegotiation_info"); // IANA registry value: 65281
}
abstract class HelloExtension {
@@ -238,9 +270,11 @@
}
}
-// Support for the server_name extension is incomplete. Parsing is implemented
-// so that we get nicer debug output, but we neither send it nor do we do
-// act on it if we receive it.
+/*
+ * Support for the server_name extension is incomplete. Parsing is implemented
+ * so that we get nicer debug output, but we neither send it nor do we do
+ * act on it if we receive it.
+ */
final class ServerNameExtension extends HelloExtension {
final static int NAME_HOST_NAME = 0;
@@ -268,9 +302,9 @@
final String hostname;
ServerName(HandshakeInStream s) throws IOException {
- length = s.getInt16();
- type = s.getInt8();
- data = s.getBytes16();
+ length = s.getInt16(); // ServerNameList length
+ type = s.getInt8(); // NameType
+ data = s.getBytes16(); // HostName (length read in getBytes16)
if (type == NAME_HOST_NAME) {
hostname = new String(data, "UTF8");
} else {
@@ -549,3 +583,85 @@
return "Extension " + type + ", formats: " + list;
}
}
+
+/*
+ * For secure renegotiation, RFC5746 defines a new TLS extension,
+ * "renegotiation_info" (with extension type 0xff01), which contains a
+ * cryptographic binding to the enclosing TLS connection (if any) for
+ * which the renegotiation is being performed. The "extension data"
+ * field of this extension contains a "RenegotiationInfo" structure:
+ *
+ * struct {
+ * opaque renegotiated_connection<0..255>;
+ * } RenegotiationInfo;
+ */
+final class RenegotiationInfoExtension extends HelloExtension {
+ private final byte[] renegotiated_connection;
+
+ RenegotiationInfoExtension(byte[] clientVerifyData,
+ byte[] serverVerifyData) {
+ super(ExtensionType.EXT_RENEGOTIATION_INFO);
+
+ if (clientVerifyData.length != 0) {
+ renegotiated_connection =
+ new byte[clientVerifyData.length + serverVerifyData.length];
+ System.arraycopy(clientVerifyData, 0, renegotiated_connection,
+ 0, clientVerifyData.length);
+
+ if (serverVerifyData.length != 0) {
+ System.arraycopy(serverVerifyData, 0, renegotiated_connection,
+ clientVerifyData.length, serverVerifyData.length);
+ }
+ } else {
+ // ignore both the client and server verify data.
+ renegotiated_connection = new byte[0];
+ }
+ }
+
+ RenegotiationInfoExtension(HandshakeInStream s, int len)
+ throws IOException {
+ super(ExtensionType.EXT_RENEGOTIATION_INFO);
+
+ // check the extension length
+ if (len < 1) {
+ throw new SSLProtocolException("Invalid " + type + " extension");
+ }
+
+ int renegoInfoDataLen = s.getInt8();
+ if (renegoInfoDataLen + 1 != len) { // + 1 = the byte we just read
+ throw new SSLProtocolException("Invalid " + type + " extension");
+ }
+
+ renegotiated_connection = new byte[renegoInfoDataLen];
+ if (renegoInfoDataLen != 0) {
+ s.read(renegotiated_connection, 0, renegoInfoDataLen);
+ }
+ }
+
+
+ // Length of the encoded extension, including the type and length fields
+ int length() {
+ return 5 + renegotiated_connection.length;
+ }
+
+ void send(HandshakeOutStream s) throws IOException {
+ s.putInt16(type.id);
+ s.putInt16(renegotiated_connection.length + 1);
+ s.putBytes8(renegotiated_connection);
+ }
+
+ boolean isEmpty() {
+ return renegotiated_connection.length == 0;
+ }
+
+ byte[] getRenegotiatedConnection() {
+ return renegotiated_connection;
+ }
+
+ public String toString() {
+ return "Extension " + type + ", renegotiated_connection: " +
+ (renegotiated_connection.length == 0 ? "<empty>" :
+ Debug.toString(renegotiated_connection));
+ }
+
+}
--- a/jdk/src/share/classes/sun/security/ssl/OutputRecord.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/OutputRecord.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -343,6 +343,9 @@
* example, Netscape Commerce 1.0 servers. The V3 message is in the
* header and the bytes passed as parameter. This routine translates
* the V3 message into an equivalent V2 one.
+ *
+ * Note that the translation will strip off all hello extensions as
+ * SSL V2.0 does not support hello extension.
*/
private void V3toV2ClientHello(byte v3Msg []) throws SSLException {
int v3SessionIdLenOffset = 2 + 32; // version + nonce
@@ -361,12 +364,21 @@
int v3CipherSpecOffset = v3CipherSpecLenOffset + 2; // skip length
int v2CipherSpecLen = 0;
count = 11;
+ boolean containsRenegoInfoSCSV = false;
for (int i = 0; i < cipherSpecs; i++) {
byte byte1, byte2;
byte1 = v3Msg[v3CipherSpecOffset++];
byte2 = v3Msg[v3CipherSpecOffset++];
v2CipherSpecLen += V3toV2CipherSuite(byte1, byte2);
+ if (!containsRenegoInfoSCSV &&
+ byte1 == (byte)0x00 && byte2 == (byte)0xFF) {
+ containsRenegoInfoSCSV = true;
+ }
+ }
+
+ if (!containsRenegoInfoSCSV) {
+ v2CipherSpecLen += V3toV2CipherSuite((byte)0x00, (byte)0xFF);
}
/*
--- a/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -275,6 +275,12 @@
private CipherBox readCipher, writeCipher;
// NOTE: compression state would be saved here
+ /*
+ * security parameters for secure renegotiation.
+ */
+ private boolean secureRenegotiation;
+ private byte[] clientVerifyData;
+ private byte[] serverVerifyData;
/*
* READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
@@ -356,6 +362,11 @@
writeCipher = CipherBox.NULL;
writeMAC = MAC.NULL;
+ // default security parameters for secure renegotiation
+ secureRenegotiation = false;
+ clientVerifyData = new byte[0];
+ serverVerifyData = new byte[0];
+
enabledCipherSuites = CipherSuiteList.getDefault();
enabledProtocols = ProtocolList.getDefault();
@@ -434,11 +445,14 @@
}
if (roleIsServer) {
handshaker = new ServerHandshaker(this, sslContext,
- enabledProtocols, doClientAuth,
- connectionState == cs_RENEGOTIATE, protocolVersion);
+ enabledProtocols, doClientAuth,
+ protocolVersion, connectionState == cs_HANDSHAKE,
+ secureRenegotiation, clientVerifyData, serverVerifyData);
} else {
handshaker = new ClientHandshaker(this, sslContext,
- enabledProtocols, protocolVersion);
+ enabledProtocols,
+ protocolVersion, connectionState == cs_HANDSHAKE,
+ secureRenegotiation, clientVerifyData, serverVerifyData);
}
handshaker.enabledCipherSuites = enabledCipherSuites;
handshaker.setEnableSessionCreation(enableSessionCreation);
@@ -640,8 +654,16 @@
break;
case cs_DATA:
- if (!Handshaker.renegotiable) {
- throw new SSLHandshakeException("renegotiation is not allowed");
+ if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
+ throw new SSLHandshakeException(
+ "Insecure renegotiation is not allowed");
+ }
+
+ if (!secureRenegotiation) {
+ if (debug != null && Debug.isOn("handshake")) {
+ System.out.println(
+ "Warning: Using insecure renegotiation");
+ }
}
// initialize the handshaker, move to cs_RENEGOTIATE
@@ -978,6 +1000,12 @@
connectionState = cs_DATA;
}
} else if (handshaker.isDone()) {
+ // reset the parameters for secure renegotiation.
+ secureRenegotiation =
+ handshaker.isSecureRenegotiation();
+ clientVerifyData = handshaker.getClientVerifyData();
+ serverVerifyData = handshaker.getServerVerifyData();
+
sess = handshaker.getSession();
if (!writer.hasOutboundData()) {
hsStatus = HandshakeStatus.FINISHED;
--- a/jdk/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -307,8 +307,9 @@
try {
ServerHandshaker handshaker = tmp.getServerHandshaker();
- for (Iterator t = enabledCipherSuites.iterator(); t.hasNext(); ) {
- CipherSuite suite = (CipherSuite)t.next();
+ for (Iterator<CipherSuite> t = enabledCipherSuites.iterator();
+ t.hasNext();) {
+ CipherSuite suite = t.next();
if (handshaker.trySetCipherSuite(suite)) {
checkedEnabled = true;
return;
--- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -275,9 +275,9 @@
* This is necessary so that processing of close_notify alerts
* from the peer are handled properly.
*/
- private Object handshakeLock;
- ReentrantLock writeLock;
- private Object readLock;
+ final private Object handshakeLock = new Object();
+ final ReentrantLock writeLock = new ReentrantLock();
+ final private Object readLock = new Object();
private InputRecord inrec;
@@ -289,6 +289,13 @@
// NOTE: compression state would be saved here
/*
+ * security parameters for secure renegotiation.
+ */
+ private boolean secureRenegotiation;
+ private byte[] clientVerifyData;
+ private byte[] serverVerifyData;
+
+ /*
* The authentication context holds all information used to establish
* who this end of the connection is (certificate chains, private keys,
* etc) and who is trusted (e.g. as CAs or websites).
@@ -528,11 +535,13 @@
writeCipher = CipherBox.NULL;
writeMAC = MAC.NULL;
+ // initial security parameters for secure renegotiation
+ secureRenegotiation = false;
+ clientVerifyData = new byte[0];
+ serverVerifyData = new byte[0];
+
enabledCipherSuites = CipherSuiteList.getDefault();
enabledProtocols = ProtocolList.getDefault();
- handshakeLock = new Object();
- writeLock = new ReentrantLock();
- readLock = new Object();
inrec = null;
// save the acc
@@ -914,6 +923,12 @@
connectionState = cs_DATA;
}
} else if (handshaker.isDone()) {
+ // reset the parameters for secure renegotiation.
+ secureRenegotiation =
+ handshaker.isSecureRenegotiation();
+ clientVerifyData = handshaker.getClientVerifyData();
+ serverVerifyData = handshaker.getServerVerifyData();
+
sess = handshaker.getSession();
handshaker = null;
connectionState = cs_DATA;
@@ -1091,11 +1106,14 @@
}
if (roleIsServer) {
handshaker = new ServerHandshaker(this, sslContext,
- enabledProtocols, doClientAuth,
- connectionState == cs_RENEGOTIATE, protocolVersion);
+ enabledProtocols, doClientAuth,
+ protocolVersion, connectionState == cs_HANDSHAKE,
+ secureRenegotiation, clientVerifyData, serverVerifyData);
} else {
handshaker = new ClientHandshaker(this, sslContext,
- enabledProtocols, protocolVersion);
+ enabledProtocols,
+ protocolVersion, connectionState == cs_HANDSHAKE,
+ secureRenegotiation, clientVerifyData, serverVerifyData);
}
handshaker.enabledCipherSuites = enabledCipherSuites;
handshaker.setEnableSessionCreation(enableSessionCreation);
@@ -1200,8 +1218,16 @@
break;
case cs_DATA:
- if (!Handshaker.renegotiable) {
- throw new SSLHandshakeException("renegotiation is not allowed");
+ if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
+ throw new SSLHandshakeException(
+ "Insecure renegotiation is not allowed");
+ }
+
+ if (!secureRenegotiation) {
+ if (debug != null && Debug.isOn("handshake")) {
+ System.out.println(
+ "Warning: Using insecure renegotiation");
+ }
}
// initialize the handshaker, move to cs_RENEGOTIATE
--- a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -69,9 +69,6 @@
// flag to check for clientCertificateVerify message
private boolean needClientVerify = false;
- // indicate a renegotiation handshaking
- private boolean isRenegotiation = false;
-
/*
* For exportable ciphersuites using non-exportable key sizes, we use
* ephemeral RSA keys. We could also do anonymous RSA in the same way
@@ -100,13 +97,15 @@
*/
ServerHandshaker(SSLSocketImpl socket, SSLContextImpl context,
ProtocolList enabledProtocols, byte clientAuth,
- boolean isRenegotiation, ProtocolVersion activeProtocolVersion) {
+ ProtocolVersion activeProtocolVersion, boolean isInitialHandshake,
+ boolean secureRenegotiation,
+ byte[] clientVerifyData, byte[] serverVerifyData) {
super(socket, context, enabledProtocols,
- (clientAuth != SSLEngineImpl.clauth_none), false);
+ (clientAuth != SSLEngineImpl.clauth_none), false,
+ activeProtocolVersion, isInitialHandshake, secureRenegotiation,
+ clientVerifyData, serverVerifyData);
doClientAuth = clientAuth;
- this.isRenegotiation = isRenegotiation;
- this.activeProtocolVersion = activeProtocolVersion;
}
/*
@@ -114,13 +113,15 @@
*/
ServerHandshaker(SSLEngineImpl engine, SSLContextImpl context,
ProtocolList enabledProtocols, byte clientAuth,
- boolean isRenegotiation, ProtocolVersion activeProtocolVersion) {
+ ProtocolVersion activeProtocolVersion,
+ boolean isInitialHandshake, boolean secureRenegotiation,
+ byte[] clientVerifyData, byte[] serverVerifyData) {
super(engine, context, enabledProtocols,
- (clientAuth != SSLEngineImpl.clauth_none), false);
+ (clientAuth != SSLEngineImpl.clauth_none), false,
+ activeProtocolVersion, isInitialHandshake, secureRenegotiation,
+ clientVerifyData, serverVerifyData);
doClientAuth = clientAuth;
- this.isRenegotiation = isRenegotiation;
- this.activeProtocolVersion = activeProtocolVersion;
}
/*
@@ -269,41 +270,122 @@
mesg.print(System.out);
}
- // if it is a renegotiation request and renegotiation is not allowed
- if (isRenegotiation && !renegotiable) {
- if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
- // response with a no_negotiation warning,
- warningSE(Alerts.alert_no_negotiation);
+ // Does the message include security renegotiation indication?
+ boolean renegotiationIndicated = false;
- // invalidate the handshake so that the caller can
- // dispose this object.
- invalidated = true;
+ // check the TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+ CipherSuiteList cipherSuites = mesg.getCipherSuites();
+ if (cipherSuites.contains(CipherSuite.C_SCSV)) {
+ renegotiationIndicated = true;
+ if (isInitialHandshake) {
+ secureRenegotiation = true;
+ } else {
+ // abort the handshake with a fatal handshake_failure alert
+ if (secureRenegotiation) {
+ fatalSE(Alerts.alert_handshake_failure,
+ "The SCSV is present in a secure renegotiation");
+ } else {
+ fatalSE(Alerts.alert_handshake_failure,
+ "The SCSV is present in a insecure renegotiation");
+ }
+ }
+ }
- // If there is still unread block in the handshake
- // input stream, it would be truncated with the disposal
- // and the next handshake message will become incomplete.
- //
- // However, according to SSL/TLS specifications, no more
- // handshake message could immediately follow ClientHello
- // or HelloRequest. But in case of any improper messages,
- // we'd better check to ensure there is no remaining bytes
- // in the handshake input stream.
- if (input.available() > 0) {
- fatalSE(Alerts.alert_unexpected_message,
- "ClientHello followed by an unexpected " +
- "handshake message");
+ // check the "renegotiation_info" extension
+ RenegotiationInfoExtension clientHelloRI = (RenegotiationInfoExtension)
+ mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
+ if (clientHelloRI != null) {
+ renegotiationIndicated = true;
+ if (isInitialHandshake) {
+ // verify the length of the "renegotiated_connection" field
+ if (!clientHelloRI.isEmpty()) {
+ // abort the handshake with a fatal handshake_failure alert
+ fatalSE(Alerts.alert_handshake_failure,
+ "The renegotiation_info field is not empty");
+ }
+ secureRenegotiation = true;
+ } else {
+ if (!secureRenegotiation) {
+ // unexpected RI extension for insecure renegotiation,
+ // abort the handshake with a fatal handshake_failure alert
+ fatalSE(Alerts.alert_handshake_failure,
+ "The renegotiation_info is present in a insecure " +
+ "renegotiation");
}
- return;
- } else {
- // For SSLv3, send the handshake_failure fatal error.
- // Note that SSLv3 does not define a no_negotiation alert
- // like TLSv1. However we cannot ignore the message
- // simply, otherwise the other side was waiting for a
- // response that would never come.
- fatalSE(Alerts.alert_handshake_failure,
- "renegotiation is not allowed");
+ // verify the client_verify_data value
+ if (!Arrays.equals(clientVerifyData,
+ clientHelloRI.getRenegotiatedConnection())) {
+ fatalSE(Alerts.alert_handshake_failure,
+ "Incorrect verify data in ClientHello " +
+ "renegotiation_info message");
+ }
+ }
+ } else if (!isInitialHandshake && secureRenegotiation) {
+ // if the connection's "secure_renegotiation" flag is set to TRUE
+ // and the "renegotiation_info" extension is not present, abort
+ // the handshake.
+ fatalSE(Alerts.alert_handshake_failure,
+ "Inconsistent secure renegotiation indication");
+ }
+
+ // if there is no security renegotiation indication or the previous
+ // handshake is insecure.
+ if (!renegotiationIndicated || !secureRenegotiation) {
+ if (isInitialHandshake) {
+ if (!allowLegacyHelloMessages) {
+ // abort the handshake with a fatal handshake_failure alert
+ fatalSE(Alerts.alert_handshake_failure,
+ "Failed to negotiate the use of secure renegotiation");
+ }
+
+ // continue with legacy ClientHello
+ if (debug != null && Debug.isOn("handshake")) {
+ System.out.println("Warning: No renegotiation " +
+ "indication in ClientHello, allow legacy ClientHello");
+ }
+ } else if (!allowUnsafeRenegotiation) {
+ // abort the handshake
+ if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
+ // response with a no_renegotiation warning,
+ warningSE(Alerts.alert_no_renegotiation);
+
+ // invalidate the handshake so that the caller can
+ // dispose this object.
+ invalidated = true;
+
+ // If there is still unread block in the handshake
+ // input stream, it would be truncated with the disposal
+ // and the next handshake message will become incomplete.
+ //
+ // However, according to SSL/TLS specifications, no more
+ // handshake message could immediately follow ClientHello
+ // or HelloRequest. But in case of any improper messages,
+ // we'd better check to ensure there is no remaining bytes
+ // in the handshake input stream.
+ if (input.available() > 0) {
+ fatalSE(Alerts.alert_unexpected_message,
+ "ClientHello followed by an unexpected " +
+ "handshake message");
+ }
+
+ return;
+ } else {
+ // For SSLv3, send the handshake_failure fatal error.
+ // Note that SSLv3 does not define a no_renegotiation
+ // alert like TLSv1. However we cannot ignore the message
+ // simply, otherwise the other side was waiting for a
+ // response that would never come.
+ fatalSE(Alerts.alert_handshake_failure,
+ "Renegotiation is not allowed");
+ }
+ } else { // !isInitialHandshake && allowUnsafeRenegotiation
+ // continue with unsafe renegotiation.
+ if (debug != null && Debug.isOn("handshake")) {
+ System.out.println(
+ "Warning: continue with insecure renegotiation");
+ }
}
}
@@ -454,7 +536,7 @@
// verify that the ciphersuite from the cached session
// is in the list of client requested ciphersuites and
// we have it enabled
- if ((isEnabled(suite) == false) ||
+ if ((isNegotiable(suite) == false) ||
(mesg.getCipherSuites().contains(suite) == false)) {
resumingSession = false;
} else {
@@ -484,8 +566,8 @@
if (!enableNewSession) {
throw new SSLException("Client did not resume a session");
}
- supportedCurves = (SupportedEllipticCurvesExtension)mesg.extensions.get
- (ExtensionType.EXT_ELLIPTIC_CURVES);
+ supportedCurves = (SupportedEllipticCurvesExtension)
+ mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
chooseCipherSuite(mesg);
session = new SSLSessionImpl(protocolVersion, cipherSuite,
sslContext.getSecureRandom(),
@@ -498,6 +580,21 @@
m1.sessionId = session.getSessionId();
m1.compression_method = session.getCompression();
+ if (secureRenegotiation) {
+ // For ServerHellos that are initial handshakes, then the
+ // "renegotiated_connection" field in "renegotiation_info"
+ // extension is of zero length.
+ //
+ // For ServerHellos that are renegotiating, this field contains
+ // the concatenation of client_verify_data and server_verify_data.
+ //
+ // Note that for initial handshakes, both the clientVerifyData
+ // variable and serverVerifyData variable are of zero length.
+ HelloExtension serverHelloRI = new RenegotiationInfoExtension(
+ clientVerifyData, serverVerifyData);
+ m1.extensions.add(serverHelloRI);
+ }
+
if (debug != null && Debug.isOn("handshake")) {
m1.print(System.out);
System.out.println("Cipher suite: " + session.getSuite());
@@ -686,11 +783,13 @@
*/
private void chooseCipherSuite(ClientHello mesg) throws IOException {
for (CipherSuite suite : mesg.getCipherSuites().collection()) {
- if (isEnabled(suite) == false) {
+ if (isNegotiable(suite) == false) {
continue;
}
+
if (doClientAuth == SSLEngineImpl.clauth_required) {
- if ((suite.keyExchange == K_DH_ANON) || (suite.keyExchange == K_ECDH_ANON)) {
+ if ((suite.keyExchange == K_DH_ANON) ||
+ (suite.keyExchange == K_ECDH_ANON)) {
continue;
}
}
@@ -728,7 +827,7 @@
return true;
}
- if (suite.isAvailable() == false) {
+ if (suite.isNegotiable() == false) {
return false;
}
@@ -1136,6 +1235,13 @@
}
/*
+ * save client verify data for secure renegotiation
+ */
+ if (secureRenegotiation) {
+ clientVerifyData = mesg.getVerifyData();
+ }
+
+ /*
* OK, it verified. If we're doing the full handshake, add that
* "Finished" message to the hash of handshake messages, then send
* the change_cipher_spec and Finished message.
@@ -1185,6 +1291,13 @@
sendChangeCipherSpec(mesg, finishedTag);
/*
+ * save server verify data for secure renegotiation
+ */
+ if (secureRenegotiation) {
+ serverVerifyData = mesg.getVerifyData();
+ }
+
+ /*
* Update state machine so client MUST send 'finished' next
* The update should only take place if it is not in the fast
* handshake mode since the server has to wait for a finished
--- a/jdk/src/share/native/sun/awt/image/BufImgSurfaceData.c Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/native/sun/awt/image/BufImgSurfaceData.c Fri Oct 08 11:27:55 2010 +0100
@@ -48,9 +48,12 @@
static jfieldID rgbID;
static jfieldID mapSizeID;
-static jfieldID CMpDataID;
+static jfieldID colorDataID;
+static jfieldID pDataID;
static jfieldID allGrayID;
+static jclass clsICMCD;
+static jmethodID initICMCDmID;
/*
* Class: sun_awt_image_BufImgSurfaceData
* Method: initIDs
@@ -58,18 +61,23 @@
*/
JNIEXPORT void JNICALL
Java_sun_awt_image_BufImgSurfaceData_initIDs
- (JNIEnv *env, jclass bisd, jclass icm)
+(JNIEnv *env, jclass bisd, jclass icm, jclass cd)
{
if (sizeof(BufImgRIPrivate) > SD_RASINFO_PRIVATE_SIZE) {
JNU_ThrowInternalError(env, "Private RasInfo structure too large!");
return;
}
+ clsICMCD = (*env)->NewWeakGlobalRef(env, cd);
+ initICMCDmID = (*env)->GetMethodID(env, cd, "<init>", "(J)V");
+ pDataID = (*env)->GetFieldID(env, cd, "pData", "J");
+
rgbID = (*env)->GetFieldID(env, icm, "rgb", "[I");
allGrayID = (*env)->GetFieldID(env, icm, "allgrayopaque", "Z");
mapSizeID = (*env)->GetFieldID(env, icm, "map_size", "I");
- CMpDataID = (*env)->GetFieldID(env, icm, "pData", "J");
- if (allGrayID == 0 || rgbID == 0 || mapSizeID == 0 || CMpDataID == 0) {
+ colorDataID = (*env)->GetFieldID(env, icm, "colorData",
+ "Lsun/awt/image/BufImgSurfaceData$ICMColorData;");
+ if (allGrayID == 0 || rgbID == 0 || mapSizeID == 0 || pDataID == 0|| colorDataID == 0 || initICMCDmID == 0) {
JNU_ThrowInternalError(env, "Could not get field IDs");
}
}
@@ -81,18 +89,9 @@
*/
JNIEXPORT void JNICALL
Java_sun_awt_image_BufImgSurfaceData_freeNativeICMData
- (JNIEnv *env, jclass sd, jobject icm)
+ (JNIEnv *env, jclass sd, jlong pData)
{
- jlong pData;
- ColorData *cdata;
-
- if (JNU_IsNull(env, icm)) {
- JNU_ThrowNullPointerException(env, "IndexColorModel cannot be null");
- return;
- }
-
- pData = (*env)->GetLongField (env, icm, CMpDataID);
- cdata = (ColorData *)pData;
+ ColorData *cdata = (ColorData*)jlong_to_ptr(pData);
freeICMColorData(cdata);
}
@@ -263,32 +262,48 @@
static ColorData *BufImg_SetupICM(JNIEnv *env,
BufImgSDOps *bisdo)
{
- ColorData *cData;
+ ColorData *cData = NULL;
+ jobject colorData;
if (JNU_IsNull(env, bisdo->icm)) {
return (ColorData *) NULL;
}
- cData = (ColorData *) JNU_GetLongFieldAsPtr(env, bisdo->icm, CMpDataID);
+ colorData = (*env)->GetObjectField(env, bisdo->icm, colorDataID);
- if (cData == NULL) {
- cData = (ColorData*)calloc(1, sizeof(ColorData));
+ if (JNU_IsNull(env, colorData)) {
+ if (JNU_IsNull(env, clsICMCD)) {
+ // we are unable to create a wrapper object
+ return (ColorData*)NULL;
+ }
+ } else {
+ cData = (ColorData*)JNU_GetLongFieldAsPtr(env, colorData, pDataID);
+ }
+
+ if (cData != NULL) {
+ return cData;
+ }
+
+ cData = (ColorData*)calloc(1, sizeof(ColorData));
- if (cData != NULL) {
- jboolean allGray
- = (*env)->GetBooleanField(env, bisdo->icm, allGrayID);
- int *pRgb = (int *)
- ((*env)->GetPrimitiveArrayCritical(env, bisdo->lutarray, NULL));
- cData->img_clr_tbl = initCubemap(pRgb, bisdo->lutsize, 32);
- if (allGray == JNI_TRUE) {
- initInverseGrayLut(pRgb, bisdo->lutsize, cData);
- }
- (*env)->ReleasePrimitiveArrayCritical(env, bisdo->lutarray, pRgb,
- JNI_ABORT);
+ if (cData != NULL) {
+ jboolean allGray
+ = (*env)->GetBooleanField(env, bisdo->icm, allGrayID);
+ int *pRgb = (int *)
+ ((*env)->GetPrimitiveArrayCritical(env, bisdo->lutarray, NULL));
+ cData->img_clr_tbl = initCubemap(pRgb, bisdo->lutsize, 32);
+ if (allGray == JNI_TRUE) {
+ initInverseGrayLut(pRgb, bisdo->lutsize, cData);
+ }
+ (*env)->ReleasePrimitiveArrayCritical(env, bisdo->lutarray, pRgb,
+ JNI_ABORT);
- initDitherTables(cData);
+ initDitherTables(cData);
- JNU_SetLongFieldFromPtr(env, bisdo->icm, CMpDataID, cData);
+ if (JNU_IsNull(env, colorData)) {
+ jlong pData = ptr_to_jlong(cData);
+ colorData = (*env)->NewObjectA(env, clsICMCD, initICMCDmID, (jvalue *)&pData);
+ (*env)->SetObjectField(env, bisdo->icm, colorDataID, colorData);
}
}
--- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Fri Oct 08 11:27:55 2010 +0100
@@ -2614,7 +2614,8 @@
JSAMPROW scanLinePtr;
int i, j;
int pixelStride;
- unsigned char *in, *out, *pixelLimit;
+ unsigned char *in, *out, *pixelLimit, *scanLineLimit;
+ unsigned int scanLineSize, pixelBufferSize;
int targetLine;
pixelBufferPtr pb;
sun_jpeg_error_ptr jerr;
@@ -2650,19 +2651,25 @@
}
+ scanLineSize = destWidth * numBands;
if ((inCs < 0) || (inCs > JCS_YCCK) ||
(outCs < 0) || (outCs > JCS_YCCK) ||
(numBands < 1) || (numBands > MAX_BANDS) ||
(srcWidth < 0) ||
(destWidth < 0) || (destWidth > srcWidth) ||
(destHeight < 0) ||
- (stepX < 0) || (stepY < 0))
+ (stepX < 0) || (stepY < 0) ||
+ ((scanLineSize / numBands) < destWidth)) /* destWidth causes an integer overflow */
{
JNU_ThrowByName(env, "javax/imageio/IIOException",
"Invalid argument to native writeImage");
return JNI_FALSE;
}
+ if (stepX > srcWidth) {
+ stepX = srcWidth;
+ }
+
bandSize = (*env)->GetIntArrayElements(env, bandSizes, NULL);
for (i = 0; i < numBands; i++) {
@@ -2710,7 +2717,7 @@
}
// Allocate a 1-scanline buffer
- scanLinePtr = (JSAMPROW)malloc(destWidth*numBands);
+ scanLinePtr = (JSAMPROW)malloc(scanLineSize);
if (scanLinePtr == NULL) {
RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
JNU_ThrowByName( env,
@@ -2718,6 +2725,7 @@
"Writing JPEG Stream");
return data->abortFlag;
}
+ scanLineLimit = scanLinePtr + scanLineSize;
/* Establish the setjmp return context for sun_jpeg_error_exit to use. */
jerr = (sun_jpeg_error_ptr) cinfo->err;
@@ -2866,6 +2874,8 @@
}
targetLine = 0;
+ pixelBufferSize = srcWidth * numBands;
+ pixelStride = numBands * stepX;
// for each line in destHeight
while ((data->abortFlag == JNI_FALSE)
@@ -2886,9 +2896,9 @@
in = data->pixelBuf.buf.bp;
out = scanLinePtr;
- pixelLimit = in + srcWidth*numBands;
- pixelStride = numBands*stepX;
- for (; in < pixelLimit; in += pixelStride) {
+ pixelLimit = in + ((pixelBufferSize > data->pixelBuf.byteBufferLength) ?
+ data->pixelBuf.byteBufferLength : pixelBufferSize);
+ for (; (in < pixelLimit) && (out < scanLineLimit); in += pixelStride) {
for (i = 0; i < numBands; i++) {
if (scale !=NULL && scale[i] != NULL) {
*out++ = scale[i][*(in+i)];
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/Security/6938813/bug6938813.java Fri Oct 08 11:27:55 2010 +0100
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6938813
+ * @summary Swing mutable statics
+ * @author Pavel Porvatov
+ */
+
+import sun.awt.AppContext;
+import sun.awt.SunToolkit;
+
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.StyleSheet;
+import javax.swing.text.html.parser.DTD;
+import javax.swing.text.html.parser.ParserDelegator;
+import java.lang.reflect.Field;
+
+public class bug6938813 {
+ public static final String DTD_KEY = "dtd_key";
+
+ private static volatile StyleSheet styleSheet;
+
+ public static void main(String[] args) throws Exception {
+ // Run validation and init values for this AppContext
+ validate();
+
+ Thread thread = new ThreadInAnotherAppContext();
+
+ thread.start();
+ thread.join();
+ }
+
+ private static void validate() throws Exception {
+ AppContext appContext = AppContext.getAppContext();
+
+ assertTrue(DTD.getDTD(DTD_KEY).getName().equals(DTD_KEY), "DTD.getDTD() mixed AppContexts");
+
+ // Spoil hash value
+ DTD invalidDtd = DTD.getDTD("invalid DTD");
+
+ DTD.putDTDHash(DTD_KEY, invalidDtd);
+
+ assertTrue(DTD.getDTD(DTD_KEY) == invalidDtd, "Something wrong with DTD.getDTD()");
+
+ Object dtdKey = getParserDelegator_DTD_KEY();
+
+ assertTrue(appContext.get(dtdKey) == null, "ParserDelegator mixed AppContexts");
+
+ // Init default DTD
+ new ParserDelegator();
+
+ Object dtdValue = appContext.get(dtdKey);
+
+ assertTrue(dtdValue != null, "ParserDelegator.defaultDTD isn't initialized");
+
+ // Try reinit default DTD
+ new ParserDelegator();
+
+ assertTrue(dtdValue == appContext.get(dtdKey), "ParserDelegator.defaultDTD created a duplicate");
+
+ HTMLEditorKit htmlEditorKit = new HTMLEditorKit();
+
+ if (styleSheet == null) {
+ // First AppContext
+ styleSheet = htmlEditorKit.getStyleSheet();
+
+ assertTrue(styleSheet != null, "htmlEditorKit.getStyleSheet() returns null");
+ assertTrue(htmlEditorKit.getStyleSheet() == styleSheet, "Something wrong with htmlEditorKit.getStyleSheet()");
+ } else {
+ assertTrue(htmlEditorKit.getStyleSheet() != styleSheet, "HtmlEditorKit.getStyleSheet() mixed AppContexts");
+ }
+ }
+
+ private static void assertTrue(boolean b, String msg) {
+ if (!b) {
+ throw new RuntimeException("Test failed: " + msg);
+ }
+ }
+
+ private static Object getParserDelegator_DTD_KEY() throws Exception {
+ Field field = ParserDelegator.class.getDeclaredField("DTD_KEY");
+
+ field.setAccessible(true);
+
+ return field.get(null);
+ }
+
+ private static class ThreadInAnotherAppContext extends Thread {
+ public ThreadInAnotherAppContext() {
+ super(new ThreadGroup("6938813"), "ThreadInAnotherAppContext");
+ }
+
+ public void run() {
+ SunToolkit.createNewAppContext();
+
+ try {
+ validate();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/UIDefaults/6622002/bug6622002.java Fri Oct 08 11:27:55 2010 +0100
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 6622002
+ * @author Alexander Potochkin
+ * @summary UIDefault.ProxyLazyValue has unsafe reflection usage
+ */
+
+import javax.swing.*;
+
+public class bug6622002 {
+ public static void main(String[] args) {
+
+ if (createPrivateValue() == null) {
+ throw new RuntimeException("The private value unexpectedly wasn't created");
+ }
+
+ if (createPublicValue() == null) {
+ throw new RuntimeException("The public value unexpectedly wasn't created");
+ }
+
+ System.setSecurityManager(new SecurityManager());
+
+ if (createPrivateValue() != null) {
+ throw new RuntimeException("The private value was unexpectedly created");
+ }
+
+ if (createPublicValue() == null) {
+ throw new RuntimeException("The public value unexpectedly wasn't created");
+ }
+ }
+
+ private static Object createPrivateValue() {
+ return new UIDefaults.ProxyLazyValue(
+ "javax.swing.MultiUIDefaults").createValue(null);
+ }
+
+ private static Object createPublicValue() {
+ return new UIDefaults.ProxyLazyValue(
+ "javax.swing.UIDefaults").createValue(null);
+ }
+}
--- a/jdk/test/sun/security/pkcs11/fips/CipherTest.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/test/sun/security/pkcs11/fips/CipherTest.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -114,10 +114,11 @@
}
boolean isEnabled() {
-// return cipherSuite.equals("SSL_RSA_WITH_RC4_128_MD5") &&
-// (clientAuth != null);
-// return cipherSuite.indexOf("_RSA_") != -1;
-// return cipherSuite.indexOf("DH_anon") != -1;
+ // ignore SCSV
+ if (cipherSuite.equals("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
+ return false;
+ }
+
return true;
}
--- a/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -114,12 +114,11 @@
}
boolean isEnabled() {
-// if (true) return cipherSuite.contains("_ECDH_");
-// return cipherSuite.equals("SSL_RSA_WITH_RC4_128_MD5") &&
-// (clientAuth != null);
-// return cipherSuite.indexOf("_RSA_") != -1;
-// return cipherSuite.indexOf("DH_anon") != -1;
-// return cipherSuite.contains("ECDSA") == false;
+ // ignore SCSV
+ if (cipherSuite.equals("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
+ return false;
+ }
+
return true;
}
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/InvalidateServerSessionRenegotiate.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/InvalidateServerSessionRenegotiate.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
* @test
* @bug 4403428
* @summary Invalidating JSSE session on server causes SSLProtocolException
- * @ignore incompatible with disabled unsafe renegotiation (6898739), please
- * reenable when safe renegotiation is implemented.
* @author Brad Wetmore
*/
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/JSSERenegotiate.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/JSSERenegotiate.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,6 @@
* @bug 4280338
* @summary "Unsupported SSL message version" SSLProtocolException
* w/SSL_RSA_WITH_NULL_MD5
- * @ignore incompatible with disabled unsafe renegotiation (6898739), please
- * reenable when safe renegotiation is implemented.
*
* @author Ram Marti
* @author Brad Wetmore
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/CheckStatus.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/CheckStatus.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
* @test
* @bug 4948079
* @summary SSLEngineResult needs updating [none yet]
- * @ignore incompatible with disabled unsafe renegotiation (6898739), please
- * reenable when safe renegotiation is implemented.
*
* This is a simple hack to test a bunch of conditions and check
* their return codes.
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ConnectionTest.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ConnectionTest.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,6 @@
* @bug 4495742
* @summary Add non-blocking SSL/TLS functionality, usable with any
* I/O abstraction
- * @ignore incompatible with disabled unsafe renegotiation (6898739), please
- * reenable when safe renegotiation is implemented.
*
* This is a bit hacky, meant to test various conditions. The main
* thing I wanted to do with this was to do buffer reads/writes
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/NoAuthClientAuth.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/NoAuthClientAuth.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
* @test
* @bug 4495742
* @summary Demonstrate SSLEngine switch from no client auth to client auth.
- * @ignore incompatible with disabled unsafe renegotiation (6898739), please
- * reenable when safe renegotiation is implemented.
*
* @author Brad R. Wetmore
*/
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -119,6 +119,15 @@
return;
}
+ /*
+ * Don't run the SCSV suite
+ */
+ if (suite.equals("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
+ System.out.println("Ignoring SCSV suite");
+ return;
+ }
+
+
if (!suite.contains("DH_anon")) {
ssle2.setNeedClientAuth(true);
}
--- a/jdk/test/sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/test/sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java Fri Oct 08 11:27:55 2010 +0100
@@ -64,6 +64,8 @@
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
+
};
private final static String[] ENABLED_UNLIMITED = {
@@ -101,6 +103,8 @@
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
+
};
// supported ciphersuites using default JCE policy jurisdiction files
@@ -133,6 +137,7 @@
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
"SSL_RSA_WITH_NULL_MD5",
"SSL_RSA_WITH_NULL_SHA",
@@ -160,6 +165,7 @@
"TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
"TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
"TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
+
};
// supported ciphersuites using unlimited JCE policy jurisdiction files
@@ -199,6 +205,7 @@
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
"SSL_RSA_WITH_NULL_MD5",
"SSL_RSA_WITH_NULL_SHA",
@@ -228,6 +235,7 @@
"TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
"TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
"TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
+
};
private static void showSuites(String[] suites) {
--- a/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java Thu Oct 07 11:35:48 2010 -0700
+++ b/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java Fri Oct 08 11:27:55 2010 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -115,10 +115,11 @@
}
boolean isEnabled() {
-// return cipherSuite.equals("SSL_RSA_WITH_RC4_128_MD5") &&
-// (clientAuth != null);
-// return cipherSuite.indexOf("_RSA_") != -1;
-// return cipherSuite.indexOf("DH_anon") != -1;
+ // ignore SCSV
+ if (cipherSuite.equals("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
+ return false;
+ }
+
return true;
}