Merge
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 5c213e0..6ed8c22 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -1048,3 +1048,4 @@
8006ef1eeba6734ea46eea6057e6e9c537b39606 jdk8u292-b06
d89ef3a0713fde8aafb81bacb78d11f92c6acdce jdk8u292-b07
6dce56b0cce7da9e417befad574ddf702404c40d jdk8u292-b08
+0c6491b8f0e2a3b40f4c8a08d3178331a711e2b3 jdk8u292-b09
diff --git a/corba/.hgtags b/corba/.hgtags
index c130e16..4699943 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -1121,3 +1121,4 @@
78f287f3333accbee8c2d661a286bbe4492743ef jdk8u292-b06
b7bd2ab7cd4e48a053e3980071df0040c7e277cb jdk8u292-b07
e871cfba551fe4fd9bc2aae297e7716591e7d9f0 jdk8u292-b08
+93fa17c348d1869c9eeefc02f3e1b76ad44b5806 jdk8u292-b09
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index 26f6856..d2301f8 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -1354,3 +1354,4 @@
a5795acea81480d6377dbc5256d82e2f25cd7394 jdk8u292-b06
f206e4bfcef993ce5a75ed54612f045ca047abd3 jdk8u292-b07
85c5bc8157df45d7351c388f18ab65297b5bdd01 jdk8u292-b08
+65907019826ad9fe7d13df531e0c108cc1f179b0 jdk8u292-b09
diff --git a/hotspot/src/share/vm/code/dependencies.cpp b/hotspot/src/share/vm/code/dependencies.cpp
index c4c8e9b..0bf0729 100644
--- a/hotspot/src/share/vm/code/dependencies.cpp
+++ b/hotspot/src/share/vm/code/dependencies.cpp
@@ -29,6 +29,7 @@
#include "ci/ciMethod.hpp"
#include "code/dependencies.hpp"
#include "compiler/compileLog.hpp"
+#include "oops/klass.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.hpp"
#include "runtime/handles.inline.hpp"
@@ -896,8 +897,9 @@
} else if (!k->oop_is_instance()) {
return false; // no methods to find in an array type
} else {
- // Search class hierarchy first.
- Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature);
+ // Search class hierarchy first, skipping private implementations
+ // as they never override any inherited methods
+ Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature, Klass::skip_private);
if (!Dependencies::is_concrete_method(m, k)) {
// Check for re-abstraction of method
if (!k->is_interface() && m != NULL && m->is_abstract()) {
@@ -907,7 +909,7 @@
ClassHierarchyWalker wf(_participants, _num_participants);
Klass* w = wf.find_witness_subtype(k);
if (w != NULL) {
- Method* wm = InstanceKlass::cast(w)->find_instance_method(_name, _signature);
+ Method* wm = InstanceKlass::cast(w)->find_instance_method(_name, _signature, Klass::skip_private);
if (!Dependencies::is_concrete_method(wm, w)) {
// Found a concrete subtype 'w' which does not override abstract method 'm'.
// Bail out because 'm' could be called with 'w' as receiver (leading to an
@@ -968,6 +970,7 @@
Klass* find_witness_in(KlassDepChange& changes,
Klass* context_type,
bool participants_hide_witnesses);
+ bool witnessed_reabstraction_in_supers(Klass* k);
public:
Klass* find_witness_subtype(Klass* context_type, KlassDepChange* changes = NULL) {
assert(doing_subtype_search(), "must set up a subtype search");
@@ -1042,7 +1045,6 @@
#define count_find_witness_calls() (0)
#endif //PRODUCT
-
Klass* ClassHierarchyWalker::find_witness_in(KlassDepChange& changes,
Klass* context_type,
bool participants_hide_witnesses) {
@@ -1080,15 +1082,20 @@
}
}
- if (is_witness(new_type) &&
- !ignore_witness(new_type)) {
- return new_type;
+ if (is_witness(new_type)) {
+ if (!ignore_witness(new_type)) {
+ return new_type;
+ }
+ } else if (!doing_subtype_search()) {
+ // No witness found, but is_witness() doesn't detect method re-abstraction in case of spot-checking.
+ if (witnessed_reabstraction_in_supers(new_type)) {
+ return new_type;
+ }
}
return NULL;
}
-
// Walk hierarchy under a context type, looking for unexpected types.
// Do not report participant types, and recursively walk beneath
// them only if participants_hide_witnesses is false.
@@ -1207,6 +1214,32 @@
#undef ADD_SUBCLASS_CHAIN
}
+bool ClassHierarchyWalker::witnessed_reabstraction_in_supers(Klass* k) {
+ if (!k->oop_is_instance()) {
+ return false; // no methods to find in an array type
+ } else {
+ // Looking for a case when an abstract method is inherited into a concrete class.
+ if (Dependencies::is_concrete_klass(k) && !k->is_interface()) {
+ Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature, Klass::skip_private);
+ if (m != NULL) {
+ return false; // no reabstraction possible: local method found
+ }
+ for (InstanceKlass* super = InstanceKlass::cast(k)->java_super(); super != NULL; super = super->java_super()) {
+ m = super->find_instance_method(_name, _signature, Klass::skip_private);
+ if (m != NULL) { // inherited method found
+ if (m->is_abstract() || m->is_overpass()) {
+ _found_methods[_num_participants] = m;
+ return true; // abstract method found
+ }
+ return false;
+ }
+ }
+ assert(false, "root method not found");
+ return true;
+ }
+ return false;
+ }
+}
bool Dependencies::is_concrete_klass(Klass* k) {
if (k->is_abstract()) return false;
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
index db86470..b6e61f8 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp
@@ -1494,18 +1494,22 @@
// find_instance_method looks up the name/signature in the local methods array
// and skips over static methods
-Method* InstanceKlass::find_instance_method(
- Array<Method*>* methods, Symbol* name, Symbol* signature) {
+Method* InstanceKlass::find_instance_method(Array<Method*>* methods,
+ Symbol* name,
+ Symbol* signature,
+ PrivateLookupMode private_mode) {
Method* meth = InstanceKlass::find_method_impl(methods, name, signature,
- find_overpass, skip_static, find_private);
+ find_overpass, skip_static, private_mode);
assert(((meth == NULL) || !meth->is_static()), "find_instance_method should have skipped statics");
return meth;
}
// find_instance_method looks up the name/signature in the local methods array
// and skips over static methods
-Method* InstanceKlass::find_instance_method(Symbol* name, Symbol* signature) {
- return InstanceKlass::find_instance_method(methods(), name, signature);
+Method* InstanceKlass::find_instance_method(Symbol* name,
+ Symbol* signature,
+ PrivateLookupMode private_mode) {
+ return InstanceKlass::find_instance_method(methods(), name, signature, private_mode);
}
// Find looks up the name/signature in the local methods array
diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp
index 5197722..3d6f859 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp
@@ -526,8 +526,11 @@
static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
// find a local method, but skip static methods
- Method* find_instance_method(Symbol* name, Symbol* signature);
- static Method* find_instance_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
+ Method* find_instance_method(Symbol* name, Symbol* signature,
+ PrivateLookupMode private_mode);
+ static Method* find_instance_method(Array<Method*>* methods,
+ Symbol* name, Symbol* signature,
+ PrivateLookupMode private_mode);
// find a local method (returns NULL if not found)
Method* find_local_method(Symbol* name, Symbol* signature,
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index ae50bc5..56d5b07 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -1085,3 +1085,4 @@
bec8fbce83278f03eb107e11b4f21796184c03ad jdk8u292-b06
1fe7316192d787d0c6846691259be4ab350b140f jdk8u292-b07
5a208ef2cc7cdbc50f0a3e50f892cea6572172f1 jdk8u292-b08
+91c9a06b7ed01e7ad2489a0592c75fa19b64e76e jdk8u292-b09
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 103a4c2..bc454e5 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -1079,3 +1079,4 @@
0bbedbbfbd1192babcc74a802dc29b19b42074a7 jdk8u292-b06
1d1070dabadf2778efca9a83e97fb5f2355c6666 jdk8u292-b07
2534e08d1f087df5e3e9dd958f9eb1510e224b11 jdk8u292-b08
+a051f44ec0260e5ef9a414fe1c6d9b8833914390 jdk8u292-b09
diff --git a/jdk/.hgtags b/jdk/.hgtags
index d2a9604..8b22844 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -1080,3 +1080,4 @@
42f6981cebc518fd4d33f8d55351b32dbd900478 jdk8u292-b06
99b8202e7f718c01393f373609615a9c2721abe3 jdk8u292-b07
d103481ecd91690051bbd06e4eb4d3f3b4938dfc jdk8u292-b08
+364cf530fbd346293f4fe51e725b1b3a807fd30f jdk8u292-b09
diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/Obj.java b/jdk/src/share/classes/com/sun/jndi/ldap/Obj.java
index 6627ab3..380025c 100644
--- a/jdk/src/share/classes/com/sun/jndi/ldap/Obj.java
+++ b/jdk/src/share/classes/com/sun/jndi/ldap/Obj.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2020, 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
@@ -235,6 +235,9 @@
String[] codebases = getCodebases(attrs.get(JAVA_ATTRIBUTES[CODEBASE]));
try {
if ((attr = attrs.get(JAVA_ATTRIBUTES[SERIALIZED_DATA])) != null) {
+ if (!VersionHelper12.isSerialDataAllowed()) {
+ throw new NamingException("Object deserialization is not allowed");
+ }
ClassLoader cl = helper.getURLClassLoader(codebases);
return deserializeObject((byte[])attr.get(), cl);
} else if ((attr = attrs.get(JAVA_ATTRIBUTES[REMOTE_LOC])) != null) {
diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java b/jdk/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java
index 468273e..fc2ece1 100644
--- a/jdk/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java
+++ b/jdk/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2020, 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
@@ -39,19 +39,48 @@
private static final String TRUST_URL_CODEBASE_PROPERTY =
"com.sun.jndi.ldap.object.trustURLCodebase";
+ // System property to control whether classes are allowed to be loaded from
+ // 'javaSerializedData' attribute
+ private static final String TRUST_SERIAL_DATA_PROPERTY =
+ "com.sun.jndi.ldap.object.trustSerialData";
+
+ /**
+ * Determines whether objects may be deserialized from the content of
+ * 'javaSerializedData' attribute.
+ */
+ private static final boolean trustSerialData;
+
// Determine whether classes may be loaded from an arbitrary URL code base.
- private static final String trustURLCodebase =
- AccessController.doPrivileged(
- new PrivilegedAction<String>() {
- public String run() {
- return System.getProperty(TRUST_URL_CODEBASE_PROPERTY,
- "false");
- }
- }
- );
+ private static final boolean trustURLCodebase;
+
+ static {
+ String trust = getPrivilegedProperty(TRUST_URL_CODEBASE_PROPERTY, "false");
+ trustURLCodebase = "true".equalsIgnoreCase(trust);
+ String trustSDString = getPrivilegedProperty(TRUST_SERIAL_DATA_PROPERTY, "true");
+ trustSerialData = "true".equalsIgnoreCase(trustSDString);
+ }
+
+ private static String getPrivilegedProperty(String propertyName, String defaultVal) {
+ PrivilegedAction<String> action = () -> System.getProperty(propertyName, defaultVal);
+ if (System.getSecurityManager() == null) {
+ return action.run();
+ } else {
+ return AccessController.doPrivileged(action);
+ }
+ }
VersionHelper12() {} // Disallow external from creating one of these.
+ /**
+ * Returns true if deserialization of objects from 'javaSerializedData'
+ * LDAP attribute is allowed.
+ *
+ * @return true if deserialization is allowed; false - otherwise
+ */
+ public static boolean isSerialDataAllowed() {
+ return trustSerialData;
+ }
+
ClassLoader getURLClassLoader(String[] url)
throws MalformedURLException {
ClassLoader parent = getContextClassLoader();
@@ -60,7 +89,7 @@
* the system property com.sun.jndi.ldap.object.trustURLCodebase
* has been set to "true".
*/
- if (url != null && "true".equalsIgnoreCase(trustURLCodebase)) {
+ if (url != null && trustURLCodebase) {
return URLClassLoader.newInstance(getUrlArray(url), parent);
} else {
return parent;
diff --git a/jdk/src/share/classes/com/sun/naming/internal/ObjectFactoriesFilter.java b/jdk/src/share/classes/com/sun/naming/internal/ObjectFactoriesFilter.java
new file mode 100644
index 0000000..e0b9384
--- /dev/null
+++ b/jdk/src/share/classes/com/sun/naming/internal/ObjectFactoriesFilter.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2020, 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 com.sun.naming.internal;
+
+import javax.naming.Reference;
+
+import sun.misc.ObjectInputFilter;
+import sun.misc.ObjectInputFilter.FilterInfo;
+import sun.misc.ObjectInputFilter.Status;
+
+import sun.security.util.SecurityProperties;
+
+/**
+ * This class implements the filter that validates object factories classes instantiated
+ * during {@link Reference} lookups.
+ * There is one system-wide filter instance per VM that can be set via
+ * the {@code "jdk.jndi.object.factoriesFilter"} system property value, or via
+ * setting the property in the security properties file. The system property value supersedes
+ * the security property value. If none of the properties are specified the default
+ * "*" value is used.
+ * The filter is implemented as {@link ObjectInputFilter} with capabilities limited to the
+ * validation of a factory's class types only ({@linkplain FilterInfo#serialClass()}).
+ * Array length, number of object references, depth, and stream size filtering capabilities are
+ * not supported by the filter.
+ */
+public final class ObjectFactoriesFilter {
+
+ /**
+ * Checks if serial filter configured with {@code "jdk.jndi.object.factoriesFilter"}
+ * system property value allows instantiation of the specified objects factory class.
+ * If the filter result is not {@linkplain Status#REJECTED REJECTED}, the filter will
+ * allow the instantiation of objects factory class.
+ *
+ * @param factoryClass objects factory class
+ * @return true - if the factory is allowed to be instantiated; false - otherwise
+ */
+ public static boolean canInstantiateObjectsFactory(Class<?> factoryClass) {
+ return checkInput(() -> factoryClass);
+ }
+
+ private static boolean checkInput(FactoryInfo factoryInfo) {
+ Status result = GLOBAL.checkInput(factoryInfo);
+ return result != Status.REJECTED;
+ }
+
+ // FilterInfo to check if objects factory class is allowed by the system-wide
+ // filter. Array length, number of object references, depth, and stream size
+ // capabilities are ignored.
+ @FunctionalInterface
+ private interface FactoryInfo extends FilterInfo {
+ @Override
+ default long arrayLength() {
+ return -1;
+ }
+
+ @Override
+ default long depth() {
+ return 1;
+ }
+
+ @Override
+ default long references() {
+ return 0;
+ }
+
+ @Override
+ default long streamBytes() {
+ return 0;
+ }
+ }
+
+ // Prevent instantiation of the factories filter class
+ private ObjectFactoriesFilter() {
+ throw new InternalError("Not instantiable");
+ }
+
+ // System property name that contains the patterns to filter object factory names
+ private static final String FACTORIES_FILTER_PROPNAME = "jdk.jndi.object.factoriesFilter";
+
+ // Default system property value that allows the load of any object factory classes
+ private static final String DEFAULT_SP_VALUE = "*";
+
+ // System wide object factories filter constructed from the system property
+ private static final ObjectInputFilter GLOBAL =
+ ObjectInputFilter.Config.createFilter(getFilterPropertyValue());
+
+ // Get security or system property value
+ private static String getFilterPropertyValue() {
+ String propVal = SecurityProperties.privilegedGetOverridable(FACTORIES_FILTER_PROPNAME);
+ return propVal != null ? propVal : DEFAULT_SP_VALUE;
+ }
+}
diff --git a/jdk/src/share/classes/com/sun/naming/internal/VersionHelper.java b/jdk/src/share/classes/com/sun/naming/internal/VersionHelper.java
index 63590be..24dc0c7 100644
--- a/jdk/src/share/classes/com/sun/naming/internal/VersionHelper.java
+++ b/jdk/src/share/classes/com/sun/naming/internal/VersionHelper.java
@@ -77,6 +77,9 @@
return helper;
}
+ public abstract Class<?> loadClassWithoutInit(String className)
+ throws ClassNotFoundException;
+
public abstract Class<?> loadClass(String className)
throws ClassNotFoundException;
diff --git a/jdk/src/share/classes/com/sun/naming/internal/VersionHelper12.java b/jdk/src/share/classes/com/sun/naming/internal/VersionHelper12.java
index 9133c73..4cbdbcd 100644
--- a/jdk/src/share/classes/com/sun/naming/internal/VersionHelper12.java
+++ b/jdk/src/share/classes/com/sun/naming/internal/VersionHelper12.java
@@ -61,6 +61,10 @@
return loadClass(className, getContextClassLoader());
}
+ public Class<?> loadClassWithoutInit(String className) throws ClassNotFoundException {
+ return loadClass(className, false, getContextClassLoader());
+ }
+
/**
* Determines whether classes may be loaded from an arbitrary URL code base.
*/
@@ -86,10 +90,15 @@
* This internal method is used with Thread Context Class Loader (TCCL),
* please don't expose this method as public.
*/
+ Class<?> loadClass(String className, boolean initialize, ClassLoader cl)
+ throws ClassNotFoundException {
+ Class<?> cls = Class.forName(className, initialize, cl);
+ return cls;
+ }
+
Class<?> loadClass(String className, ClassLoader cl)
throws ClassNotFoundException {
- Class<?> cls = Class.forName(className, true, cl);
- return cls;
+ return loadClass(className, true, cl);
}
/**
diff --git a/jdk/src/share/classes/java/io/File.java b/jdk/src/share/classes/java/io/File.java
index ad1978a..e2321fa 100644
--- a/jdk/src/share/classes/java/io/File.java
+++ b/jdk/src/share/classes/java/io/File.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2021, 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
@@ -500,6 +500,9 @@
public File getParentFile() {
String p = this.getParent();
if (p == null) return null;
+ if (getClass() != File.class) {
+ p = fs.normalize(p);
+ }
return new File(p, this.prefixLength);
}
@@ -572,6 +575,9 @@
*/
public File getAbsoluteFile() {
String absPath = getAbsolutePath();
+ if (getClass() != File.class) {
+ absPath = fs.normalize(absPath);
+ }
return new File(absPath, fs.prefixLength(absPath));
}
@@ -643,6 +649,9 @@
*/
public File getCanonicalFile() throws IOException {
String canonPath = getCanonicalPath();
+ if (getClass() != File.class) {
+ canonPath = fs.normalize(canonPath);
+ }
return new File(canonPath, fs.prefixLength(canonPath));
}
@@ -1114,6 +1123,26 @@
* the directory
*/
public String[] list() {
+ return normalizedList();
+ }
+
+ /**
+ * Returns an array of strings naming the files and directories in the
+ * directory denoted by this abstract pathname. The strings are
+ * ensured to represent normalized paths.
+ *
+ * @return An array of strings naming the files and directories in the
+ * directory denoted by this abstract pathname. The array will be
+ * empty if the directory is empty. Returns {@code null} if
+ * this abstract pathname does not denote a directory, or if an
+ * I/O error occurs.
+ *
+ * @throws SecurityException
+ * If a security manager exists and its {@link
+ * SecurityManager#checkRead(String)} method denies read access to
+ * the directory
+ */
+ private final String[] normalizedList() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(path);
@@ -1121,7 +1150,15 @@
if (isInvalid()) {
return null;
}
- return fs.list(this);
+ String[] s = fs.list(this);
+ if (s != null && getClass() != File.class) {
+ String[] normalized = new String[s.length];
+ for (int i = 0; i < s.length; i++) {
+ normalized[i] = fs.normalize(s[i]);
+ }
+ s = normalized;
+ }
+ return s;
}
/**
@@ -1154,7 +1191,7 @@
* @see java.nio.file.Files#newDirectoryStream(Path,String)
*/
public String[] list(FilenameFilter filter) {
- String names[] = list();
+ String names[] = normalizedList();
if ((names == null) || (filter == null)) {
return names;
}
@@ -1206,7 +1243,7 @@
* @since 1.2
*/
public File[] listFiles() {
- String[] ss = list();
+ String[] ss = normalizedList();
if (ss == null) return null;
int n = ss.length;
File[] fs = new File[n];
@@ -1247,7 +1284,7 @@
* @see java.nio.file.Files#newDirectoryStream(Path,String)
*/
public File[] listFiles(FilenameFilter filter) {
- String ss[] = list();
+ String ss[] = normalizedList();
if (ss == null) return null;
ArrayList<File> files = new ArrayList<>();
for (String s : ss)
@@ -1285,7 +1322,7 @@
* @see java.nio.file.Files#newDirectoryStream(Path,java.nio.file.DirectoryStream.Filter)
*/
public File[] listFiles(FileFilter filter) {
- String ss[] = list();
+ String ss[] = normalizedList();
if (ss == null) return null;
ArrayList<File> files = new ArrayList<>();
for (String s : ss) {
diff --git a/jdk/src/share/classes/java/security/cert/CertPathHelperImpl.java b/jdk/src/share/classes/java/security/cert/CertPathHelperImpl.java
index fd9e111..c56a5f1 100644
--- a/jdk/src/share/classes/java/security/cert/CertPathHelperImpl.java
+++ b/jdk/src/share/classes/java/security/cert/CertPathHelperImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2020, 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
@@ -63,4 +63,8 @@
protected void implSetDateAndTime(X509CRLSelector sel, Date date, long skew) {
sel.setDateAndTime(date, skew);
}
+
+ protected boolean implIsJdkCA(TrustAnchor anchor) {
+ return anchor.isJdkCA();
+ }
}
diff --git a/jdk/src/share/classes/java/security/cert/TrustAnchor.java b/jdk/src/share/classes/java/security/cert/TrustAnchor.java
index e5be6a6..d141410 100644
--- a/jdk/src/share/classes/java/security/cert/TrustAnchor.java
+++ b/jdk/src/share/classes/java/security/cert/TrustAnchor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2020, 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
@@ -30,6 +30,7 @@
import javax.security.auth.x500.X500Principal;
+import sun.security.util.AnchorCertificates;
import sun.security.x509.NameConstraintsExtension;
import sun.security.x509.X500Name;
@@ -68,6 +69,12 @@
private final X509Certificate trustedCert;
private byte[] ncBytes;
private NameConstraintsExtension nc;
+ private boolean jdkCA;
+ private boolean hasJdkCABeenChecked;
+
+ static {
+ CertPathHelperImpl.initialize();
+ }
/**
* Creates an instance of {@code TrustAnchor} with the specified
@@ -330,4 +337,18 @@
sb.append(" Name Constraints: " + nc.toString() + "\n");
return sb.toString();
}
+
+ /**
+ * Returns true if anchor is a JDK CA (a root CA that is included by
+ * default in the cacerts keystore).
+ */
+ synchronized boolean isJdkCA() {
+ if (!hasJdkCABeenChecked) {
+ if (trustedCert != null) {
+ jdkCA = AnchorCertificates.contains(trustedCert);
+ }
+ hasJdkCABeenChecked = true;
+ }
+ return jdkCA;
+ }
}
diff --git a/jdk/src/share/classes/javax/naming/spi/NamingManager.java b/jdk/src/share/classes/javax/naming/spi/NamingManager.java
index 19b8bb5..9e04662 100644
--- a/jdk/src/share/classes/javax/naming/spi/NamingManager.java
+++ b/jdk/src/share/classes/javax/naming/spi/NamingManager.java
@@ -31,6 +31,8 @@
import java.net.MalformedURLException;
import javax.naming.*;
+
+import com.sun.naming.internal.ObjectFactoriesFilter;
import com.sun.naming.internal.VersionHelper;
import com.sun.naming.internal.ResourceManager;
import com.sun.naming.internal.FactoryEnumeration;
@@ -143,7 +145,11 @@
// Try to use current class loader
try {
- clas = helper.loadClass(factoryName);
+ clas = helper.loadClassWithoutInit(factoryName);
+ // Validate factory's class with the objects factory serial filter
+ if (!ObjectFactoriesFilter.canInstantiateObjectsFactory(clas)) {
+ return null;
+ }
} catch (ClassNotFoundException e) {
// ignore and continue
// e.printStackTrace();
@@ -156,6 +162,11 @@
(codebase = ref.getFactoryClassLocation()) != null) {
try {
clas = helper.loadClass(factoryName, codebase);
+ // Validate factory's class with the objects factory serial filter
+ if (clas == null ||
+ !ObjectFactoriesFilter.canInstantiateObjectsFactory(clas)) {
+ return null;
+ }
} catch (ClassNotFoundException e) {
}
}
diff --git a/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java b/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java
index 03d072b..cc63d69 100644
--- a/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java
+++ b/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java
@@ -35,26 +35,28 @@
import java.security.cert.X509Certificate;
import java.security.*;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
-import java.util.EnumSet;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import sun.misc.HexDumpEncoder;
import sun.security.timestamp.TimestampToken;
-import sun.security.util.ConstraintsParameters;
import sun.security.util.Debug;
import sun.security.util.DerEncoder;
import sun.security.util.DerInputStream;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import sun.security.util.DisabledAlgorithmConstraints;
+import sun.security.util.JarConstraintsParameters;
import sun.security.util.KeyUtil;
import sun.security.util.ObjectIdentifier;
+import sun.security.util.SignatureUtil;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
import sun.security.x509.KeyUsageExtension;
-import sun.security.util.SignatureUtil;
/**
* A SignerInfo, as defined in PKCS#7's signedData type.
@@ -63,16 +65,8 @@
*/
public class SignerInfo implements DerEncoder {
- // Digest and Signature restrictions
- private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET =
- Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
-
- private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET =
- Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
-
private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK =
- new DisabledAlgorithmConstraints(
- DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
+ DisabledAlgorithmConstraints.jarConstraints();
BigInteger version;
X500Name issuerName;
@@ -87,6 +81,14 @@
PKCS9Attributes authenticatedAttributes;
PKCS9Attributes unauthenticatedAttributes;
+ /**
+ * A map containing the algorithms in this SignerInfo. This is used to
+ * avoid checking algorithms to see if they are disabled more than once.
+ * The key is the AlgorithmId of the algorithm, and the value is the name of
+ * the field or attribute.
+ */
+ private Map<AlgorithmId, String> algorithms = new HashMap<>();
+
public SignerInfo(X500Name issuerName,
BigInteger serial,
AlgorithmId digestAlgorithmId,
@@ -313,21 +315,15 @@
throws NoSuchAlgorithmException, SignatureException {
try {
+ Timestamp timestamp = getTimestamp();
ContentInfo content = block.getContentInfo();
if (data == null) {
data = content.getContentBytes();
}
- Timestamp timestamp = null;
- try {
- timestamp = getTimestamp();
- } catch (Exception ignore) {
- }
-
- ConstraintsParameters cparams =
- new ConstraintsParameters(timestamp);
- String digestAlgname = getDigestAlgorithmId().getName();
+ String digestAlgName = digestAlgorithmId.getName();
+ algorithms.put(digestAlgorithmId, "SignerInfo digestAlgorithm field");
byte[] dataSigned;
@@ -353,21 +349,11 @@
if (messageDigest == null) // fail if there is no message digest
return null;
- // check that digest algorithm is not restricted
- try {
- JAR_DISABLED_CHECK.permits(digestAlgname, cparams);
- } catch (CertPathValidatorException e) {
- throw new SignatureException(e.getMessage(), e);
- }
-
- MessageDigest md = MessageDigest.getInstance(digestAlgname);
+ MessageDigest md = MessageDigest.getInstance(digestAlgName);
byte[] computedMessageDigest = md.digest(data);
- if (messageDigest.length != computedMessageDigest.length)
+ if (!MessageDigest.isEqual(messageDigest, computedMessageDigest)) {
return null;
- for (int i = 0; i < messageDigest.length; i++) {
- if (messageDigest[i] != computedMessageDigest[i])
- return null;
}
// message digest attribute matched
@@ -381,21 +367,23 @@
// put together digest algorithm and encryption algorithm
// to form signing algorithm
- String encryptionAlgname =
+ String encryptionAlgName =
getDigestEncryptionAlgorithmId().getName();
// Workaround: sometimes the encryptionAlgname is actually
// a signature name
- String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgname);
- if (tmp != null) encryptionAlgname = tmp;
- String algname = AlgorithmId.makeSigAlg(
- digestAlgname, encryptionAlgname);
-
- // check that jar signature algorithm is not restricted
+ String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgName);
+ if (tmp != null) encryptionAlgName = tmp;
+ String sigAlgName = AlgorithmId.makeSigAlg(
+ digestAlgName, encryptionAlgName);
try {
- JAR_DISABLED_CHECK.permits(algname, cparams);
- } catch (CertPathValidatorException e) {
- throw new SignatureException(e.getMessage(), e);
+ ObjectIdentifier oid = AlgorithmId.get(sigAlgName).getOID();
+ AlgorithmId sigAlgId =
+ new AlgorithmId(oid,
+ digestEncryptionAlgorithmId.getParameters());
+ algorithms.put(sigAlgId,
+ "SignerInfo digestEncryptionAlgorithm field");
+ } catch (NoSuchAlgorithmException ignore) {
}
X509Certificate cert = getCertificate(block);
@@ -404,14 +392,6 @@
}
PublicKey key = cert.getPublicKey();
- // check if the public key is restricted
- if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
- throw new SignatureException("Public key check failed. " +
- "Disabled key used: " +
- KeyUtil.getKeySize(key) + " bit " +
- key.getAlgorithm());
- }
-
if (cert.hasUnsupportedCriticalExtension()) {
throw new SignatureException("Certificate has unsupported "
+ "critical extension(s)");
@@ -448,13 +428,13 @@
}
}
- Signature sig = Signature.getInstance(algname);
+ Signature sig = Signature.getInstance(sigAlgName);
AlgorithmParameters ap =
digestEncryptionAlgorithmId.getParameters();
try {
SignatureUtil.initVerifyWithParam(sig, key,
- SignatureUtil.getParamSpec(algname, ap));
+ SignatureUtil.getParamSpec(sigAlgName, ap));
} catch (ProviderException | InvalidAlgorithmParameterException |
InvalidKeyException e) {
throw new SignatureException(e.getMessage(), e);
@@ -464,9 +444,8 @@
if (sig.verify(encryptedDigest)) {
return this;
}
- } catch (IOException e) {
- throw new SignatureException("IO error verifying signature:\n" +
- e.getMessage());
+ } catch (IOException | CertificateException e) {
+ throw new SignatureException("Error verifying signature", e);
}
return null;
}
@@ -564,6 +543,9 @@
// Extract the signer (the Timestamping Authority)
// while verifying the content
SignerInfo[] tsa = tsToken.verify(encTsTokenInfo);
+ if (tsa == null || tsa.length == 0) {
+ throw new SignatureException("Unable to verify timestamp");
+ }
// Expect only one signer
ArrayList<X509Certificate> chain = tsa[0].getCertificateChain(tsToken);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
@@ -572,6 +554,7 @@
TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
// Check that the signature timestamp applies to this signature
verifyTimestamp(tsTokenInfo);
+ algorithms.putAll(tsa[0].algorithms);
// Create a timestamp object
timestamp = new Timestamp(tsTokenInfo.getDate(), tsaChain);
return timestamp;
@@ -584,18 +567,13 @@
*/
private void verifyTimestamp(TimestampToken token)
throws NoSuchAlgorithmException, SignatureException {
- String digestAlgname = token.getHashAlgorithm().getName();
- // check that algorithm is not restricted
- if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, digestAlgname,
- null)) {
- throw new SignatureException("Timestamp token digest check failed. " +
- "Disabled algorithm used: " + digestAlgname);
- }
- MessageDigest md =
- MessageDigest.getInstance(digestAlgname);
+ AlgorithmId digestAlgId = token.getHashAlgorithm();
+ algorithms.put(digestAlgId, "TimestampToken digestAlgorithm field");
- if (!Arrays.equals(token.getHashedMessage(),
+ MessageDigest md = MessageDigest.getInstance(digestAlgId.getName());
+
+ if (!MessageDigest.isEqual(token.getHashedMessage(),
md.digest(encryptedDigest))) {
throw new SignatureException("Signature timestamp (#" +
@@ -636,4 +614,35 @@
}
return out;
}
+
+ /**
+ * Verify all of the algorithms in the array of SignerInfos against the
+ * constraints in the jdk.jar.disabledAlgorithms security property.
+ *
+ * @param infos array of SignerInfos
+ * @param params constraint parameters
+ * @param name the name of the signer's PKCS7 file
+ * @return a set of algorithms that passed the checks and are not disabled
+ */
+ public static Set<String> verifyAlgorithms(SignerInfo[] infos,
+ JarConstraintsParameters params, String name) throws SignatureException {
+ Map<AlgorithmId, String> algorithms = new HashMap<>();
+ for (SignerInfo info : infos) {
+ algorithms.putAll(info.algorithms);
+ }
+
+ Set<String> enabledAlgorithms = new HashSet<>();
+ try {
+ for (Map.Entry<AlgorithmId, String> algorithm : algorithms.entrySet()) {
+ params.setExtendedExceptionMsg(name, algorithm.getValue());
+ AlgorithmId algId = algorithm.getKey();
+ JAR_DISABLED_CHECK.permits(algId.getName(),
+ algId.getParameters(), params);
+ enabledAlgorithms.add(algId.getName());
+ }
+ } catch (CertPathValidatorException e) {
+ throw new SignatureException(e);
+ }
+ return enabledAlgorithms;
+ }
}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
index 8282d51..56f26d6 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2020, 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
@@ -27,8 +27,6 @@
import java.security.AlgorithmConstraints;
import java.security.CryptoPrimitive;
-import java.security.Timestamp;
-import java.security.cert.CertPathValidator;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
@@ -53,14 +51,13 @@
import java.security.interfaces.DSAPublicKey;
import java.security.spec.DSAPublicKeySpec;
-import sun.security.util.AnchorCertificates;
import sun.security.util.ConstraintsParameters;
import sun.security.util.Debug;
import sun.security.util.DisabledAlgorithmConstraints;
import sun.security.validator.Validator;
+import sun.security.x509.AlgorithmId;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CRLImpl;
-import sun.security.x509.AlgorithmId;
/**
* A {@code PKIXCertPathChecker} implementation to check whether a
@@ -78,10 +75,10 @@
private final AlgorithmConstraints constraints;
private final PublicKey trustedPubKey;
- private final Date pkixdate;
+ private final Date date;
private PublicKey prevPubKey;
- private final Timestamp jarTimestamp;
private final String variant;
+ private TrustAnchor anchor;
private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
@@ -94,95 +91,70 @@
CryptoPrimitive.KEY_AGREEMENT));
private static final DisabledAlgorithmConstraints
- certPathDefaultConstraints = new DisabledAlgorithmConstraints(
- DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
-
- // If there is no "cacerts" keyword, then disable anchor checking
- private static final boolean publicCALimits =
- certPathDefaultConstraints.checkProperty("jdkCA");
-
- // If anchor checking enabled, this will be true if the trust anchor
- // has a match in the cacerts file
- private boolean trustedMatch = false;
+ certPathDefaultConstraints =
+ DisabledAlgorithmConstraints.certPathConstraints();
/**
- * Create a new {@code AlgorithmChecker} with the given algorithm
- * given {@code TrustAnchor} and {@code String} variant.
+ * Create a new {@code AlgorithmChecker} with the given
+ * {@code TrustAnchor} and {@code String} variant.
*
* @param anchor the trust anchor selected to validate the target
* certificate
- * @param variant is the Validator variants of the operation. A null value
+ * @param variant the Validator variant of the operation. A null value
* passed will set it to Validator.GENERIC.
*/
public AlgorithmChecker(TrustAnchor anchor, String variant) {
- this(anchor, certPathDefaultConstraints, null, null, variant);
+ this(anchor, certPathDefaultConstraints, null, variant);
}
/**
* Create a new {@code AlgorithmChecker} with the given
- * {@code AlgorithmConstraints}, {@code Timestamp}, and {@code String}
- * variant.
+ * {@code AlgorithmConstraints} and {@code String} variant.
*
* Note that this constructor can initialize a variation of situations where
- * the AlgorithmConstraints, Timestamp, or Variant maybe known.
+ * the AlgorithmConstraints or Variant maybe known.
*
* @param constraints the algorithm constraints (or null)
- * @param jarTimestamp Timestamp passed for JAR timestamp constraint
- * checking. Set to null if not applicable.
- * @param variant is the Validator variants of the operation. A null value
+ * @param variant the Validator variant of the operation. A null value
* passed will set it to Validator.GENERIC.
*/
- public AlgorithmChecker(AlgorithmConstraints constraints,
- Timestamp jarTimestamp, String variant) {
- this(null, constraints, null, jarTimestamp, variant);
+ public AlgorithmChecker(AlgorithmConstraints constraints, String variant) {
+ this(null, constraints, null, variant);
}
/**
* Create a new {@code AlgorithmChecker} with the
- * given {@code TrustAnchor}, {@code AlgorithmConstraints},
- * {@code Timestamp}, and {@code String} variant.
+ * given {@code TrustAnchor}, {@code AlgorithmConstraints}, {@code Date},
+ * and {@code String} variant.
*
* @param anchor the trust anchor selected to validate the target
* certificate
* @param constraints the algorithm constraints (or null)
- * @param pkixdate The date specified by the PKIXParameters date. If the
- * PKIXParameters is null, the current date is used. This
- * should be null when jar files are being checked.
- * @param jarTimestamp Timestamp passed for JAR timestamp constraint
- * checking. Set to null if not applicable.
- * @param variant is the Validator variants of the operation. A null value
+ * @param date the date specified by the PKIXParameters date, or the
+ * JAR timestamp if jar files are being validated and the
+ * JAR is timestamped. May be null if no timestamp or
+ * PKIXParameter date is set.
+ * @param variant the Validator variant of the operation. A null value
* passed will set it to Validator.GENERIC.
*/
public AlgorithmChecker(TrustAnchor anchor,
- AlgorithmConstraints constraints, Date pkixdate,
- Timestamp jarTimestamp, String variant) {
+ AlgorithmConstraints constraints, Date date, String variant) {
if (anchor != null) {
if (anchor.getTrustedCert() != null) {
this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
- // Check for anchor certificate restrictions
- trustedMatch = checkFingerprint(anchor.getTrustedCert());
- if (trustedMatch && debug != null) {
- debug.println("trustedMatch = true");
- }
} else {
this.trustedPubKey = anchor.getCAPublicKey();
}
+ this.anchor = anchor;
} else {
this.trustedPubKey = null;
- if (debug != null) {
- debug.println("TrustAnchor is null, trustedMatch is false.");
- }
}
this.prevPubKey = this.trustedPubKey;
this.constraints = (constraints == null ? certPathDefaultConstraints :
constraints);
- // If we are checking jar files, set pkixdate the same as the timestamp
- // for certificate checking
- this.pkixdate = (jarTimestamp != null ? jarTimestamp.getTimestamp() :
- pkixdate);
- this.jarTimestamp = jarTimestamp;
+ this.date = date;
this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
}
@@ -194,24 +166,11 @@
* certificate
* @param pkixdate Date the constraints are checked against. The value is
* either the PKIXParameters date or null for the current date.
- * @param variant is the Validator variants of the operation. A null value
+ * @param variant the Validator variant of the operation. A null value
* passed will set it to Validator.GENERIC.
*/
public AlgorithmChecker(TrustAnchor anchor, Date pkixdate, String variant) {
- this(anchor, certPathDefaultConstraints, pkixdate, null, variant);
- }
-
- // Check this 'cert' for restrictions in the AnchorCertificates
- // trusted certificates list
- private static boolean checkFingerprint(X509Certificate cert) {
- if (!publicCALimits) {
- return false;
- }
-
- if (debug != null) {
- debug.println("AlgorithmChecker.contains: " + cert.getSigAlgName());
- }
- return AnchorCertificates.contains(cert);
+ this(anchor, certPathDefaultConstraints, pkixdate, variant);
}
@Override
@@ -318,18 +277,19 @@
}
ConstraintsParameters cp =
- new ConstraintsParameters((X509Certificate)cert,
- trustedMatch, pkixdate, jarTimestamp, variant);
+ new CertPathConstraintsParameters(x509Cert, variant,
+ anchor, date);
// Check against local constraints if it is DisabledAlgorithmConstraints
if (constraints instanceof DisabledAlgorithmConstraints) {
- ((DisabledAlgorithmConstraints)constraints).permits(currSigAlg, cp);
+ ((DisabledAlgorithmConstraints)constraints).permits(currSigAlg,
+ currSigAlgParams, cp);
// DisabledAlgorithmsConstraints does not check primitives, so key
// additional key check.
} else {
// Perform the default constraints checking anyway.
- certPathDefaultConstraints.permits(currSigAlg, cp);
+ certPathDefaultConstraints.permits(currSigAlg, currSigAlgParams, cp);
// Call locally set constraints to check key with primitives.
if (!constraints.permits(primitives, currPubKey)) {
throw new CertPathValidatorException(
@@ -408,14 +368,10 @@
// Don't bother to change the trustedPubKey.
if (anchor.getTrustedCert() != null) {
prevPubKey = anchor.getTrustedCert().getPublicKey();
- // Check for anchor certificate restrictions
- trustedMatch = checkFingerprint(anchor.getTrustedCert());
- if (trustedMatch && debug != null) {
- debug.println("trustedMatch = true");
- }
} else {
prevPubKey = anchor.getCAPublicKey();
}
+ this.anchor = anchor;
}
}
@@ -424,11 +380,12 @@
*
* @param key the public key to verify the CRL signature
* @param crl the target CRL
- * @param variant is the Validator variants of the operation. A null value
+ * @param variant the Validator variant of the operation. A null value
* passed will set it to Validator.GENERIC.
+ * @param anchor the trust anchor selected to validate the CRL issuer
*/
- static void check(PublicKey key, X509CRL crl, String variant)
- throws CertPathValidatorException {
+ static void check(PublicKey key, X509CRL crl, String variant,
+ TrustAnchor anchor) throws CertPathValidatorException {
X509CRLImpl x509CRLImpl = null;
try {
@@ -438,7 +395,7 @@
}
AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
- check(key, algorithmId, variant);
+ check(key, algorithmId, variant, anchor);
}
/**
@@ -446,16 +403,16 @@
*
* @param key the public key to verify the CRL signature
* @param algorithmId signature algorithm Algorithm ID
- * @param variant is the Validator variants of the operation. A null value
- * passed will set it to Validator.GENERIC.
+ * @param variant the Validator variant of the operation. A null
+ * value passed will set it to Validator.GENERIC.
+ * @param anchor the trust anchor selected to validate the public key
*/
- static void check(PublicKey key, AlgorithmId algorithmId, String variant)
- throws CertPathValidatorException {
- String sigAlgName = algorithmId.getName();
- AlgorithmParameters sigAlgParams = algorithmId.getParameters();
+ static void check(PublicKey key, AlgorithmId algorithmId, String variant,
+ TrustAnchor anchor) throws CertPathValidatorException {
- certPathDefaultConstraints.permits(new ConstraintsParameters(
- sigAlgName, sigAlgParams, key, variant));
+ certPathDefaultConstraints.permits(algorithmId.getName(),
+ algorithmId.getParameters(),
+ new CertPathConstraintsParameters(key, variant, anchor));
}
}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/CertPathConstraintsParameters.java b/jdk/src/share/classes/sun/security/provider/certpath/CertPathConstraintsParameters.java
new file mode 100644
index 0000000..01e87fb
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CertPathConstraintsParameters.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2020, 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 sun.security.provider.certpath;
+
+import java.security.Key;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Set;
+import java.util.Collections;
+
+import sun.security.util.ConstraintsParameters;
+import sun.security.validator.Validator;
+
+/**
+ * This class contains parameters for checking certificates against
+ * constraints specified in the jdk.certpath.disabledAlgorithms security
+ * property.
+ */
+class CertPathConstraintsParameters implements ConstraintsParameters {
+ // The public key of the certificate
+ private final Key key;
+ // The certificate's trust anchor which will be checked against the
+ // jdkCA constraint, if specified.
+ private final TrustAnchor anchor;
+ // The PKIXParameter validity date or the timestamp of the signed JAR
+ // file, if this chain is associated with a timestamped signed JAR.
+ private final Date date;
+ // The variant or usage of this certificate
+ private final String variant;
+ // The certificate being checked (may be null if a CRL or OCSPResponse is
+ // being checked)
+ private final X509Certificate cert;
+
+ public CertPathConstraintsParameters(X509Certificate cert,
+ String variant, TrustAnchor anchor, Date date) {
+ this(cert.getPublicKey(), variant, anchor, date, cert);
+ }
+
+ public CertPathConstraintsParameters(Key key, String variant,
+ TrustAnchor anchor) {
+ this(key, variant, anchor, null, null);
+ }
+
+ private CertPathConstraintsParameters(Key key, String variant,
+ TrustAnchor anchor, Date date, X509Certificate cert) {
+ this.key = key;
+ this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
+ this.anchor = anchor;
+ this.date = date;
+ this.cert = cert;
+ }
+
+ @Override
+ public boolean anchorIsJdkCA() {
+ return CertPathHelper.isJdkCA(anchor);
+ }
+
+ @Override
+ public Set<Key> getKeys() {
+ return (key == null) ? Collections.emptySet()
+ : Collections.singleton(key);
+ }
+
+ @Override
+ public Date getDate() {
+ return date;
+ }
+
+ @Override
+ public String getVariant() {
+ return variant;
+ }
+
+ @Override
+ public String extendedExceptionMsg() {
+ return (cert == null ? "."
+ : " used with certificate: " +
+ cert.getSubjectX500Principal());
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("[\n");
+ sb.append("\n Variant: ").append(variant);
+ if (anchor != null) {
+ sb.append("\n Anchor: ").append(anchor);
+ }
+ if (cert != null) {
+ sb.append("\n Cert Issuer: ")
+ .append(cert.getIssuerX500Principal());
+ sb.append("\n Cert Subject: ")
+ .append(cert.getSubjectX500Principal());
+ }
+ if (key != null) {
+ sb.append("\n Key: ").append(key.getAlgorithm());
+ }
+ if (date != null) {
+ sb.append("\n Date: ").append(date);
+ }
+ sb.append("\n]");
+ return sb.toString();
+ }
+}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/CertPathHelper.java b/jdk/src/share/classes/sun/security/provider/certpath/CertPathHelper.java
index af6da8a..7c02007 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/CertPathHelper.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CertPathHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2020, 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
@@ -28,13 +28,14 @@
import java.util.Date;
import java.util.Set;
+import java.security.cert.TrustAnchor;
import java.security.cert.X509CertSelector;
import java.security.cert.X509CRLSelector;
import sun.security.x509.GeneralNameInterface;
/**
- * Helper class that allows access to Sun specific known-public methods in the
+ * Helper class that allows access to JDK specific known-public methods in the
* java.security.cert package. It relies on a subclass in the
* java.security.cert packages that is initialized before any of these methods
* are called (achieved via static initializers).
@@ -59,6 +60,8 @@
protected abstract void implSetDateAndTime(X509CRLSelector sel, Date date, long skew);
+ protected abstract boolean implIsJdkCA(TrustAnchor anchor);
+
static void setPathToNames(X509CertSelector sel,
Set<GeneralNameInterface> names) {
instance.implSetPathToNames(sel, names);
@@ -67,4 +70,8 @@
public static void setDateAndTime(X509CRLSelector sel, Date date, long skew) {
instance.implSetDateAndTime(sel, date, skew);
}
+
+ public static boolean isJdkCA(TrustAnchor anchor) {
+ return (anchor == null) ? false : instance.implIsJdkCA(anchor);
+ }
}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java
index e4429e0..5880025 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java
@@ -73,7 +73,7 @@
throws CertStoreException
{
return getCRLs(selector, signFlag, prevKey, null, provider, certStores,
- reasonsMask, trustAnchors, validity, variant);
+ reasonsMask, trustAnchors, validity, variant, null);
}
/**
* Return the X509CRLs matching this selector. The selector must be
@@ -90,8 +90,14 @@
Date validity)
throws CertStoreException
{
+ if (trustAnchors.isEmpty()) {
+ throw new CertStoreException(
+ "at least one TrustAnchor must be specified");
+ }
+ TrustAnchor anchor = trustAnchors.iterator().next();
return getCRLs(selector, signFlag, prevKey, null, provider, certStores,
- reasonsMask, trustAnchors, validity, Validator.VAR_GENERIC);
+ reasonsMask, trustAnchors, validity,
+ Validator.VAR_PLUGIN_CODE_SIGNING, anchor);
}
/**
@@ -107,7 +113,8 @@
boolean[] reasonsMask,
Set<TrustAnchor> trustAnchors,
Date validity,
- String variant)
+ String variant,
+ TrustAnchor anchor)
throws CertStoreException
{
X509Certificate cert = selector.getCertificateChecking();
@@ -136,7 +143,7 @@
DistributionPoint point = t.next();
Collection<X509CRL> crls = getCRLs(selector, certImpl,
point, reasonsMask, signFlag, prevKey, prevCert, provider,
- certStores, trustAnchors, validity, variant);
+ certStores, trustAnchors, validity, variant, anchor);
results.addAll(crls);
}
if (debug != null) {
@@ -161,7 +168,8 @@
X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,
boolean signFlag, PublicKey prevKey, X509Certificate prevCert,
String provider, List<CertStore> certStores,
- Set<TrustAnchor> trustAnchors, Date validity, String variant)
+ Set<TrustAnchor> trustAnchors, Date validity, String variant,
+ TrustAnchor anchor)
throws CertStoreException {
// check for full name
@@ -224,7 +232,7 @@
selector.setIssuerNames(null);
if (selector.match(crl) && verifyCRL(certImpl, point, crl,
reasonsMask, signFlag, prevKey, prevCert, provider,
- trustAnchors, certStores, validity, variant)) {
+ trustAnchors, certStores, validity, variant, anchor)) {
crls.add(crl);
}
} catch (IOException | CRLException e) {
@@ -333,7 +341,8 @@
X509CRL crl, boolean[] reasonsMask, boolean signFlag,
PublicKey prevKey, X509Certificate prevCert, String provider,
Set<TrustAnchor> trustAnchors, List<CertStore> certStores,
- Date validity, String variant) throws CRLException, IOException {
+ Date validity, String variant, TrustAnchor anchor)
+ throws CRLException, IOException {
if (debug != null) {
debug.println("DistributionPointFetcher.verifyCRL: " +
@@ -680,7 +689,7 @@
// check the crl signature algorithm
try {
- AlgorithmChecker.check(prevKey, crl, variant);
+ AlgorithmChecker.check(prevKey, crl, variant, anchor);
} catch (CertPathValidatorException cpve) {
if (debug != null) {
debug.println("CRL signature algorithm check failed: " + cpve);
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java b/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java
index dce7302..a7e17e1 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java
@@ -121,7 +121,8 @@
throws IOException, CertPathValidatorException
{
return check(cert, issuerCert, responderURI, responderCert, date,
- Collections.<Extension>emptyList(), Validator.VAR_GENERIC);
+ Collections.<Extension>emptyList(),
+ Validator.VAR_PLUGIN_CODE_SIGNING);
}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
index 933c6a0..d616367 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2021, 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
@@ -465,6 +465,7 @@
}
// Check whether the signer cert returned by the responder is trusted
+ boolean signedByTrustedResponder = false;
if (signerCert != null) {
// Check if the response is signed by the issuing CA
if (signerCert.getSubjectX500Principal().equals(
@@ -479,6 +480,7 @@
// Check if the response is signed by a trusted responder
} else if (signerCert.equals(responderCert)) {
+ signedByTrustedResponder = true;
if (debug != null) {
debug.println("OCSP response is signed by a Trusted " +
"Responder");
@@ -569,7 +571,10 @@
if (signerCert != null) {
// Check algorithm constraints specified in security property
// "jdk.certpath.disabledAlgorithms".
- AlgorithmChecker.check(signerCert.getPublicKey(), sigAlgId, variant);
+ AlgorithmChecker.check(signerCert.getPublicKey(), sigAlgId, variant,
+ signedByTrustedResponder
+ ? new TrustAnchor(responderCert, null)
+ : issuerInfo.getAnchor());
if (!verifySignature(signerCert)) {
throw new CertPathValidatorException(
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/PKIX.java b/jdk/src/share/classes/sun/security/provider/certpath/PKIX.java
index 8a177c0..b0b18ce 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIX.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIX.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, 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,6 +33,7 @@
import javax.security.auth.x500.X500Principal;
import sun.security.util.Debug;
+import sun.security.validator.Validator;
/**
* Common utility methods and classes used by the PKIX CertPathValidator and
@@ -87,7 +88,7 @@
private Set<TrustAnchor> anchors;
private List<X509Certificate> certs;
private Timestamp timestamp;
- private String variant;
+ private String variant = Validator.VAR_GENERIC;
ValidatorParams(CertPath cp, PKIXParameters params)
throws InvalidAlgorithmParameterException
@@ -155,9 +156,17 @@
}
Date date() {
if (!gotDate) {
- date = params.getDate();
- if (date == null)
- date = new Date();
+ // use timestamp if checking signed code that is
+ // timestamped, otherwise use date parameter
+ if (timestamp != null &&
+ (variant.equals(Validator.VAR_CODE_SIGNING) ||
+ variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING))) {
+ date = timestamp.getTimestamp();
+ } else {
+ date = params.getDate();
+ if (date == null)
+ date = new Date();
+ }
gotDate = true;
}
return date;
@@ -198,10 +207,6 @@
return params;
}
- Timestamp timestamp() {
- return timestamp;
- }
-
String variant() {
return variant;
}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
index 4165a0a..b5dfd5a 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2020, 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
@@ -31,7 +31,6 @@
import java.util.*;
import sun.security.provider.certpath.PKIX.ValidatorParams;
-import sun.security.validator.Validator;
import sun.security.x509.X509CertImpl;
import sun.security.util.Debug;
@@ -174,7 +173,7 @@
// add standard checkers that we will be using
certPathCheckers.add(untrustedChecker);
certPathCheckers.add(new AlgorithmChecker(anchor, null, params.date(),
- params.timestamp(), params.variant()));
+ params.variant()));
certPathCheckers.add(new KeyChecker(certPathLen,
params.targetCertConstraints()));
certPathCheckers.add(new ConstraintsChecker(certPathLen));
@@ -191,19 +190,7 @@
rootNode);
certPathCheckers.add(pc);
- // the time that the certificate validity period should be
- // checked against
- Date timeToCheck = null;
- // use timestamp if checking signed code that is timestamped, otherwise
- // use date parameter from PKIXParameters
- if ((params.variant() == Validator.VAR_CODE_SIGNING ||
- params.variant() == Validator.VAR_PLUGIN_CODE_SIGNING) &&
- params.timestamp() != null) {
- timeToCheck = params.timestamp().getTimestamp();
- } else {
- timeToCheck = params.date();
- }
- BasicChecker bc = new BasicChecker(anchor, timeToCheck,
+ BasicChecker bc = new BasicChecker(anchor, params.date(),
params.sigProvider(), false);
certPathCheckers.add(bc);
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java b/jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java
index c8c5226..7abb65f 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java
@@ -579,7 +579,7 @@
approvedCRLs.addAll(DistributionPointFetcher.getCRLs(
sel, signFlag, prevKey, prevCert,
params.sigProvider(), certStores, reasonsMask,
- anchors, null, params.variant()));
+ anchors, null, params.variant(), anchor));
}
} catch (CertStoreException e) {
if (e instanceof CertStoreTypeException) {
@@ -853,7 +853,7 @@
if (DistributionPointFetcher.verifyCRL(
certImpl, point, crl, reasonsMask, signFlag,
prevKey, null, params.sigProvider(), anchors,
- certStores, params.date(), params.variant()))
+ certStores, params.date(), params.variant(), anchor))
{
results.add(crl);
}
diff --git a/jdk/src/share/classes/sun/security/ssl/SSLContextImpl.java b/jdk/src/share/classes/sun/security/ssl/SSLContextImpl.java
index 7e3115e..cd0e9e9 100644
--- a/jdk/src/share/classes/sun/security/ssl/SSLContextImpl.java
+++ b/jdk/src/share/classes/sun/security/ssl/SSLContextImpl.java
@@ -1374,7 +1374,7 @@
// A forward checker, need to check from trust to target
if (checkedLength >= 0) {
AlgorithmChecker checker =
- new AlgorithmChecker(constraints, null,
+ new AlgorithmChecker(constraints,
(checkClientTrusted ? Validator.VAR_TLS_CLIENT :
Validator.VAR_TLS_SERVER));
checker.init(false);
diff --git a/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java b/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java
index b874cf3..bac96e3 100644
--- a/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java
+++ b/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java
@@ -831,8 +831,7 @@
AlgorithmConstraints constraints, Certificate[] chain,
String variant) {
- AlgorithmChecker checker =
- new AlgorithmChecker(constraints, null, variant);
+ AlgorithmChecker checker = new AlgorithmChecker(constraints, variant);
try {
checker.init(false);
} catch (CertPathValidatorException cpve) {
diff --git a/jdk/src/share/classes/sun/security/util/AnchorCertificates.java b/jdk/src/share/classes/sun/security/util/AnchorCertificates.java
index af77f8f..8ed6a18 100644
--- a/jdk/src/share/classes/sun/security/util/AnchorCertificates.java
+++ b/jdk/src/share/classes/sun/security/util/AnchorCertificates.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2020, 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.Enumeration;
import java.util.HashSet;
import java.util.Set;
+import javax.security.auth.x500.X500Principal;
import sun.security.x509.X509CertImpl;
@@ -47,6 +48,7 @@
private static final Debug debug = Debug.getInstance("certpath");
private static final String HASH = "SHA-256";
private static Set<String> certs = Collections.emptySet();
+ private static Set<X500Principal> certIssuers = Collections.emptySet();
static {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@@ -60,15 +62,16 @@
try (FileInputStream fis = new FileInputStream(f)) {
cacerts.load(fis, null);
certs = new HashSet<>();
+ certIssuers = new HashSet<>();
Enumeration<String> list = cacerts.aliases();
- String alias;
while (list.hasMoreElements()) {
- alias = list.nextElement();
+ String alias = list.nextElement();
// Check if this cert is labeled a trust anchor.
if (alias.contains(" [jdk")) {
X509Certificate cert = (X509Certificate) cacerts
.getCertificate(alias);
certs.add(X509CertImpl.getFingerprint(HASH, cert));
+ certIssuers.add(cert.getSubjectX500Principal());
}
}
}
@@ -84,10 +87,10 @@
}
/**
- * Checks if a certificate is a trust anchor.
+ * Checks if a certificate is a JDK trust anchor.
*
* @param cert the certificate to check
- * @return true if the certificate is trusted.
+ * @return true if the certificate is a JDK trust anchor
*/
public static boolean contains(X509Certificate cert) {
String key = X509CertImpl.getFingerprint(HASH, cert);
@@ -99,5 +102,15 @@
return result;
}
+ /**
+ * Checks if a JDK trust anchor is the issuer of a certificate.
+ *
+ * @param cert the certificate to check
+ * @return true if the certificate is issued by a trust anchor
+ */
+ public static boolean issuerOf(X509Certificate cert) {
+ return certIssuers.contains(cert.getIssuerX500Principal());
+ }
+
private AnchorCertificates() {}
}
diff --git a/jdk/src/share/classes/sun/security/util/ConstraintsParameters.java b/jdk/src/share/classes/sun/security/util/ConstraintsParameters.java
index 8a5ab0f..f7fc4bf 100644
--- a/jdk/src/share/classes/sun/security/util/ConstraintsParameters.java
+++ b/jdk/src/share/classes/sun/security/util/ConstraintsParameters.java
@@ -25,160 +25,42 @@
package sun.security.util;
-import sun.security.validator.Validator;
-
-import java.security.AlgorithmParameters;
import java.security.Key;
-import java.security.Timestamp;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.ECKey;
import java.util.Date;
+import java.util.Set;
/**
- * This class contains parameters for checking against constraints that extend
- * past the publicly available parameters in java.security.AlgorithmConstraints.
-
- * This is currently on passed between between PKIX, AlgorithmChecker,
- * and DisabledAlgorithmConstraints.
+ * This interface contains parameters for checking against constraints that
+ * extend past the publicly available parameters in
+ * java.security.AlgorithmConstraints.
*/
-public class ConstraintsParameters {
- /*
- * The below 3 values are used the same as the permit() methods
- * published in java.security.AlgorithmConstraints.
+public interface ConstraintsParameters {
+
+ /**
+ * Returns true if a certificate chains back to a trusted JDK root CA.
*/
- // Algorithm string to be checked against constraints
- private final String algorithm;
- // AlgorithmParameters to the algorithm being checked
- private final AlgorithmParameters algParams;
- // Key being checked against constraints
- private final Key key;
+ boolean anchorIsJdkCA();
- /*
- * New values that are checked against constraints that the current public
- * API does not support.
+ /**
+ * Returns the set of keys that should be checked against the
+ * constraints, or an empty set if there are no keys to be checked.
*/
- // A certificate being passed to check against constraints.
- private final X509Certificate cert;
- // This is true if the trust anchor in the certificate chain matches a cert
- // in AnchorCertificates
- private final boolean trustedMatch;
- // PKIXParameter date
- private final Date pkixDate;
- // Timestamp of the signed JAR file
- private final Timestamp jarTimestamp;
- private final String variant;
- // Named Curve
- private final String[] curveStr;
- private static final String[] EMPTYLIST = new String[0];
+ Set<Key> getKeys();
- public ConstraintsParameters(X509Certificate c, boolean match,
- Date pkixdate, Timestamp jarTime, String variant) {
- cert = c;
- trustedMatch = match;
- pkixDate = pkixdate;
- jarTimestamp = jarTime;
- this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
- algorithm = null;
- algParams = null;
- key = null;
- if (c != null) {
- curveStr = getNamedCurveFromKey(c.getPublicKey());
- } else {
- curveStr = EMPTYLIST;
- }
- }
+ /**
+ * Returns the date that should be checked against the constraints, or
+ * null if not set.
+ */
+ Date getDate();
- public ConstraintsParameters(String algorithm, AlgorithmParameters params,
- Key key, String variant) {
- this.algorithm = algorithm;
- algParams = params;
- this.key = key;
- curveStr = getNamedCurveFromKey(key);
- cert = null;
- trustedMatch = false;
- pkixDate = null;
- jarTimestamp = null;
- this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
- }
+ /**
+ * Returns the Validator variant.
+ */
+ String getVariant();
-
- public ConstraintsParameters(X509Certificate c) {
- this(c, false, null, null,
- Validator.VAR_GENERIC);
- }
-
- public ConstraintsParameters(Timestamp jarTime) {
- this(null, false, null, jarTime, Validator.VAR_GENERIC);
- }
-
- public String getAlgorithm() {
- return algorithm;
- }
-
- public AlgorithmParameters getAlgParams() {
- return algParams;
- }
-
- public Key getKey() {
- return key;
- }
-
- // Returns if the trust anchor has a match if anchor checking is enabled.
- public boolean isTrustedMatch() {
- return trustedMatch;
- }
-
- public X509Certificate getCertificate() {
- return cert;
- }
-
- public Date getPKIXParamDate() {
- return pkixDate;
- }
-
- public Timestamp getJARTimestamp() {
- return jarTimestamp;
- }
-
- public String getVariant() {
- return variant;
- }
-
- public String[] getNamedCurve() {
- return curveStr;
- }
-
- public static String[] getNamedCurveFromKey(Key key) {
- if (key instanceof ECKey) {
- NamedCurve nc = CurveDB.lookup(((ECKey)key).getParams());
- return (nc == null ? EMPTYLIST : CurveDB.getNamesByOID(nc.getObjectId()));
- } else {
- return EMPTYLIST;
- }
- }
-
- public String toString() {
- StringBuilder s = new StringBuilder();
- s.append("Cert: ");
- if (cert != null) {
- s.append(cert.toString());
- s.append("\nSigAlgo: ");
- s.append(cert.getSigAlgName());
- } else {
- s.append("None");
- }
- s.append("\nAlgParams: ");
- if (getAlgParams() != null) {
- getAlgParams().toString();
- } else {
- s.append("None");
- }
- s.append("\nNamedCurves: ");
- for (String c : getNamedCurve()) {
- s.append(c + " ");
- }
- s.append("\nVariant: " + getVariant());
- return s.toString();
- }
-
+ /**
+ * Returns an extended message used in exceptions. See
+ * DisabledAlgorithmConstraints for usage.
+ */
+ String extendedExceptionMsg();
}
diff --git a/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
index f0a1229..51e6256 100644
--- a/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
+++ b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
@@ -29,14 +29,19 @@
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
-import java.security.CryptoPrimitive;
import java.security.AlgorithmParameters;
+import java.security.CryptoPrimitive;
import java.security.Key;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorException.BasicReason;
-import java.security.cert.X509Certificate;
+import java.security.interfaces.ECKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.PSSParameterSpec;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
@@ -46,6 +51,7 @@
import java.util.Map;
import java.util.Set;
import java.util.Collection;
+import java.util.Collections;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.regex.Pattern;
@@ -80,9 +86,27 @@
private static final String PROPERTY_DISABLED_EC_CURVES =
"jdk.disabled.namedCurves";
+ private static class CertPathHolder {
+ static final DisabledAlgorithmConstraints CONSTRAINTS =
+ new DisabledAlgorithmConstraints(PROPERTY_CERTPATH_DISABLED_ALGS);
+ }
+
+ private static class JarHolder {
+ static final DisabledAlgorithmConstraints CONSTRAINTS =
+ new DisabledAlgorithmConstraints(PROPERTY_JAR_DISABLED_ALGS);
+ }
+
private final List<String> disabledAlgorithms;
private final Constraints algorithmConstraints;
+ public static DisabledAlgorithmConstraints certPathConstraints() {
+ return CertPathHolder.CONSTRAINTS;
+ }
+
+ public static DisabledAlgorithmConstraints jarConstraints() {
+ return JarHolder.CONSTRAINTS;
+ }
+
/**
* Initialize algorithm constraints with the specified security property.
*
@@ -123,7 +147,7 @@
disabledAlgorithms.addAll(ecindex,
getAlgorithms(PROPERTY_DISABLED_EC_CURVES));
}
- algorithmConstraints = new Constraints(disabledAlgorithms);
+ algorithmConstraints = new Constraints(propertyName, disabledAlgorithms);
}
/*
@@ -168,32 +192,54 @@
return checkConstraints(primitives, algorithm, key, parameters);
}
- public final void permits(ConstraintsParameters cp)
- throws CertPathValidatorException {
- permits(cp.getAlgorithm(), cp);
+ public final void permits(String algorithm, AlgorithmParameters ap,
+ ConstraintsParameters cp) throws CertPathValidatorException {
+
+ permits(algorithm, cp);
+ if (ap != null) {
+ permits(ap, cp);
+ }
}
- public final void permits(String algorithm, Key key,
- AlgorithmParameters params, String variant)
- throws CertPathValidatorException {
- permits(algorithm, new ConstraintsParameters(algorithm, params, key,
- (variant == null) ? Validator.VAR_GENERIC : variant));
+ private void permits(AlgorithmParameters ap, ConstraintsParameters cp)
+ throws CertPathValidatorException {
+
+ switch (ap.getAlgorithm().toUpperCase(Locale.ENGLISH)) {
+ case "RSASSA-PSS":
+ permitsPSSParams(ap, cp);
+ break;
+ default:
+ // unknown algorithm, just ignore
+ }
}
- /*
- * Check if a x509Certificate object is permitted. Check if all
- * algorithms are allowed, certificate constraints, and the
- * public key against key constraints.
- *
- * Uses new style permit() which throws exceptions.
- */
+ private void permitsPSSParams(AlgorithmParameters ap,
+ ConstraintsParameters cp) throws CertPathValidatorException {
+
+ try {
+ PSSParameterSpec pssParams =
+ ap.getParameterSpec(PSSParameterSpec.class);
+ String digestAlg = pssParams.getDigestAlgorithm();
+ permits(digestAlg, cp);
+ AlgorithmParameterSpec mgfParams = pssParams.getMGFParameters();
+ if (mgfParams instanceof MGF1ParameterSpec) {
+ String mgfDigestAlg =
+ ((MGF1ParameterSpec)mgfParams).getDigestAlgorithm();
+ if (!mgfDigestAlg.equalsIgnoreCase(digestAlg)) {
+ permits(mgfDigestAlg, cp);
+ }
+ }
+ } catch (InvalidParameterSpecException ipse) {
+ // ignore
+ }
+ }
public final void permits(String algorithm, ConstraintsParameters cp)
throws CertPathValidatorException {
- // Check if named curves in the ConstraintParameters are disabled.
- if (cp.getNamedCurve() != null) {
- for (String curve : cp.getNamedCurve()) {
+ // Check if named curves in the key are disabled.
+ for (Key key : cp.getKeys()) {
+ for (String curve : getNamedCurveFromKey(key)) {
if (!checkAlgorithm(disabledAlgorithms, curve, decomposer)) {
throw new CertPathValidatorException(
"Algorithm constraints check failed on disabled " +
@@ -206,15 +252,14 @@
algorithmConstraints.permits(algorithm, cp);
}
- // Check if a string is contained inside the property
- public boolean checkProperty(String param) {
- param = param.toLowerCase(Locale.ENGLISH);
- for (String block : disabledAlgorithms) {
- if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) {
- return true;
- }
+ private static List<String> getNamedCurveFromKey(Key key) {
+ if (key instanceof ECKey) {
+ NamedCurve nc = CurveDB.lookup(((ECKey)key).getParams());
+ return (nc == null ? Collections.emptyList()
+ : Arrays.asList(CurveDB.getNamesByOID(nc.getObjectId())));
+ } else {
+ return Collections.emptyList();
}
- return false;
}
// Check algorithm constraints with key and algorithm
@@ -238,8 +283,8 @@
return false;
}
- // If this is an elliptic curve, check disabled the named curve.
- for (String curve : ConstraintsParameters.getNamedCurveFromKey(key)) {
+ // If this is an elliptic curve, check if it is disabled
+ for (String curve : getNamedCurveFromKey(key)) {
if (!permits(primitives, curve, null)) {
return false;
}
@@ -276,7 +321,7 @@
"denyAfter\\s+(\\d{4})-(\\d{2})-(\\d{2})");
}
- public Constraints(List<String> constraintArray) {
+ public Constraints(String propertyName, List<String> constraintArray) {
for (String constraintEntry : constraintArray) {
if (constraintEntry == null || constraintEntry.isEmpty()) {
continue;
@@ -391,7 +436,7 @@
}
}
- // Get applicable constraints based off the signature algorithm
+ // Get applicable constraints based off the algorithm
private List<Constraint> getConstraints(String algorithm) {
return constraintsMap.get(algorithm.toUpperCase(Locale.ENGLISH));
}
@@ -435,13 +480,12 @@
return true;
}
- // Check if constraints permit this cert.
public void permits(String algorithm, ConstraintsParameters cp)
throws CertPathValidatorException {
- X509Certificate cert = cp.getCertificate();
if (debug != null) {
- debug.println("Constraints.permits(): " + cp.toString());
+ debug.println("Constraints.permits(): " + algorithm + ", "
+ + cp.toString());
}
// Get all signature algorithms to check for constraints
@@ -451,13 +495,10 @@
algorithms.add(algorithm);
}
- // Attempt to add the public key algorithm if cert provided
- if (cert != null) {
- algorithms.add(cert.getPublicKey().getAlgorithm());
+ for (Key key : cp.getKeys()) {
+ algorithms.add(key.getAlgorithm());
}
- if (cp.getKey() != null) {
- algorithms.add(cp.getKey().getAlgorithm());
- }
+
// Check all applicable constraints
for (String alg : algorithms) {
List<Constraint> list = getConstraints(alg);
@@ -548,7 +589,7 @@
* {@code next()} with the same {@code ConstraintsParameters}
* parameter passed if multiple constraints need to be checked.
*
- * @param cp CertConstraintParameter containing certificate info
+ * @param cp ConstraintsParameter containing certificate info
* @throws CertPathValidatorException if constraint disallows.
*
*/
@@ -597,14 +638,6 @@
boolean next(Key key) {
return nextConstraint != null && nextConstraint.permits(key);
}
-
- String extendedMsg(ConstraintsParameters cp) {
- return (cp.getCertificate() == null ? "." :
- " used with certificate: " +
- cp.getCertificate().getSubjectX500Principal() +
- (cp.getVariant() != Validator.VAR_GENERIC ?
- ". Usage was " + cp.getVariant() : "."));
- }
}
/*
@@ -628,14 +661,15 @@
debug.println("jdkCAConstraints.permits(): " + algorithm);
}
- // Check chain has a trust anchor in cacerts
- if (cp.isTrustedMatch()) {
+ // Check if any certs chain back to at least one trust anchor in
+ // cacerts
+ if (cp.anchorIsJdkCA()) {
if (next(cp)) {
return;
}
throw new CertPathValidatorException(
"Algorithm constraints check failed on certificate " +
- "anchor limits. " + algorithm + extendedMsg(cp),
+ "anchor limits. " + algorithm + cp.extendedExceptionMsg(),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
@@ -700,15 +734,10 @@
Date currentDate;
String errmsg;
- if (cp.getJARTimestamp() != null) {
- currentDate = cp.getJARTimestamp().getTimestamp();
- errmsg = "JAR Timestamp date: ";
- } else if (cp.getPKIXParamDate() != null) {
- currentDate = cp.getPKIXParamDate();
- errmsg = "PKIXParameter date: ";
+ if (cp.getDate() != null) {
+ currentDate = cp.getDate();
} else {
currentDate = new Date();
- errmsg = "Current date: ";
}
if (!denyAfterDate.after(currentDate)) {
@@ -718,8 +747,8 @@
throw new CertPathValidatorException(
"denyAfter constraint check failed: " + algorithm +
" used with Constraint date: " +
- dateFormat.format(denyAfterDate) + "; " + errmsg +
- dateFormat.format(currentDate) + extendedMsg(cp),
+ dateFormat.format(denyAfterDate) + "; params date: " +
+ dateFormat.format(currentDate) + cp.extendedExceptionMsg(),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
@@ -756,19 +785,27 @@
@Override
public void permits(ConstraintsParameters cp)
throws CertPathValidatorException {
+ String variant = cp.getVariant();
for (String usage : usages) {
- String v = null;
- if (usage.compareToIgnoreCase("TLSServer") == 0) {
- v = Validator.VAR_TLS_SERVER;
- } else if (usage.compareToIgnoreCase("TLSClient") == 0) {
- v = Validator.VAR_TLS_CLIENT;
- } else if (usage.compareToIgnoreCase("SignedJAR") == 0) {
- v = Validator.VAR_PLUGIN_CODE_SIGNING;
+ boolean match = false;
+ switch (usage.toLowerCase()) {
+ case "tlsserver":
+ match = variant.equals(Validator.VAR_TLS_SERVER);
+ break;
+ case "tlsclient":
+ match = variant.equals(Validator.VAR_TLS_CLIENT);
+ break;
+ case "signedjar":
+ match =
+ variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING) ||
+ variant.equals(Validator.VAR_CODE_SIGNING) ||
+ variant.equals(Validator.VAR_TSA_SERVER);
+ break;
}
if (debug != null) {
- debug.println("Checking if usage constraint \"" + v +
+ debug.println("Checking if usage constraint \"" + usage +
"\" matches \"" + cp.getVariant() + "\"");
// Because usage checking can come from many places
// a stack trace is very helpful.
@@ -777,13 +814,13 @@
(new Exception()).printStackTrace(ps);
debug.println(ba.toString());
}
- if (cp.getVariant().compareTo(v) == 0) {
+ if (match) {
if (next(cp)) {
return;
}
throw new CertPathValidatorException("Usage constraint " +
usage + " check failed: " + algorithm +
- extendedMsg(cp),
+ cp.extendedExceptionMsg(),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
@@ -837,31 +874,25 @@
}
/*
- * If we are passed a certificate, extract the public key and use it.
- *
- * Check if each constraint fails and check if there is a linked
- * constraint Any permitted constraint will exit the linked list
- * to allow the operation.
+ * For each key, check if each constraint fails and check if there is
+ * a linked constraint. Any permitted constraint will exit the linked
+ * list to allow the operation.
*/
@Override
public void permits(ConstraintsParameters cp)
throws CertPathValidatorException {
- Key key = null;
- if (cp.getKey() != null) {
- key = cp.getKey();
- } else if (cp.getCertificate() != null) {
- key = cp.getCertificate().getPublicKey();
- }
- if (key != null && !permitsImpl(key)) {
- if (nextConstraint != null) {
- nextConstraint.permits(cp);
- return;
- }
- throw new CertPathValidatorException(
- "Algorithm constraints check failed on keysize limits. " +
- algorithm + " " + KeyUtil.getKeySize(key) + "bit key" +
- extendedMsg(cp),
+ for (Key key : cp.getKeys()) {
+ if (!permitsImpl(key)) {
+ if (nextConstraint != null) {
+ nextConstraint.permits(cp);
+ continue;
+ }
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on keysize limits: " +
+ algorithm + " " + KeyUtil.getKeySize(key) + " bit key" +
+ cp.extendedExceptionMsg(),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+ }
}
}
@@ -938,7 +969,7 @@
throws CertPathValidatorException {
throw new CertPathValidatorException(
"Algorithm constraints check failed on disabled " +
- "algorithm: " + algorithm + extendedMsg(cp),
+ "algorithm: " + algorithm + cp.extendedExceptionMsg(),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
diff --git a/jdk/src/share/classes/sun/security/util/JarConstraintsParameters.java b/jdk/src/share/classes/sun/security/util/JarConstraintsParameters.java
new file mode 100644
index 0000000..81fe0ea
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/util/JarConstraintsParameters.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2020, 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 sun.security.util;
+
+import java.security.CodeSigner;
+import java.security.Key;
+import java.security.Timestamp;
+import java.security.cert.CertPath;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import sun.security.util.AnchorCertificates;
+import sun.security.util.ConstraintsParameters;
+import sun.security.validator.Validator;
+
+/**
+ * This class contains parameters for checking signed JARs against
+ * constraints specified in the jdk.jar.disabledAlgorithms security
+ * property.
+ */
+public class JarConstraintsParameters implements ConstraintsParameters {
+
+ // true if chain is anchored by a JDK root CA
+ private boolean anchorIsJdkCA;
+ private boolean anchorIsJdkCASet;
+ // The timestamp of the signed JAR file, if timestamped
+ private Date timestamp;
+ // The keys of the signers
+ private final Set<Key> keys;
+ // The certs in the signers' chains that are issued by the trust anchor
+ private final Set<X509Certificate> certsIssuedByAnchor;
+ // The extended exception message
+ private String message;
+
+ /**
+ * Create a JarConstraintsParameters.
+ *
+ * @param signers the CodeSigners that signed the JAR
+ */
+ public JarConstraintsParameters(CodeSigner[] signers) {
+ this.keys = new HashSet<>();
+ this.certsIssuedByAnchor = new HashSet<>();
+ Date latestTimestamp = null;
+ boolean skipTimestamp = false;
+
+ // Iterate over the signers and extract the keys, the latest
+ // timestamp, and the last certificate of each chain which can be
+ // used for checking if the signer's certificate chains back to a
+ // JDK root CA
+ for (CodeSigner signer : signers) {
+ init(signer.getSignerCertPath());
+ Timestamp timestamp = signer.getTimestamp();
+ if (timestamp == null) {
+ // this means one of the signers doesn't have a timestamp
+ // and the JAR should be treated as if it isn't timestamped
+ latestTimestamp = null;
+ skipTimestamp = true;
+ } else {
+ // add the key and last cert of TSA too
+ init(timestamp.getSignerCertPath());
+ if (!skipTimestamp) {
+ Date timestampDate = timestamp.getTimestamp();
+ if (latestTimestamp == null) {
+ latestTimestamp = timestampDate;
+ } else {
+ if (latestTimestamp.before(timestampDate)) {
+ latestTimestamp = timestampDate;
+ }
+ }
+ }
+ }
+ }
+ this.timestamp = latestTimestamp;
+ }
+
+ // extract last certificate and key from chain
+ private void init(CertPath cp) {
+ @SuppressWarnings("unchecked")
+ List<X509Certificate> chain =
+ (List<X509Certificate>)cp.getCertificates();
+ if (!chain.isEmpty()) {
+ this.certsIssuedByAnchor.add(chain.get(chain.size() - 1));
+ this.keys.add(chain.get(0).getPublicKey());
+ }
+ }
+
+ @Override
+ public String getVariant() {
+ return Validator.VAR_GENERIC;
+ }
+
+ /**
+ * Since loading the cacerts keystore can be an expensive operation,
+ * this is only performed if this method is called during a "jdkCA"
+ * constraints check of a disabled algorithm, and the result is cached.
+ *
+ * @return true if at least one of the certificates are issued by a
+ * JDK root CA
+ */
+ @Override
+ public boolean anchorIsJdkCA() {
+ if (anchorIsJdkCASet) {
+ return anchorIsJdkCA;
+ }
+ for (X509Certificate cert : certsIssuedByAnchor) {
+ if (AnchorCertificates.issuerOf(cert)) {
+ anchorIsJdkCA = true;
+ break;
+ }
+ }
+ anchorIsJdkCASet = true;
+ return anchorIsJdkCA;
+ }
+
+ @Override
+ public Date getDate() {
+ return timestamp;
+ }
+
+ @Override
+ public Set<Key> getKeys() {
+ return keys;
+ }
+
+ /**
+ * Sets the extended error message. Note: this should be used
+ * carefully as it is specific to the attribute/entry/file being checked.
+ *
+ * @param file the name of the signature related file being verified
+ * @param target the attribute containing the algorithm that is being
+ * checked
+ */
+ public void setExtendedExceptionMsg(String file, String target) {
+ message = " used" + (target != null ? " with " + target : "") +
+ " in " + file + " file.";
+ }
+
+ @Override
+ public String extendedExceptionMsg() {
+ return message;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("[\n");
+ sb.append("\n Variant: ").append(getVariant());
+ sb.append("\n Certs Issued by Anchor:");
+ for (X509Certificate cert : certsIssuedByAnchor) {
+ sb.append("\n Cert Issuer: ")
+ .append(cert.getIssuerX500Principal());
+ sb.append("\n Cert Subject: ")
+ .append(cert.getSubjectX500Principal());
+ }
+ for (Key key : keys) {
+ sb.append("\n Key: ").append(key.getAlgorithm());
+ }
+ if (timestamp != null) {
+ sb.append("\n Timestamp: ").append(timestamp);
+ }
+ sb.append("\n]");
+ return sb.toString();
+ }
+}
diff --git a/jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java b/jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java
index 02dd765..9a6de1f 100644
--- a/jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java
+++ b/jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2020, 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
@@ -27,13 +27,12 @@
import java.security.*;
import java.io.*;
-import java.security.CodeSigner;
import java.util.*;
import java.util.jar.*;
-import java.util.Base64;
-
import sun.security.jca.Providers;
+import sun.security.util.DisabledAlgorithmConstraints;
+import sun.security.util.JarConstraintsParameters;
/**
* This class is used to verify each entry in a jar file with its
@@ -202,12 +201,29 @@
throw new SecurityException("digest missing for " + name);
}
- if (signers != null)
+ if (signers != null) {
return signers;
+ }
+
+ JarConstraintsParameters params =
+ getParams(verifiedSigners, sigFileSigners);
for (int i=0; i < digests.size(); i++) {
- MessageDigest digest = digests.get(i);
+ MessageDigest digest = digests.get(i);
+ if (params != null) {
+ try {
+ params.setExtendedExceptionMsg(JarFile.MANIFEST_NAME,
+ name + " entry");
+ DisabledAlgorithmConstraints.jarConstraints()
+ .permits(digest.getAlgorithm(), params);
+ } catch (GeneralSecurityException e) {
+ if (debug != null) {
+ debug.println("Digest algorithm is restricted: " + e);
+ }
+ return null;
+ }
+ }
byte [] manHash = manifestHashes.get(i);
byte [] theHash = digest.digest();
@@ -232,6 +248,38 @@
return signers;
}
+ /**
+ * Get constraints parameters for JAR. The constraints should be
+ * checked against all code signers. Returns the parameters,
+ * or null if the signers for this entry have already been checked.
+ */
+ private JarConstraintsParameters getParams(
+ Map<String, CodeSigner[]> verifiedSigners,
+ Map<String, CodeSigner[]> sigFileSigners) {
+
+ // verifiedSigners is usually preloaded with the Manifest's signers.
+ // If verifiedSigners contains the Manifest, then it will have all of
+ // the signers of the JAR. But if it doesn't then we need to fallback
+ // and check verifiedSigners to see if the signers of this entry have
+ // been checked already.
+ if (verifiedSigners.containsKey(JarFile.MANIFEST_NAME)) {
+ if (verifiedSigners.size() > 1) {
+ // this means we already checked it previously
+ return null;
+ } else {
+ return new JarConstraintsParameters(
+ verifiedSigners.get(JarFile.MANIFEST_NAME));
+ }
+ } else {
+ CodeSigner[] signers = sigFileSigners.get(name);
+ if (verifiedSigners.containsValue(signers)) {
+ return null;
+ } else {
+ return new JarConstraintsParameters(signers);
+ }
+ }
+ }
+
// for the toHex function
private static final char[] hexc =
{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
diff --git a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java
index 8301502..f34307b 100644
--- a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java
+++ b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2020, 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,7 +32,6 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
-import java.security.Timestamp;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
@@ -45,6 +44,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarException;
import java.util.jar.JarFile;
@@ -59,10 +59,6 @@
/* Are we debugging ? */
private static final Debug debug = Debug.getInstance("jar");
- private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK =
- new DisabledAlgorithmConstraints(
- DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
-
private ArrayList<CodeSigner[]> signerCache;
private static final String ATTR_DIGEST =
@@ -92,13 +88,13 @@
/* for generating certpath objects */
private CertificateFactory certificateFactory = null;
- /** Algorithms that have been checked if they are weak. */
- private Map<String, Boolean> permittedAlgs= new HashMap<>();
-
- /** TSA timestamp of signed jar. The newest timestamp is used. If there
- * was no TSA timestamp used when signed, current time is used ("null").
+ /** Algorithms that have been previously checked against disabled
+ * constraints.
*/
- private Timestamp timestamp = null;
+ private Map<String, Boolean> permittedAlgs = new HashMap<>();
+
+ /** ConstraintsParameters for checking disabled algorithms */
+ private JarConstraintsParameters params;
/**
* Create the named SignatureFileVerifier.
@@ -291,32 +287,23 @@
name);
}
-
CodeSigner[] newSigners = getSigners(infos, block);
// make sure we have something to do all this work for...
- if (newSigners == null)
+ if (newSigners == null) {
return;
+ }
- /*
- * Look for the latest timestamp in the signature block. If an entry
- * has no timestamp, use current time (aka null).
- */
- for (CodeSigner s: newSigners) {
- if (debug != null) {
- debug.println("Gathering timestamp for: " + s.toString());
- }
- if (s.getTimestamp() == null) {
- timestamp = null;
- break;
- } else if (timestamp == null) {
- timestamp = s.getTimestamp();
- } else {
- if (timestamp.getTimestamp().before(
- s.getTimestamp().getTimestamp())) {
- timestamp = s.getTimestamp();
- }
- }
+ // check if any of the algorithms used to verify the SignerInfos
+ // are disabled
+ params = new JarConstraintsParameters(newSigners);
+ Set<String> notDisabledAlgorithms =
+ SignerInfo.verifyAlgorithms(infos, params, name + " PKCS7");
+
+ // add the SignerInfo algorithms that are ok to the permittedAlgs map
+ // so they are not checked again
+ for (String algorithm : notDisabledAlgorithms) {
+ permittedAlgs.put(algorithm, Boolean.TRUE);
}
Iterator<Map.Entry<String,Attributes>> entries =
@@ -367,13 +354,14 @@
* store the result. If the algorithm is in the map use that result.
* False is returned for weak algorithm, true for good algorithms.
*/
- boolean permittedCheck(String key, String algorithm) {
+ private boolean permittedCheck(String key, String algorithm) {
Boolean permitted = permittedAlgs.get(algorithm);
if (permitted == null) {
try {
- JAR_DISABLED_CHECK.permits(algorithm,
- new ConstraintsParameters(timestamp));
- } catch(GeneralSecurityException e) {
+ params.setExtendedExceptionMsg(name + ".SF", key + " attribute");
+ DisabledAlgorithmConstraints
+ .jarConstraints().permits(algorithm, params);
+ } catch (GeneralSecurityException e) {
permittedAlgs.put(algorithm, Boolean.FALSE);
permittedAlgs.put(key.toUpperCase(), Boolean.FALSE);
if (debug != null) {
diff --git a/jdk/src/share/classes/sun/security/validator/PKIXValidator.java b/jdk/src/share/classes/sun/security/validator/PKIXValidator.java
index b196a19..80bee9e 100644
--- a/jdk/src/share/classes/sun/security/validator/PKIXValidator.java
+++ b/jdk/src/share/classes/sun/security/validator/PKIXValidator.java
@@ -239,7 +239,7 @@
// add a new algorithm constraints checker
if (constraints != null) {
pkixParameters.addCertPathChecker(
- new AlgorithmChecker(constraints, null, variant));
+ new AlgorithmChecker(constraints, variant));
}
// attach it to the PKIXBuilderParameters.
diff --git a/jdk/src/share/classes/sun/security/validator/SimpleValidator.java b/jdk/src/share/classes/sun/security/validator/SimpleValidator.java
index d426a21..a18e3ce 100644
--- a/jdk/src/share/classes/sun/security/validator/SimpleValidator.java
+++ b/jdk/src/share/classes/sun/security/validator/SimpleValidator.java
@@ -162,7 +162,7 @@
AlgorithmChecker appAlgChecker = null;
if (constraints != null) {
appAlgChecker = new AlgorithmChecker(anchor, constraints, null,
- null, variant);
+ variant);
}
// verify top down, starting at the certificate issued by
diff --git a/jdk/src/share/classes/sun/security/x509/AlgorithmId.java b/jdk/src/share/classes/sun/security/x509/AlgorithmId.java
index d363e6e..502c52f 100644
--- a/jdk/src/share/classes/sun/security/x509/AlgorithmId.java
+++ b/jdk/src/share/classes/sun/security/x509/AlgorithmId.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2021, 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,6 +81,7 @@
*/
protected DerValue params;
+ private transient byte[] encodedParams;
/**
* Constructs an algorithm ID which will be initialized
@@ -109,6 +110,18 @@
algid = oid;
algParams = algparams;
constructedFromDer = false;
+ if (algParams != null) {
+ try {
+ encodedParams = algParams.getEncoded();
+ } catch (IOException ioe) {
+ // It should be safe to ignore this.
+ // This exception can occur if AlgorithmParameters was not
+ // initialized (which should not occur), or if it was
+ // initialized with bogus parameters, which should have
+ // been detected when init was called.
+ assert false;
+ }
+ }
}
private AlgorithmId(ObjectIdentifier oid, DerValue params)
@@ -116,6 +129,7 @@
this.algid = oid;
this.params = params;
if (this.params != null) {
+ encodedParams = params.toByteArray();
decodeParams();
}
}
@@ -134,7 +148,7 @@
}
// Decode (parse) the parameters
- algParams.init(params.toByteArray());
+ algParams.init(encodedParams.clone());
}
/**
@@ -153,6 +167,7 @@
*
* @exception IOException on encoding error.
*/
+ @Override
public void derEncode (OutputStream out) throws IOException {
DerOutputStream bytes = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream();
@@ -160,8 +175,8 @@
bytes.putOID(algid);
// Setup params from algParams since no DER encoding is given
if (constructedFromDer == false) {
- if (algParams != null) {
- params = new DerValue(algParams.getEncoded());
+ if (encodedParams != null) {
+ params = new DerValue(encodedParams);
} else {
params = null;
}
@@ -248,7 +263,7 @@
if ((params != null) && algid.equals((Object)specifiedWithECDSA_oid)) {
try {
AlgorithmId paramsId =
- AlgorithmId.parse(new DerValue(params.toByteArray()));
+ AlgorithmId.parse(new DerValue(encodedParams));
String paramsName = paramsId.getName();
algName = makeSigAlg(paramsName, "EC");
} catch (IOException e) {
@@ -266,6 +281,10 @@
* Returns the DER encoded parameter, which can then be
* used to initialize java.security.AlgorithmParameters.
*
+ * Note that this* method should always return a new array as it is called
+ * directly by the JDK implementation of X509Certificate.getSigAlgParams()
+ * and X509CRL.getSigAlgParams().
+ *
* Note: for ecdsa-with-SHA2 plus hash algorithm (Ex: SHA-256), this method
* returns null because {@link #getName()} has already returned the "full"
* signature algorithm (Ex: SHA256withECDSA).
@@ -273,9 +292,9 @@
* @return DER encoded parameters, or null not present.
*/
public byte[] getEncodedParams() throws IOException {
- return (params == null || algid.equals(specifiedWithECDSA_oid))
+ return (encodedParams == null || algid.equals(specifiedWithECDSA_oid))
? null
- : params.toByteArray();
+ : encodedParams.clone();
}
/**
@@ -283,9 +302,8 @@
* with the same parameters.
*/
public boolean equals(AlgorithmId other) {
- boolean paramsEqual =
- (params == null ? other.params == null : params.equals(other.params));
- return (algid.equals((Object)other.algid) && paramsEqual);
+ return algid.equals((Object)other.algid) &&
+ Arrays.equals(encodedParams, other.encodedParams);
}
/**
@@ -295,6 +313,7 @@
*
* @param other preferably an AlgorithmId, else an ObjectIdentifier
*/
+ @Override
public boolean equals(Object other) {
if (this == other) {
return true;
@@ -321,11 +340,11 @@
*
* @return a hashcode for this AlgorithmId.
*/
+ @Override
public int hashCode() {
- StringBuilder sbuf = new StringBuilder();
- sbuf.append(algid.toString());
- sbuf.append(paramsToString());
- return sbuf.toString().hashCode();
+ int hashCode = algid.hashCode();
+ hashCode = 31 * hashCode + Arrays.hashCode(encodedParams);
+ return hashCode;
}
/**
@@ -333,10 +352,10 @@
* This may be redefined by subclasses which parse those parameters.
*/
protected String paramsToString() {
- if (params == null) {
+ if (encodedParams == null) {
return "";
} else if (algParams != null) {
- return algParams.toString();
+ return ", " + algParams.toString();
} else {
return ", params unparsed";
}
@@ -345,6 +364,7 @@
/**
* Returns a string describing the algorithm and its parameters.
*/
+ @Override
public String toString() {
return getName() + paramsToString();
}
diff --git a/jdk/src/share/lib/security/java.security-aix b/jdk/src/share/lib/security/java.security-aix
index da45e1e..44d746b 100644
--- a/jdk/src/share/lib/security/java.security-aix
+++ b/jdk/src/share/lib/security/java.security-aix
@@ -1191,3 +1191,26 @@
# System value prevails. The default value of the property is "false".
#
#jdk.security.allowNonCaAnchor=true
+
+#
+# JNDI Object Factories Filter
+#
+# This filter is used by the JNDI runtime to control the set of object factory classes
+# which will be allowed to instantiate objects from object references returned by
+# naming/directory systems. The factory class named by the reference instance will be
+# matched against this filter. The filter property supports pattern-based filter syntax
+# with the same format as jdk.serialFilter.
+#
+# Each pattern is matched against the factory class name to allow or disallow it's
+# instantiation. The access to a factory class is allowed unless the filter returns
+# REJECTED.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# If the system property jdk.jndi.object.factoriesFilter is also specified, it supersedes
+# the security property value defined here. The default value of the property is "*".
+#
+# The default pattern value allows any object factory class specified by the reference
+# instance to recreate the referenced object.
+#jdk.jndi.object.factoriesFilter=*
\ No newline at end of file
diff --git a/jdk/src/share/lib/security/java.security-linux b/jdk/src/share/lib/security/java.security-linux
index 2d3b9a4..87f8a31 100644
--- a/jdk/src/share/lib/security/java.security-linux
+++ b/jdk/src/share/lib/security/java.security-linux
@@ -1197,3 +1197,26 @@
# System value prevails. The default value of the property is "false".
#
#jdk.security.allowNonCaAnchor=true
+
+#
+# JNDI Object Factories Filter
+#
+# This filter is used by the JNDI runtime to control the set of object factory classes
+# which will be allowed to instantiate objects from object references returned by
+# naming/directory systems. The factory class named by the reference instance will be
+# matched against this filter. The filter property supports pattern-based filter syntax
+# with the same format as jdk.serialFilter.
+#
+# Each pattern is matched against the factory class name to allow or disallow it's
+# instantiation. The access to a factory class is allowed unless the filter returns
+# REJECTED.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# If the system property jdk.jndi.object.factoriesFilter is also specified, it supersedes
+# the security property value defined here. The default value of the property is "*".
+#
+# The default pattern value allows any object factory class specified by the reference
+# instance to recreate the referenced object.
+#jdk.jndi.object.factoriesFilter=*
\ No newline at end of file
diff --git a/jdk/src/share/lib/security/java.security-macosx b/jdk/src/share/lib/security/java.security-macosx
index 6589ba9..6c0f7a5 100644
--- a/jdk/src/share/lib/security/java.security-macosx
+++ b/jdk/src/share/lib/security/java.security-macosx
@@ -1195,3 +1195,26 @@
# System value prevails. The default value of the property is "false".
#
#jdk.security.allowNonCaAnchor=true
+
+#
+# JNDI Object Factories Filter
+#
+# This filter is used by the JNDI runtime to control the set of object factory classes
+# which will be allowed to instantiate objects from object references returned by
+# naming/directory systems. The factory class named by the reference instance will be
+# matched against this filter. The filter property supports pattern-based filter syntax
+# with the same format as jdk.serialFilter.
+#
+# Each pattern is matched against the factory class name to allow or disallow it's
+# instantiation. The access to a factory class is allowed unless the filter returns
+# REJECTED.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# If the system property jdk.jndi.object.factoriesFilter is also specified, it supersedes
+# the security property value defined here. The default value of the property is "*".
+#
+# The default pattern value allows any object factory class specified by the reference
+# instance to recreate the referenced object.
+#jdk.jndi.object.factoriesFilter=*
\ No newline at end of file
diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris
index 762bdc8..cd0a720 100644
--- a/jdk/src/share/lib/security/java.security-solaris
+++ b/jdk/src/share/lib/security/java.security-solaris
@@ -1193,3 +1193,26 @@
# System value prevails. The default value of the property is "false".
#
#jdk.security.allowNonCaAnchor=true
+
+#
+# JNDI Object Factories Filter
+#
+# This filter is used by the JNDI runtime to control the set of object factory classes
+# which will be allowed to instantiate objects from object references returned by
+# naming/directory systems. The factory class named by the reference instance will be
+# matched against this filter. The filter property supports pattern-based filter syntax
+# with the same format as jdk.serialFilter.
+#
+# Each pattern is matched against the factory class name to allow or disallow it's
+# instantiation. The access to a factory class is allowed unless the filter returns
+# REJECTED.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# If the system property jdk.jndi.object.factoriesFilter is also specified, it supersedes
+# the security property value defined here. The default value of the property is "*".
+#
+# The default pattern value allows any object factory class specified by the reference
+# instance to recreate the referenced object.
+#jdk.jndi.object.factoriesFilter=*
\ No newline at end of file
diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows
index 757f2d1..3951655 100644
--- a/jdk/src/share/lib/security/java.security-windows
+++ b/jdk/src/share/lib/security/java.security-windows
@@ -1195,3 +1195,26 @@
# System value prevails. The default value of the property is "false".
#
#jdk.security.allowNonCaAnchor=true
+
+#
+# JNDI Object Factories Filter
+#
+# This filter is used by the JNDI runtime to control the set of object factory classes
+# which will be allowed to instantiate objects from object references returned by
+# naming/directory systems. The factory class named by the reference instance will be
+# matched against this filter. The filter property supports pattern-based filter syntax
+# with the same format as jdk.serialFilter.
+#
+# Each pattern is matched against the factory class name to allow or disallow it's
+# instantiation. The access to a factory class is allowed unless the filter returns
+# REJECTED.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# If the system property jdk.jndi.object.factoriesFilter is also specified, it supersedes
+# the security property value defined here. The default value of the property is "*".
+#
+# The default pattern value allows any object factory class specified by the reference
+# instance to recreate the referenced object.
+#jdk.jndi.object.factoriesFilter=*
\ No newline at end of file
diff --git a/jdk/src/windows/classes/java/lang/ProcessImpl.java b/jdk/src/windows/classes/java/lang/ProcessImpl.java
index 5c43ef7..92c6db1 100644
--- a/jdk/src/windows/classes/java/lang/ProcessImpl.java
+++ b/jdk/src/windows/classes/java/lang/ProcessImpl.java
@@ -181,9 +181,9 @@
private static final char ESCAPE_VERIFICATION[][] = {
// We guarantee the only command file execution for implicit [cmd.exe] run.
// http://technet.microsoft.com/en-us/library/bb490954.aspx
- {' ', '\t', '<', '>', '&', '|', '^'},
- {' ', '\t', '<', '>'},
- {' ', '\t', '<', '>'},
+ {' ', '\t', '\"', '<', '>', '&', '|', '^'},
+ {' ', '\t', '\"', '<', '>'},
+ {' ', '\t', '\"', '<', '>'},
{' ', '\t'}
};
@@ -243,18 +243,27 @@
}
/**
- * Return the argument without quotes (1st and last) if present, else the arg.
+ * Return the argument without quotes (1st and last) if properly quoted, else the arg.
+ * A properly quoted string has first and last characters as quote and
+ * the last quote is not escaped.
* @param str a string
- * @return the string without 1st and last quotes
+ * @return the string without quotes
*/
private static String unQuote(String str) {
- int len = str.length();
- return (len >= 2 && str.charAt(0) == DOUBLEQUOTE && str.charAt(len - 1) == DOUBLEQUOTE)
- ? str.substring(1, len - 1)
- : str;
+ if (!str.startsWith("\"") || !str.endsWith("\"") || str.length() < 2)
+ return str; // no beginning or ending quote, or too short not quoted
+
+ if (str.endsWith("\\\"")) {
+ return str; // not properly quoted, treat as unquoted
+ }
+ // Strip leading and trailing quotes
+ return str.substring(1, str.length() - 1);
}
private static boolean needsEscaping(int verificationType, String arg) {
+ if (arg.isEmpty())
+ return true; // Empty string is to be quoted
+
// Switch off MS heuristic for internal ["].
// Please, use the explicit [cmd.exe] call
// if you need the internal ["].
diff --git a/jdk/test/java/security/cert/X509Certificate/GetSigAlgParams.java b/jdk/test/java/security/cert/X509Certificate/GetSigAlgParams.java
new file mode 100644
index 0000000..aaec28c
--- /dev/null
+++ b/jdk/test/java/security/cert/X509Certificate/GetSigAlgParams.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8259428
+ * @summary Verify X509Certificate.getSigAlgParams() returns new array each
+ * time it is called
+ */
+
+import java.security.cert.X509Certificate;
+import sun.security.tools.keytool.CertAndKeyGen;
+import sun.security.x509.X500Name;
+
+public class GetSigAlgParams {
+
+ public static void main(String[] args) throws Exception {
+
+ CertAndKeyGen cakg = new CertAndKeyGen("RSASSA-PSS", "RSASSA-PSS");
+ cakg.generate(1024);
+ X509Certificate c = cakg.getSelfCertificate(new X500Name("CN=Me"), 100);
+ if (c.getSigAlgParams() == c.getSigAlgParams()) {
+ throw new Exception("Encoded params are the same byte array");
+ }
+ }
+}
diff --git a/jdk/test/sun/security/pkcs/pkcs8/PKCS8Test.java b/jdk/test/sun/security/pkcs/pkcs8/PKCS8Test.java
index af40667..f8f9383 100644
--- a/jdk/test/sun/security/pkcs/pkcs8/PKCS8Test.java
+++ b/jdk/test/sun/security/pkcs/pkcs8/PKCS8Test.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2021, 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
@@ -53,7 +53,7 @@
static final DerOutputStream derOutput = new DerOutputStream();
static final String FORMAT = "PKCS#8";
- static final String EXPECTED_ALG_ID_CHRS = "DSA\n\tp: 02\n\tq: 03\n"
+ static final String EXPECTED_ALG_ID_CHRS = "DSA, \n\tp: 02\n\tq: 03\n"
+ "\tg: 04\n";
static final String ALGORITHM = "DSA";
static final String EXCEPTION_MESSAGE = "version mismatch: (supported: "
diff --git a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
index c96666e..8578324 100644
--- a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
+++ b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
@@ -450,7 +450,7 @@
sign("tsdisabled", "-digestalg", "MD5",
"-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
.shouldHaveExitValue(68)
- .shouldContain("The timestamp is invalid. Without a valid timestamp")
+ .shouldContain("TSA certificate chain is invalid")
.shouldMatch("MD5.*-digestalg.*is disabled")
.shouldMatch("MD5.*-tsadigestalg.*is disabled")
.shouldMatch("MD5withRSA.*-sigalg.*is disabled");
@@ -458,7 +458,6 @@
signVerbose("tsdisabled", "unsigned.jar", "tsdisabled2.jar", "signer")
.shouldHaveExitValue(64)
- .shouldContain("The timestamp is invalid. Without a valid timestamp")
.shouldContain("TSA certificate chain is invalid");
// Disabled timestamp is an error and jar treated unsigned
@@ -771,7 +770,7 @@
.shouldMatch("Timestamp signature algorithm: .*key.*(disabled)");
verify(file, "-J-Djava.security.debug=jar")
.shouldHaveExitValue(16)
- .shouldMatch("SignatureException:.*disabled");
+ .shouldMatch("SignatureException:.*keysize");
}
static void checkHalfWeak(String file) throws Exception {
diff --git a/jdk/test/sun/security/x509/AlgorithmId/AlgorithmIdEqualsHashCode.java b/jdk/test/sun/security/x509/AlgorithmId/AlgorithmIdEqualsHashCode.java
index 00ac82f..a634f07 100644
--- a/jdk/test/sun/security/x509/AlgorithmId/AlgorithmIdEqualsHashCode.java
+++ b/jdk/test/sun/security/x509/AlgorithmId/AlgorithmIdEqualsHashCode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2021, 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,12 +24,16 @@
/*
* @test
* @author Gary Ellison
- * @bug 4170635
+ * @bug 4170635 8258247
* @summary Verify equals()/hashCode() contract honored
*/
import java.io.*;
+import java.security.AlgorithmParameters;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.PSSParameterSpec;
+import sun.security.util.DerValue;
import sun.security.x509.*;
public class AlgorithmIdEqualsHashCode {
@@ -40,7 +44,6 @@
AlgorithmId ai2 = AlgorithmId.get("DH");
AlgorithmId ai3 = AlgorithmId.get("DH");
-
// supposedly transitivity is broken
// System.out.println(ai1.equals(ai2));
// System.out.println(ai2.equals(ai3));
@@ -56,5 +59,42 @@
else
throw new Exception("Failed equals()/hashCode() contract");
+ // check that AlgorithmIds with same name but different params
+ // are not equal
+ AlgorithmParameters algParams1 =
+ AlgorithmParameters.getInstance("RSASSA-PSS");
+ AlgorithmParameters algParams2 =
+ AlgorithmParameters.getInstance("RSASSA-PSS");
+ algParams1.init(new PSSParameterSpec("SHA-1", "MGF1",
+ MGF1ParameterSpec.SHA1, 20, PSSParameterSpec.TRAILER_FIELD_BC));
+ algParams2.init(new PSSParameterSpec("SHA-256", "MGF1",
+ MGF1ParameterSpec.SHA1, 20, PSSParameterSpec.TRAILER_FIELD_BC));
+ ai1 = new AlgorithmId(AlgorithmId.RSASSA_PSS_oid, algParams1);
+ ai2 = new AlgorithmId(AlgorithmId.RSASSA_PSS_oid, algParams2);
+ if (ai1.equals(ai2)) {
+ throw new Exception("Failed equals() contract");
+ } else {
+ System.out.println("PASSED equals() test");
+ }
+
+ // check that two AlgorithmIds created with the same parameters but
+ // one with DER encoded parameters and the other with
+ // AlgorithmParameters are equal
+ byte[] encoded = ai1.encode();
+ ai3 = AlgorithmId.parse(new DerValue(encoded));
+ if (!ai1.equals(ai3)) {
+ throw new Exception("Failed equals() contract");
+ } else {
+ System.out.println("PASSED equals() test");
+ }
+
+ // check that two AlgorithmIds created with different parameters but
+ // one with DER encoded parameters and the other with
+ // AlgorithmParameters are not equal
+ if (ai2.equals(ai3)) {
+ throw new Exception("Failed equals() contract");
+ } else {
+ System.out.println("PASSED equals() test");
+ }
}
}
diff --git a/langtools/.hgtags b/langtools/.hgtags
index aa0c06d..3ab6120 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -1086,3 +1086,4 @@
21738367961ed2263de0fc0b9eca36da78e51674 jdk8u292-b06
376b8ec147cf881c1139331f64c258bfc1550119 jdk8u292-b07
65614a3f68a2ef8a853f2c0505b8bbbf3a1414c3 jdk8u292-b08
+eabecd4e5adc603f93dc891b6245f8164d97517d jdk8u292-b09
diff --git a/nashorn/.hgtags b/nashorn/.hgtags
index 7eb463e..28c99ea 100644
--- a/nashorn/.hgtags
+++ b/nashorn/.hgtags
@@ -1120,3 +1120,4 @@
c9e3db7c1e846089d9ed3625facaca4c86309e1d jdk8u292-b06
931e337c2cd5abfbcacd6097ae8fb5b3ef41508f jdk8u292-b07
49a8f2a3868880ef94d5381964deb17fa2b4b71c jdk8u292-b08
+fcc7f620398f1b641bf7c9dc508df2f741dd5659 jdk8u292-b09