changeset 1230:1f0dd7a7e0cc jdk7u151-b00

8182054: Improve wsdl support Summary: Also reviewed by Roman Grigoriadi <roman.grigoriadi@oracle.com> Reviewed-by: joehw, lancea
author aefimov
date Thu, 27 Jul 2017 04:25:00 +0100
parents 2f079804f696
children 3233576db658
files src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/Options.java src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WsimportOptions.java src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/DOMForest.java src/share/jaxws_classes/com/sun/tools/internal/xjc/Options.java src/share/jaxws_classes/com/sun/xml/internal/ws/util/DOMUtil.java src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java
diffstat 6 files changed, 198 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/Options.java	Wed May 03 03:39:48 2017 +0100
+++ b/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/Options.java	Thu Jul 27 04:25:00 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, 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
@@ -79,6 +79,15 @@
      */
     public boolean nocompile;
 
+    /**
+     * If true XML security features when parsing XML documents will be disabled.
+     * The default value is false.
+     *
+     * Boolean
+     * @since 2.2.9
+     */
+    public boolean disableXmlSecurity;
+
     public enum Target {
         V2_0, V2_1, V2_2;
 
@@ -310,6 +319,9 @@
                 throw new BadCommandLineException(WscompileMessages.WSCOMPILE_NO_SUCH_DIRECTORY(sourceDir.getPath()));
             }
             return 2;
+        } else if (args[i].equals("-disableXmlSecurity")) {
+            disableXmlSecurity();
+            return 1;
         } else if (args[i].equals("-extension")) {
             compatibilityMode = EXTENSION;
             return 1;
@@ -326,6 +338,11 @@
         return 0;
     }
 
+    // protected method to allow overriding
+    protected void disableXmlSecurity() {
+        disableXmlSecurity= true;
+    }
+
     /**
      * Obtains an operand and reports an error if it's not there.
      */
--- a/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WsimportOptions.java	Wed May 03 03:39:48 2017 +0100
+++ b/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WsimportOptions.java	Thu Jul 27 04:25:00 2017 +0100
@@ -445,4 +445,10 @@
             }
         }
     }
+
+    @Override
+    protected void disableXmlSecurity() {
+        super.disableXmlSecurity();
+        schemaCompiler.getOptions().disableXmlSecurity = true;
+    }
 }
--- a/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/DOMForest.java	Wed May 03 03:39:48 2017 +0100
+++ b/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/DOMForest.java	Thu Jul 27 04:25:00 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,15 +26,12 @@
 package com.sun.tools.internal.ws.wsdl.parser;
 
 import com.sun.istack.internal.NotNull;
-import com.sun.tools.internal.ws.resources.WscompileMessages;
-import com.sun.tools.internal.ws.wscompile.AbortException;
-import com.sun.tools.internal.ws.wscompile.DefaultAuthenticator;
+import com.sun.tools.internal.ws.util.xml.XmlUtil;
 import com.sun.tools.internal.ws.wscompile.ErrorReceiver;
 import com.sun.tools.internal.ws.wscompile.WsimportOptions;
 import com.sun.tools.internal.ws.wsdl.document.schema.SchemaConstants;
 import com.sun.tools.internal.xjc.reader.internalizer.LocatorTable;
 import com.sun.xml.internal.bind.marshaller.DataWriter;
-import com.sun.xml.internal.ws.util.JAXWSUtils;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -51,9 +48,6 @@
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.sax.SAXResult;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLSession;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -118,13 +112,13 @@
         this.entityResolver = entityResolver;
         this.errorReceiver = errReceiver;
         this.logic = logic;
+        // secure xml processing can be switched off if input requires it
+        boolean disableXmlSecurity = options == null ? false : options.disableXmlSecurity;
+
+        DocumentBuilderFactory dbf = XmlUtil.newDocumentBuilderFactory(disableXmlSecurity);
+        this.parserFactory = XmlUtil.newSAXParserFactory(disableXmlSecurity);
         try {
-            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-            dbf.setNamespaceAware(true);
             this.documentBuilder = dbf.newDocumentBuilder();
-
-            this.parserFactory = SAXParserFactory.newInstance();
-            this.parserFactory.setNamespaceAware(true);
         } catch (ParserConfigurationException e) {
             throw new AssertionError(e);
         }
