# HG changeset patch # User Andrew John Hughes # Date 1604283987 0 # Node ID b8b51d9e706f77f7e4588e45a7802ee6445350cc # Parent 1a9e79164f5eaa8dd2c812b14d760a5f510c2324# Parent 56d605a523882681de2bd6497e0372ccdf537185 Merge jdk7u281-ga diff -r 1a9e79164f5e -r b8b51d9e706f .hgtags --- a/.hgtags Sat Sep 26 19:05:32 2020 +0100 +++ b/.hgtags Mon Nov 02 02:26:27 2020 +0000 @@ -725,3 +725,6 @@ 5b06aa7a2fcc0e17cafbcce2456978da85677c56 jdk7u271-ga 6d1d19e80aa0dab8aa3e9b53549b0c91d3f2798d icedtea-2.6.23 6d1d19e80aa0dab8aa3e9b53549b0c91d3f2798d icedtea-2.6.24pre00 +5b06aa7a2fcc0e17cafbcce2456978da85677c56 jdk7u281-b00 +963d6ac6635a93e024892a977b7cf31974c820be jdk7u281-b01 +963d6ac6635a93e024892a977b7cf31974c820be jdk7u281-ga diff -r 1a9e79164f5e -r b8b51d9e706f src/share/classes/com/sun/jndi/ldap/Connection.java --- a/src/share/classes/com/sun/jndi/ldap/Connection.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/classes/com/sun/jndi/ldap/Connection.java Mon Nov 02 02:26:27 2020 +0000 @@ -158,6 +158,13 @@ int readTimeout; int connectTimeout; + + // Is connection upgraded to SSL via STARTTLS extended operation + private volatile boolean isUpgradedToStartTls; + + // Lock to maintain isUpgradedToStartTls state + final Object startTlsLock = new Object(); + private static final boolean IS_HOSTNAME_VERIFICATION_DISABLED = hostnameVerificationDisabledValue(); @@ -745,6 +752,23 @@ outStream = newOut; } + /* + * Replace streams and set isUpdradedToStartTls flag to the provided value + */ + synchronized public void replaceStreams(InputStream newIn, OutputStream newOut, boolean isStartTls) { + synchronized (startTlsLock) { + replaceStreams(newIn, newOut); + isUpgradedToStartTls = isStartTls; + } + } + + /* + * Returns true if connection was upgraded to SSL with STARTTLS extended operation + */ + public boolean isUpgradedToStartTls() { + return isUpgradedToStartTls; + } + /** * Used by Connection thread to read inStream into a local variable. * This ensures that there is no contention between the main thread @@ -899,6 +923,11 @@ // is equal to & 0x80 (i.e. length byte with high bit off). if ((seqlen & 0x80) == 0x80) { seqlenlen = seqlen & 0x7f; // number of length bytes + // Check the length of length field, since seqlen is int + // the number of bytes can't be greater than 4 + if (seqlenlen > 4) { + throw new IOException("Length coded with too many bytes: " + seqlenlen); + } bytesread = 0; eos = false; @@ -926,6 +955,13 @@ offset += bytesread; } + if (seqlenlen > bytesread) { + throw new IOException("Unexpected EOF while reading length"); + } + + if (seqlen < 0) { + throw new IOException("Length too big: " + (((long) seqlen) & 0xFFFFFFFFL)); + } // read in seqlen bytes byte[] left = readFully(in, seqlen); inbuf = Arrays.copyOf(inbuf, offset + left.length); diff -r 1a9e79164f5e -r b8b51d9e706f src/share/classes/com/sun/jndi/ldap/LdapClient.java --- a/src/share/classes/com/sun/jndi/ldap/LdapClient.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/classes/com/sun/jndi/ldap/LdapClient.java Mon Nov 02 02:26:27 2020 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, 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 @@ -396,6 +396,12 @@ return (conn.inStream instanceof SaslInputStream); } + // Returns true if client connection was upgraded + // with STARTTLS extended operation on the server side + boolean isUpgradedToStartTls() { + return conn.isUpgradedToStartTls(); + } + synchronized void incRefCount() { ++referenceCount; if (debug > 1) { diff -r 1a9e79164f5e -r b8b51d9e706f src/share/classes/com/sun/jndi/ldap/LdapCtx.java --- a/src/share/classes/com/sun/jndi/ldap/LdapCtx.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/classes/com/sun/jndi/ldap/LdapCtx.java Mon Nov 02 02:26:27 2020 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, 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 @@ -33,13 +33,19 @@ import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; import java.util.Locale; +import java.util.Set; import java.util.Vector; import java.util.Hashtable; +import java.util.HashSet; import java.util.List; import java.util.StringTokenizer; import java.util.Enumeration; + import java.io.IOException; import java.io.OutputStream; @@ -200,6 +206,27 @@ private static final String REPLY_QUEUE_SIZE = "com.sun.jndi.ldap.search.replyQueueSize"; + // System and environment property name to control allowed list of + // authentication mechanisms: "all" or "" or "mech1,mech2,...,mechN" + // "all": allow all mechanisms, + // "": allow none + // or comma separated list of allowed authentication mechanisms + // Note: "none" or "anonymous" are always allowed. + private static final String ALLOWED_MECHS_SP = + "jdk.jndi.ldap.mechsAllowedToSendCredentials"; + + // System property value + private static final String ALLOWED_MECHS_SP_VALUE = + getMechsAllowedToSendCredentials(); + + // Set of authentication mechanisms allowed by the system property + private static final Set MECHS_ALLOWED_BY_SP = + getMechsFromPropertyValue(ALLOWED_MECHS_SP_VALUE); + + // The message to use in NamingException if the transmission of plain credentials are not allowed + private static final String UNSECURED_CRED_TRANSMIT_MSG = + "Transmission of credentials over unsecured connection is not allowed"; + // ----------------- Fields that don't change ----------------------- private static final NameParser parser = new LdapNameParser(); @@ -235,7 +262,8 @@ Name currentParsedDN; // DN of this context Vector respCtls = null; // Response controls read Control[] reqCtls = null; // Controls to be sent with each request - + // Used to track if context was seen to be secured with STARTTLS extended operation + volatile boolean contextSeenStartTlsEnabled; // ------------- Private instance variables ------------------------ @@ -2669,6 +2697,82 @@ ensureOpen(); // open or reauthenticated } + // Load 'mechsAllowedToSendCredentials' system property value + private static String getMechsAllowedToSendCredentials() { + return AccessController.doPrivileged( + new PrivilegedAction() { + public String run() { + return System.getProperty(ALLOWED_MECHS_SP); + } + } + ); + } + + // Get set of allowed authentication mechanism names from the property value + private static Set getMechsFromPropertyValue(String propValue) { + if (propValue == null || propValue.isEmpty()) { + return Collections.emptySet(); + } + + Set s = new HashSet<>(); + for (String part : propValue.split("\\s*,\\s*")) { + if (!part.isEmpty()) { + s.add(part.toLowerCase(Locale.ROOT)); + } + } + return s; + } + + // Returns true if TLS connection opened using "ldaps" scheme, or using "ldap" and then upgraded with + // startTLS extended operation, and startTLS is still active. + private boolean isConnectionEncrypted() { + return hasLdapsScheme || clnt.isUpgradedToStartTls(); + } + + // Ensure connection and context are in a safe state to transmit credentials + private void ensureCanTransmitCredentials(String authMechanism) throws NamingException { + + // "none" and "anonumous" authentication mechanisms are allowed unconditionally + if ("none".equalsIgnoreCase(authMechanism) || "anonymous".equalsIgnoreCase(authMechanism)) { + return; + } + + // Check environment first + String allowedMechanismsOrTrue = (String) envprops.get(ALLOWED_MECHS_SP); + boolean useSpMechsCache = false; + boolean anyPropertyIsSet = ALLOWED_MECHS_SP_VALUE != null || allowedMechanismsOrTrue != null; + + // If current connection is not encrypted, and context seen to be secured with STARTTLS + // or 'mechsAllowedToSendCredentials' is set to any value via system/context environment properties + if (!isConnectionEncrypted() && (contextSeenStartTlsEnabled || anyPropertyIsSet)) { + // First, check if security principal is provided in context environment for "simple" + // authentication mechanism. There is no check for other SASL mechanisms since the credentials + // can be specified via other properties + if ("simple".equalsIgnoreCase(authMechanism) && !envprops.containsKey(SECURITY_PRINCIPAL)) { + return; + } + + // If null - will use mechanism name cached from system property + if (allowedMechanismsOrTrue == null) { + useSpMechsCache = true; + allowedMechanismsOrTrue = ALLOWED_MECHS_SP_VALUE; + } + + // If the property value (system or environment) is 'all': + // any kind of authentication is allowed unconditionally - no check is needed + if ("all".equalsIgnoreCase(allowedMechanismsOrTrue)) { + return; + } + + // Get the set with allowed authentication mechanisms and check current mechanism + Set allowedAuthMechs = useSpMechsCache ? + MECHS_ALLOWED_BY_SP : getMechsFromPropertyValue(allowedMechanismsOrTrue); + if (!allowedAuthMechs.contains(authMechanism)) { + throw new NamingException(UNSECURED_CRED_TRANSMIT_MSG); + } + } + } + private void ensureOpen() throws NamingException { ensureOpen(false); } @@ -2770,6 +2874,9 @@ // Required for SASL client identity envprops); + // Mark current context as secure if the connection is acquired + // from the pool and it is secure. + contextSeenStartTlsEnabled |= clnt.isUpgradedToStartTls(); /** * Pooled connections are preauthenticated; @@ -2788,8 +2895,12 @@ ldapVersion = LdapClient.LDAP_VERSION3; } - LdapResult answer = clnt.authenticate(initial, - user, passwd, ldapVersion, authMechanism, bindCtls, envprops); + LdapResult answer; + synchronized (clnt.conn.startTlsLock) { + ensureCanTransmitCredentials(authMechanism); + answer = clnt.authenticate(initial, user, passwd, ldapVersion, + authMechanism, bindCtls, envprops); + } respCtls = answer.resControls; // retrieve (bind) response controls @@ -3293,6 +3404,7 @@ String domainName = (String) (envprops != null ? envprops.get(DOMAIN_NAME) : null); ((StartTlsResponseImpl)er).setConnection(clnt.conn, domainName); + contextSeenStartTlsEnabled |= startTLS; } return er; diff -r 1a9e79164f5e -r b8b51d9e706f src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java --- a/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java Mon Nov 02 02:26:27 2020 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, 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 @@ -266,7 +266,7 @@ // Replace SSL streams with the original streams ldapConnection.replaceStreams( - originalInputStream, originalOutputStream); + originalInputStream, originalOutputStream, false); if (debug) { System.out.println("StartTLS: closing SSL Socket"); @@ -356,7 +356,7 @@ // Replace original streams with the new SSL streams ldapConnection.replaceStreams(sslSocket.getInputStream(), - sslSocket.getOutputStream()); + sslSocket.getOutputStream(), true); if (debug) { System.out.println("StartTLS: Replaced IO Streams"); } diff -r 1a9e79164f5e -r b8b51d9e706f src/share/classes/java/io/ObjectInputStream.java --- a/src/share/classes/java/io/ObjectInputStream.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/classes/java/io/ObjectInputStream.java Mon Nov 02 02:26:27 2020 +0000 @@ -28,6 +28,7 @@ import java.io.ObjectStreamClass.WeakClassKey; import java.lang.ref.ReferenceQueue; import java.lang.reflect.Array; +import java.lang.reflect.InvocationHandler; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import java.security.AccessControlContext; @@ -50,6 +51,7 @@ import sun.reflect.misc.ReflectUtil; import sun.util.logging.PlatformLogger; import sun.security.action.GetBooleanAction; +import sun.security.action.GetIntegerAction; /** * An ObjectInputStream deserializes primitive data and objects previously @@ -252,6 +254,15 @@ static final boolean SET_FILTER_AFTER_READ = privilegedGetProperty("jdk.serialSetFilterAfterRead"); + /** + * Property to override the implementation limit on the number + * of interfaces allowed for Proxies. The property value is clamped to 0..65535. + * The maximum number of interfaces allowed for a proxy is limited to 65535 by + * {@link java.lang.reflect.Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)} + */ + static final int PROXY_INTERFACE_LIMIT = Math.max(0, Math.min(65535, + privilegedGetIntegerProperty("jdk.serialProxyInterfaceLimit", 65535))); + private static boolean privilegedGetProperty(String theProp) { if (System.getSecurityManager() == null) { return Boolean.getBoolean(theProp); @@ -260,6 +271,15 @@ new GetBooleanAction(theProp)); } } + + private static int privilegedGetIntegerProperty(String theProp, int defaultValue) { + if (System.getSecurityManager() == null) { + return Integer.getInteger(theProp, defaultValue); + } else { + return AccessController.doPrivileged( + new GetIntegerAction(theProp, defaultValue)); + } + } } static { @@ -1862,14 +1882,23 @@ int numIfaces = bin.readInt(); if (numIfaces > 65535) { - throw new InvalidObjectException("interface limit exceeded: " - + numIfaces); + // Report specification limit exceeded + throw new InvalidObjectException("interface limit exceeded: " + + numIfaces + + ", limit: " + Caches.PROXY_INTERFACE_LIMIT); } String[] ifaces = new String[numIfaces]; for (int i = 0; i < numIfaces; i++) { ifaces[i] = bin.readUTF(); } + // Recheck against implementation limit and throw with interface names + if (numIfaces > Caches.PROXY_INTERFACE_LIMIT) { + throw new InvalidObjectException("interface limit exceeded: " + + numIfaces + + ", limit: " + Caches.PROXY_INTERFACE_LIMIT + + "; " + Arrays.toString(ifaces)); + } Class cl = null; ClassNotFoundException resolveEx = null; bin.setBlockDataMode(true); @@ -1892,6 +1921,11 @@ } } catch (ClassNotFoundException ex) { resolveEx = ex; + } catch (OutOfMemoryError memerr) { + IOException ex = new InvalidObjectException("Proxy interface limit exceeded: " + + Arrays.toString(ifaces)); + ex.initCause(memerr); + throw ex; } // Call filterCheck on the class before reading anything else @@ -1903,6 +1937,11 @@ totalObjectRefs++; depth++; desc.initProxy(cl, resolveEx, readClassDesc(false)); + } catch (OutOfMemoryError memerr) { + IOException ex = new InvalidObjectException("Proxy interface limit exceeded: " + + Arrays.toString(ifaces)); + ex.initCause(memerr); + throw ex; } finally { depth--; } diff -r 1a9e79164f5e -r b8b51d9e706f src/share/classes/java/nio/X-Buffer.java.template --- a/src/share/classes/java/nio/X-Buffer.java.template Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/classes/java/nio/X-Buffer.java.template Mon Nov 02 02:26:27 2020 +0000 @@ -411,11 +411,11 @@ public int read(CharBuffer target) throws IOException { // Determine the number of bytes n that can be transferred int targetRemaining = target.remaining(); - int remaining = remaining(); + int limit = limit(); + int remaining = limit - position(); if (remaining == 0) return -1; int n = Math.min(remaining, targetRemaining); - int limit = limit(); // Set source limit to prevent target overflow if (targetRemaining < remaining) limit(position() + n); @@ -1130,10 +1130,15 @@ if (!(ob instanceof $Type$Buffer)) return false; $Type$Buffer that = ($Type$Buffer)ob; - if (this.remaining() != that.remaining()) + int thisPos = this.position(); + int thisLim = this.limit(); + int thatPos = that.position(); + int thatLim = that.limit(); + int thisRem = thisLim - thisPos; + int thatRem = thatLim - thatPos; + if (thisRem < 0 || thisRem != thatRem) return false; - int p = this.position(); - for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) + for (int i = thisLim - 1, j = thatLim - 1; i >= thisPos; i--, j--) if (!equals(this.get(i), that.get(j))) return false; return true; @@ -1171,13 +1176,20 @@ * is less than, equal to, or greater than the given buffer */ public int compareTo($Type$Buffer that) { - int n = this.position() + Math.min(this.remaining(), that.remaining()); - for (int i = this.position(), j = that.position(); i < n; i++, j++) { + int thisPos = this.position(); + int thisRem = this.limit() - thisPos; + int thatPos = that.position(); + int thatRem = that.limit() - thatPos; + int length = Math.min(thisRem, thatRem); + if (length < 0) + return -1; + int n = thisPos + Math.min(thisRem, thatRem); + for (int i = thisPos, j = thatPos; i < n; i++, j++) { int cmp = compare(this.get(i), that.get(j)); if (cmp != 0) return cmp; } - return this.remaining() - that.remaining(); + return thisRem - thatRem; } private static int compare($type$ x, $type$ y) { diff -r 1a9e79164f5e -r b8b51d9e706f src/share/classes/java/util/Calendar.java --- a/src/share/classes/java/util/Calendar.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/classes/java/util/Calendar.java Mon Nov 02 02:26:27 2020 +0000 @@ -1912,7 +1912,9 @@ lenient == that.lenient && firstDayOfWeek == that.firstDayOfWeek && minimalDaysInFirstWeek == that.minimalDaysInFirstWeek && - zone.equals(that.zone); + (zone instanceof ZoneInfo ? + zone.equals(that.zone) : + zone.equals(that.getTimeZone())); } catch (Exception e) { // Note: GregorianCalendar.computeTime throws // IllegalArgumentException if the ERA value is invalid diff -r 1a9e79164f5e -r b8b51d9e706f src/share/classes/sun/security/ssl/HandshakeMessage.java --- a/src/share/classes/sun/security/ssl/HandshakeMessage.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/classes/sun/security/ssl/HandshakeMessage.java Mon Nov 02 02:26:27 2020 +0000 @@ -45,6 +45,7 @@ import javax.net.ssl.*; +import sun.security.action.GetIntegerAction; import sun.security.internal.spec.TlsPrfParameterSpec; import sun.security.ssl.CipherSuite.*; import static sun.security.ssl.CipherSuite.PRF.*; @@ -433,6 +434,10 @@ private int messageLength; + // Set the max certificate chain length to 10 + static final int maxCertificateChainLength = AccessController.doPrivileged( + new GetIntegerAction("jdk.tls.maxCertificateChainLength", 10)).intValue(); + CertificateMsg(X509Certificate[] certs) { chain = certs; } @@ -450,6 +455,15 @@ cf = CertificateFactory.getInstance("X.509"); } v.add(cf.generateCertificate(new ByteArrayInputStream(cert))); + + if (v.size() > maxCertificateChainLength) { + throw new SSLProtocolException( + "The certificate chain length (" + + v.size() + + ") exceeds the maximum allowed length (" + + maxCertificateChainLength + + ")"); + } } catch (CertificateException e) { throw (SSLProtocolException)new SSLProtocolException( e.getMessage()).initCause(e); diff -r 1a9e79164f5e -r b8b51d9e706f src/share/classes/sun/security/ssl/Handshaker.java --- a/src/share/classes/sun/security/ssl/Handshaker.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/classes/sun/security/ssl/Handshaker.java Mon Nov 02 02:26:27 2020 +0000 @@ -36,6 +36,7 @@ import javax.net.ssl.*; import sun.misc.HexDumpEncoder; +import sun.security.action.GetIntegerAction; import sun.security.internal.spec.*; import sun.security.internal.interfaces.TlsMasterSecret; @@ -186,6 +187,10 @@ static final boolean allowLegacyMasterSecret = Debug.getBooleanProperty("jdk.tls.allowLegacyMasterSecret", true); + // Set the max size limit for Handshake Message to 2^15 + static final int maxHandshakeMessageSize = AccessController.doPrivileged( + new GetIntegerAction("jdk.tls.maxHandshakeMessageSize", 32768)).intValue(); + // Is it requested to use extended master secret extension? boolean requestedToUseEMS = false; @@ -936,6 +941,15 @@ messageType = (byte)input.getInt8(); messageLen = input.getInt24(); + if (messageLen > maxHandshakeMessageSize) { + throw new SSLProtocolException( + "The size of the handshake message (" + + messageLen + + ") exceeds the maximum allowed size (" + + maxHandshakeMessageSize + + ")"); + } + if (input.available() < messageLen) { input.reset(); return; diff -r 1a9e79164f5e -r b8b51d9e706f src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java --- a/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Mon Nov 02 02:26:27 2020 +0000 @@ -252,10 +252,10 @@ int space = constraintEntry.indexOf(' '); String algorithm = AlgorithmDecomposer.hashName( ((space > 0 ? constraintEntry.substring(0, space) : - constraintEntry). - toUpperCase(Locale.ENGLISH))); + constraintEntry))); - List constraintList = constraintsMap.get(algorithm); + List constraintList = constraintsMap.get( + algorithm.toUpperCase(Locale.ENGLISH)); if (constraintList == null) { constraintList = new ArrayList<>(1); } @@ -264,7 +264,8 @@ for (String alias : AlgorithmDecomposer.getAliases(algorithm)) { List aliasList = constraintsMap.get(alias); if (aliasList == null) { - constraintsMap.put(alias, constraintList); + constraintsMap.put( + alias.toUpperCase(Locale.ENGLISH), constraintList); } } if (space <= 0) { @@ -354,7 +355,7 @@ // Get applicable constraints based off the signature algorithm private List getConstraints(String algorithm) { - return constraintsMap.get(algorithm); + return constraintsMap.get(algorithm.toUpperCase(Locale.ENGLISH)); } // Check if KeySizeConstraints permit the specified key @@ -410,6 +411,7 @@ Set algorithms = new HashSet<>(); if (algorithm != null) { algorithms.addAll(AlgorithmDecomposer.decomposeOneHash(algorithm)); + algorithms.add(algorithm); } // Attempt to add the public key algorithm if cert provided diff -r 1a9e79164f5e -r b8b51d9e706f src/share/classes/sun/security/util/UntrustedCertificates.java --- a/src/share/classes/sun/security/util/UntrustedCertificates.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/classes/sun/security/util/UntrustedCertificates.java Mon Nov 02 02:26:27 2020 +0000 @@ -31,7 +31,7 @@ import java.security.PrivilegedAction; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; -import java.util.*; +import java.util.Properties; import sun.security.x509.X509CertImpl; /** @@ -58,10 +58,6 @@ "lib/security/blacklisted.certs"); try (FileInputStream fin = new FileInputStream(f)) { props.load(fin); - // It's said that the fingerprint could contain colons - for (Map.Entry e: props.entrySet()) { - e.setValue(stripColons(e.getValue())); - } } catch (IOException fnfe) { if (debug != null) { debug.println("Error parsing blacklisted.certs"); @@ -73,21 +69,6 @@ algorithm = props.getProperty(ALGORITHM_KEY); } - private static String stripColons(Object input) { - String s = (String)input; - char[] letters = s.toCharArray(); - int pos = 0; - for (int i = 0; i < letters.length; i++) { - if (letters[i] != ':') { - if (i != pos) { - letters[pos] = letters[i]; - } - pos++; - } - } - if (pos == letters.length) return s; - else return new String(letters, 0, pos); - } /** * Checks if a certificate is untrusted. * diff -r 1a9e79164f5e -r b8b51d9e706f src/share/lib/security/BlacklistedCertsConverter.java --- a/src/share/lib/security/BlacklistedCertsConverter.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/lib/security/BlacklistedCertsConverter.java Mon Nov 02 02:26:27 2020 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -21,13 +21,26 @@ * questions. */ +import java.io.IOException; +import java.math.BigInteger; import java.security.MessageDigest; +import java.security.PublicKey; import java.security.NoSuchAlgorithmException; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.security.interfaces.ECPublicKey; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import sun.security.util.DerInputStream; +import sun.security.util.DerOutputStream; +import sun.security.util.DerValue; /** * This is the tool to convert blacklisted.certs.pem to blacklisted.certs. @@ -48,9 +61,14 @@ Collection certs = cf.generateCertificates(System.in); System.out.println("Algorithm=" + mdAlg); + Set fingerprints = new TreeSet<>(); for (Certificate cert: certs) { - System.out.println( - getCertificateFingerPrint(mdAlg, (X509Certificate)cert)); + fingerprints.addAll( + getCertificateFingerPrints(mdAlg, (X509Certificate)cert)); + } + + for (String s: fingerprints) { + System.out.println(s); } } @@ -67,23 +85,90 @@ } /** - * Gets the requested finger print of the certificate. + * Gets the requested fingerprints of the certificate. */ - private static String getCertificateFingerPrint(String mdAlg, - X509Certificate cert) { - String fingerPrint = ""; - try { - byte[] encCertInfo = cert.getEncoded(); + private static List getCertificateFingerPrints( + String mdAlg, X509Certificate cert) throws Exception { + List fingerprints = new ArrayList<>(); + for (byte[] encoding : altEncodings(cert)) { MessageDigest md = MessageDigest.getInstance(mdAlg); - byte[] digest = md.digest(encCertInfo); + byte[] digest = md.digest(encoding); StringBuffer buf = new StringBuffer(); for (int i = 0; i < digest.length; i++) { byte2hex(digest[i], buf); } - fingerPrint = buf.toString(); - } catch (NoSuchAlgorithmException | CertificateEncodingException e) { - // ignored + fingerprints.add(buf.toString()); + } + return fingerprints; + } + + private static List altEncodings(X509Certificate c) + throws Exception { + List result = new ArrayList<>(); + + DerValue d = new DerValue(c.getEncoded()); + DerValue[] seq = new DerValue[3]; + // tbsCertificate + seq[0] = d.data.getDerValue(); + // signatureAlgorithm + seq[1] = d.data.getDerValue(); + // signature + seq[2] = d.data.getDerValue(); + + List algIds = Arrays.asList(seq[1], altAlgId(seq[1])); + + List sigs; + PublicKey p = c.getPublicKey(); + if (p instanceof ECPublicKey) { + ECPublicKey ep = (ECPublicKey) p; + BigInteger mod = ep.getParams().getOrder(); + sigs = Arrays.asList(seq[2], altSig(mod, seq[2])); + } else { + sigs = Arrays.asList(seq[2]); } - return fingerPrint; + + for (DerValue algId : algIds) { + for (DerValue sig : sigs) { + DerOutputStream tmp = new DerOutputStream(); + tmp.putDerValue(seq[0]); + tmp.putDerValue(algId); + tmp.putDerValue(sig); + DerOutputStream tmp2 = new DerOutputStream(); + tmp2.write(DerValue.tag_Sequence, tmp); + result.add(tmp2.toByteArray()); + } + } + return result; + } + + private static DerValue altSig(BigInteger mod, DerValue sig) + throws IOException { + byte[] sigBits = sig.getBitString(); + DerInputStream in = + new DerInputStream(sigBits, 0, sigBits.length, false); + DerValue[] values = in.getSequence(2); + BigInteger r = values[0].getBigInteger(); + BigInteger s = values[1].getBigInteger(); + BigInteger s2 = s.negate().mod(mod); + DerOutputStream out = new DerOutputStream(); + out.putInteger(r); + out.putInteger(s2); + DerOutputStream tmp = new DerOutputStream(); + tmp.putBitString(new DerValue(DerValue.tag_Sequence, + out.toByteArray()).toByteArray()); + return new DerValue(tmp.toByteArray()); + } + + private static DerValue altAlgId(DerValue algId) throws IOException { + DerInputStream in = algId.toDerInputStream(); + DerOutputStream bytes = new DerOutputStream(); + bytes.putOID(in.getOID()); + // encode parameters as NULL if not present or omit if NULL + if (in.available() == 0) { + bytes.putNull(); + } + DerOutputStream tmp = new DerOutputStream(); + tmp.write(DerValue.tag_Sequence, bytes); + return new DerValue(tmp.toByteArray()); } } diff -r 1a9e79164f5e -r b8b51d9e706f src/share/lib/security/blacklisted.certs --- a/src/share/lib/security/blacklisted.certs Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/lib/security/blacklisted.certs Mon Nov 02 02:26:27 2020 +0000 @@ -1,20 +1,39 @@ -Algorithm=SHA-256 -76A45A496031E4DD2D7ED23E8F6FF97DBDEA980BAAC8B0BA94D7EDB551348645 -4CBBF8256BC9888A8007B2F386940A2E394378B0D903CBB3863C5A6394B889CE -D24566BF315F4E597D6E381C87119FB4198F5E9E2607F5F4AB362EF7E2E7672F -14E6D2764A4B06701C6CBC376A253775F79C782FBCB6C0EE6F99DE4BA1024ADD -D3A936E1A7775A45217C8296A1F22AC5631DCDEC45594099E78EEEBBEDCBA967 -5E83124D68D24E8E177E306DF643D5EA99C5A94D6FC34B072F7544A1CABB7C7B -9ED8F9B0E8E42A1656B8E1DD18F42BA42DC06FE52686173BA2FC70E756F207DC -FDEDB5BDFCB67411513A61AEE5CB5B5D7C52AF06028EFC996CC1B05B1D6CEA2B -A686FEE577C88AB664D0787ECDFFF035F4806F3DE418DC9E4D516324FFF02083 -4FEE0163686ECBD65DB968E7494F55D84B25486D438E9DE558D629D28CD4D176 -8A1BD21661C60015065212CC98B1ABB50DFD14C872A208E66BAE890F25C448AF -B8686723E415534BC0DBD16326F9486F85B0B0799BF6639334E61DAAE67F36CD -3946901F46B0071E90D78279E82FABABCA177231A704BE72C5B0E8918566EA66 -31C8FD37DB9B56E708B03D1F01848B068C6DA66F36FB5D82C008C6040FA3E133 -450F1B421BB05C8609854884559C323319619E8B06B001EA2DCBB74A23AA3BE2 -FC02FD48DB92D4DCE6F11679D38354CF750CFC7F584A520EB90BDE80E241F2BD -DF21016B00FC54F9FE3BC8B039911BB216E9162FAD2FD14D990AB96E951B49BE -F5B6F88F75D391A4B1EB336F9E201239FB6B1377DB8CFA7B84736216E5AFFFD7 -EC30C9C3065A06BB07DC5B1C6B497F370C1CA65C0F30C08E042BA6BCECC78F2C +Algorithm=SHA-256 +03DB9E5E79FE6117177F81C11595AF598CB176AF766290DBCEB2C318B32E39A2 +08C396C006A21055D00826A5781A5CCFCE2C8D053AB3C197637A4A7A5BB9A650 +14E6D2764A4B06701C6CBC376A253775F79C782FBCB6C0EE6F99DE4BA1024ADD +1C5E6985ACC09221DBD1A4B7BBC6D3A8C3F8540D19F20763A9537FDD42B4FFE7 +1F6BF8A3F2399AF7FD04516C2719C566CBAD51F412738F66D0457E1E6BDE6F2D +2A464E4113141352C7962FBD1706ED4B88533EF24D7BBA6CCC5D797FD202F1C4 +31C8FD37DB9B56E708B03D1F01848B068C6DA66F36FB5D82C008C6040FA3E133 +3946901F46B0071E90D78279E82FABABCA177231A704BE72C5B0E8918566EA66 +3E11CF90719F6FB44D94EAC9A156B89BEBE7B8598F28EC58913F2BFCAF91D0C0 +423279423B9FC8CB06F1BB7C3B247522B948D5F18939F378ECC901126DE40BFB +450F1B421BB05C8609854884559C323319619E8B06B001EA2DCBB74A23AA3BE2 +4CBBF8256BC9888A8007B2F386940A2E394378B0D903CBB3863C5A6394B889CE +4FEE0163686ECBD65DB968E7494F55D84B25486D438E9DE558D629D28CD4D176 +535D04DFCE027C70BD5F8A9E0AD4F218E9AFDCF5BBCF9B6DE0D81E148E2E3172 +568FAF38D9F155F624838E2181B1CEB4D8459305EE652B0F810C97C3611BFE19 +585CFE6B7436CBD4E732763A2137D7F49599BA9B1790E688FCEC799C58EB84A6 +5E83124D68D24E8E177E306DF643D5EA99C5A94D6FC34B072F7544A1CABB7C7B +71CB00749B9130FB2707A2664BFF958D0FCC8E161D9674C7450BA0FC2BEAF9D3 +76A45A496031E4DD2D7ED23E8F6FF97DBDEA980BAAC8B0BA94D7EDB551348645 +8A1BD21661C60015065212CC98B1ABB50DFD14C872A208E66BAE890F25C448AF +9ED8F9B0E8E42A1656B8E1DD18F42BA42DC06FE52686173BA2FC70E756F207DC +9FADCE80D62A959F9930D748488C1E22E821F4E1E4A43584B848C2FC11E04D77 +A686FEE577C88AB664D0787ECDFFF035F4806F3DE418DC9E4D516324FFF02083 +A90132CEA1D4F7185E4F688EFFD16F6AC14DFD78356A807599A5DABBEEF3333E +B8686723E415534BC0DBD16326F9486F85B0B0799BF6639334E61DAAE67F36CD +C0D1F42B9F4BF7ACC045B7BB5D4805E10737F67B6310CE505248D543D0D5FE07 +D0156949F1381943442C6974E9B5B49EF441BB799EF20477B90A89C3F33620CE +D151962D954970501C60079258EBCFA38502E0A9F03CD640322B08C0A3117FE5 +D24566BF315F4E597D6E381C87119FB4198F5E9E2607F5F4AB362EF7E2E7672F +D3A936E1A7775A45217C8296A1F22AC5631DCDEC45594099E78EEEBBEDCBA967 +D6CEAE5D9E047FAF7D797858D229AC991AD44316D1E2A37A21926D763153593A +DF21016B00FC54F9FE3BC8B039911BB216E9162FAD2FD14D990AB96E951B49BE +E0E740E4B0F8B3548181FF75B5372FAF4C70B99EC995D694ED0FB91B03FF8D21 +EC30C9C3065A06BB07DC5B1C6B497F370C1CA65C0F30C08E042BA6BCECC78F2C +F5B6F88F75D391A4B1EB336F9E201239FB6B1377DB8CFA7B84736216E5AFFFD7 +FBB12938ABD86C125796EDF4162D291028890A7D6C0C1CCA75FD4B95EBFA7A1A +FC02FD48DB92D4DCE6F11679D38354CF750CFC7F584A520EB90BDE80E241F2BD +FDEDB5BDFCB67411513A61AEE5CB5B5D7C52AF06028EFC996CC1B05B1D6CEA2B diff -r 1a9e79164f5e -r b8b51d9e706f src/share/native/sun/awt/image/jpeg/jpeg-6b/jdhuff.c diff -r 1a9e79164f5e -r b8b51d9e706f src/share/native/sun/awt/image/jpeg/jpeg-6b/jdinput.c diff -r 1a9e79164f5e -r b8b51d9e706f src/share/native/sun/awt/image/jpeg/jpeg-6b/jdmarker.c diff -r 1a9e79164f5e -r b8b51d9e706f src/share/native/sun/awt/image/jpeg/jpeg-6b/jmemnobs.c --- a/src/share/native/sun/awt/image/jpeg/jpeg-6b/jmemnobs.c Sat Sep 26 19:05:32 2020 +0100 +++ b/src/share/native/sun/awt/image/jpeg/jpeg-6b/jmemnobs.c Mon Nov 02 02:26:27 2020 +0000 @@ -70,13 +70,16 @@ /* * This routine computes the total memory space available for allocation. - * Here we always say, "we got all you want bud!" */ GLOBAL(size_t) jpeg_mem_available (j_common_ptr cinfo, size_t min_bytes_needed, size_t max_bytes_needed, size_t already_allocated) { + if (cinfo->mem->max_memory_to_use) + return cinfo->mem->max_memory_to_use - already_allocated; + + /* Here we say, "we got all you want bud!" */ return max_bytes_needed; } diff -r 1a9e79164f5e -r b8b51d9e706f src/share/native/sun/awt/image/jpeg/jpeg-6b/jpeglib.h diff -r 1a9e79164f5e -r b8b51d9e706f src/solaris/classes/sun/nio/fs/UnixUriUtils.java --- a/src/solaris/classes/sun/nio/fs/UnixUriUtils.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/solaris/classes/sun/nio/fs/UnixUriUtils.java Mon Nov 02 02:26:27 2020 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -83,7 +83,8 @@ if (b == 0) throw new IllegalArgumentException("Nul character not allowed"); } else { - assert c < 0x80; + if (c == 0 || c >= 0x80) + throw new IllegalArgumentException("Bad escape"); b = (byte)c; } result[rlen++] = b; @@ -115,9 +116,10 @@ // trailing slash if directory if (sb.charAt(sb.length()-1) != '/') { try { + up.checkRead(); if (UnixFileAttributes.get(up, true).isDirectory()) sb.append('/'); - } catch (UnixException x) { + } catch (SecurityException | UnixException x) { // ignore } } diff -r 1a9e79164f5e -r b8b51d9e706f src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java --- a/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java Mon Nov 02 02:26:27 2020 +0000 @@ -57,10 +57,15 @@ // query HKEY_CLASSES_ROOT\ String key = filename.substring(dot); - NativeBuffer keyBuffer = WindowsNativeDispatcher.asNativeBuffer(key); - NativeBuffer nameBuffer = WindowsNativeDispatcher.asNativeBuffer("Content Type"); + NativeBuffer keyBuffer = null; + NativeBuffer nameBuffer = null; try { + keyBuffer = WindowsNativeDispatcher.asNativeBuffer(key); + nameBuffer = WindowsNativeDispatcher.asNativeBuffer("Content Type"); return queryStringValue(keyBuffer.address(), nameBuffer.address()); + } catch (WindowsException we) { + we.rethrowAsIOException(file.toString()); + return null; // keep compiler happy } finally { nameBuffer.release(); keyBuffer.release(); diff -r 1a9e79164f5e -r b8b51d9e706f src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java --- a/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Mon Nov 02 02:26:27 2020 +0000 @@ -1093,7 +1093,12 @@ private static final Unsafe unsafe = Unsafe.getUnsafe(); - static NativeBuffer asNativeBuffer(String s) { + static NativeBuffer asNativeBuffer(String s) throws WindowsException { + if (s.length() > (Integer.MAX_VALUE - 2)/2) { + throw new WindowsException + ("String too long to convert to native buffer"); + } + int stringLengthInBytes = s.length() << 1; int sizeInBytes = stringLengthInBytes + 2; // char terminator diff -r 1a9e79164f5e -r b8b51d9e706f src/windows/classes/sun/nio/fs/WindowsUriSupport.java --- a/src/windows/classes/sun/nio/fs/WindowsUriSupport.java Sat Sep 26 19:05:32 2020 +0100 +++ b/src/windows/classes/sun/nio/fs/WindowsUriSupport.java Mon Nov 02 02:26:27 2020 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -104,8 +104,9 @@ boolean addSlash = false; if (!s.endsWith("\\")) { try { + path.checkRead(); addSlash = WindowsFileAttributes.get(path, true).isDirectory(); - } catch (WindowsException x) { + } catch (SecurityException | WindowsException x) { } } diff -r 1a9e79164f5e -r b8b51d9e706f test/lib/security/CheckBlacklistedCerts.java --- a/test/lib/security/CheckBlacklistedCerts.java Sat Sep 26 19:05:32 2020 +0100 +++ b/test/lib/security/CheckBlacklistedCerts.java Mon Nov 02 02:26:27 2020 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8011402 + * @bug 8011402 8237995 * @summary Move blacklisting certificate logic from hard code to data */ @@ -115,7 +115,8 @@ System.out.println("There are " + acount + " algorithms"); failed = true; } - if (ccount != blacklisted.size() + // There are two unique fingerprints for each RSA certificate + if (ccount != blacklisted.size() * 2 && !blacklisted.isEmpty()) { System.out.println("Wrong blacklisted.certs size: " + ccount + " fingerprints, "