# HG changeset patch # User igerasim # Date 1524116130 25200 # Node ID 568328b5aea2d44bef5c2c69c52e5114d9adf96f # Parent 706392d93e025f360ade290f36c7cb93295ec415 8194534: Manifest better support Reviewed-by: mchung, igerasim diff -r 706392d93e02 -r 568328b5aea2 src/share/classes/java/net/URLClassLoader.java --- a/src/share/classes/java/net/URLClassLoader.java Thu Aug 09 16:15:14 2018 +0300 +++ b/src/share/classes/java/net/URLClassLoader.java Wed Apr 18 22:35:30 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -45,6 +45,7 @@ import java.security.Permission; import java.security.PermissionCollection; import sun.misc.Resource; +import sun.misc.SharedSecrets; import sun.misc.URLClassPath; import sun.net.www.ParseUtil; import sun.security.util.SecurityConstants; @@ -314,13 +315,13 @@ protected Package definePackage(String name, Manifest man, URL url) throws IllegalArgumentException { - String path = name.replace('.', '/').concat("/"); String specTitle = null, specVersion = null, specVendor = null; String implTitle = null, implVersion = null, implVendor = null; String sealed = null; URL sealBase = null; - Attributes attr = man.getAttributes(path); + Attributes attr = SharedSecrets.javaUtilJarAccess() + .getTrustedAttributes(man, name.replace('.', '/').concat("/")); if (attr != null) { specTitle = attr.getValue(Name.SPECIFICATION_TITLE); specVersion = attr.getValue(Name.SPECIFICATION_VERSION); @@ -364,10 +365,12 @@ /* * Returns true if the specified package name is sealed according to the * given manifest. + * + * @throws SecurityException if the package name is untrusted in the manifest */ private boolean isSealed(String name, Manifest man) { - String path = name.replace('.', '/').concat("/"); - Attributes attr = man.getAttributes(path); + Attributes attr = SharedSecrets.javaUtilJarAccess() + .getTrustedAttributes(man, name.replace('.', '/').concat("/")); String sealed = null; if (attr != null) { sealed = attr.getValue(Name.SEALED); diff -r 706392d93e02 -r 568328b5aea2 src/share/classes/java/util/jar/JarFile.java --- a/src/share/classes/java/util/jar/JarFile.java Thu Aug 09 16:15:14 2018 +0300 +++ b/src/share/classes/java/util/jar/JarFile.java Wed Apr 18 22:35:30 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -177,10 +177,10 @@ if (manEntry != null) { if (verify) { byte[] b = getBytes(manEntry); - man = new Manifest(new ByteArrayInputStream(b)); if (!jvInitialized) { jv = new JarVerifier(b); } + man = new Manifest(jv, new ByteArrayInputStream(b)); } else { man = new Manifest(super.getInputStream(manEntry)); } diff -r 706392d93e02 -r 568328b5aea2 src/share/classes/java/util/jar/JarVerifier.java --- a/src/share/classes/java/util/jar/JarVerifier.java Thu Aug 09 16:15:14 2018 +0300 +++ b/src/share/classes/java/util/jar/JarVerifier.java Wed Apr 18 22:35:30 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -866,4 +866,24 @@ static CodeSource getUnsignedCS(URL url) { return new VerifierCodeSource(null, url, (java.security.cert.Certificate[]) null); } + + /** + * Returns whether the name is trusted. Used by + * {@link Manifest#getTrustedAttributes(String)}. + */ + boolean isTrustedManifestEntry(String name) { + // How many signers? MANIFEST.MF is always verified + CodeSigner[] forMan = (CodeSigner[]) verifiedSigners.get(JarFile.MANIFEST_NAME); + if (forMan == null) { + return true; + } + // Check sigFileSigners first, because we are mainly dealing with + // non-file entries which will stay in sigFileSigners forever. + CodeSigner[] forName = (CodeSigner[]) sigFileSigners.get(name); + if (forName == null) { + forName = (CodeSigner[]) verifiedSigners.get(name); + } + // Returns trusted if all signers sign the entry + return forName != null && forName.length == forMan.length; + } } diff -r 706392d93e02 -r 568328b5aea2 src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java --- a/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Thu Aug 09 16:15:14 2018 +0300 +++ b/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Wed Apr 18 22:35:30 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, 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 @@ -60,4 +60,9 @@ public List getManifestDigests(JarFile jar) { return jar.getManifestDigests(); } + + public Attributes getTrustedAttributes(Manifest man, String name) { + return man.getTrustedAttributes(name); + } + } diff -r 706392d93e02 -r 568328b5aea2 src/share/classes/java/util/jar/Manifest.java --- a/src/share/classes/java/util/jar/Manifest.java Thu Aug 09 16:15:14 2018 +0300 +++ b/src/share/classes/java/util/jar/Manifest.java Wed Apr 18 22:35:30 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -48,15 +48,19 @@ */ public class Manifest implements Cloneable { // manifest main attributes - private Attributes attr = new Attributes(); + private final Attributes attr = new Attributes(); // manifest entries - private Map entries = new HashMap(); + private final Map entries = new HashMap(); + + // associated JarVerifier, not null when called by JarFile::getManifest. + private final JarVerifier jv; /** * Constructs a new, empty Manifest. */ public Manifest() { + jv = null; } /** @@ -66,7 +70,16 @@ * @throws IOException if an I/O error has occured */ public Manifest(InputStream is) throws IOException { + this(null, is); + } + + /** + * Constructs a new Manifest from the specified input stream + * and associates it with a JarVerifier. + */ + Manifest(JarVerifier jv, InputStream is) throws IOException { read(is); + this.jv = jv; } /** @@ -77,6 +90,7 @@ public Manifest(Manifest man) { attr.putAll(man.getMainAttributes()); entries.putAll(man.getEntries()); + jv = man.jv; } /** @@ -127,6 +141,23 @@ } /** + * Returns the Attributes for the specified entry name, if trusted. + * + * @param name entry name + * @return returns the same result as {@link #getAttributes(String)} + * @throws SecurityException if the associated jar is signed but this entry + * has been modified after signing (i.e. the section in the manifest + * does not exist in SF files of all signers). + */ + Attributes getTrustedAttributes(String name) { + Attributes result = getAttributes(name); + if (result != null && jv != null && ! jv.isTrustedManifestEntry(name)) { + throw new SecurityException("Untrusted manifest entry: " + name); + } + return result; + } + + /** * Clears the main Attributes as well as the entries in this Manifest. */ public void clear() { diff -r 706392d93e02 -r 568328b5aea2 src/share/classes/sun/misc/JavaUtilJarAccess.java --- a/src/share/classes/sun/misc/JavaUtilJarAccess.java Thu Aug 09 16:15:14 2018 +0300 +++ b/src/share/classes/sun/misc/JavaUtilJarAccess.java Wed Apr 18 22:35:30 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, 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,8 +30,10 @@ import java.security.CodeSource; import java.util.Enumeration; import java.util.List; +import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.jar.Manifest; public interface JavaUtilJarAccess { public boolean jarFileHasClassPathAttribute(JarFile jar) throws IOException; @@ -41,4 +43,5 @@ public Enumeration entries2(JarFile jar); public void setEagerValidation(JarFile jar, boolean eager); public List getManifestDigests(JarFile jar); + public Attributes getTrustedAttributes(Manifest man, String name); }