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