1 /*
   2  * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package xpath;
  25 
  26 import java.io.IOException;
  27 import java.io.InputStream;
  28 import java.util.Iterator;
  29 import java.util.List;
  30 
  31 import javax.xml.XMLConstants;
  32 import javax.xml.namespace.NamespaceContext;
  33 import javax.xml.namespace.QName;
  34 import javax.xml.parsers.DocumentBuilder;
  35 import javax.xml.parsers.DocumentBuilderFactory;
  36 import javax.xml.parsers.ParserConfigurationException;
  37 import javax.xml.xpath.XPath;
  38 import javax.xml.xpath.XPathExpressionException;
  39 import javax.xml.xpath.XPathFactory;
  40 import javax.xml.xpath.XPathFactoryConfigurationException;
  41 import javax.xml.xpath.XPathFunction;
  42 import javax.xml.xpath.XPathFunctionException;
  43 import javax.xml.xpath.XPathFunctionResolver;
  44 
  45 import org.testng.Assert;
  46 import org.testng.annotations.Test;
  47 import org.w3c.dom.Document;
  48 import org.xml.sax.SAXException;
  49 
  50 /*
  51  * @summary Test when FEATURE_SECURE_PROCESSING is true, calling an external function will cause XPathFunctionException.
  52  */
  53 public class SecureProcessingTest {
  54     static boolean _isSecureMode = false;
  55     static {
  56         if (System.getSecurityManager() != null) {
  57             _isSecureMode = true;
  58             System.out.println("Security Manager is present");
  59         } else {
  60             System.out.println("Security Manager is NOT present");
  61         }
  62     }
  63 
  64     @Test
  65     public final void testSecureProcessing() {
  66 
  67         final String XPATH_EXPRESSION = "ext:helloWorld()";
  68 
  69         // the xml source
  70         InputStream xmlStream = this.getClass().getResourceAsStream("SecureProcessingTest.xml");
  71 
  72         DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
  73         DocumentBuilder documentBuilder = null;
  74         Document document = null;
  75 
  76         try {
  77             documentBuilder = documentBuilderFactory.newDocumentBuilder();
  78             document = documentBuilder.parse(xmlStream);
  79         } catch (ParserConfigurationException parserConfigurationException) {
  80             parserConfigurationException.printStackTrace();
  81             Assert.fail(parserConfigurationException.toString());
  82         } catch (SAXException saxException) {
  83             saxException.printStackTrace();
  84             Assert.fail(saxException.toString());
  85         } catch (IOException ioException) {
  86             ioException.printStackTrace();
  87             Assert.fail(ioException.toString());
  88         }
  89 
  90         // the XPath
  91         XPathFactory xPathFactory = null;
  92         XPath xPath = null;
  93         String xPathResult = null;
  94 
  95         // SECURE_PROCESSING == false
  96         // evaluate an expression with a user defined function with a non-secure
  97         // XPath
  98         // expect success
  99         if (!_isSecureMode) { // jaxp secure feature can not be turned off when
 100                               // security manager is present
 101             try {
 102                 xPathFactory = xPathFactory.newInstance();
 103                 xPathFactory.setXPathFunctionResolver(new MyXPathFunctionResolver());
 104                 xPathFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
 105 
 106                 xPath = xPathFactory.newXPath();
 107                 xPath.setNamespaceContext(new MyNamespaceContext());
 108 
 109                 xPathResult = xPath.evaluate(XPATH_EXPRESSION, document);
 110             } catch (XPathFactoryConfigurationException xPathFactoryConfigurationException) {
 111                 xPathFactoryConfigurationException.printStackTrace();
 112                 Assert.fail(xPathFactoryConfigurationException.toString());
 113             } catch (XPathExpressionException xPathExpressionException) {
 114                 xPathExpressionException.printStackTrace();
 115                 Assert.fail(xPathExpressionException.toString());
 116             }
 117 
 118             // expected success
 119             System.out.println("XPath result (SECURE_PROCESSING == false) = \"" + xPathResult + "\"");
 120         }
 121         // now try with SECURE_PROCESSING == true
 122         // evaluate an expression with a user defined function with a secure
 123         // XPath
 124         // expect Exception
 125         boolean securityException = false;
 126         try {
 127             xPathFactory = xPathFactory.newInstance();
 128             xPathFactory.setXPathFunctionResolver(new MyXPathFunctionResolver());
 129             xPathFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
 130 
 131             xPath = xPathFactory.newXPath();
 132             xPath.setNamespaceContext(new MyNamespaceContext());
 133 
 134             xPathResult = xPath.evaluate(XPATH_EXPRESSION, document);
 135         } catch (XPathFactoryConfigurationException xPathFactoryConfigurationException) {
 136             xPathFactoryConfigurationException.printStackTrace();
 137             Assert.fail(xPathFactoryConfigurationException.toString());
 138         } catch (XPathFunctionException xPathFunctionException) {
 139             // expected security exception
 140             securityException = true;
 141             xPathFunctionException.printStackTrace(System.out);
 142         } catch (XPathExpressionException xPathExpressionException) {
 143             xPathExpressionException.printStackTrace();
 144             Assert.fail(xPathExpressionException.toString());
 145         }
 146 
 147         // expected Exception
 148         if (!securityException) {
 149             Assert.fail("XPath result (SECURE_PROCESSING == true) = \"" + xPathResult + "\"");
 150         }
 151     }
 152 
 153     public class MyXPathFunctionResolver implements XPathFunctionResolver {
 154 
 155         public XPathFunction resolveFunction(QName functionName, int arity) {
 156 
 157             // not a real ewsolver, always return a default XPathFunction
 158             return new MyXPathFunction();
 159         }
 160     }
 161 
 162     public class MyXPathFunction implements XPathFunction {
 163 
 164         public Object evaluate(List list) throws XPathFunctionException {
 165 
 166             return "Hello World";
 167         }
 168     }
 169 
 170     public class MyNamespaceContext implements NamespaceContext {
 171 
 172         public String getNamespaceURI(String prefix) {
 173             if (prefix == null) {
 174                 throw new IllegalArgumentException("The prefix cannot be null.");
 175             }
 176 
 177             if (prefix.equals("ext")) {
 178                 return "http://ext.com";
 179             } else {
 180                 return null;
 181             }
 182         }
 183 
 184         public String getPrefix(String namespace) {
 185 
 186             if (namespace == null) {
 187                 throw new IllegalArgumentException("The namespace uri cannot be null.");
 188             }
 189 
 190             if (namespace.equals("http://ext.com")) {
 191                 return "ext";
 192             } else {
 193                 return null;
 194             }
 195         }
 196 
 197         public Iterator getPrefixes(String namespace) {
 198             return null;
 199         }
 200     }
 201 }