From 38479150516d0f851b1f4a1bea410de11ca2614b Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Wed, 11 Jun 2014 16:25:59 -0400 Subject: [PATCH] 8038913: Bolster XML support Reviewed-by: xuelei, skoivu --- .../apache/xml/internal/security/Init.java | 72 +++++++++++-------- .../security/algorithms/JCEMapper.java | 7 ++ .../algorithms/SignatureAlgorithm.java | 13 +++- .../internal/security/c14n/Canonicalizer.java | 9 ++- .../keys/keyresolver/KeyResolver.java | 13 ++++ .../security/transforms/Transform.java | 7 ++ .../internal/security/utils/ElementProxy.java | 3 + .../internal/security/utils/JavaUtils.java | 22 ++++++ .../xml/internal/security/utils/XMLUtils.java | 12 ++++ .../utils/resolver/ResourceResolver.java | 13 ++++ 10 files changed, 136 insertions(+), 35 deletions(-) diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java index 6176370878a..5f3b9f53c8f 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java @@ -25,6 +25,8 @@ package com.sun.org.apache.xml.internal.security; import java.io.InputStream; import java.security.AccessController; import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.List; @@ -35,6 +37,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper; import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm; import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; +import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolver; import com.sun.org.apache.xml.internal.security.transforms.Transform; import com.sun.org.apache.xml.internal.security.utils.ElementProxy; @@ -118,43 +121,50 @@ public class Init { log.log(java.util.logging.Level.FINE, "Registering default algorithms"); } try { - // - // Bind the default prefixes - // - ElementProxy.registerDefaultPrefixes(); + AccessController.doPrivileged(new PrivilegedExceptionAction(){ + @Override public Void run() throws XMLSecurityException { + // + // Bind the default prefixes + // + ElementProxy.registerDefaultPrefixes(); - // - // Set the default Transforms - // - Transform.registerDefaultAlgorithms(); + // + // Set the default Transforms + // + Transform.registerDefaultAlgorithms(); - // - // Set the default signature algorithms - // - SignatureAlgorithm.registerDefaultAlgorithms(); + // + // Set the default signature algorithms + // + SignatureAlgorithm.registerDefaultAlgorithms(); - // - // Set the default JCE algorithms - // - JCEMapper.registerDefaultAlgorithms(); + // + // Set the default JCE algorithms + // + JCEMapper.registerDefaultAlgorithms(); - // - // Set the default c14n algorithms - // - Canonicalizer.registerDefaultAlgorithms(); + // + // Set the default c14n algorithms + // + Canonicalizer.registerDefaultAlgorithms(); - // - // Register the default resolvers - // - ResourceResolver.registerDefaultResolvers(); + // + // Register the default resolvers + // + ResourceResolver.registerDefaultResolvers(); - // - // Register the default key resolvers - // - KeyResolver.registerDefaultResolvers(); - } catch (Exception ex) { - log.log(java.util.logging.Level.SEVERE, ex.getMessage(), ex); - ex.printStackTrace(); + // + // Register the default key resolvers + // + KeyResolver.registerDefaultResolvers(); + + return null; + } + }); + } catch (PrivilegedActionException ex) { + XMLSecurityException xse = (XMLSecurityException)ex.getException(); + log.log(java.util.logging.Level.SEVERE, xse.getMessage(), xse); + xse.printStackTrace(); } } diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java index 6001e510532..3656f248848 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java @@ -27,6 +27,7 @@ import java.util.concurrent.ConcurrentHashMap; import com.sun.org.apache.xml.internal.security.encryption.XMLCipher; import com.sun.org.apache.xml.internal.security.signature.XMLSignature; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import org.w3c.dom.Element; @@ -49,8 +50,11 @@ public class JCEMapper { * * @param id * @param algorithm + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the JCE algorithm */ public static void register(String id, Algorithm algorithm) { + JavaUtils.checkRegisterPermission(); algorithmsMap.put(id, algorithm); } @@ -296,8 +300,11 @@ public class JCEMapper { /** * Sets the default Provider for obtaining the security algorithms * @param provider the default providerId. + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the JCE provider */ public static void setProviderId(String provider) { + JavaUtils.checkRegisterPermission(); providerName = provider; } diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java index 6e94f4b16d9..253e35ca864 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java @@ -37,6 +37,7 @@ import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; import com.sun.org.apache.xml.internal.security.signature.XMLSignature; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException; import com.sun.org.apache.xml.internal.security.utils.Constants; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -314,18 +315,21 @@ public class SignatureAlgorithm extends Algorithm { } /** - * Registers implementing class of the Transform algorithm with algorithmURI + * Registers implementing class of the SignatureAlgorithm with algorithmURI * - * @param algorithmURI algorithmURI URI representation of Transform algorithm. + * @param algorithmURI algorithmURI URI representation of SignatureAlgorithm. * @param implementingClass implementingClass the implementing class of * {@link SignatureAlgorithmSpi} * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI is already registered * @throws XMLSignatureException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the signature algorithm */ @SuppressWarnings("unchecked") public static void register(String algorithmURI, String implementingClass) throws AlgorithmAlreadyRegisteredException, ClassNotFoundException, XMLSignatureException { + JavaUtils.checkRegisterPermission(); if (log.isLoggable(java.util.logging.Level.FINE)) { log.log(java.util.logging.Level.FINE, "Try to register " + algorithmURI + " " + implementingClass); } @@ -352,15 +356,18 @@ public class SignatureAlgorithm extends Algorithm { /** * Registers implementing class of the Transform algorithm with algorithmURI * - * @param algorithmURI algorithmURI URI representation of Transform algorithm. + * @param algorithmURI algorithmURI URI representation of SignatureAlgorithm. * @param implementingClass implementingClass the implementing class of * {@link SignatureAlgorithmSpi} * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI is already registered * @throws XMLSignatureException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the signature algorithm */ public static void register(String algorithmURI, Class implementingClass) throws AlgorithmAlreadyRegisteredException, ClassNotFoundException, XMLSignatureException { + JavaUtils.checkRegisterPermission(); if (log.isLoggable(java.util.logging.Level.FINE)) { log.log(java.util.logging.Level.FINE, "Try to register " + algorithmURI + " " + implementingClass); } diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java index 2f0b31f5ed4..ae33b72c91d 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java @@ -41,6 +41,7 @@ import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicaliz import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer20010315WithComments; import com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerPhysical; import com.sun.org.apache.xml.internal.security.exceptions.AlgorithmAlreadyRegisteredException; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -142,10 +143,13 @@ public class Canonicalizer { * @param algorithmURI * @param implementingClass * @throws AlgorithmAlreadyRegisteredException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the canonicalizer */ @SuppressWarnings("unchecked") public static void register(String algorithmURI, String implementingClass) throws AlgorithmAlreadyRegisteredException, ClassNotFoundException { + JavaUtils.checkRegisterPermission(); // check whether URI is already registered Class registeredClass = canonicalizerHash.get(algorithmURI); @@ -166,9 +170,12 @@ public class Canonicalizer { * @param algorithmURI * @param implementingClass * @throws AlgorithmAlreadyRegisteredException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the canonicalizer */ - public static void register(String algorithmURI, Class implementingClass) + public static void register(String algorithmURI, Class implementingClass) throws AlgorithmAlreadyRegisteredException, ClassNotFoundException { + JavaUtils.checkRegisterPermission(); // check whether URI is already registered Class registeredClass = canonicalizerHash.get(algorithmURI); diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java index fe541ff044f..e8622d938b6 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java @@ -42,6 +42,7 @@ import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.X509SKIResolver; import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.X509SubjectNameResolver; import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -175,9 +176,12 @@ public class KeyResolver { * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the key resolver */ public static void register(String className, boolean globalResolver) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + JavaUtils.checkRegisterPermission(); KeyResolverSpi keyResolverSpi = (KeyResolverSpi) Class.forName(className).newInstance(); keyResolverSpi.setGlobalResolver(globalResolver); @@ -195,8 +199,11 @@ public class KeyResolver { * * @param className * @param globalResolver Whether the KeyResolverSpi is a global resolver or not + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the key resolver */ public static void registerAtStart(String className, boolean globalResolver) { + JavaUtils.checkRegisterPermission(); KeyResolverSpi keyResolverSpi = null; Exception ex = null; try { @@ -228,11 +235,14 @@ public class KeyResolver { * * @param keyResolverSpi a KeyResolverSpi instance to register * @param start whether to register the KeyResolverSpi at the start of the list or not + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the key resolver */ public static void register( KeyResolverSpi keyResolverSpi, boolean start ) { + JavaUtils.checkRegisterPermission(); KeyResolver resolver = new KeyResolver(keyResolverSpi); if (start) { resolverVector.add(0, resolver); @@ -254,9 +264,12 @@ public class KeyResolver { * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the key resolver */ public static void registerClassNames(List classNames) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + JavaUtils.checkRegisterPermission(); List keyResolverList = new ArrayList(classNames.size()); for (String className : classNames) { KeyResolverSpi keyResolverSpi = diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java index 37d67ba9f24..3fc1d21bb9c 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java @@ -46,6 +46,7 @@ import com.sun.org.apache.xml.internal.security.transforms.implementations.Trans import com.sun.org.apache.xml.internal.security.transforms.implementations.TransformXSLT; import com.sun.org.apache.xml.internal.security.utils.Constants; import com.sun.org.apache.xml.internal.security.utils.HelperNodeList; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy; import com.sun.org.apache.xml.internal.security.utils.XMLUtils; import org.w3c.dom.Document; @@ -181,11 +182,14 @@ public final class Transform extends SignatureElementProxy { * class of {@link TransformSpi} * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI * is already registered + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the transform */ @SuppressWarnings("unchecked") public static void register(String algorithmURI, String implementingClass) throws AlgorithmAlreadyRegisteredException, ClassNotFoundException, InvalidTransformException { + JavaUtils.checkRegisterPermission(); // are we already registered? Class transformSpi = transformSpiHash.get(algorithmURI); if (transformSpi != null) { @@ -206,9 +210,12 @@ public final class Transform extends SignatureElementProxy { * class of {@link TransformSpi} * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI * is already registered + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the transform */ public static void register(String algorithmURI, Class implementingClass) throws AlgorithmAlreadyRegisteredException { + JavaUtils.checkRegisterPermission(); // are we already registered? Class transformSpi = transformSpiHash.get(algorithmURI); if (transformSpi != null) { diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java index ac7a53eba4f..fe8bdb1f1d6 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java @@ -468,9 +468,12 @@ public abstract class ElementProxy { * @param namespace * @param prefix * @throws XMLSecurityException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the default prefix */ public static void setDefaultPrefix(String namespace, String prefix) throws XMLSecurityException { + JavaUtils.checkRegisterPermission(); if (prefixMappings.containsValue(prefix)) { String storedPrefix = prefixMappings.get(namespace); if (!storedPrefix.equals(prefix)) { diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java index 99b2d1f77e1..80c582fe8e2 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java @@ -28,6 +28,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.security.SecurityPermission; /** * A collection of different, general-purpose methods for JAVA-specific things @@ -39,6 +40,10 @@ public class JavaUtils { private static java.util.logging.Logger log = java.util.logging.Logger.getLogger(JavaUtils.class.getName()); + private static final SecurityPermission REGISTER_PERMISSION = + new SecurityPermission( + "com.sun.org.apache.xml.internal.security.register"); + private JavaUtils() { // we don't allow instantiation } @@ -146,6 +151,23 @@ public class JavaUtils { return retBytes; } + /** + * Throws a {@code SecurityException} if a security manager is installed + * and the caller is not allowed to register an implementation of an + * algorithm, transform, or other security sensitive XML Signature function. + * + * @throws SecurityException if a security manager is installed and the + * caller has not been granted the + * {@literal "com.sun.org.apache.xml.internal.security.register"} + * {@code SecurityPermission} + */ + public static void checkRegisterPermission() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(REGISTER_PERMISSION); + } + } + /** * Converts an ASN.1 DSA value to a XML Signature DSA Value. * diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java index b73e5e8a5ec..3463dc75fec 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java @@ -80,32 +80,44 @@ public class XMLUtils { /** * Set the prefix for the digital signature namespace * @param prefix the new prefix for the digital signature namespace + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the prefix */ public static void setDsPrefix(String prefix) { + JavaUtils.checkRegisterPermission(); dsPrefix = prefix; } /** * Set the prefix for the digital signature 1.1 namespace * @param prefix the new prefix for the digital signature 1.1 namespace + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the prefix */ public static void setDs11Prefix(String prefix) { + JavaUtils.checkRegisterPermission(); ds11Prefix = prefix; } /** * Set the prefix for the encryption namespace * @param prefix the new prefix for the encryption namespace + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the prefix */ public static void setXencPrefix(String prefix) { + JavaUtils.checkRegisterPermission(); xencPrefix = prefix; } /** * Set the prefix for the encryption namespace 1.1 * @param prefix the new prefix for the encryption namespace 1.1 + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the prefix */ public static void setXenc11Prefix(String prefix) { + JavaUtils.checkRegisterPermission(); xenc11Prefix = prefix; } diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java index 7570a019064..012d2fb8bc4 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Map; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverDirectHTTP; import com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment; import com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverLocalFilesystem; @@ -199,9 +200,12 @@ public class ResourceResolver { * the class cannot be registered. * * @param className the name of the ResourceResolverSpi class to be registered + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register a resource resolver */ @SuppressWarnings("unchecked") public static void register(String className) { + JavaUtils.checkRegisterPermission(); try { Class resourceResolverClass = (Class) Class.forName(className); @@ -216,9 +220,12 @@ public class ResourceResolver { * list. This method logs a warning if the class cannot be registered. * * @param className the name of the ResourceResolverSpi class to be registered + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register a resource resolver */ @SuppressWarnings("unchecked") public static void registerAtStart(String className) { + JavaUtils.checkRegisterPermission(); try { Class resourceResolverClass = (Class) Class.forName(className); @@ -233,8 +240,11 @@ public class ResourceResolver { * cannot be registered. * @param className * @param start + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register a resource resolver */ public static void register(Class className, boolean start) { + JavaUtils.checkRegisterPermission(); try { ResourceResolverSpi resourceResolverSpi = className.newInstance(); register(resourceResolverSpi, start); @@ -250,8 +260,11 @@ public class ResourceResolver { * cannot be registered. * @param resourceResolverSpi * @param start + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register a resource resolver */ public static void register(ResourceResolverSpi resourceResolverSpi, boolean start) { + JavaUtils.checkRegisterPermission(); synchronized(resolverList) { if (start) { resolverList.add(0, new ResourceResolver(resourceResolverSpi));