1 /*
2 * Copyright (c) 1997, 2013, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
261
262 private static final String NONE = "NONE";
263 private static final String P11KEYSTORE = "PKCS11";
264
265 private static final String SELF = "${{self}}";
266 private static final String X500PRINCIPAL =
267 "javax.security.auth.x500.X500Principal";
268 private static final String POLICY = "java.security.policy";
269 private static final String SECURITY_MANAGER = "java.security.manager";
270 private static final String POLICY_URL = "policy.url.";
271 private static final String AUTH_POLICY = "java.security.auth.policy";
272 private static final String AUTH_POLICY_URL = "auth.policy.url.";
273
274 private static final int DEFAULT_CACHE_SIZE = 1;
275
276 // contains the policy grant entries, PD cache, and alias mapping
277 private AtomicReference<PolicyInfo> policyInfo = new AtomicReference<>();
278 private boolean constructed = false;
279
280 private boolean expandProperties = true;
281 private boolean ignoreIdentityScope = true;
282 private boolean allowSystemProperties = true;
283 private boolean notUtf8 = false;
284 private URL url;
285
286 // for use with the reflection API
287
288 private static final Class<?>[] PARAMS0 = { };
289 private static final Class<?>[] PARAMS1 = { String.class };
290 private static final Class<?>[] PARAMS2 = { String.class, String.class };
291
292 /**
293 * Initializes the Policy object and reads the default policy
294 * configuration file(s) into the Policy object.
295 */
296 public PolicyFile() {
297 init((URL)null);
298 }
299
300 /**
301 * Initializes the Policy object and reads the default policy
398 *
399 * grant signedBy "Duke" {
400 * permission java.io.FilePermission "/tmp/*", "read,write";
401 * };
402 *
403 * // grant everyone the following permission
404 *
405 * grant {
406 * permission java.util.PropertyPermission "java.vendor";
407 * };
408 * </pre>
409 */
410 private void init(URL url) {
411 // Properties are set once for each init(); ignore changes between
412 // between diff invocations of initPolicyFile(policy, url, info).
413 String numCacheStr =
414 AccessController.doPrivileged(new PrivilegedAction<String>() {
415 public String run() {
416 expandProperties = "true".equalsIgnoreCase
417 (Security.getProperty("policy.expandProperties"));
418 ignoreIdentityScope = "true".equalsIgnoreCase
419 (Security.getProperty("policy.ignoreIdentityScope"));
420 allowSystemProperties = "true".equalsIgnoreCase
421 (Security.getProperty("policy.allowSystemProperty"));
422 notUtf8 = "false".equalsIgnoreCase
423 (System.getProperty("sun.security.policy.utf8"));
424 return System.getProperty("sun.security.policy.numcaches");
425 }});
426
427 int numCaches;
428 if (numCacheStr != null) {
429 try {
430 numCaches = Integer.parseInt(numCacheStr);
431 } catch (NumberFormatException e) {
432 numCaches = DEFAULT_CACHE_SIZE;
433 }
434 } else {
435 numCaches = DEFAULT_CACHE_SIZE;
436 }
437 // System.out.println("number caches=" + numCaches);
438 PolicyInfo newInfo = new PolicyInfo(numCaches);
439 initPolicyFile(newInfo, url);
1189
1190 CodeSource canonCodeSource = AccessController.doPrivileged(
1191 new java.security.PrivilegedAction<CodeSource>(){
1192 public CodeSource run() {
1193 return canonicalizeCodebase(cs, true);
1194 }
1195 });
1196
1197 return getPermissions(perms, canonCodeSource, null);
1198 }
1199
1200 private Permissions getPermissions(Permissions perms,
1201 final CodeSource cs,
1202 Principal[] principals) {
1203 PolicyInfo pi = policyInfo.get();
1204
1205 for (PolicyEntry entry : pi.policyEntries) {
1206 addPermissions(perms, cs, principals, entry);
1207 }
1208
1209 // Go through policyEntries gotten from identity db; sync required
1210 // because checkForTrustedIdentity (below) might update list
1211 synchronized (pi.identityPolicyEntries) {
1212 for (PolicyEntry entry : pi.identityPolicyEntries) {
1213 addPermissions(perms, cs, principals, entry);
1214 }
1215 }
1216
1217 // now see if any of the keys are trusted ids.
1218 if (!ignoreIdentityScope) {
1219 Certificate certs[] = cs.getCertificates();
1220 if (certs != null) {
1221 for (int k=0; k < certs.length; k++) {
1222 Object idMap = pi.aliasMapping.get(certs[k]);
1223 if (idMap == null &&
1224 checkForTrustedIdentity(certs[k], pi)) {
1225 // checkForTrustedIdentity added it
1226 // to the policy for us. next time
1227 // around we'll find it. This time
1228 // around we need to add it.
1229 perms.add(SecurityConstants.ALL_PERMISSION);
1230 }
1231 }
1232 }
1233 }
1234 return perms;
1235 }
1236
1237 private void addPermissions(Permissions perms,
1238 final CodeSource cs,
1239 Principal[] principals,
1240 final PolicyEntry entry) {
1241
1242 if (debug != null) {
1243 debug.println("evaluate codesources:\n" +
1244 "\tPolicy CodeSource: " + entry.getCodeSource() + "\n" +
1245 "\tActive CodeSource: " + cs);
1246 }
1247
1248 // check to see if the CodeSource implies
1249 Boolean imp = AccessController.doPrivileged
1250 (new PrivilegedAction<Boolean>() {
1251 public Boolean run() {
1252 return entry.getCodeSource().implies(cs);
1253 }
1603 } else {
1604
1605 // build an info array for every
1606 // one of the current Domain's principals
1607
1608 String[][] info = new String[pdp.length][2];
1609
1610 for (int i = 0; i < pdp.length; i++) {
1611 info[i][0] = pdp[i].getClass().getName();
1612 info[i][1] = pdp[i].getName();
1613 }
1614 return info;
1615 }
1616 }
1617
1618 /*
1619 * Returns the signer certificates from the list of certificates
1620 * associated with the given code source.
1621 *
1622 * The signer certificates are those certificates that were used
1623 * to verifysigned code originating from the codesource location.
1624 *
1625 * This method assumes that in the given code source, each signer
1626 * certificate is followed by its supporting certificate chain
1627 * (which may be empty), and that the signer certificate and its
1628 * supporting certificate chain are ordered bottom-to-top
1629 * (i.e., with the signer certificate first and the (root) certificate
1630 * authority last).
1631 */
1632 protected Certificate[] getSignerCertificates(CodeSource cs) {
1633 Certificate[] certs = null;
1634 if ((certs = cs.getCertificates()) == null)
1635 return null;
1636 for (int i=0; i<certs.length; i++) {
1637 if (!(certs[i] instanceof X509Certificate))
1638 return cs.getCertificates();
1639 }
1640
1641 // Do we have to do anything?
1642 int i = 0;
1643 int count = 0;
1900 if (debug != null) {
1901 debug.println(" -- No certificate for '" +
1902 alias +
1903 "' - ignoring entry");
1904 }
1905 return null;
1906 } else {
1907 X509Certificate x509Cert = (X509Certificate)cert;
1908
1909 // 4702543: X500 names with an EmailAddress
1910 // were encoded incorrectly. create new
1911 // X500Principal name with correct encoding
1912
1913 X500Principal p = new X500Principal
1914 (x509Cert.getSubjectX500Principal().toString());
1915 return p.getName();
1916 }
1917 }
1918
1919 /**
1920 * Checks public key. If it is marked as trusted in
1921 * the identity database, add it to the policy
1922 * with the AllPermission.
1923 */
1924 private boolean checkForTrustedIdentity(final Certificate cert,
1925 PolicyInfo myInfo)
1926 {
1927 return false;
1928 }
1929
1930 /**
1931 * Each entry in the policy configuration file is represented by a
1932 * PolicyEntry object. <p>
1933 *
1934 * A PolicyEntry is a (CodeSource,Permission) pair. The
1935 * CodeSource contains the (URL, PublicKey) that together identify
1936 * where the Java bytecodes come from and who (if anyone) signed
1937 * them. The URL could refer to localhost. The URL could also be
1938 * null, meaning that this policy entry is given to all comers, as
1939 * long as they match the signer field. The signer could be null,
1940 * meaning the code is not signed. <p>
1941 *
1942 * The Permission contains the (Type, Name, Action) triplet. <p>
1943 *
1944 * For now, the Policy object retrieves the public key from the
1945 * X.509 certificate on disk that corresponds to the signedBy
1946 * alias specified in the Policy config file. For reasons of
1947 * efficiency, the Policy object keeps a hashtable of certs already
1948 * read in. This could be replaced by a secure internal key
1949 * store.
1950 *
2265 * Returns a string describing this SelfPermission. The convention
2266 * is to specify the class name, the permission name, and the actions,
2267 * in the following format: '(unresolved "ClassName" "name" "actions")'.
2268 *
2269 * @return information about this SelfPermission.
2270 */
2271 @Override public String toString() {
2272 return "(SelfPermission " + type + " " + name + " " + actions + ")";
2273 }
2274 }
2275
2276 /**
2277 * holds policy information that we need to synch on
2278 */
2279 private static class PolicyInfo {
2280 private static final boolean verbose = false;
2281
2282 // Stores grant entries in the policy
2283 final List<PolicyEntry> policyEntries;
2284
2285 // Stores grant entries gotten from identity database
2286 // Use separate lists to avoid sync on policyEntries
2287 final List<PolicyEntry> identityPolicyEntries;
2288
2289 // Maps aliases to certs
2290 final Map<Object, Object> aliasMapping;
2291
2292 // Maps ProtectionDomain to PermissionCollection
2293 private final ProtectionDomainCache[] pdMapping;
2294 private java.util.Random random;
2295
2296 PolicyInfo(int numCaches) {
2297 policyEntries = new ArrayList<>();
2298 identityPolicyEntries =
2299 Collections.synchronizedList(new ArrayList<PolicyEntry>(2));
2300 aliasMapping = Collections.synchronizedMap(new HashMap<>(11));
2301
2302 pdMapping = new ProtectionDomainCache[numCaches];
2303 JavaSecurityProtectionDomainAccess jspda
2304 = SharedSecrets.getJavaSecurityProtectionDomainAccess();
2305 for (int i = 0; i < numCaches; i++) {
2306 pdMapping[i] = jspda.getProtectionDomainCache();
2307 }
2308 if (numCaches > 1) {
2309 random = new java.util.Random();
2310 }
2311 }
2312 ProtectionDomainCache getPdMapping() {
2313 if (pdMapping.length == 1) {
2314 return pdMapping[0];
2315 } else {
2316 int i = java.lang.Math.abs(random.nextInt() % pdMapping.length);
2317 return pdMapping[i];
2318 }
2319 }
|
1 /*
2 * Copyright (c) 1997, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
261
262 private static final String NONE = "NONE";
263 private static final String P11KEYSTORE = "PKCS11";
264
265 private static final String SELF = "${{self}}";
266 private static final String X500PRINCIPAL =
267 "javax.security.auth.x500.X500Principal";
268 private static final String POLICY = "java.security.policy";
269 private static final String SECURITY_MANAGER = "java.security.manager";
270 private static final String POLICY_URL = "policy.url.";
271 private static final String AUTH_POLICY = "java.security.auth.policy";
272 private static final String AUTH_POLICY_URL = "auth.policy.url.";
273
274 private static final int DEFAULT_CACHE_SIZE = 1;
275
276 // contains the policy grant entries, PD cache, and alias mapping
277 private AtomicReference<PolicyInfo> policyInfo = new AtomicReference<>();
278 private boolean constructed = false;
279
280 private boolean expandProperties = true;
281 private boolean allowSystemProperties = true;
282 private boolean notUtf8 = false;
283 private URL url;
284
285 // for use with the reflection API
286
287 private static final Class<?>[] PARAMS0 = { };
288 private static final Class<?>[] PARAMS1 = { String.class };
289 private static final Class<?>[] PARAMS2 = { String.class, String.class };
290
291 /**
292 * Initializes the Policy object and reads the default policy
293 * configuration file(s) into the Policy object.
294 */
295 public PolicyFile() {
296 init((URL)null);
297 }
298
299 /**
300 * Initializes the Policy object and reads the default policy
397 *
398 * grant signedBy "Duke" {
399 * permission java.io.FilePermission "/tmp/*", "read,write";
400 * };
401 *
402 * // grant everyone the following permission
403 *
404 * grant {
405 * permission java.util.PropertyPermission "java.vendor";
406 * };
407 * </pre>
408 */
409 private void init(URL url) {
410 // Properties are set once for each init(); ignore changes between
411 // between diff invocations of initPolicyFile(policy, url, info).
412 String numCacheStr =
413 AccessController.doPrivileged(new PrivilegedAction<String>() {
414 public String run() {
415 expandProperties = "true".equalsIgnoreCase
416 (Security.getProperty("policy.expandProperties"));
417 allowSystemProperties = "true".equalsIgnoreCase
418 (Security.getProperty("policy.allowSystemProperty"));
419 notUtf8 = "false".equalsIgnoreCase
420 (System.getProperty("sun.security.policy.utf8"));
421 return System.getProperty("sun.security.policy.numcaches");
422 }});
423
424 int numCaches;
425 if (numCacheStr != null) {
426 try {
427 numCaches = Integer.parseInt(numCacheStr);
428 } catch (NumberFormatException e) {
429 numCaches = DEFAULT_CACHE_SIZE;
430 }
431 } else {
432 numCaches = DEFAULT_CACHE_SIZE;
433 }
434 // System.out.println("number caches=" + numCaches);
435 PolicyInfo newInfo = new PolicyInfo(numCaches);
436 initPolicyFile(newInfo, url);
1186
1187 CodeSource canonCodeSource = AccessController.doPrivileged(
1188 new java.security.PrivilegedAction<CodeSource>(){
1189 public CodeSource run() {
1190 return canonicalizeCodebase(cs, true);
1191 }
1192 });
1193
1194 return getPermissions(perms, canonCodeSource, null);
1195 }
1196
1197 private Permissions getPermissions(Permissions perms,
1198 final CodeSource cs,
1199 Principal[] principals) {
1200 PolicyInfo pi = policyInfo.get();
1201
1202 for (PolicyEntry entry : pi.policyEntries) {
1203 addPermissions(perms, cs, principals, entry);
1204 }
1205
1206 return perms;
1207 }
1208
1209 private void addPermissions(Permissions perms,
1210 final CodeSource cs,
1211 Principal[] principals,
1212 final PolicyEntry entry) {
1213
1214 if (debug != null) {
1215 debug.println("evaluate codesources:\n" +
1216 "\tPolicy CodeSource: " + entry.getCodeSource() + "\n" +
1217 "\tActive CodeSource: " + cs);
1218 }
1219
1220 // check to see if the CodeSource implies
1221 Boolean imp = AccessController.doPrivileged
1222 (new PrivilegedAction<Boolean>() {
1223 public Boolean run() {
1224 return entry.getCodeSource().implies(cs);
1225 }
1575 } else {
1576
1577 // build an info array for every
1578 // one of the current Domain's principals
1579
1580 String[][] info = new String[pdp.length][2];
1581
1582 for (int i = 0; i < pdp.length; i++) {
1583 info[i][0] = pdp[i].getClass().getName();
1584 info[i][1] = pdp[i].getName();
1585 }
1586 return info;
1587 }
1588 }
1589
1590 /*
1591 * Returns the signer certificates from the list of certificates
1592 * associated with the given code source.
1593 *
1594 * The signer certificates are those certificates that were used
1595 * to verify signed code originating from the codesource location.
1596 *
1597 * This method assumes that in the given code source, each signer
1598 * certificate is followed by its supporting certificate chain
1599 * (which may be empty), and that the signer certificate and its
1600 * supporting certificate chain are ordered bottom-to-top
1601 * (i.e., with the signer certificate first and the (root) certificate
1602 * authority last).
1603 */
1604 protected Certificate[] getSignerCertificates(CodeSource cs) {
1605 Certificate[] certs = null;
1606 if ((certs = cs.getCertificates()) == null)
1607 return null;
1608 for (int i=0; i<certs.length; i++) {
1609 if (!(certs[i] instanceof X509Certificate))
1610 return cs.getCertificates();
1611 }
1612
1613 // Do we have to do anything?
1614 int i = 0;
1615 int count = 0;
1872 if (debug != null) {
1873 debug.println(" -- No certificate for '" +
1874 alias +
1875 "' - ignoring entry");
1876 }
1877 return null;
1878 } else {
1879 X509Certificate x509Cert = (X509Certificate)cert;
1880
1881 // 4702543: X500 names with an EmailAddress
1882 // were encoded incorrectly. create new
1883 // X500Principal name with correct encoding
1884
1885 X500Principal p = new X500Principal
1886 (x509Cert.getSubjectX500Principal().toString());
1887 return p.getName();
1888 }
1889 }
1890
1891 /**
1892 * Each entry in the policy configuration file is represented by a
1893 * PolicyEntry object. <p>
1894 *
1895 * A PolicyEntry is a (CodeSource,Permission) pair. The
1896 * CodeSource contains the (URL, PublicKey) that together identify
1897 * where the Java bytecodes come from and who (if anyone) signed
1898 * them. The URL could refer to localhost. The URL could also be
1899 * null, meaning that this policy entry is given to all comers, as
1900 * long as they match the signer field. The signer could be null,
1901 * meaning the code is not signed. <p>
1902 *
1903 * The Permission contains the (Type, Name, Action) triplet. <p>
1904 *
1905 * For now, the Policy object retrieves the public key from the
1906 * X.509 certificate on disk that corresponds to the signedBy
1907 * alias specified in the Policy config file. For reasons of
1908 * efficiency, the Policy object keeps a hashtable of certs already
1909 * read in. This could be replaced by a secure internal key
1910 * store.
1911 *
2226 * Returns a string describing this SelfPermission. The convention
2227 * is to specify the class name, the permission name, and the actions,
2228 * in the following format: '(unresolved "ClassName" "name" "actions")'.
2229 *
2230 * @return information about this SelfPermission.
2231 */
2232 @Override public String toString() {
2233 return "(SelfPermission " + type + " " + name + " " + actions + ")";
2234 }
2235 }
2236
2237 /**
2238 * holds policy information that we need to synch on
2239 */
2240 private static class PolicyInfo {
2241 private static final boolean verbose = false;
2242
2243 // Stores grant entries in the policy
2244 final List<PolicyEntry> policyEntries;
2245
2246 // Maps aliases to certs
2247 final Map<Object, Object> aliasMapping;
2248
2249 // Maps ProtectionDomain to PermissionCollection
2250 private final ProtectionDomainCache[] pdMapping;
2251 private java.util.Random random;
2252
2253 PolicyInfo(int numCaches) {
2254 policyEntries = new ArrayList<>();
2255 aliasMapping = Collections.synchronizedMap(new HashMap<>(11));
2256
2257 pdMapping = new ProtectionDomainCache[numCaches];
2258 JavaSecurityProtectionDomainAccess jspda
2259 = SharedSecrets.getJavaSecurityProtectionDomainAccess();
2260 for (int i = 0; i < numCaches; i++) {
2261 pdMapping[i] = jspda.getProtectionDomainCache();
2262 }
2263 if (numCaches > 1) {
2264 random = new java.util.Random();
2265 }
2266 }
2267 ProtectionDomainCache getPdMapping() {
2268 if (pdMapping.length == 1) {
2269 return pdMapping[0];
2270 } else {
2271 int i = java.lang.Math.abs(random.nextInt() % pdMapping.length);
2272 return pdMapping[i];
2273 }
2274 }
|