@@ -368,7 +362,10 @@
     public void dump(OutputStream out) throws IOException {
         try {
             // create identity transformer
-            Transformer it = TransformerFactory.newInstance().newTransformer();
+            // secure xml processing can be switched off if input requires it
+            boolean secureProcessingEnabled = options == null || !options.disableXmlSecurity;
+            TransformerFactory tf = XmlUtil.newTransformerFactory(secureProcessingEnabled);
+            Transformer it = tf.newTransformer();
 
             for (Map.Entry<String, Document> e : core.entrySet()) {
                 out.write(("---<< " + e.getKey() + '\n').getBytes());
--- a/src/share/jaxws_classes/com/sun/tools/internal/xjc/Options.java	Wed May 03 03:39:48 2017 +0100
+++ b/src/share/jaxws_classes/com/sun/tools/internal/xjc/Options.java	Thu Jul 27 04:25:00 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, 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,6 +104,15 @@
     public String encoding;
 
     /**
+     * If true XML security features when parsing XML documents will be disabled.
+     * The default value is false.
+     *
+     * Boolean
+     * @since 2.2.6
+     */
+    public boolean disableXmlSecurity;
+
+    /**
      * Check the source schemas with extra scrutiny.
      * The exact meaning depends on the schema language.
      */
@@ -540,6 +549,10 @@
             enableIntrospection = true;
             return 1;
         }
+        if (args[i].equals("-disableXmlSecurity")) {
+            disableXmlSecurity = true;
+            return 1;
+        }
         if (args[i].equals("-contentForWildcard")) {
             contentForWildcard = true;
             return 1;
--- a/src/share/jaxws_classes/com/sun/xml/internal/ws/util/DOMUtil.java	Wed May 03 03:39:48 2017 +0100
+++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/util/DOMUtil.java	Thu Jul 27 04:25:00 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,29 +25,27 @@
 
 package com.sun.xml.internal.ws.util;
 
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
+import com.sun.istack.internal.NotNull;
+import com.sun.istack.internal.Nullable;
+import com.sun.xml.internal.ws.util.xml.XmlUtil;
 
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
-import javax.xml.XMLConstants;
-import javax.xml.namespace.NamespaceContext;
-import java.io.IOException;
-import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import java.util.ArrayList;
 
-import com.sun.istack.internal.NotNull;
-import com.sun.istack.internal.Nullable;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 /**
  * @author: JAXWS Development Team
@@ -63,8 +61,7 @@
         synchronized (DOMUtil.class) {
             if (db == null) {
                 try {
-                    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-                    dbf.setNamespaceAware(true);
+                    DocumentBuilderFactory dbf = XmlUtil.newDocumentBuilderFactory();
                     db = dbf.newDocumentBuilder();
                 } catch (ParserConfigurationException e) {
                     throw new FactoryConfigurationError(e);
@@ -74,28 +71,6 @@
         }
     }
 
-    public static Node createDOMNode(InputStream inputStream) {
-
-        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        dbf.setNamespaceAware(true);
-        dbf.setValidating(false);
-        try {
-            DocumentBuilder builder = dbf.newDocumentBuilder();
-            try {
-                return builder.parse(inputStream);
-            } catch (SAXException e) {
-                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
-            } catch (IOException e) {
-                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
-            }
-        } catch (ParserConfigurationException pce) {
-            IllegalArgumentException iae = new IllegalArgumentException(pce.getMessage());
-            iae.initCause(pce);
-            throw iae;
-        }
-        return null;
-    }
-
     /**
      * Traverses a DOM node and writes out on a streaming writer.
      *
@@ -112,6 +87,7 @@
                 switch (child.getNodeType()) {
                     case Node.PROCESSING_INSTRUCTION_NODE:
                         writer.writeProcessingInstruction(child.getNodeValue());
+                        break;
                     case Node.DOCUMENT_TYPE_NODE:
                         break;
                     case Node.CDATA_SECTION_NODE:
@@ -126,6 +102,7 @@
                     case Node.ELEMENT_NODE:
                         serializeNode((Element) child, writer);
                         break;
+                    default: break;
                 }
             }
         }
@@ -222,8 +199,9 @@
         for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) {
             if (n.getNodeType() == Node.ELEMENT_NODE) {
                 Element c = (Element) n;
-                if (c.getLocalName().equals(local) && c.getNamespaceURI().equals(nsUri))
+                if (c.getLocalName().equals(local) && c.getNamespaceURI().equals(nsUri)) {
                     return c;
+                }
             }
         }
         return null;
@@ -232,8 +210,11 @@
     private static
     @NotNull
     String fixNull(@Nullable String s) {
-        if (s == null) return "";
-        else return s;
+        if (s == null) {
+            return "";
+        } else {
+            return s;
+        }
     }
 
     /**
--- a/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java	Wed May 03 03:39:48 2017 +0100
+++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java	Thu Jul 27 04:25:00 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -40,13 +40,18 @@
 import org.xml.sax.EntityResolver;
 import org.xml.sax.ErrorHandler;
 import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
 import org.xml.sax.SAXParseException;
 import org.xml.sax.XMLReader;
 import org.xml.sax.InputSource;
 
+import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParserFactory;
+import javax.xml.stream.XMLInputFactory;
 import javax.xml.transform.Result;
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
@@ -57,16 +62,22 @@
 import javax.xml.transform.sax.TransformerHandler;
 import javax.xml.transform.stream.StreamSource;
 import javax.xml.ws.WebServiceException;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPathFactoryConfigurationException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.List;
 import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * @author WS Development Team
@@ -75,6 +86,27 @@
     private final static String LEXICAL_HANDLER_PROPERTY =
         "http://xml.org/sax/properties/lexical-handler";
 
+    private static final String DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
+
+    private static final String EXTERNAL_GE = "http://xml.org/sax/features/external-general-entities";
+
+    private static final String EXTERNAL_PE = "http://xml.org/sax/features/external-parameter-entities";
+
+    private static final String LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
+
+    private static final Logger LOGGER = Logger.getLogger(XmlUtil.class.getName());
+
+    private static final String DISABLE_XML_SECURITY = "com.sun.xml.internal.ws.disableXmlSecurity";
+
+    private static boolean XML_SECURITY_DISABLED = AccessController.doPrivileged(
+            new PrivilegedAction<Boolean>() {
+                @Override
+                public Boolean run() {
+                    return Boolean.getBoolean(DISABLE_XML_SECURITY);
+                }
+            }
+    );
+
     public static String getPrefix(String s) {
         int i = s.indexOf(':');
         if (i == -1)
@@ -163,7 +195,7 @@
     }
 
     public static String getTextForNode(Node node) {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
 
         NodeList children = node.getChildNodes();
         if (children.getLength() == 0)
@@ -334,15 +366,108 @@
      * {@link ErrorHandler} that always treat the error as fatal.
      */
     public static final ErrorHandler DRACONIAN_ERROR_HANDLER = new ErrorHandler() {
+        @Override
         public void warning(SAXParseException exception) {
         }
 
+        @Override
         public void error(SAXParseException exception) throws SAXException {
             throw exception;
         }
 
+        @Override
         public void fatalError(SAXParseException exception) throws SAXException {
             throw exception;
         }
     };
+
+    public static DocumentBuilderFactory newDocumentBuilderFactory() {
+        return newDocumentBuilderFactory(false);
+    }
+
+    public static DocumentBuilderFactory newDocumentBuilderFactory(boolean disableSecurity) {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        String featureToSet = XMLConstants.FEATURE_SECURE_PROCESSING;
+        try {
+            boolean securityOn = !isXMLSecurityDisabled(disableSecurity);
+            factory.setFeature(featureToSet, securityOn);
+            factory.setNamespaceAware(true);
+            if (securityOn) {
+                factory.setExpandEntityReferences(false);
+                featureToSet = DISALLOW_DOCTYPE_DECL;
+                factory.setFeature(featureToSet, true);
+                featureToSet = EXTERNAL_GE;
+                factory.setFeature(featureToSet, false);
+                featureToSet = EXTERNAL_PE;
+                factory.setFeature(featureToSet, false);
+                featureToSet = LOAD_EXTERNAL_DTD;
+                factory.setFeature(featureToSet, false);
+            }
+        } catch (ParserConfigurationException e) {
+            LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support "+featureToSet+" feature!", new Object[] {factory.getClass().getName()} );
+        }
+        return factory;
+    }
+
+    public static TransformerFactory newTransformerFactory(boolean secureXmlProcessingEnabled) {
+        TransformerFactory factory = TransformerFactory.newInstance();
+        try {
+            factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, isXMLSecurityDisabled(secureXmlProcessingEnabled));
+        } catch (TransformerConfigurationException e) {
+            LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[]{factory.getClass().getName()});
+        }
+        return factory;
+    }
+
+    public static TransformerFactory newTransformerFactory() {
+        return newTransformerFactory(true);
+    }
+
+    public static SAXParserFactory newSAXParserFactory(boolean disableSecurity) {
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        String featureToSet = XMLConstants.FEATURE_SECURE_PROCESSING;
+        try {
+            boolean securityOn = !isXMLSecurityDisabled(disableSecurity);
+            factory.setFeature(featureToSet, securityOn);
+            factory.setNamespaceAware(true);
+            if (securityOn) {
+                featureToSet = DISALLOW_DOCTYPE_DECL;
+                factory.setFeature(featureToSet, true);
+                featureToSet = EXTERNAL_GE;
+                factory.setFeature(featureToSet, false);
+                featureToSet = EXTERNAL_PE;
+                factory.setFeature(featureToSet, false);
+                featureToSet = LOAD_EXTERNAL_DTD;
+                factory.setFeature(featureToSet, false);
+            }
+        } catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
+            LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support "+featureToSet+" feature!", new Object[]{factory.getClass().getName()});
+        }
+        return factory;
+    }
+
+    public static XPathFactory newXPathFactory(boolean secureXmlProcessingEnabled) {
+        XPathFactory factory = XPathFactory.newInstance();
+        try {
+            factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, isXMLSecurityDisabled(secureXmlProcessingEnabled));
+        } catch (XPathFactoryConfigurationException e) {
+            LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[] { factory.getClass().getName() } );
+        }
+        return factory;
+    }
+
+    public static XMLInputFactory newXMLInputFactory(boolean secureXmlProcessingEnabled)  {
+        XMLInputFactory factory = XMLInputFactory.newInstance();
+        if (isXMLSecurityDisabled(secureXmlProcessingEnabled)) {
+            // TODO-Miran: are those apppropriate defaults?
+            factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
+            factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
+        }
+        return factory;
+    }
+
+    private static boolean isXMLSecurityDisabled(boolean runtimeDisabled) {
+        return XML_SECURITY_DISABLED || runtimeDisabled;
+    }
+
 }