Mercurial > hg > release > icedtea6-1.9
changeset 2259:821336d74fc7
Security update.
2010-10-05 Andrew John Hughes <ahughes@redhat.com>
* patches/security/20100330/hotspot/original/6626217.patch:
Remove dead security patch.
* Makefile.am: Add new patches.
* NEWS: List security updates.
* patches/security/20101012/6559775.patch,
* patches/security/20101012/6891766.patch,
* patches/security/20101012/6914943.patch,
* patches/security/20101012/6925710.patch,
* patches/security/20101012/6938813.patch,
* patches/security/20101012/6957564.patch,
* patches/security/20101012/6958060.patch,
* patches/security/20101012/6963023.patch,
* patches/security/20101012/6963489.patch,
* patches/security/20101012/6966692.patch:
New security patches.
author | Andrew John Hughes <ahughes@redhat.com> |
---|---|
date | Wed, 06 Oct 2010 00:23:56 +0100 |
parents | f1c14c74edd7 |
children | 5a4598d77f03 |
files | ChangeLog Makefile.am NEWS patches/security/20100330/hotspot/original/6626217.patch patches/security/20101012/6559775.patch patches/security/20101012/6891766.patch patches/security/20101012/6914943.patch patches/security/20101012/6925710.patch patches/security/20101012/6938813.patch patches/security/20101012/6957564.patch patches/security/20101012/6958060.patch patches/security/20101012/6963023.patch patches/security/20101012/6963489.patch patches/security/20101012/6966692.patch |
diffstat | 14 files changed, 4338 insertions(+), 180 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Oct 04 23:47:52 2010 +0100 +++ b/ChangeLog Wed Oct 06 00:23:56 2010 +0100 @@ -1,3 +1,21 @@ +2010-10-05 Andrew John Hughes <ahughes@redhat.com> + + * patches/security/20100330/hotspot/original/6626217.patch: + Remove dead security patch. + * Makefile.am: Add new patches. + * NEWS: List security updates. + * patches/security/20101012/6559775.patch, + * patches/security/20101012/6891766.patch, + * patches/security/20101012/6914943.patch, + * patches/security/20101012/6925710.patch, + * patches/security/20101012/6938813.patch, + * patches/security/20101012/6957564.patch, + * patches/security/20101012/6958060.patch, + * patches/security/20101012/6963023.patch, + * patches/security/20101012/6963489.patch, + * patches/security/20101012/6966692.patch: + New security patches. + 2010-09-17 Andrew John Hughes <ahughes@redhat.com> * Makefile.am:
--- a/Makefile.am Mon Oct 04 23:47:52 2010 +0100 +++ b/Makefile.am Wed Oct 06 00:23:56 2010 +0100 @@ -199,7 +199,20 @@ ICEDTEA_FSG_PATCHES = +SECURITY_PATCHES = \ + patches/security/20101012/6891766.patch \ + patches/security/20101012/6925710.patch \ + patches/security/20101012/6938813.patch \ + patches/security/20101012/6957564.patch \ + patches/security/20101012/6958060.patch \ + patches/security/20101012/6963023.patch \ + patches/security/20101012/6963489.patch \ + patches/security/20101012/6966692.patch \ + patches/security/20101012/6914943.patch \ + patches/security/20101012/6559775.patch + ICEDTEA_PATCHES = \ + $(SECURITY_PATCHES) \ patches/icedtea-notice-safepoints.patch \ patches/icedtea-parisc-opt.patch \ patches/icedtea-lucene-crash.patch \
--- a/NEWS Mon Oct 04 23:47:52 2010 +0100 +++ b/NEWS Wed Oct 06 00:23:56 2010 +0100 @@ -10,6 +10,17 @@ New in release 1.9.1 (2010-XX-XX): * HotSpot 19 supported; use --with-hotspot-build=hs19 to enable. +* Security updates + - S6914943, CVE-2009-3555: TLS: MITM attacks via session renegotiation + - S6559775, CVE-2010-3568: OpenJDK Deserialization Race condition + - S6891766, CVE-2010-3554: OpenJDK corba reflection vulnerabilities + - S6925710, CVE-2010-3562: OpenJDK IndexColorModel double-free + - S6938813, CVE-2010-3557: OpenJDK Swing mutable static + - S6957564, CVE-2010-3548: OpenJDK DNS server IP address information leak + - S6958060, CVE-2010-3564: OpenJDK kerberos vulnerability + - S6963023, CVE-2010-3565: OpenJDK JPEG writeImage remote code execution + - S6963489, CVE-2010-3566: OpenJDK ICC Profile remote code execution + - S6966692, CVE-2010-3569: OpenJDK Serialization inconsistencies * Backports - S6638712: Inference with wildcard types causes selection of inapplicable method - S6650759: Inference of formal type parameter (unused in formal parameters) is not performed
--- a/patches/security/20100330/hotspot/original/6626217.patch Mon Oct 04 23:47:52 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -# HG changeset patch -# User acorn -# Date 1261523209 18000 -# Node ID 209a7a8a8f966dc4d6b45333cf4f3fa6648a6ecb -# Parent 75e095764f403b7425e30711b00cc038554a1ae9 -6626217: Fixed loader constraint array handling -Summary: Loader constraints track array elements, not arrays themselves. -Reviewed-by: dcubed, kevinw - -diff --git openjdk.orig/hotspot/src/share/vm/ci/ciEnv.cpp openjdk/hotspot/src/share/vm/ci/ciEnv.cpp ---- openjdk.orig/hotspot/src/share/vm/ci/ciEnv.cpp -+++ openjdk/hotspot/src/share/vm/ci/ciEnv.cpp -@@ -348,30 +348,6 @@ ciKlass* ciEnv::get_klass_by_name_impl(c - if (found_klass != NULL) { - // Found it. Build a CI handle. - return get_object(found_klass)->as_klass(); -- } -- -- // If we fail to find an array klass, look again for its element type. -- // The element type may be available either locally or via constraints. -- // In either case, if we can find the element type in the system dictionary, -- // we must build an array type around it. The CI requires array klasses -- // to be loaded if their element klasses are loaded, except when memory -- // is exhausted. -- if (sym->byte_at(0) == '[' && -- (sym->byte_at(1) == '[' || sym->byte_at(1) == 'L')) { -- // We have an unloaded array. -- // Build it on the fly if the element class exists. -- symbolOop elem_sym = oopFactory::new_symbol(sym->as_utf8()+1, -- sym->utf8_length()-1, -- KILL_COMPILE_ON_FATAL_(fail_type)); -- // Get element ciKlass recursively. -- ciKlass* elem_klass = -- get_klass_by_name_impl(accessing_klass, -- get_object(elem_sym)->as_symbol(), -- require_local); -- if (elem_klass != NULL && elem_klass->is_loaded()) { -- // Now make an array for it -- return ciObjArrayKlass::make_impl(elem_klass); -- } - } - - if (require_local) return NULL; -diff --git openjdk.orig/hotspot/src/share/vm/classfile/loaderConstraints.cpp openjdk/hotspot/src/share/vm/classfile/loaderConstraints.cpp ---- openjdk.orig/hotspot/src/share/vm/classfile/loaderConstraints.cpp -+++ openjdk/hotspot/src/share/vm/classfile/loaderConstraints.cpp -@@ -338,32 +338,6 @@ klassOop LoaderConstraintTable::find_con - } - - --klassOop LoaderConstraintTable::find_constrained_elem_klass(symbolHandle name, -- symbolHandle elem_name, -- Handle loader, -- TRAPS) { -- LoaderConstraintEntry *p = *(find_loader_constraint(name, loader)); -- if (p != NULL) { -- assert(p->klass() == NULL, "Expecting null array klass"); -- -- // The array name has a constraint, but it will not have a class. Check -- // each loader for an associated elem -- for (int i = 0; i < p->num_loaders(); i++) { -- Handle no_protection_domain; -- -- klassOop k = SystemDictionary::find(elem_name, p->loader(i), no_protection_domain, THREAD); -- if (k != NULL) { -- // Return the first elem klass found. -- return k; -- } -- } -- } -- -- // No constraints, or else no klass loaded yet. -- return NULL; --} -- -- - void LoaderConstraintTable::ensure_loader_constraint_capacity( - LoaderConstraintEntry *p, - int nfree) { -diff --git openjdk.orig/hotspot/src/share/vm/classfile/loaderConstraints.hpp openjdk/hotspot/src/share/vm/classfile/loaderConstraints.hpp ---- openjdk.orig/hotspot/src/share/vm/classfile/loaderConstraints.hpp -+++ openjdk/hotspot/src/share/vm/classfile/loaderConstraints.hpp -@@ -67,9 +67,6 @@ public: - Handle loader2, bool is_method, TRAPS); - - klassOop find_constrained_klass(symbolHandle name, Handle loader); -- klassOop find_constrained_elem_klass(symbolHandle name, symbolHandle elem_name, -- Handle loader, TRAPS); -- - - // Class loader constraints - -diff --git openjdk.orig/hotspot/src/share/vm/classfile/systemDictionary.cpp openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp ---- openjdk.orig/hotspot/src/share/vm/classfile/systemDictionary.cpp -+++ openjdk/hotspot/src/share/vm/classfile/systemDictionary.cpp -@@ -2113,9 +2113,8 @@ klassOop SystemDictionary::find_constrai - // a loader constraint that would require this loader to return the - // klass that is already loaded. - if (FieldType::is_array(class_name())) { -- // Array classes are hard because their klassOops are not kept in the -- // constraint table. The array klass may be constrained, but the elem class -- // may not be. -+ // For array classes, their klassOops are not kept in the -+ // constraint table. The element klassOops are. - jint dimension; - symbolOop object_key; - BasicType t = FieldType::get_array_info(class_name(), &dimension, -@@ -2125,8 +2124,9 @@ klassOop SystemDictionary::find_constrai - } else { - symbolHandle elem_name(THREAD, object_key); - MutexLocker mu(SystemDictionary_lock, THREAD); -- klass = constraints()->find_constrained_elem_klass(class_name, elem_name, class_loader, THREAD); -+ klass = constraints()->find_constrained_klass(elem_name, class_loader); - } -+ // If element class already loaded, allocate array klass - if (klass != NULL) { - klass = Klass::cast(klass)->array_klass_or_null(dimension); - } -@@ -2142,24 +2142,40 @@ klassOop SystemDictionary::find_constrai - - bool SystemDictionary::add_loader_constraint(symbolHandle class_name, - Handle class_loader1, -- Handle class_loader2, -- Thread* THREAD) { -- unsigned int d_hash1 = dictionary()->compute_hash(class_name, class_loader1); -+ Handle class_loader2, -+ Thread* THREAD) { -+ symbolHandle constraint_name; -+ if (!FieldType::is_array(class_name())) { -+ constraint_name = class_name; -+ } else { -+ // For array classes, their klassOops are not kept in the -+ // constraint table. The element classes are. -+ jint dimension; -+ symbolOop object_key; -+ BasicType t = FieldType::get_array_info(class_name(), &dimension, -+ &object_key, CHECK_(false)); -+ // primitive types always pass -+ if (t != T_OBJECT) { -+ return true; -+ } else { -+ constraint_name = symbolHandle(THREAD, object_key); -+ } -+ } -+ unsigned int d_hash1 = dictionary()->compute_hash(constraint_name, class_loader1); - int d_index1 = dictionary()->hash_to_index(d_hash1); - -- unsigned int d_hash2 = dictionary()->compute_hash(class_name, class_loader2); -+ unsigned int d_hash2 = dictionary()->compute_hash(constraint_name, class_loader2); - int d_index2 = dictionary()->hash_to_index(d_hash2); -+ { -+ MutexLocker mu_s(SystemDictionary_lock, THREAD); - -- { -- MutexLocker mu_s(SystemDictionary_lock, THREAD); -+ // Better never do a GC while we're holding these oops -+ No_Safepoint_Verifier nosafepoint; - -- // Better never do a GC while we're holding these oops -- No_Safepoint_Verifier nosafepoint; -- -- klassOop klass1 = find_class(d_index1, d_hash1, class_name, class_loader1); -- klassOop klass2 = find_class(d_index2, d_hash2, class_name, class_loader2); -- return constraints()->add_entry(class_name, klass1, class_loader1, -- klass2, class_loader2); -+ klassOop klass1 = find_class(d_index1, d_hash1, constraint_name, class_loader1); -+ klassOop klass2 = find_class(d_index2, d_hash2, constraint_name, class_loader2); -+ return constraints()->add_entry(constraint_name, klass1, class_loader1, -+ klass2, class_loader2); - } - } - -@@ -2191,6 +2207,7 @@ symbolOop SystemDictionary::find_resolut - // Returns the name of the type that failed a loader constraint check, or - // NULL if no constraint failed. The returned C string needs cleaning up - // with a ResourceMark in the caller -+// Arrays are not added to the loader constraint table, their elements are. - char* SystemDictionary::check_signature_loaders(symbolHandle signature, - Handle loader1, Handle loader2, - bool is_method, TRAPS) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/security/20101012/6559775.patch Wed Oct 06 00:23:56 2010 +0100 @@ -0,0 +1,317 @@ +# HG changeset patch +# User skoppar +# Date 1285671517 25200 +# Node ID 57681551c11efbec9906bdf321554aabcac25228 +# Parent bb1c74cae929a5903c0aca64b9e5a7f67726b02a +6559775: Race allows defaultReadObject to be invoked instead of readFields during deserialization +Reviewed-by: hawtin + +diff --git a/make/java/java/FILES_java.gmk b/make/java/java/FILES_java.gmk +--- openjdk.orig/jdk/make/java/java/FILES_java.gmk ++++ openjdk/jdk/make/java/java/FILES_java.gmk +@@ -384,6 +384,7 @@ JAVA_JAVA_java = \ + java/io/FilePermission.java \ + java/io/Serializable.java \ + java/io/Externalizable.java \ ++ java/io/SerialCallbackContext.java \ + java/io/Bits.java \ + java/io/ObjectInput.java \ + java/io/ObjectInputStream.java \ +diff --git a/src/share/classes/java/io/ObjectInputStream.java b/src/share/classes/java/io/ObjectInputStream.java +--- openjdk.orig/jdk/src/share/classes/java/io/ObjectInputStream.java ++++ openjdk/jdk/src/share/classes/java/io/ObjectInputStream.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2006, 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 +@@ -264,7 +264,7 @@ public class ObjectInputStream + * object currently being deserialized and descriptor for current class. + * Null when not during readObject upcall. + */ +- private CallbackContext curContext; ++ private SerialCallbackContext curContext; + + /** + * Creates an ObjectInputStream that reads from the specified InputStream. +@@ -1797,7 +1797,7 @@ public class ObjectInputStream + private void readExternalData(Externalizable obj, ObjectStreamClass desc) + throws IOException + { +- CallbackContext oldContext = curContext; ++ SerialCallbackContext oldContext = curContext; + curContext = null; + try { + boolean blocked = desc.hasBlockExternalData(); +@@ -1856,10 +1856,10 @@ public class ObjectInputStream + slotDesc.hasReadObjectMethod() && + handles.lookupException(passHandle) == null) + { +- CallbackContext oldContext = curContext; ++ SerialCallbackContext oldContext = curContext; + + try { +- curContext = new CallbackContext(obj, slotDesc); ++ curContext = new SerialCallbackContext(obj, slotDesc); + + bin.setBlockDataMode(true); + slotDesc.invokeReadObject(obj, this); +@@ -3504,42 +3504,4 @@ public class ObjectInputStream + } + } + +- /** +- * Context that during upcalls to class-defined readObject methods; holds +- * object currently being deserialized and descriptor for current class. +- * This context keeps a boolean state to indicate that defaultReadObject +- * or readFields has already been invoked with this context or the class's +- * readObject method has returned; if true, the getObj method throws +- * NotActiveException. +- */ +- private static class CallbackContext { +- private final Object obj; +- private final ObjectStreamClass desc; +- private final AtomicBoolean used = new AtomicBoolean(); +- +- public CallbackContext(Object obj, ObjectStreamClass desc) { +- this.obj = obj; +- this.desc = desc; +- } +- +- public Object getObj() throws NotActiveException { +- checkAndSetUsed(); +- return obj; +- } +- +- public ObjectStreamClass getDesc() { +- return desc; +- } +- +- private void checkAndSetUsed() throws NotActiveException { +- if (!used.compareAndSet(false, true)) { +- throw new NotActiveException( +- "not in readObject invocation or fields already read"); +- } +- } +- +- public void setUsed() { +- used.set(true); +- } +- } + } +diff --git a/src/share/classes/java/io/ObjectOutputStream.java b/src/share/classes/java/io/ObjectOutputStream.java +--- openjdk.orig/jdk/src/share/classes/java/io/ObjectOutputStream.java ++++ openjdk/jdk/src/share/classes/java/io/ObjectOutputStream.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2006, 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 +@@ -35,6 +35,7 @@ import java.util.concurrent.ConcurrentHa + import java.util.concurrent.ConcurrentHashMap; + import java.util.concurrent.ConcurrentMap; + import static java.io.ObjectStreamClass.processQueue; ++import java.io.SerialCallbackContext; + + /** + * An ObjectOutputStream writes primitive data types and graphs of Java objects +@@ -191,10 +192,12 @@ public class ObjectOutputStream + private boolean enableReplace; + + // values below valid only during upcalls to writeObject()/writeExternal() +- /** object currently being serialized */ +- private Object curObj; +- /** descriptor for current class (null if in writeExternal()) */ +- private ObjectStreamClass curDesc; ++ /** ++ * Context during upcalls to class-defined writeObject methods; holds ++ * object currently being serialized and descriptor for current class. ++ * Null when not during writeObject upcall. ++ */ ++ private SerialCallbackContext curContext; + /** current PutField object */ + private PutFieldImpl curPut; + +@@ -426,9 +429,11 @@ public class ObjectOutputStream + * <code>OutputStream</code> + */ + public void defaultWriteObject() throws IOException { +- if (curObj == null || curDesc == null) { ++ if ( curContext == null ) { + throw new NotActiveException("not in call to writeObject"); + } ++ Object curObj = curContext.getObj(); ++ ObjectStreamClass curDesc = curContext.getDesc(); + bout.setBlockDataMode(false); + defaultWriteFields(curObj, curDesc); + bout.setBlockDataMode(true); +@@ -446,9 +451,11 @@ public class ObjectOutputStream + */ + public ObjectOutputStream.PutField putFields() throws IOException { + if (curPut == null) { +- if (curObj == null || curDesc == null) { ++ if (curContext == null) { + throw new NotActiveException("not in call to writeObject"); + } ++ Object curObj = curContext.getObj(); ++ ObjectStreamClass curDesc = curContext.getDesc(); + curPut = new PutFieldImpl(curDesc); + } + return curPut; +@@ -1420,17 +1427,15 @@ public class ObjectOutputStream + * writeExternal() method. + */ + private void writeExternalData(Externalizable obj) throws IOException { +- Object oldObj = curObj; +- ObjectStreamClass oldDesc = curDesc; + PutFieldImpl oldPut = curPut; +- curObj = obj; +- curDesc = null; + curPut = null; +- ++ SerialCallbackContext oldContext = curContext; ++ + if (extendedDebugInfo) { + debugInfoStack.push("writeExternal data"); + } + try { ++ curContext = null; + if (protocol == PROTOCOL_VERSION_1) { + obj.writeExternal(this); + } else { +@@ -1440,13 +1445,12 @@ public class ObjectOutputStream + bout.writeByte(TC_ENDBLOCKDATA); + } + } finally { ++ curContext = oldContext; + if (extendedDebugInfo) { + debugInfoStack.pop(); + } + } + +- curObj = oldObj; +- curDesc = oldDesc; + curPut = oldPut; + } + +@@ -1461,12 +1465,9 @@ public class ObjectOutputStream + for (int i = 0; i < slots.length; i++) { + ObjectStreamClass slotDesc = slots[i].desc; + if (slotDesc.hasWriteObjectMethod()) { +- Object oldObj = curObj; +- ObjectStreamClass oldDesc = curDesc; + PutFieldImpl oldPut = curPut; +- curObj = obj; +- curDesc = slotDesc; + curPut = null; ++ SerialCallbackContext oldContext = curContext; + + if (extendedDebugInfo) { + debugInfoStack.push( +@@ -1474,18 +1475,19 @@ public class ObjectOutputStream + slotDesc.getName() + "\")"); + } + try { ++ curContext = new SerialCallbackContext(obj, slotDesc); + bout.setBlockDataMode(true); + slotDesc.invokeWriteObject(obj, this); + bout.setBlockDataMode(false); + bout.writeByte(TC_ENDBLOCKDATA); + } finally { ++ curContext.setUsed(); ++ curContext = oldContext; + if (extendedDebugInfo) { + debugInfoStack.pop(); + } + } + +- curObj = oldObj; +- curDesc = oldDesc; + curPut = oldPut; + } else { + defaultWriteFields(obj, slotDesc); +diff --git a/src/share/classes/java/io/SerialCallbackContext.java b/src/share/classes/java/io/SerialCallbackContext.java +new file mode 100644 +--- /dev/null ++++ openjdk/jdk/src/share/classes/java/io/SerialCallbackContext.java +@@ -0,0 +1,76 @@ ++/* ++ * 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 ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * 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. ++ */ ++ ++ package java.io; ++ ++ /** ++ * Context during upcalls from object stream to class-defined ++ * readObject/writeObject methods. ++ * Holds object currently being deserialized and descriptor for current class. ++ * ++ * This context keeps track of the thread it was constructed on, and allows ++ * only a single call of defaultReadObject, readFields, defaultWriteObject ++ * or writeFields which must be invoked on the same thread before the class's ++ * readObject/writeObject method has returned. ++ * If not set to the current thread, the getObj method throws NotActiveException. ++ */ ++ final class SerialCallbackContext { ++ private final Object obj; ++ private final ObjectStreamClass desc; ++ /** ++ * Thread this context is in use by. ++ * As this only works in one thread, we do not need to worry about thread-safety. ++ */ ++ private Thread thread; ++ ++ public SerialCallbackContext(Object obj, ObjectStreamClass desc) { ++ this.obj = obj; ++ this.desc = desc; ++ this.thread = Thread.currentThread(); ++ } ++ ++ public Object getObj() throws NotActiveException { ++ checkAndSetUsed(); ++ return obj; ++ } ++ ++ public ObjectStreamClass getDesc() { ++ return desc; ++ } ++ ++ private void checkAndSetUsed() throws NotActiveException { ++ if (thread != Thread.currentThread()) { ++ throw new NotActiveException( ++ "not in readObject invocation or fields already read"); ++ } ++ thread = null; ++ } ++ ++ public void setUsed() { ++ thread = null; ++ } ++ } ++ ++
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/security/20101012/6891766.patch Wed Oct 06 00:23:56 2010 +0100 @@ -0,0 +1,1147 @@ +# HG changeset patch +# User skoppar +# Date 1285393528 25200 +# Node ID b7961cc671c6518ebcda4f87f4b4455f1c2c4acb +# Parent 01863f27b876774673117c3f0503be9c465f55d9 +6891766: Vulnerabilities in use of reflection in CORBA +Reviewed-by: hawtin + +diff --git a/src/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java b/src/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java +--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java ++++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1998, 2004, 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 +@@ -2553,8 +2553,8 @@ public class IIOPInputStream + bridge.putObject( o, key, v ) ; + } catch (Exception e) { + throw utilWrapper.errorSetObjectField( e, fieldName, +- ObjectUtility.compactObjectToString( o ), +- ObjectUtility.compactObjectToString( v )) ; ++ o.toString(), ++ v.toString() ) ; + } + } + +@@ -2566,7 +2566,7 @@ public class IIOPInputStream + bridge.putBoolean( o, key, v ) ; + } catch (Exception e) { + throw utilWrapper.errorSetBooleanField( e, fieldName, +- ObjectUtility.compactObjectToString( o ), ++ o.toString(), + new Boolean(v) ) ; + } + } +@@ -2579,7 +2579,7 @@ public class IIOPInputStream + bridge.putByte( o, key, v ) ; + } catch (Exception e) { + throw utilWrapper.errorSetByteField( e, fieldName, +- ObjectUtility.compactObjectToString( o ), ++ o.toString(), + new Byte(v) ) ; + } + } +@@ -2592,7 +2592,7 @@ public class IIOPInputStream + bridge.putChar( o, key, v ) ; + } catch (Exception e) { + throw utilWrapper.errorSetCharField( e, fieldName, +- ObjectUtility.compactObjectToString( o ), ++ o.toString(), + new Character(v) ) ; + } + } +@@ -2605,7 +2605,7 @@ public class IIOPInputStream + bridge.putShort( o, key, v ) ; + } catch (Exception e) { + throw utilWrapper.errorSetShortField( e, fieldName, +- ObjectUtility.compactObjectToString( o ), ++ o.toString(), + new Short(v) ) ; + } + } +@@ -2618,7 +2618,7 @@ public class IIOPInputStream + bridge.putInt( o, key, v ) ; + } catch (Exception e) { + throw utilWrapper.errorSetIntField( e, fieldName, +- ObjectUtility.compactObjectToString( o ), ++ o.toString(), + new Integer(v) ) ; + } + } +@@ -2631,7 +2631,7 @@ public class IIOPInputStream + bridge.putLong( o, key, v ) ; + } catch (Exception e) { + throw utilWrapper.errorSetLongField( e, fieldName, +- ObjectUtility.compactObjectToString( o ), ++ o.toString(), + new Long(v) ) ; + } + } +@@ -2644,7 +2644,7 @@ public class IIOPInputStream + bridge.putFloat( o, key, v ) ; + } catch (Exception e) { + throw utilWrapper.errorSetFloatField( e, fieldName, +- ObjectUtility.compactObjectToString( o ), ++ o.toString(), + new Float(v) ) ; + } + } +@@ -2657,7 +2657,7 @@ public class IIOPInputStream + bridge.putDouble( o, key, v ) ; + } catch (Exception e) { + throw utilWrapper.errorSetDoubleField( e, fieldName, +- ObjectUtility.compactObjectToString( o ), ++ o.toString(), + new Double(v) ) ; + } + } +diff --git a/src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java b/src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java +--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java ++++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1998, 2004, 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 +@@ -32,32 +32,22 @@ package com.sun.corba.se.impl.io; + package com.sun.corba.se.impl.io; + + import javax.rmi.CORBA.Util; +-import javax.rmi.PortableRemoteObject; + + import java.util.Hashtable; +-import java.util.Stack; + import java.io.IOException; +-import java.util.EmptyStackException; + +-import com.sun.corba.se.impl.util.Utility; +-import com.sun.corba.se.impl.io.IIOPInputStream; +-import com.sun.corba.se.impl.io.IIOPOutputStream; + import com.sun.corba.se.impl.util.RepositoryId; + import com.sun.corba.se.impl.util.Utility; + + import org.omg.CORBA.TCKind; + +-import org.omg.CORBA.MARSHAL; +-import org.omg.CORBA.BAD_PARAM; +-import org.omg.CORBA.CompletionStatus; + import org.omg.CORBA.portable.IndirectionException; + import com.sun.org.omg.SendingContext.CodeBase; + import com.sun.org.omg.SendingContext.CodeBaseHelper; + + import java.security.AccessController; + import java.security.PrivilegedAction; +- +-import com.sun.corba.se.impl.io.IIOPInputStream.ActiveRecursionManager; ++import java.security.PrivilegedExceptionAction; + + import com.sun.corba.se.spi.logging.CORBALogDomains; + import com.sun.corba.se.impl.logging.OMGSystemException; +@@ -809,65 +799,163 @@ public class ValueHandlerImpl implements + return "com.sun.corba.se.impl.io.IIOPOutputStream"; + } + +- private com.sun.corba.se.impl.io.IIOPOutputStream createOutputStream() { +- return (com.sun.corba.se.impl.io.IIOPOutputStream)AccessController.doPrivileged( +- new StreamFactory(getOutputStreamClassName())); ++ private IIOPOutputStream createOutputStream() { ++ final String name = getOutputStreamClassName(); ++ try { ++ IIOPOutputStream stream = createOutputStreamBuiltIn(name); ++ if (stream != null) { ++ return stream; ++ } ++ return createCustom(IIOPOutputStream.class, name); ++ } catch (Throwable t) { ++ // Throw exception under the carpet. ++ InternalError ie = new InternalError( ++ "Error loading " + name ++ ); ++ ie.initCause(t); ++ throw ie; ++ } ++ } ++ ++ /** ++ * Construct a built in implementation with priveleges. ++ * Returning null indicates a non-built is specified. ++ */ ++ private IIOPOutputStream createOutputStreamBuiltIn( ++ final String name ++ ) throws Throwable { ++ try { ++ return AccessController.doPrivileged( ++ new PrivilegedExceptionAction<IIOPOutputStream>() { ++ public IIOPOutputStream run() throws IOException { ++ return createOutputStreamBuiltInNoPriv(name); ++ } ++ } ++ ); ++ } catch (java.security.PrivilegedActionException exc) { ++ throw exc.getCause(); ++ } ++ } ++ ++ /** ++ * Returning null indicates a non-built is specified. ++ */ ++ private IIOPOutputStream createOutputStreamBuiltInNoPriv( ++ final String name ++ ) throws IOException { ++ return ++ name.equals( ++ IIOPOutputStream ++ .class.getName() ++ ) ? ++ new IIOPOutputStream() : ++ ++ name.equals( ++ com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3 ++ .class.getName() ++ ) ? ++ new com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3() : ++ ++ name.equals( ++ com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3_1 ++ .class.getName() ++ ) ? ++ new com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3_1() : ++ ++ null; + } + + protected String getInputStreamClassName() { + return "com.sun.corba.se.impl.io.IIOPInputStream"; + } + +- private com.sun.corba.se.impl.io.IIOPInputStream createInputStream() { +- return (com.sun.corba.se.impl.io.IIOPInputStream)AccessController.doPrivileged( +- new StreamFactory(getInputStreamClassName())); ++ private IIOPInputStream createInputStream() { ++ final String name = getInputStreamClassName(); ++ try { ++ IIOPInputStream stream = createInputStreamBuiltIn(name); ++ if (stream != null) { ++ return stream; ++ } ++ return createCustom(IIOPInputStream.class, name); ++ } catch (Throwable t) { ++ // Throw exception under the carpet. ++ InternalError ie = new InternalError( ++ "Error loading " + name ++ ); ++ ie.initCause(t); ++ throw ie; ++ } + } + + /** +- * Instantiates a class of the given name using the system ClassLoader +- * as part of a PrivilegedAction. +- * +- * It's private final so hopefully people can't grab it outside of +- * this class. +- * +- * If you're worried that someone could subclass ValueHandlerImpl, +- * install his own streams, and snoop what's on the wire: +- * Someone can do that only if he's allowed to use the feature +- * of installing his own javax.rmi.CORBA.Util delegate (via a +- * JVM property or orb.properties file, read the first time the +- * Util class is used). If he can do that, he can snoop +- * anything on the wire, anyway, without abusing the +- * StreamFactory class. ++ * Construct a built in implementation with priveleges. ++ * Returning null indicates a non-built is specified. + */ +- private static final class StreamFactory implements PrivilegedAction { +- private String className; ++ private IIOPInputStream createInputStreamBuiltIn( ++ final String name ++ ) throws Throwable { ++ try { ++ return AccessController.doPrivileged( ++ new PrivilegedExceptionAction<IIOPInputStream>() { ++ public IIOPInputStream run() throws IOException { ++ return createInputStreamBuiltInNoPriv(name); ++ } ++ } ++ ); ++ } catch (java.security.PrivilegedActionException exc) { ++ throw exc.getCause(); ++ } ++ } ++ ++ /** ++ * Returning null indicates a non-built is specified. ++ */ ++ private IIOPInputStream createInputStreamBuiltInNoPriv( ++ final String name ++ ) throws IOException { ++ return ++ name.equals( ++ IIOPInputStream ++ .class.getName() ++ ) ? ++ new IIOPInputStream() : ++ ++ name.equals( ++ com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3 ++ .class.getName() ++ ) ? ++ new com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3() : ++ ++ name.equals( ++ com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3_1 ++ .class.getName() ++ ) ? ++ new com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3_1() : ++ ++ null; ++ } + +- public StreamFactory (String _className) { +- className = _className; +- } +- +- public Object run() { +- try { +- // Note: We must use the system ClassLoader here +- // since we want to load classes outside of the +- // core JDK when running J2EE Pure ORB and +- // talking to Kestrel. ++ /** ++ * Create a custom implementation without privileges. ++ */ ++ private <T> T createCustom( ++ final Class<T> type, final String className ++ ) throws Throwable { ++ // Note: We use the thread context or system ClassLoader here ++ // since we want to load classes outside of the ++ // core JDK when running J2EE Pure ORB and ++ // talking to Kestrel. + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if (cl == null) + cl = ClassLoader.getSystemClassLoader(); + +- Class streamClass = cl.loadClass(className); ++ Class<?> clazz = cl.loadClass(className); ++ Class<? extends T> streamClass = clazz.asSubclass(type); + + // Since the ClassLoader should cache the class, this isn't + // as expensive as it looks. + return streamClass.newInstance(); + +- } catch(Throwable t) { +- InternalError ie = new InternalError( "Error loading " + className ) ; +- ie.initCause( t ) ; +- throw ie ; +- } +- } + } + + /** +diff --git a/src/share/classes/com/sun/corba/se/impl/orb/PrefixParserAction.java b/src/share/classes/com/sun/corba/se/impl/orb/PrefixParserAction.java +--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/orb/PrefixParserAction.java ++++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/orb/PrefixParserAction.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002, 2003, 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 +@@ -110,7 +110,7 @@ public class PrefixParserAction extends + throw wrapper.couldNotSetArray( thr, + getPropertyName(), new Integer(ctr), + componentType, new Integer(size), +- ObjectUtility.compactObjectToString( obj )) ; ++ obj.toString() ) ; + } + ctr++ ; + } +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectUtility.java b/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectUtility.java +--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectUtility.java ++++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectUtility.java +@@ -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 +@@ -50,103 +50,8 @@ import java.math.BigDecimal ; + import java.math.BigDecimal ; + + public final class ObjectUtility { +- private boolean useToString ; +- private boolean isIndenting ; +- private int initialLevel ; +- private int increment ; +- private ClassMap classToPrinter = new ClassMap() ; ++ private ObjectUtility() {} + +- private static ObjectUtility standard = new ObjectUtility( false, true, +- 0, 4 ) ; +- private static ObjectUtility compact = new ObjectUtility( true, false, +- 0, 4 ) ; +- +- private ObjectUtility( boolean useToString, boolean isIndenting, +- int initialLevel, int increment ) +- { +- this.useToString = useToString ; +- this.isIndenting = isIndenting ; +- this.initialLevel = initialLevel ; +- this.increment = increment ; +- classToPrinter.put( Properties.class, propertiesPrinter ) ; +- classToPrinter.put( Collection.class, collectionPrinter ) ; +- classToPrinter.put( Map.class, mapPrinter ) ; +- } +- +- /** Construct an Utility instance with the desired objectToString +- * behavior. +- */ +- public static ObjectUtility make( boolean useToString, boolean isIndenting, +- int initialLevel, int increment ) +- { +- return new ObjectUtility( useToString, isIndenting, initialLevel, +- increment ) ; +- } +- +- /** Construct an Utility instance with the desired objectToString +- * behavior. +- */ +- public static ObjectUtility make( boolean useToString, boolean isIndenting ) +- { +- return new ObjectUtility( useToString, isIndenting, 0, 4 ) ; +- } +- +- /** Get the standard Utility object that supports objectToString with +- * indented display and no use of toString() methods. +- */ +- public static ObjectUtility make() +- { +- return standard ; +- } +- +- /** A convenience method that gives the default behavior: use indenting +- * to display the object's structure and do not use built-in toString +- * methods. +- */ +- public static String defaultObjectToString( java.lang.Object object ) +- { +- return standard.objectToString( object ) ; +- } +- +- public static String compactObjectToString( java.lang.Object object ) +- { +- return compact.objectToString( object ) ; +- } +- +- /** objectToString handles display of arbitrary objects. It correctly +- * handles objects whose elements form an arbitrary graph. It uses +- * reflection to display the contents of any kind of object. +- * An object's toString() method may optionally be used, but the default +- * is to ignore all toString() methods except for those defined for +- * primitive types, primitive type wrappers, and strings. +- */ +- public String objectToString(java.lang.Object obj) +- { +- IdentityHashMap printed = new IdentityHashMap() ; +- ObjectWriter result = ObjectWriter.make( isIndenting, initialLevel, +- increment ) ; +- objectToStringHelper( printed, result, obj ) ; +- return result.toString() ; +- } +- +- // Perform a deep structural equality comparison of the two objects. +- // This handles all arrays, maps, and sets specially, otherwise +- // it just calls the object's equals() method. +- public static boolean equals( java.lang.Object obj1, java.lang.Object obj2 ) +- { +- // Set of pairs of objects that have been (or are being) considered for +- // equality. Such pairs are presumed to be equals. If they are not, +- // this will be detected eventually and the equals method will return +- // false. +- Set considered = new HashSet() ; +- +- // Map that gives the corresponding component of obj2 for a component +- // of obj1. This is used to check for the same aliasing and use of +- // equal objects in both objects. +- Map counterpart = new IdentityHashMap() ; +- +- return equalsHelper( counterpart, considered, obj1, obj2 ) ; +- } + + /** If arr1 and arr2 are both arrays of the same component type, + * return an array of that component type that consists of the +@@ -179,544 +84,4 @@ public final class ObjectUtility { + return result ; + } + +-//=========================================================================== +-// Implementation +-//=========================================================================== +- +- private void objectToStringHelper( IdentityHashMap printed, +- ObjectWriter result, java.lang.Object obj) +- { +- if (obj==null) { +- result.append( "null" ) ; +- result.endElement() ; +- } else { +- Class cls = obj.getClass() ; +- result.startObject( obj ) ; +- +- if (printed.keySet().contains( obj )) { +- result.endObject( "*VISITED*" ) ; +- } else { +- printed.put( obj, null ) ; +- +- if (mustUseToString(cls)) { +- result.endObject( obj.toString() ) ; +- } else { +- // First, handle any classes that have special printer +- // methods defined. This is useful when the class +- // overrides toString with something that +- // is not sufficiently detailed. +- ObjectPrinter printer = (ObjectPrinter)(classToPrinter.get( +- cls )) ; +- if (printer != null) { +- printer.print( printed, result, obj ) ; +- result.endObject() ; +- } else { +- Class compClass = cls.getComponentType() ; +- +- if (compClass == null) +- // handleObject always calls endObject +- handleObject( printed, result, obj ) ; +- else { +- handleArray( printed, result, obj ) ; +- result.endObject() ; +- } +- } +- } +- } +- } +- } +- +- private static interface ObjectPrinter { +- void print( IdentityHashMap printed, ObjectWriter buff, +- java.lang.Object obj ) ; +- } +- +- private ObjectPrinter propertiesPrinter = new ObjectPrinter() { +- public void print( IdentityHashMap printed, ObjectWriter buff, +- java.lang.Object obj ) +- { +- if (!(obj instanceof Properties)) +- throw new Error() ; +- +- Properties props = (Properties)obj ; +- Enumeration keys = props.propertyNames() ; +- while (keys.hasMoreElements()) { +- String key = (String)(keys.nextElement()) ; +- String value = props.getProperty( key ) ; +- buff.startElement() ; +- buff.append( key ) ; +- buff.append( "=" ) ; +- buff.append( value ) ; +- buff.endElement() ; +- } +- } +- } ; +- +- private ObjectPrinter collectionPrinter = new ObjectPrinter() { +- public void print( IdentityHashMap printed, ObjectWriter buff, +- java.lang.Object obj ) +- { +- if (!(obj instanceof Collection)) +- throw new Error() ; +- +- Collection coll = (Collection)obj ; +- Iterator iter = coll.iterator() ; +- while (iter.hasNext()) { +- java.lang.Object element = iter.next() ; +- buff.startElement() ; +- objectToStringHelper( printed, buff, element ) ; +- buff.endElement() ; +- } +- } +- } ; +- +- private ObjectPrinter mapPrinter = new ObjectPrinter() { +- public void print( IdentityHashMap printed, ObjectWriter buff, +- java.lang.Object obj ) +- { +- if (!(obj instanceof Map)) +- throw new Error() ; +- +- Map map = (Map)obj ; +- Iterator iter = map.entrySet().iterator() ; +- while (iter.hasNext()) { +- Entry entry = (Entry)(iter.next()) ; +- buff.startElement() ; +- objectToStringHelper( printed, buff, entry.getKey() ) ; +- buff.append( "=>" ) ; +- objectToStringHelper( printed, buff, entry.getValue() ) ; +- buff.endElement() ; +- } +- } +- } ; +- +- private static class ClassMap { +- ArrayList data ; +- +- public ClassMap() +- { +- data = new ArrayList() ; +- } +- +- /** Return the first element of the ClassMap that is assignable to cls. +- * The order is determined by the order in which the put method was +- * called. Returns null if there is no match. +- */ +- public java.lang.Object get( Class cls ) +- { +- Iterator iter = data.iterator() ; +- while (iter.hasNext()) { +- java.lang.Object[] arr = (java.lang.Object[])(iter.next()) ; +- Class key = (Class)(arr[0]) ; +- if (key.isAssignableFrom( cls )) +- return arr[1] ; +- } +- +- return null ; +- } +- +- /** Add obj to the map with key cls. Note that order matters, +- * as the first match is returned. +- */ +- public void put( Class cls, java.lang.Object obj ) +- { +- java.lang.Object[] pair = { cls, obj } ; +- data.add( pair ) ; +- } +- } +- +- private boolean mustUseToString( Class cls ) +- { +- // These probably never occur +- if (cls.isPrimitive()) +- return true ; +- +- // We must use toString for all primitive wrappers, since +- // otherwise the code recurses endlessly (access value field +- // inside Integer, returns another Integer through reflection). +- if ((cls == Integer.class) || +- (cls == BigInteger.class) || +- (cls == BigDecimal.class) || +- (cls == String.class) || +- (cls == StringBuffer.class) || +- (cls == Long.class) || +- (cls == Short.class) || +- (cls == Byte.class) || +- (cls == Character.class) || +- (cls == Float.class) || +- (cls == Double.class) || +- (cls == Boolean.class)) +- return true ; +- +- if (useToString) { +- try { +- cls.getDeclaredMethod( "toString", (Class[])null ) ; +- return true ; +- } catch (Exception exc) { +- return false ; +- } +- } +- +- return false ; +- } +- +- private void handleObject( IdentityHashMap printed, ObjectWriter result, +- java.lang.Object obj ) +- { +- Class cls = obj.getClass() ; +- +- try { +- Field[] fields; +- SecurityManager security = System.getSecurityManager(); +- if (security != null && !Modifier.isPublic(cls.getModifiers())) { +- fields = new Field[0]; +- } else { +- fields = cls.getDeclaredFields(); +- } +- +- for (int ctr=0; ctr<fields.length; ctr++ ) { +- final Field fld = fields[ctr] ; +- int modifiers = fld.getModifiers() ; +- +- // Do not display field if it is static, since these fields +- // are always the same for every instances. This could +- // be made configurable, but I don't think it is +- // useful to do so. +- if (!Modifier.isStatic( modifiers )) { +- if (security != null) { +- if (!Modifier.isPublic(modifiers)) +- continue; +- } +- result.startElement() ; +- result.append( fld.getName() ) ; +- result.append( ":" ) ; +- +- try { +- // Make sure that we can read the field if it is +- // not public +- AccessController.doPrivileged( new PrivilegedAction() { +- public Object run() { +- fld.setAccessible( true ) ; +- return null ; +- } +- } ) ; +- +- java.lang.Object value = fld.get( obj ) ; +- objectToStringHelper( printed, result, value ) ; +- } catch (Exception exc2) { +- result.append( "???" ) ; +- } +- +- result.endElement() ; +- } +- } +- +- result.endObject() ; +- } catch (Exception exc2) { +- result.endObject( obj.toString() ) ; +- } +- } +- +- private void handleArray( IdentityHashMap printed, ObjectWriter result, +- java.lang.Object obj ) +- { +- Class compClass = obj.getClass().getComponentType() ; +- if (compClass == boolean.class) { +- boolean[] arr = (boolean[])obj ; +- for (int ctr=0; ctr<arr.length; ctr++) { +- result.startElement() ; +- result.append( arr[ctr] ) ; +- result.endElement() ; +- } +- } else if (compClass == byte.class) { +- byte[] arr = (byte[])obj ; +- for (int ctr=0; ctr<arr.length; ctr++) { +- result.startElement() ; +- result.append( arr[ctr] ) ; +- result.endElement() ; +- } +- } else if (compClass == short.class) { +- short[] arr = (short[])obj ; +- for (int ctr=0; ctr<arr.length; ctr++) { +- result.startElement() ; +- result.append( arr[ctr] ) ; +- result.endElement() ; +- } +- } else if (compClass == int.class) { +- int[] arr = (int[])obj ; +- for (int ctr=0; ctr<arr.length; ctr++) { +- result.startElement() ; +- result.append( arr[ctr] ) ; +- result.endElement() ; +- } +- } else if (compClass == long.class) { +- long[] arr = (long[])obj ; +- for (int ctr=0; ctr<arr.length; ctr++) { +- result.startElement() ; +- result.append( arr[ctr] ) ; +- result.endElement() ; +- } +- } else if (compClass == char.class) { +- char[] arr = (char[])obj ; +- for (int ctr=0; ctr<arr.length; ctr++) { +- result.startElement() ; +- result.append( arr[ctr] ) ; +- result.endElement() ; +- } +- } else if (compClass == float.class) { +- float[] arr = (float[])obj ; +- for (int ctr=0; ctr<arr.length; ctr++) { +- result.startElement() ; +- result.append( arr[ctr] ) ; +- result.endElement() ; +- } +- } else if (compClass == double.class) { +- double[] arr = (double[])obj ; +- for (int ctr=0; ctr<arr.length; ctr++) { +- result.startElement() ; +- result.append( arr[ctr] ) ; +- result.endElement() ; +- } +- } else { // array of object +- java.lang.Object[] arr = (java.lang.Object[])obj ; +- for (int ctr=0; ctr<arr.length; ctr++) { +- result.startElement() ; +- objectToStringHelper( printed, result, arr[ctr] ) ; +- result.endElement() ; +- } +- } +- } +- +- private static class Pair +- { +- private java.lang.Object obj1 ; +- private java.lang.Object obj2 ; +- +- Pair( java.lang.Object obj1, java.lang.Object obj2 ) +- { +- this.obj1 = obj1 ; +- this.obj2 = obj2 ; +- } +- +- public boolean equals( java.lang.Object obj ) +- { +- if (!(obj instanceof Pair)) +- return false ; +- +- Pair other = (Pair)obj ; +- return other.obj1 == obj1 && other.obj2 == obj2 ; +- } +- +- public int hashCode() +- { +- return System.identityHashCode( obj1 ) ^ +- System.identityHashCode( obj2 ) ; +- } +- } +- +- private static boolean equalsHelper( Map counterpart, Set considered, +- java.lang.Object obj1, java.lang.Object obj2 ) +- { +- if ((obj1 == null) || (obj2 == null)) +- return obj1 == obj2 ; +- +- java.lang.Object other2 = counterpart.get( obj1 ) ; +- if (other2 == null) { +- other2 = obj2 ; +- counterpart.put( obj1, other2 ) ; +- } +- +- if (obj1 == other2) +- return true ; +- +- if (obj2 != other2) +- return false ; +- +- Pair pair = new Pair( obj1, obj2 ) ; +- if (considered.contains( pair )) +- return true ; +- else +- considered.add( pair ) ; +- +- if (obj1 instanceof java.lang.Object[] && +- obj2 instanceof java.lang.Object[]) +- return equalArrays( counterpart, considered, +- (java.lang.Object[])obj1, (java.lang.Object[])obj2 ) ; +- else if (obj1 instanceof Map && obj2 instanceof Map) +- return equalMaps( counterpart, considered, +- (Map)obj1, (Map)obj2 ) ; +- else if (obj1 instanceof Set && obj2 instanceof Set) +- return equalSets( counterpart, considered, +- (Set)obj1, (Set)obj2 ) ; +- else if (obj1 instanceof List && obj2 instanceof List) +- return equalLists( counterpart, considered, +- (List)obj1, (List)obj2 ) ; +- else if (obj1 instanceof boolean[] && obj2 instanceof boolean[]) +- return Arrays.equals( (boolean[])obj1, (boolean[])obj2 ) ; +- else if (obj1 instanceof byte[] && obj2 instanceof byte[]) +- return Arrays.equals( (byte[])obj1, (byte[])obj2 ) ; +- else if (obj1 instanceof char[] && obj2 instanceof char[]) +- return Arrays.equals( (char[])obj1, (char[])obj2 ) ; +- else if (obj1 instanceof double[] && obj2 instanceof double[]) +- return Arrays.equals( (double[])obj1, (double[])obj2 ) ; +- else if (obj1 instanceof float[] && obj2 instanceof float[]) +- return Arrays.equals( (float[])obj1, (float[])obj2 ) ; +- else if (obj1 instanceof int[] && obj2 instanceof int[]) +- return Arrays.equals( (int[])obj1, (int[])obj2 ) ; +- else if (obj1 instanceof long[] && obj2 instanceof long[]) +- return Arrays.equals( (long[])obj1, (long[])obj2 ) ; +- else { +- Class cls = obj1.getClass() ; +- if (cls != obj2.getClass()) +- return obj1.equals( obj2 ) ; +- else +- return equalsObject( counterpart, considered, cls, obj1, obj2 ) ; +- } +- } +- +- private static boolean equalsObject( Map counterpart, Set considered, +- Class cls, java.lang.Object obj1, java.lang.Object obj2 ) +- { +- Class objectClass = java.lang.Object.class ; +- if (cls == objectClass) +- return true ; +- +- Class[] equalsTypes = { objectClass } ; +- try { +- Method equalsMethod = cls.getDeclaredMethod( "equals", +- equalsTypes ) ; +- return obj1.equals( obj2 ) ; +- } catch (Exception exc) { +- if (equalsObjectFields( counterpart, considered, +- cls, obj1, obj2 )) +- return equalsObject( counterpart, considered, +- cls.getSuperclass(), obj1, obj2 ) ; +- else +- return false ; +- } +- } +- +- private static boolean equalsObjectFields( Map counterpart, Set considered, +- Class cls, java.lang.Object obj1, java.lang.Object obj2 ) +- { +- Field[] fields = cls.getDeclaredFields() ; +- for (int ctr=0; ctr<fields.length; ctr++) { +- try { +- final Field field = fields[ctr] ; +- // Ignore static fields +- if (!Modifier.isStatic( field.getModifiers())) { +- AccessController.doPrivileged(new PrivilegedAction() { +- public Object run() { +- field.setAccessible( true ) ; +- return null ; +- } +- } ) ; +- +- java.lang.Object value1 = field.get( obj1 ) ; +- java.lang.Object value2 = field.get( obj2 ) ; +- if (!equalsHelper( counterpart, considered, value1, +- value2 )) +- return false ; +- } +- } catch (IllegalAccessException exc) { +- return false ; +- } +- } +- +- return true ; +- } +- +- private static boolean equalArrays( Map counterpart, Set considered, +- java.lang.Object[] arr1, java.lang.Object[] arr2 ) +- { +- int len = arr1.length ; +- if (len != arr2.length) +- return false ; +- +- for (int ctr = 0; ctr<len; ctr++ ) +- if (!equalsHelper( counterpart, considered, arr1[ctr], arr2[ctr] )) +- return false ; +- +- return true ; +- } +- +- private static boolean equalMaps( Map counterpart, Set considered, +- Map map1, Map map2 ) +- { +- if (map2.size() != map1.size()) +- return false; +- +- try { +- Iterator i = map1.entrySet().iterator(); +- while (i.hasNext()) { +- Entry e = (Entry) i.next(); +- java.lang.Object key = e.getKey(); +- java.lang.Object value = e.getValue(); +- if (value == null) { +- if (!(map2.get(key)==null && map2.containsKey(key))) +- return false; +- } else { +- if (!equalsHelper( counterpart, considered, +- value, map2.get(key))) +- return false; +- } +- } +- } catch(ClassCastException unused) { +- return false; +- } catch(NullPointerException unused) { +- return false; +- } +- +- return true; +- } +- +- // Obviously this is an inefficient quadratic algorithm. +- // This is taken pretty directly from AbstractSet and AbstractCollection +- // in the JDK. +- // For HashSet, an O(n) (with a good hash function) algorithm +- // is possible, and likewise TreeSet, since it is +- // ordered, is O(n). But this is not worth the effort here. +- // Note that the inner loop uses equals, not equalsHelper. +- // This is needed because of the searching behavior of this test. +- // However, note that this will NOT correctly handle sets that +- // contain themselves as members, or that have members that reference +- // themselves. These cases will cause infinite regress! +- private static boolean equalSets( Map counterpart, Set considered, +- Set set1, Set set2 ) +- { +- if (set1.size() != set2.size()) +- return false ; +- +- Iterator e1 = set1.iterator() ; +- while (e1.hasNext()) { +- java.lang.Object obj1 = e1.next() ; +- +- boolean found = false ; +- Iterator e2 = set2.iterator() ; +- while (e2.hasNext() && !found) { +- java.lang.Object obj2 = e2.next() ; +- found = equals( obj1, obj2 ) ; +- } +- +- if (!found) +- return false ; +- } +- +- return true ; +- } +- +- private static boolean equalLists( Map counterpart, Set considered, +- List list1, List list2 ) +- { +- ListIterator e1 = list1.listIterator(); +- ListIterator e2 = list2.listIterator(); +- while(e1.hasNext() && e2.hasNext()) { +- java.lang.Object o1 = e1.next(); +- java.lang.Object o2 = e2.next(); +- if (!(o1==null ? o2==null : equalsHelper( +- counterpart, considered, o1, o2))) +- return false; +- } +- return !(e1.hasNext() || e2.hasNext()); +- } + } +diff --git a/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelAcceptorImpl.java b/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelAcceptorImpl.java +--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelAcceptorImpl.java ++++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelAcceptorImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2001, 2004, 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 +@@ -33,14 +33,7 @@ import java.nio.channels.SelectionKey; + import java.nio.channels.SelectionKey; + import java.nio.channels.ServerSocketChannel; + import java.nio.channels.SocketChannel; +-import java.security.AccessController; +-import java.security.PrivilegedAction; +-import java.util.Collection; + import java.util.Iterator; +-import java.util.LinkedList; +- +-import org.omg.CORBA.CompletionStatus; +-import org.omg.CORBA.INTERNAL; + + import com.sun.corba.se.pept.broker.Broker; + import com.sun.corba.se.pept.encoding.InputObject; +@@ -61,18 +54,12 @@ import com.sun.corba.se.spi.ior.iiop.IIO + import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate ; + import com.sun.corba.se.spi.ior.iiop.GIOPVersion ; + import com.sun.corba.se.spi.ior.iiop.AlternateIIOPAddressComponent; +-import com.sun.corba.se.spi.legacy.connection.LegacyServerSocketEndPointInfo; + import com.sun.corba.se.spi.logging.CORBALogDomains; +-import com.sun.corba.se.spi.monitoring.LongMonitoredAttributeBase; +-import com.sun.corba.se.spi.monitoring.MonitoringConstants; +-import com.sun.corba.se.spi.monitoring.MonitoringFactories; +-import com.sun.corba.se.spi.monitoring.MonitoredObject; + import com.sun.corba.se.spi.orb.ORB; + import com.sun.corba.se.spi.orbutil.threadpool.Work; + import com.sun.corba.se.spi.protocol.CorbaMessageMediator; + import com.sun.corba.se.spi.transport.CorbaAcceptor; + import com.sun.corba.se.spi.transport.CorbaConnection; +-import com.sun.corba.se.spi.transport.CorbaContactInfo; + import com.sun.corba.se.spi.transport.SocketInfo; + import com.sun.corba.se.spi.transport.SocketOrChannelAcceptor; + +@@ -82,7 +69,6 @@ import com.sun.corba.se.impl.oa.poa.Poli + import com.sun.corba.se.impl.oa.poa.Policies; // REVISIT impl/poa specific + import com.sun.corba.se.impl.orbutil.ORBConstants; + import com.sun.corba.se.impl.orbutil.ORBUtility; +-import com.sun.corba.se.impl.ior.iiop.JavaSerializationComponent; + + // BEGIN Legacy support. + import com.sun.corba.se.spi.legacy.connection.LegacyServerSocketEndPointInfo; +@@ -442,12 +428,7 @@ public class SocketOrChannelAcceptorImpl + dprint(".doWork->: " + this); + } + if (selectionKey.isAcceptable()) { +- AccessController.doPrivileged(new PrivilegedAction() { +- public java.lang.Object run() { + accept(); +- return null; +- } +- }); + } else { + if (orb.transportDebugFlag) { + dprint(".doWork: ! selectionKey.isAcceptable: " + this); +diff --git a/src/share/classes/com/sun/corba/se/spi/orb/OperationFactory.java b/src/share/classes/com/sun/corba/se/spi/orb/OperationFactory.java +--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/orb/OperationFactory.java ++++ openjdk/corba/src/share/classes/com/sun/corba/se/spi/orb/OperationFactory.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002, 2003, 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 +@@ -25,6 +25,7 @@ package com.sun.corba.se.spi.orb ; + package com.sun.corba.se.spi.orb ; + + import java.util.StringTokenizer ; ++import java.util.Arrays ; + + import java.lang.reflect.Array ; + +@@ -446,7 +447,7 @@ public abstract class OperationFactory { + public String toString() { + return "sequenceAction(separator=\"" + sep + + "\",actions=" + +- ObjectUtility.compactObjectToString(actions) + ")" ; ++ Arrays.toString(actions) + ")" ; + } + } + +@@ -533,7 +534,7 @@ public abstract class OperationFactory { + + public String toString() { + return "mapSequenceAction(" + +- ObjectUtility.compactObjectToString(op) + ")" ; ++ Arrays.toString(op) + ")" ; + } + } + +diff --git a/src/share/classes/com/sun/corba/se/spi/orb/ParserImplBase.java b/src/share/classes/com/sun/corba/se/spi/orb/ParserImplBase.java +--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/orb/ParserImplBase.java ++++ openjdk/corba/src/share/classes/com/sun/corba/se/spi/orb/ParserImplBase.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002, 2003, 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 +@@ -125,7 +125,7 @@ public abstract class ParserImplBase { + // Since exc wraps the actual exception, use exc.getCause() + // instead of exc. + throw wrapper.errorSettingField( exc.getCause(), name, +- ObjectUtility.compactObjectToString(value) ) ; ++ value.toString() ) ; + } + } +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/security/20101012/6914943.patch Wed Oct 06 00:23:56 2010 +0100 @@ -0,0 +1,2129 @@ +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/Alerts.java Sat Jun 12 00:03:38 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/Alerts.java Sat Jun 12 00:03:37 2010 +@@ -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; +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Sat Jun 12 00:03:40 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Sat Jun 12 00:03:39 2010 +@@ -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 +@@ -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 +@@ -191,7 +197,7 @@ + if (s == null) { + throw new IllegalArgumentException("Name must not be null"); + } +- CipherSuite c = (CipherSuite)nameMap.get(s); ++ CipherSuite c = nameMap.get(s); + if ((c == null) || (c.allowed == false)) { + throw new IllegalArgumentException("Unsupported ciphersuite " + s); + } +@@ -268,8 +274,11 @@ + + // 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; + final boolean allowed; +@@ -344,7 +353,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); +@@ -362,7 +372,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); + } +@@ -395,12 +406,13 @@ + } + + private static synchronized boolean isAvailable(BulkCipher cipher) { +- Boolean b = (Boolean)availableCache.get(cipher); ++ Boolean b = availableCache.get(cipher); + 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) { +@@ -452,18 +464,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); +@@ -479,94 +501,160 @@ + // 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 + // the debug output. +@@ -610,4 +698,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); + } +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java Sat Jun 12 00:03:46 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java Sat Jun 12 00:03:42 2010 +@@ -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); + } + +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Sat Jun 12 00:03:47 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Sat Jun 12 00:03:46 2010 +@@ -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 +@@ -97,16 +97,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); + } + + /* +@@ -254,10 +262,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. +@@ -268,26 +277,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(); + } + } +@@ -322,6 +329,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 +@@ -329,10 +398,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) { +@@ -428,7 +498,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); + } +@@ -814,6 +885,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 +@@ -866,6 +944,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.) +@@ -878,12 +963,15 @@ + * Returns a ClientHello message to kickstart renegotiations + */ + HandshakeMessage getKickstartMessage() throws SSLException { +- ClientHello mesg = new ClientHello(sslContext.getSecureRandom(), +- protocolVersion); +- maxProtocolVersion = protocolVersion; ++ // session ID of the ClientHello message ++ SessionId sessionId = SSLSessionImpl.nullSession.getSessionId(); + +- clnt_random = mesg.clnt_random; ++ // a list of cipher suites sent by the client ++ CipherSuiteList cipherSuites = enabledCipherSuites; + ++ // set the max protocol version this client is supporting. ++ maxProtocolVersion = protocolVersion; ++ + // + // Try to resume an existing session. This might be mandatory, + // given certain API options. +@@ -907,9 +995,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; + } +@@ -929,9 +1017,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 +@@ -940,33 +1027,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; ++ ++ 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); + } + } +- if (session == null) { +- if (enableNewSession) { +- mesg.sessionId = SSLSessionImpl.nullSession.getSessionId(); +- } else { +- throw new SSLException("No existing session to resume."); ++ ++ 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); + } + +- // +- // All we have left to do is fill out the cipher suites. +- // (If this changes, change the 'return' above!) +- // +- mesg.setCipherSuites(enabledCipherSuites); ++ // make sure there is a negotiable cipher suite. ++ boolean negotiable = false; ++ for (CipherSuite suite : cipherSuites.collection()) { ++ if (isNegotiable(suite)) { ++ negotiable = true; ++ break; ++ } ++ } + +- return mesg; ++ 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; + } + + /* +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java Sat Jun 12 00:03:58 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java Sat Jun 12 00:03:57 2010 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2007, 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 +@@ -173,9 +173,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() { } +@@ -211,10 +209,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; +@@ -226,27 +221,48 @@ + + private final static byte[] NULL_COMPRESSION = new byte[] {0}; + +- ClientHello(SecureRandom generator, ProtocolVersion protocolVersion) { ++ ClientHello(SecureRandom generator, ProtocolVersion protocolVersion, ++ SessionId sessionId, CipherSuiteList cipherSuites) { ++ + this.protocolVersion = protocolVersion; ++ this.sessionId = sessionId; ++ this.cipherSuites = cipherSuites; ++ ++ if (cipherSuites.containsEC()) { ++ extensions.add(SupportedEllipticCurvesExtension.DEFAULT); ++ extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT); ++ } ++ + clnt_random = new RandomCookie(generator); + compression_methods = NULL_COMPRESSION; +- // sessionId, cipher_suites TBS later + } + ++ ClientHello(HandshakeInStream s, int messageLength) throws IOException { ++ protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8()); ++ clnt_random = new RandomCookie(s); ++ sessionId = new SessionId(s.getBytes8()); ++ cipherSuites = new CipherSuiteList(s); ++ compression_methods = s.getBytes8(); ++ if (messageLength() != messageLength) { ++ extensions = new HelloExtensions(s); ++ } ++ } ++ + CipherSuiteList getCipherSuites() { + return 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); +- } ++ // 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... +@@ -259,17 +275,7 @@ + + extensions.length(); + } + +- ClientHello(HandshakeInStream s, int messageLength) throws IOException { +- protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8()); +- clnt_random = new RandomCookie(s); +- sessionId = new SessionId(s.getBytes8()); +- cipherSuites = new CipherSuiteList(s); +- compression_methods = s.getBytes8(); +- if (messageLength() != messageLength) { +- extensions = new HelloExtensions(s); +- } +- } +- ++ @Override + void send(HandshakeOutStream s) throws IOException { + s.putInt8(protocolVersion.major); + s.putInt8(protocolVersion.minor); +@@ -280,6 +286,7 @@ + extensions.send(s); + } + ++ @Override + void print(PrintStream s) throws IOException { + s.println("*** ClientHello, " + protocolVersion); + +@@ -316,7 +323,6 @@ + CipherSuite cipherSuite; + byte compression_method; + HelloExtensions extensions = new HelloExtensions(); +- int extensionLength; + + ServerHello() { + // empty +@@ -1427,8 +1433,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; + +@@ -1470,7 +1474,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); +@@ -1544,14 +1548,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")) { +@@ -1559,7 +1574,6 @@ + s.println("***"); + } + } +- + } + + // +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/Handshaker.java Sat Jun 12 00:04:00 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/Handshaker.java Sat Jun 12 00:04:00 2010 +@@ -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(); + } + + /** +@@ -458,6 +501,27 @@ + return session; + } + ++ /* ++ * 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. +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/HelloExtensions.java Sat Jun 12 00:04:15 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/HelloExtensions.java Sat Jun 12 00:04:07 2010 +@@ -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 { +@@ -222,7 +254,6 @@ + if (len != 0) { + s.read(data); + } +- + } + + int length() { +@@ -239,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; +@@ -269,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,4 +582,86 @@ + } + 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)); ++ } ++ + } +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/OutputRecord.java Sat Jun 12 00:04:17 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/OutputRecord.java Sat Jun 12 00:04:16 2010 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2007, 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,6 +364,7 @@ + int v3CipherSpecOffset = v3CipherSpecLenOffset + 2; // skip length + int v2CipherSpecLen = 0; + count = 11; ++ boolean containsRenegoInfoSCSV = false; + for (int i = 0; i < cipherSpecs; i++) { + byte byte1, byte2; + +@@ -367,8 +371,16 @@ + 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); ++ } ++ + /* + * Build the first part of the V3 record header from the V2 one + * that's now buffered up. (Lengths are fixed up later). +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java Sat Jun 12 00:04:19 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java Sat Jun 12 00:04:18 2010 +@@ -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); +@@ -623,10 +637,18 @@ + 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 + initHandshaker(); + break; +@@ -961,6 +983,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; +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java Sat Jun 12 00:04:37 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/SSLServerSocketImpl.java Sat Jun 12 00:04:36 2010 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2007, 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; +@@ -318,7 +319,6 @@ + tmp.closeSocket(); + } + +- + // + // diagnostic text here is currently appropriate + // since it's only certificate unavailability that can +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Sat Jun 12 00:04:39 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Sat Jun 12 00:04:38 2010 +@@ -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). +@@ -525,11 +532,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 +@@ -911,6 +920,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; +@@ -1088,11 +1103,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); +@@ -1197,10 +1215,18 @@ + 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 + initHandshaker(); + break; +--- openjdk.orig/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java Sat Jun 12 00:04:41 2010 ++++ openjdk/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java Sat Jun 12 00:04:40 2010 +@@ -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 +@@ -74,9 +74,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 +@@ -105,13 +102,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; + } + + /* +@@ -119,13 +118,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; + } + + /* +@@ -274,44 +275,125 @@ + 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"); + } + +- return; ++ secureRenegotiation = true; + } 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"); ++ 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"); ++ } ++ ++ // verify the client_verify_data value ++ if (!Arrays.equals(clientVerifyData, ++ clientHelloRI.getRenegotiatedConnection())) { ++ fatalSE(Alerts.alert_handshake_failure, ++ "Incorrect verify date 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"); ++ } ++ } ++ } ++ + /* + * Always make sure this entire record has been digested before we + * start emitting output, to ensure correct digesting order. +@@ -459,7 +541,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 { +@@ -489,8 +571,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(), +@@ -503,6 +585,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()); +@@ -691,11 +788,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; + } + } +@@ -733,7 +832,7 @@ + return true; + } + +- if (suite.isAvailable() == false) { ++ if (suite.isNegotiable() == false) { + return false; + } + +@@ -1140,6 +1239,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. +@@ -1189,6 +1295,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 +--- openjdk.orig/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java Sat Jun 12 00:04:45 2010 ++++ openjdk/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java Sat Jun 12 00:04:44 2010 +@@ -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; + } + +--- openjdk.orig/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/InvalidateServerSessionRenegotiate.java Sat Jun 12 00:04:48 2010 ++++ openjdk/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/InvalidateServerSessionRenegotiate.java Sat Jun 12 00:04:47 2010 +@@ -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 + */ + +--- openjdk.orig/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/JSSERenegotiate.java Sat Jun 12 00:04:50 2010 ++++ openjdk/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/JSSERenegotiate.java Sat Jun 12 00:04:49 2010 +@@ -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 +--- openjdk.orig/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/CheckStatus.java Sat Jun 12 00:04:53 2010 ++++ openjdk/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/CheckStatus.java Sat Jun 12 00:04:53 2010 +@@ -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. +--- openjdk.orig/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ConnectionTest.java Sat Jun 12 00:04:55 2010 ++++ openjdk/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ConnectionTest.java Sat Jun 12 00:04:55 2010 +@@ -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 +--- openjdk.orig/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/NoAuthClientAuth.java Sat Jun 12 00:04:57 2010 ++++ openjdk/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/NoAuthClientAuth.java Sat Jun 12 00:04:57 2010 +@@ -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 + */ +--- openjdk.orig/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java Sat Jun 12 00:05:00 2010 ++++ openjdk/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java Sat Jun 12 00:04:59 2010 +@@ -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); + } +--- openjdk.orig/jdk/test/sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java Sat Jun 12 00:05:02 2010 ++++ openjdk/jdk/test/sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java Sat Jun 12 00:05:01 2010 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002, 2003, 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 +@@ -52,6 +52,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 = { +@@ -73,6 +75,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 +@@ -93,6 +97,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", ++ + "SSL_RSA_WITH_NULL_MD5", + "SSL_RSA_WITH_NULL_SHA", + "SSL_DH_anon_WITH_RC4_128_MD5", +@@ -110,7 +116,8 @@ + "TLS_KRB5_EXPORT_WITH_RC4_40_SHA", + "TLS_KRB5_EXPORT_WITH_RC4_40_MD5", + "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", +- "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5" ++ "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", ++ + }; + + // supported ciphersuites using unlimited JCE policy jurisdiction files +@@ -134,6 +141,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", ++ + "SSL_RSA_WITH_NULL_MD5", + "SSL_RSA_WITH_NULL_SHA", + "SSL_DH_anon_WITH_RC4_128_MD5", +@@ -152,7 +161,8 @@ + "TLS_KRB5_EXPORT_WITH_RC4_40_SHA", + "TLS_KRB5_EXPORT_WITH_RC4_40_MD5", + "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", +- "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5" ++ "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", ++ + }; + + private static void showSuites(String[] suites) { +--- openjdk.orig/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java Sat Jun 12 00:05:05 2010 ++++ openjdk/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java Sat Jun 12 00:05:04 2010 +@@ -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; + } +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/security/20101012/6925710.patch Wed Oct 06 00:23:56 2010 +0100 @@ -0,0 +1,198 @@ +--- openjdk.orig/jdk/src/share/classes/java/awt/image/IndexColorModel.java 2010-06-21 14:30:52.862900000 +0400 ++++ openjdk/jdk/src/share/classes/java/awt/image/IndexColorModel.java 2010-06-21 14:30:51.982900000 +0400 +@@ -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); + } + + /** +--- openjdk.orig/jdk/src/share/classes/sun/awt/image/BufImgSurfaceData.java 2010-06-21 14:31:00.760900000 +0400 ++++ openjdk/jdk/src/share/classes/sun/awt/image/BufImgSurfaceData.java 2010-06-21 14:30:59.812900000 +0400 +@@ -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; ++ } ++ } ++ } + } +--- openjdk.orig/jdk/src/share/native/sun/awt/image/BufImgSurfaceData.c 2010-06-21 14:31:07.594900000 +0400 ++++ openjdk/jdk/src/share/native/sun/awt/image/BufImgSurfaceData.c 2010-06-21 14:31:06.640900000 +0400 +@@ -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); + } + +@@ -259,32 +258,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); + } + } +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/security/20101012/6938813.patch Wed Oct 06 00:23:56 2010 +0100 @@ -0,0 +1,196 @@ +--- openjdk.orig/jdk/src/share/classes/javax/swing/text/html/HTMLEditorKit.java 2010-06-21 16:21:48.890625000 +0400 ++++ openjdk/jdk/src/share/classes/javax/swing/text/html/HTMLEditorKit.java 2010-06-21 16:21:48.437500000 +0400 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2007, 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; +--- openjdk.orig/jdk/src/share/classes/javax/swing/text/html/parser/DTD.java 2010-06-21 16:21:51.406250000 +0400 ++++ openjdk/jdk/src/share/classes/javax/swing/text/html/parser/DTD.java 2010-06-21 16:21:50.968750000 +0400 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1998, 2006, 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; +@@ -316,13 +318,14 @@ + } + + /** +- * The hashtable of DTDs. ++ * The hashtable key of DTDs in AppContext. + */ +- static Hashtable dtdHash = new Hashtable(); ++ private static final Object DTD_HASH_KEY = new Object(); ++ ++ public static void putDTDHash(String name, DTD dtd) { ++ getDtdHash().put(name, dtd); ++ } + +- public static void putDTDHash(String name, DTD dtd) { +- dtdHash.put(name, dtd); +- } + /** + * Returns a DTD with the specified <code>name</code>. If + * a DTD with that name doesn't exist, one is created +@@ -334,13 +337,27 @@ + */ + public static DTD getDTD(String name) throws IOException { + name = name.toLowerCase(); +- DTD 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 +--- openjdk.orig/jdk/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java 2010-06-21 16:21:53.640625000 +0400 ++++ openjdk/jdk/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java 2010-06-21 16:21:53.187500000 +0400 +@@ -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(); + } + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/security/20101012/6957564.patch Wed Oct 06 00:23:56 2010 +0100 @@ -0,0 +1,77 @@ +--- openjdk.orig/jdk/src/share/classes/com/sun/jndi/dns/DnsContextFactory.java 2010-06-17 12:52:22.000000000 +0800 ++++ openjdk/jdk/src/share/classes/com/sun/jndi/dns/DnsContextFactory.java 2010-06-17 12:52:22.000000000 +0800 +@@ -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 platformServers = +- ResolverConfiguration.open().nameservers(); ++ List platformServers = filterNameServers( ++ ResolverConfiguration.open().nameservers(), false); + if (!platformServers.isEmpty()) { + servers.addAll(platformServers); + continue; // on to next URL (if any, which is unlikely) +@@ -214,4 +217,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; ++ } ++ } + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/security/20101012/6958060.patch Wed Oct 06 00:23:56 2010 +0100 @@ -0,0 +1,15 @@ +--- openjdk.orig/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java 2010-06-17 12:54:06.000000000 +0800 ++++ openjdk/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java 2010-06-17 12:54:06.000000000 +0800 +@@ -209,6 +209,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]) ||
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/security/20101012/6963023.patch Wed Oct 06 00:23:56 2010 +0100 @@ -0,0 +1,95 @@ +--- openjdk.orig/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Tue Jun 29 14:11:32 2010 ++++ openjdk/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Tue Jun 29 14:11:31 2010 +@@ -2619,7 +2619,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; +@@ -2655,6 +2656,7 @@ + + } + ++ scanLineSize = destWidth * numBands; + if ((inCs < 0) || (inCs > JCS_YCCK) || + (outCs < 0) || (outCs > JCS_YCCK) || + (numBands < 1) || (numBands > MAX_BANDS) || +@@ -2661,7 +2663,8 @@ + (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"); +@@ -2668,6 +2671,10 @@ + return JNI_FALSE; + } + ++ if (stepX > srcWidth) { ++ stepX = srcWidth; ++ } ++ + bandSize = (*env)->GetIntArrayElements(env, bandSizes, NULL); + + for (i = 0; i < numBands; i++) { +@@ -2707,7 +2714,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, +@@ -2715,6 +2722,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; +@@ -2863,6 +2871,8 @@ + } + + targetLine = 0; ++ pixelBufferSize = srcWidth * numBands; ++ pixelStride = numBands * stepX; + + // for each line in destHeight + while ((data->abortFlag == JNI_FALSE) +@@ -2883,10 +2893,10 @@ + + in = data->pixelBuf.buf.bp; + out = scanLinePtr; +- pixelLimit = in + srcWidth*numBands; +- pixelStride = numBands*stepX; ++ pixelLimit = in + ((pixelBufferSize > data->pixelBuf.byteBufferLength) ? ++ data->pixelBuf.byteBufferLength : pixelBufferSize); + if (mustScale) { +- for (; in < pixelLimit; in += pixelStride) { ++ for (; (in < pixelLimit) && (out < scanLineLimit); in += pixelStride) { + for (i = 0; i < numBands; i++) { + *out++ = data->scale[i][*(in+i)]; + #ifdef DEBUG +@@ -2902,11 +2912,11 @@ + #endif + } + } else { +- for (; in < pixelLimit; in += pixelStride) { ++ for (; (in < pixelLimit) && (out < scanLineLimit); in += pixelStride) { + for (i = 0; i < numBands; i++) { + *out++ = *(in+i); + } +- } ++ } + } + // write it out + jpeg_write_scanlines(cinfo, (JSAMPARRAY)&scanLinePtr, 1);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/security/20101012/6963489.patch Wed Oct 06 00:23:56 2010 +0100 @@ -0,0 +1,31 @@ +diff -Nru openjdk.orig/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c openjdk/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c +--- openjdk.orig/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c 2010-10-04 13:45:59.000000000 +0100 ++++ openjdk/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c 2010-10-04 13:50:53.713627849 +0100 +@@ -687,6 +687,9 @@ + LPGAMMATABLE Shapes1[3]; + + GrayTRC = cmsReadICCGamma(hProfile, icSigGrayTRCTag); ++ if (!GrayTRC) { ++ return NULL; ++ } + FromLstarToXYZ(GrayTRC, Shapes1); + + if (GrayTRC == NULL) +diff -Nru openjdk.orig/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c openjdk/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c +--- openjdk.orig/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c 2010-06-21 22:15:42.000000000 +0100 ++++ openjdk/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c 2010-10-04 13:50:53.697629314 +0100 +@@ -190,12 +190,12 @@ + "sTrans.xf == NULL"); + JNU_ThrowByName(env, "java/awt/color/CMMException", + "Cannot get color transform"); ++ } else { ++ Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sTrans.j); + } +- + if (iccArray != &_iccArray[0]) { + free(iccArray); + } +- Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sTrans.j); + return sTrans.j; + } +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/security/20101012/6966692.patch Wed Oct 06 00:23:56 2010 +0100 @@ -0,0 +1,91 @@ +# HG changeset patch +# User skoppar +# Date 1285671701 25200 +# Node ID 6b2459c081422100ef7a70230741da63aa3b59a0 +# Parent 57681551c11efbec9906bdf321554aabcac25228 +6966692: defaultReadObject can set a field multiple times +Reviewed-by: hawtin + +diff --git a/src/share/classes/java/io/ObjectStreamClass.java b/src/share/classes/java/io/ObjectStreamClass.java +--- openjdk.orig/jdk/src/share/classes/java/io/ObjectStreamClass.java ++++ openjdk/jdk/src/share/classes/java/io/ObjectStreamClass.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2006, 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 +@@ -1837,8 +1837,10 @@ public class ObjectStreamClass implement + private final ObjectStreamField[] fields; + /** number of primitive fields */ + private final int numPrimFields; +- /** unsafe field keys */ +- private final long[] keys; ++ /** unsafe field keys for reading fields - may contain dupes */ ++ private final long[] readKeys; ++ /** unsafe fields keys for writing fields - no dupes */ ++ private final long[] writeKeys; + /** field data offsets */ + private final int[] offsets; + /** field type codes */ +@@ -1856,16 +1858,21 @@ public class ObjectStreamClass implement + FieldReflector(ObjectStreamField[] fields) { + this.fields = fields; + int nfields = fields.length; +- keys = new long[nfields]; ++ readKeys = new long[nfields]; ++ writeKeys = new long[nfields]; + offsets = new int[nfields]; + typeCodes = new char[nfields]; + ArrayList typeList = new ArrayList(); ++ Set<Long> usedKeys = new HashSet<Long>(); + + for (int i = 0; i < nfields; i++) { + ObjectStreamField f = fields[i]; + Field rf = f.getField(); +- keys[i] = (rf != null) ? ++ long key = (rf != null) ? + unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET; ++ readKeys[i] = key; ++ writeKeys[i] = usedKeys.add(key) ? ++ key : Unsafe.INVALID_FIELD_OFFSET; + offsets[i] = f.getOffset(); + typeCodes[i] = f.getTypeCode(); + if (!f.isPrimitive()) { +@@ -1901,7 +1908,7 @@ public class ObjectStreamClass implement + * in array should be equal to Unsafe.INVALID_FIELD_OFFSET. + */ + for (int i = 0; i < numPrimFields; i++) { +- long key = keys[i]; ++ long key = readKeys[i]; + int off = offsets[i]; + switch (typeCodes[i]) { + case 'Z': +@@ -1952,7 +1959,7 @@ public class ObjectStreamClass implement + throw new NullPointerException(); + } + for (int i = 0; i < numPrimFields; i++) { +- long key = keys[i]; ++ long key = writeKeys[i]; + if (key == Unsafe.INVALID_FIELD_OFFSET) { + continue; // discard value + } +@@ -2013,7 +2020,7 @@ public class ObjectStreamClass implement + switch (typeCodes[i]) { + case 'L': + case '[': +- vals[offsets[i]] = unsafe.getObject(obj, keys[i]); ++ vals[offsets[i]] = unsafe.getObject(obj, readKeys[i]); + break; + + default: +@@ -2034,7 +2041,7 @@ public class ObjectStreamClass implement + throw new NullPointerException(); + } + for (int i = numPrimFields; i < fields.length; i++) { +- long key = keys[i]; ++ long key = writeKeys[i]; + if (key == Unsafe.INVALID_FIELD_OFFSET) { + continue; // discard value + }