1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.xalan.internal.utils;
  23 
  24 import java.io.File;
  25 import java.io.FileInputStream;
  26 import java.io.FileNotFoundException;
  27 import java.io.IOException;
  28 import java.io.InputStream;
  29 import java.net.URL;
  30 
  31 import java.security.AccessController;
  32 import java.security.PrivilegedAction;
  33 import java.security.PrivilegedActionException;
  34 import java.security.PrivilegedExceptionAction;
  35 import java.util.ListResourceBundle;
  36 import java.util.Locale;
  37 import java.util.MissingResourceException;
  38 import java.util.ResourceBundle;
  39 import java.util.Properties;
  40 
  41 /**
  42  * This class is duplicated for each subpackage so keep it in sync. It is
  43  * package private and therefore is not exposed as part of any API.
  44  *
  45  * @xerces.internal
  46  */
  47 public final class SecuritySupport {
  48 
  49     private static final SecuritySupport securitySupport = new SecuritySupport();
  50 
  51     /**
  52      * Return an instance of this class.
  53      */
  54     public static SecuritySupport getInstance() {
  55         return securitySupport;
  56     }
  57 
  58     public static ClassLoader getContextClassLoader() {
  59         return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
  60             public Object run() {
  61                 ClassLoader cl = null;
  62                 try {
  63                     cl = Thread.currentThread().getContextClassLoader();
  64                 } catch (SecurityException ex) {
  65                 }
  66                 return cl;
  67             }
  68         });
  69     }
  70 
  71     static ClassLoader getSystemClassLoader() {
  72         return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
  73             public Object run() {
  74                 ClassLoader cl = null;
  75                 try {
  76                     cl = ClassLoader.getSystemClassLoader();
  77                 } catch (SecurityException ex) {
  78                 }
  79                 return cl;
  80             }
  81         });
  82     }
  83 
  84     static ClassLoader getParentClassLoader(final ClassLoader cl) {
  85         return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
  86             public Object run() {
  87                 ClassLoader parent = null;
  88                 try {
  89                     parent = cl.getParent();
  90                 } catch (SecurityException ex) {
  91                 }
  92 
  93                 // eliminate loops in case of the boot
  94                 // ClassLoader returning itself as a parent
  95                 return (parent == cl) ? null : parent;
  96             }
  97         });
  98     }
  99 
 100     public static String getSystemProperty(final String propName) {
 101         return (String) AccessController.doPrivileged(new PrivilegedAction() {
 102             public Object run() {
 103                 return System.getProperty(propName);
 104             }
 105         });
 106     }
 107 
 108     public static String getSystemProperty(final String propName, final String def) {
 109         return (String) AccessController.doPrivileged(new PrivilegedAction() {
 110             public Object run() {
 111                 return System.getProperty(propName, def);
 112             }
 113         });
 114     }
 115 
 116     static FileInputStream getFileInputStream(final File file)
 117             throws FileNotFoundException {
 118         try {
 119             return (FileInputStream) AccessController.doPrivileged(new PrivilegedExceptionAction() {
 120                 public Object run() throws FileNotFoundException {
 121                     return new FileInputStream(file);
 122                 }
 123             });
 124         } catch (PrivilegedActionException e) {
 125             throw (FileNotFoundException)e.getException();
 126         }
 127     }
 128 
 129     /**
 130      * Return resource using the same classloader for the ObjectFactory by
 131      * default or bootclassloader when Security Manager is in place
 132      */
 133     public static InputStream getResourceAsStream(final String name) {
 134         if (System.getSecurityManager()!=null) {
 135             return getResourceAsStream(null, name);
 136         } else {
 137             return getResourceAsStream(ObjectFactory.findClassLoader(), name);
 138         }
 139     }
 140 
 141     public static InputStream getResourceAsStream(final ClassLoader cl,
 142             final String name) {
 143         return (InputStream) AccessController.doPrivileged(new PrivilegedAction() {
 144             public Object run() {
 145                 InputStream ris;
 146                 if (cl == null) {
 147                     ris = Object.class.getResourceAsStream("/"+name);
 148                 } else {
 149                     ris = cl.getResourceAsStream(name);
 150                 }
 151                 return ris;
 152             }
 153         });
 154     }
 155 
 156     /**
 157      * Gets a resource bundle using the specified base name, the default locale, and the caller's class loader.
 158      * @param bundle the base name of the resource bundle, a fully qualified class name
 159      * @return a resource bundle for the given base name and the default locale
 160      */
 161     public static ListResourceBundle getResourceBundle(String bundle) {
 162         return getResourceBundle(bundle, Locale.getDefault());
 163     }
 164 
 165     /**
 166      * Gets a resource bundle using the specified base name and locale, and the caller's class loader.
 167      * @param bundle the base name of the resource bundle, a fully qualified class name
 168      * @param locale the locale for which a resource bundle is desired
 169      * @return a resource bundle for the given base name and locale
 170      */
 171     public static ListResourceBundle getResourceBundle(final String bundle, final Locale locale) {
 172         return AccessController.doPrivileged(new PrivilegedAction<ListResourceBundle>() {
 173             public ListResourceBundle run() {
 174                 try {
 175                     return (ListResourceBundle)ResourceBundle.getBundle(bundle, locale);
 176                 } catch (MissingResourceException e) {
 177                     try {
 178                         return (ListResourceBundle)ResourceBundle.getBundle(bundle, new Locale("en", "US"));
 179                     } catch (MissingResourceException e2) {
 180                         throw new MissingResourceException(
 181                                 "Could not load any resource bundle by " + bundle, bundle, "");
 182                     }
 183                 }
 184             }
 185         });
 186     }
 187 
 188     public static boolean getFileExists(final File f) {
 189         return ((Boolean) AccessController.doPrivileged(new PrivilegedAction() {
 190                     public Object run() {
 191                         return f.exists() ? Boolean.TRUE : Boolean.FALSE;
 192                     }
 193                 })).booleanValue();
 194     }
 195 
 196     static long getLastModified(final File f) {
 197         return ((Long) AccessController.doPrivileged(new PrivilegedAction() {
 198                     public Object run() {
 199                         return new Long(f.lastModified());
 200                     }
 201                 })).longValue();
 202     }
 203 
 204     /**
 205      * Strip off path from an URI
 206      *
 207      * @param uri an URI with full path
 208      * @return the file name only
 209      */
 210     public static String sanitizePath(String uri) {
 211         if (uri == null) {
 212             return "";
 213         }
 214         int i = uri.lastIndexOf("/");
 215         if (i > 0) {
 216             return uri.substring(i+1, uri.length());
 217         }
 218         return "";
 219     }
 220 
 221     /**
 222      * Check the protocol used in the systemId against allowed protocols
 223      *
 224      * @param systemId the Id of the URI
 225      * @param allowedProtocols a list of allowed protocols separated by comma
 226      * @param accessAny keyword to indicate allowing any protocol
 227      * @return the name of the protocol if rejected, null otherwise
 228      */
 229     public static String checkAccess(String systemId, String allowedProtocols, String accessAny) throws IOException {
 230         if (systemId == null || (allowedProtocols != null &&
 231                 allowedProtocols.equalsIgnoreCase(accessAny))) {
 232             return null;
 233         }
 234 
 235         String protocol;
 236         if (systemId.indexOf(":")==-1) {
 237             protocol = "file";
 238         } else {
 239             URL url = new URL(systemId);
 240             protocol = url.getProtocol();
 241             if (protocol.equalsIgnoreCase("jar")) {
 242                 String path = url.getPath();
 243                 protocol = path.substring(0, path.indexOf(":"));
 244             }
 245         }
 246 
 247         if (isProtocolAllowed(protocol, allowedProtocols)) {
 248             //access allowed
 249             return null;
 250         } else {
 251             return protocol;
 252         }
 253     }
 254 
 255     /**
 256      * Check if the protocol is in the allowed list of protocols. The check
 257      * is case-insensitive while ignoring whitespaces.
 258      *
 259      * @param protocol a protocol
 260      * @param allowedProtocols a list of allowed protocols
 261      * @return true if the protocol is in the list
 262      */
 263     private static boolean isProtocolAllowed(String protocol, String allowedProtocols) {
 264          if (allowedProtocols == null) {
 265              return false;
 266          }
 267          String temp[] = allowedProtocols.split(",");
 268          for (String t : temp) {
 269              t = t.trim();
 270              if (t.equalsIgnoreCase(protocol)) {
 271                  return true;
 272              }
 273          }
 274          return false;
 275      }
 276 
 277     /**
 278      * Read JAXP system property in this order: system property,
 279      * $java.home/lib/jaxp.properties if the system property is not specified
 280      *
 281      * @param propertyId the Id of the property
 282      * @return the value of the property
 283      */
 284     public static String getJAXPSystemProperty(String sysPropertyId) {
 285         String accessExternal = getSystemProperty(sysPropertyId);
 286         if (accessExternal == null) {
 287             accessExternal = readJAXPProperty(sysPropertyId);
 288         }
 289         return accessExternal;
 290     }
 291 
 292     /**
 293      * Read from $java.home/lib/jaxp.properties for the specified property
 294      * The program
 295      *
 296      * @param propertyId the Id of the property
 297      * @return the value of the property
 298      */
 299     static String readJAXPProperty(String propertyId) {
 300         String value = null;
 301         InputStream is = null;
 302         try {
 303             if (firstTime) {
 304                 synchronized (cacheProps) {
 305                     if (firstTime) {
 306                         String configFile = getSystemProperty("java.home") + File.separator +
 307                             "lib" + File.separator + "jaxp.properties";
 308                         File f = new File(configFile);
 309                         if (getFileExists(f)) {
 310                             is = getFileInputStream(f);
 311                             cacheProps.load(is);
 312                         }
 313                         firstTime = false;
 314                     }
 315                 }
 316             }
 317             value = cacheProps.getProperty(propertyId);
 318 
 319         }
 320         catch (Exception ex) {}
 321         finally {
 322             if (is != null) {
 323                 try {
 324                     is.close();
 325                 } catch (IOException ex) {}
 326             }
 327         }
 328 
 329         return value;
 330     }
 331 
 332     /**
 333      * Cache for properties in java.home/lib/jaxp.properties
 334      */
 335     static final Properties cacheProps = new Properties();
 336 
 337     /**
 338      * Flag indicating if the program has tried reading java.home/lib/jaxp.properties
 339      */
 340     static volatile boolean firstTime = true;
 341 
 342     private SecuritySupport () {}
 343 }