public static void main(String[] args) throws Exception { List<String> pkgs = new ArrayList<>(Arrays.asList(packages)); String osName = System.getProperty("os.name"); if (osName.contains("OS X")) { pkgs.add("apple."); // add apple package for OS X } else if (osName.startsWith("Windows")) { pkgs.add("com.sun.java.accessibility."); } List<String> jspkgs = getPackages(Security.getProperty("package.access")); // Sort to ensure lists are comparable Collections.sort(pkgs); Collections.sort(jspkgs); if (!pkgs.equals(jspkgs)) { for (String p : pkgs) if (!jspkgs.contains(p)) System.out.println("In golden set, but not in j.s file: " + p); for (String p : jspkgs) if (!pkgs.contains(p)) System.out.println("In j.s file, but not in golden set: " + p); throw new RuntimeException( "restricted packages are not " + "consistent with java.security file"); } System.setSecurityManager(new SecurityManager()); SecurityManager sm = System.getSecurityManager(); for (String pkg : packages) { String subpkg = pkg + "foo"; try { sm.checkPackageAccess(pkg); throw new RuntimeException("Able to access " + pkg + " package"); } catch (SecurityException se) { } try { sm.checkPackageAccess(subpkg); throw new RuntimeException("Able to access " + subpkg + " package"); } catch (SecurityException se) { } try { sm.checkPackageDefinition(pkg); throw new RuntimeException("Able to define class in " + pkg + " package"); } catch (SecurityException se) { } try { sm.checkPackageDefinition(subpkg); throw new RuntimeException("Able to define class in " + subpkg + " package"); } catch (SecurityException se) { } } System.out.println("Test passed"); }
/** {@inheritDoc} */ @SuppressWarnings("all") protected Class findClass(final String className) throws ClassNotFoundException { // first think check if we are allowed to define the package SecurityManager securityManager = System.getSecurityManager(); if (securityManager != null) { String packageName; int packageEnd = className.lastIndexOf('.'); if (packageEnd >= 0) { packageName = className.substring(0, packageEnd); securityManager.checkPackageDefinition(packageName); } } // convert the class name to a file name String resourceName = className.replace('.', '/') + ".class"; // find the class file resource ResourceHandle resourceHandle = resourceFinder.getResource(resourceName); if (resourceHandle == null) { throw new ClassNotFoundException(className); } byte[] bytes; Manifest manifest; try { // get the bytes from the class file bytes = resourceHandle.getBytes(); // get the manifest for defining the packages manifest = resourceHandle.getManifest(); } catch (IOException e) { throw new ClassNotFoundException(className, e); } // get the certificates for the code source Certificate[] certificates = resourceHandle.getCertificates(); // the code source url is used to define the package and as the security context for the class URL codeSourceUrl = resourceHandle.getCodeSourceUrl(); // define the package (required for security) definePackage(className, codeSourceUrl, manifest); // this is the security context of the class CodeSource codeSource = new CodeSource(codeSourceUrl, certificates); // load the class into the vm Class clazz = defineClass(className, bytes, 0, bytes.length, codeSource); return clazz; }
/** * Lädt die per Name angegebene Klasse. sse. Im Namen kann entweder der Punkt oder der * Schrägstrich als Paket-Trennzeichen benutzt werden. Mit der Option <code>resolve</code> * kann entschieden werden, ob die Auflösung von Abhängigkeiten nötig ist. Bei * <code>true</code> werden auch die von dieser Klasse benötigten Klassen geladen. * * @param name Name der Klasse * @param resolve Option <code>true</code> um Abhängigkeitem zu laden * @return die geladene Klasse, ist diese nicht ermittelbar, führt der Aufruf zur Ausnahme * <code>ClassNotFoundException</code> */ protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Class source; InputStream input; Iterator iterator; SecurityManager security; String packet; ZipEntry entry; ZipFile store; byte[] bytes; int cursor; int size; int volume; name = (name == null) ? "" : name.trim(); if (name.length() == 0) return null; source = (Class) this.classes.get(name); if (source != null) return source; try { // die Berechtigung zur Definition der Klasse wird geprueft, wenn // ein entsprechender SecurityManager vorliegt, ohne ist Definition // aller Klassen zulaessig security = System.getSecurityManager(); cursor = name.lastIndexOf('.'); packet = (cursor > -1) ? name.substring(0, cursor) : ""; // prueft die Berechtigung zum Laden der Klasse/Paket, liegt diese // Berechtigung nicht vor, fuehrt dies zur SecurityException if (security != null) security.checkPackageDefinition(packet); // das Package wird registriert if (super.getPackage(packet) == null) super.definePackage(packet, null, null, null, null, null, null, null); } catch (SecurityException exception) { if (this.loader == null) throw exception; this.loader.loadClass(name); } try { // die Klasse wird versucht als (System)Klasse zu laden source = (this.loader == null) ? null : this.loader.loadClass(name); if (source != null) { if (resolve) super.resolveClass(source); return source; } } catch (Exception exception) { source = null; } // alle Bibliotheken werden ermittelt iterator = this.libraries.iterator(); for (store = null; iterator.hasNext(); ) { try { // das Zip-Archiv wird geoeffnet store = new ZipFile((File) iterator.next()); // der Klassenname wird vereinheitlicht entry = store.getEntry(name.replace('.', '/').concat(".class")); if (entry != null) { input = store.getInputStream(entry); volume = (int) entry.getSize(); bytes = new byte[volume]; size = cursor = 0; // der Datenstrom wird ausgelesen while (volume > 0 && (size = input.read(bytes, cursor, volume)) >= 0) { cursor += size; volume -= size; } // die Klasse wird ueber den ClassLoader definiert source = super.defineClass(name, bytes, 0, bytes.length); // die Klasse wird als geladen registriert this.classes.put(name, source); // gegebenfalls werden die Abhaengigkeitem aufgeloest if (resolve) super.resolveClass(source); return source; } } catch (Throwable throwable) { // keine Fehlerbehandlung vorgesehen } finally { // das Zip-Archiv wird geschlossen try { store.close(); } catch (Throwable throwable) { // keine Fehlerbehandlung vorgesehen } } } throw new ClassNotFoundException(name); }
@Override public void checkPackageDefinition(final String pPkg) { if (finalSecurityManager != null) finalSecurityManager.checkPackageDefinition(pPkg); }