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