All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ro.esolutions.licensing.LicenseSecurityManager Maven / Gradle / Ivy

The newest version!
/*
 * LicenseSecurityManager.java from LicenseManager modified Monday, June 25, 2012 23:54:40 CDT (-0500).
 *
 * Copyright 2010-2013 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ro.esolutions.licensing;

import java.io.FileDescriptor;
import java.lang.reflect.Member;
import java.net.InetAddress;
import java.security.Permission;

import ro.esolutions.licensing.exception.InsecureEnvironmentException;

/**
 * This security manager is one of the most integral pieces to the license manager. It prevents reflection attacks from
 * disabling or compromising the security features in this product.
*
* When the security manager is initialized, it first checks if a different security manager is already installed in * this JVM. If no security manager is installed already, then this security manager installs itself.
*
* If another security manager is already installed, this checks to make sure it prevents reflection attacks against * critical LicenseManager classes. If it prevents attacks, it is a suitable security manager and allowed to remain. If * it does not prevent attacks, this attempts to override the currently installed security manager and install itself. * If the existing security manager prevents this from installing itself, an {@link InsecureEnvironmentException} is * thrown and the LicenseManager fails to start.
*
* When this security manager installs itself over another, it will nest the other security manager within itself and * call all appropriate checking methods on that other security manager after this manager performs its analog * checks.
*
* When reflection is used to access non-public methods, fields, classes or interfaces, the JVM first consults the * installed security manager to ensure that the access is permitted. This security manager throws an exception if the * protected or private object being accessed via reflection belongs to the security manager package.
*
* Finally, this security manager will prevent other security managers from installing themselves over this one, so * that these security measures are not compromised. * * @author Nick Williams * @version 1.0.0 * @since 1.0.0 */ final class LicenseSecurityManager extends SecurityManager { private static LicenseSecurityManager instance; private static final String FEATURE_RESTRICTION = FeatureRestriction.class.getCanonicalName(); private static final String SIGNED_LICENSE = SignedLicense.class.getCanonicalName(); private static final RuntimePermission CHECK_MEMBER_ACCESS_PERMISSION = new RuntimePermission("accessDeclaredMembers"); private static final RuntimePermission SET_SECURITY_MANAGER_PERMISSION = new RuntimePermission("setSecurityManager"); static { final SecurityManager manager = System.getSecurityManager(); if (manager == null) { // install the security manager LicenseSecurityManager.installSecurityManagerWithParent(null); } else if (!manager.getClass().equals(LicenseSecurityManager.class)) { if (!LicenseSecurityManager.securityManagerIsSuitableReplacement(manager)) { // if it's not a suitable replacement, reset the security manager LicenseSecurityManager.installSecurityManagerWithParent(manager); } } } private static boolean securityManagerIsSuitableReplacement(final SecurityManager securityManager) { if (securityManager == null) throw new IllegalArgumentException("Parameter securityManager cannot be null!"); // Make sure we can't call java.lang.Class#getDeclared*() on License try { securityManager.checkMemberAccess(License.class, Member.DECLARED); return false; } catch (final SecurityException ignore) { // this is a good thing } // Make sure we can't call java.lang.Class#getDeclared*() on LicenseManager try { securityManager.checkMemberAccess(LicenseManager.class, Member.DECLARED); return false; } catch (SecurityException ignore) { // this is a good thing } // Make sure we can't call java.lang.System#setSecurityManager() try { securityManager.checkPermission(LicenseSecurityManager.SET_SECURITY_MANAGER_PERMISSION); return false; } catch (SecurityException ignore) { // this is a good thing } return true; } private static void installSecurityManagerWithParent(final SecurityManager parent) { try { // install the security manager LicenseSecurityManager.instance = new LicenseSecurityManager(parent); System.setSecurityManager(LicenseSecurityManager.instance); } catch (SecurityException e) { // since we can't install the security manager, indicate that the environment is insecure throw new InsecureEnvironmentException(e); } } private final SecurityManager next; private LicenseSecurityManager(final SecurityManager next) { super(); this.next = next; } @Override @SuppressWarnings("deprecation") public void checkMemberAccess(final Class reflectionClass,final int memberAccessType) { if (reflectionClass == null) { throw new IllegalArgumentException("Parameter reflectionClass cannot be null."); } this.inCheck = true; try { if (memberAccessType != Member.PUBLIC) { /* * We check class canonical name, not class object, for equivalency. This is because * (SomeClass.class == SomeClass.class) evaluates to false when the classes are loaded by two different * ClassLoaders and (SomeClass.class.equals(SomeClass.class)) evaluates to false when the classes are * loaded by two different ClassLoaders. Only their class canonical names are guaranteed to be the same. */ final Package packageObject = reflectionClass.getPackage(); if ( packageObject != null && packageObject.getName().startsWith("ro.esolutions.licensing") && !reflectionClass.getCanonicalName().equals(LicenseSecurityManager.FEATURE_RESTRICTION) && !reflectionClass.getCanonicalName().equals(LicenseSecurityManager.SIGNED_LICENSE) ) { throw new SecurityException("Reflection access to non-public members of LicenseManager class [" + reflectionClass.getSimpleName() + "] prohibited."); } if (reflectionClass == java.lang.Class.class || reflectionClass == java.lang.System.class) { Class stack[] = getClassContext(); if (stack.length < 4 || !stack[3].getPackage().getName().startsWith("java.")) throw new SecurityException("Reflection access to non-public members of java.lang.Class " + "and java.lang.System prohibited."); } if (this.next != null) { /* * Per Java SE 6 documentation for java.lang.SecurityManager#checkMemberAccess: If this method is * overridden, then a call to super.checkMemberAccess cannot be made, as the default implementation * of checkMemberAccess relies on the code being checked being at a stack depth of 4. So, we * copy-and-paste the implementation from Java SE 6. * * this.next.checkMemberAccess(reflectionClass, memberAccessType); * * Copyright 1994-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ final Class stack[] = getClassContext(); /* * stack depth of 4 should be the caller of one of the * methods in java.lang.Class that invoke checkMember * access. The stack should look like: * * someCaller [3] * java.lang.Class.someReflectionAPI [2] * java.lang.Class.checkMemberAccess [1] * SecurityManager.checkMemberAccess [0] * */ if ((stack.length < 4) || (stack[3].getClassLoader() != reflectionClass.getClassLoader())) { this.checkPermission(LicenseSecurityManager.CHECK_MEMBER_ACCESS_PERMISSION); } } } } finally { this.inCheck = false; } } @Override @SuppressWarnings("deprecation") public void checkPermission(final Permission permission) { this.inCheck = true; try { if (permission.getName().equals("setSecurityManager")) throw new SecurityException("Setting a SecurityManager other than the LicenseSecurityManager is prohibited."); if (this.next != null) this.next.checkPermission(permission); } finally { this.inCheck = false; } } @Override public void checkPackageAccess(final String packageName) { if (this.next != null) { this.next.checkPackageAccess(packageName); } } @Override public void checkPermission(final Permission permission,final Object object) { if (this.next != null) { this.next.checkPermission(permission, object); } } @Override public void checkCreateClassLoader() { if (this.next != null) { this.next.checkCreateClassLoader(); } } @Override public void checkAccess(final Thread thread) { if (this.next != null) { this.next.checkAccess(thread); } } @Override public void checkAccess(final ThreadGroup threadGroup) { if (this.next != null) { this.next.checkAccess(threadGroup); } } @Override public void checkExit(final int i) { if (this.next != null) { this.next.checkExit(i); } } @Override public void checkExec(final String s) { if (this.next != null) { this.next.checkExec(s); } } @Override public void checkLink(final String s) { if (this.next != null) { this.next.checkLink(s); } } @Override public void checkRead(final FileDescriptor fileDescriptor) { if (this.next != null) { this.next.checkRead(fileDescriptor); } } @Override public void checkRead(final String s) { if (this.next != null) this.next.checkRead(s); } @Override public void checkRead(final String s,final Object o) { if (this.next != null) this.next.checkRead(s); } @Override public void checkWrite(final FileDescriptor fileDescriptor) { if (this.next != null) this.next.checkWrite(fileDescriptor); } @Override public void checkWrite(final String s) { if (this.next != null) this.next.checkWrite(s); } @Override public void checkDelete(final String s) { if (this.next != null) this.next.checkDelete(s); } @Override public void checkConnect(final String s,final int i) { if (this.next != null) this.next.checkConnect(s, i); } @Override public void checkConnect(final String s,final int i,final Object o) { if (this.next != null) this.next.checkConnect(s, i, o); } @Override public void checkListen(final int i) { if (this.next != null) this.next.checkListen(i); } @Override public void checkAccept(final String s,final int i) { if (this.next != null) this.next.checkAccept(s, i); } @Override public void checkMulticast(final InetAddress inetAddress) { if (this.next != null) this.next.checkMulticast(inetAddress); } @Override @Deprecated public void checkMulticast(final InetAddress inetAddress,final byte b) { if (this.next != null) this.next.checkMulticast(inetAddress, b); } @Override public void checkPropertiesAccess() { if (this.next != null) this.next.checkPropertiesAccess(); } @Override public void checkPropertyAccess(final String s) { if (this.next != null) this.next.checkPropertyAccess(s); } @Override public void checkPrintJobAccess() { if (this.next != null) this.next.checkPrintJobAccess(); } @Override @Deprecated public void checkSystemClipboardAccess() { if (this.next != null) this.next.checkSystemClipboardAccess(); } @Override @Deprecated public void checkAwtEventQueueAccess() { if (this.next != null) this.next.checkAwtEventQueueAccess(); } @Override public void checkPackageDefinition(final String s) { if (this.next != null) this.next.checkPackageDefinition(s); } @Override public void checkSetFactory() { if (this.next != null) this.next.checkSetFactory(); } @Override public void checkSecurityAccess(final String s) { if (this.next != null) this.next.checkSecurityAccess(s); } @Override @Deprecated public boolean checkTopLevelWindow(final Object window) { return this.next == null || this.next.checkTopLevelWindow(window); } @Override public ThreadGroup getThreadGroup() { return this.next != null ? this.next.getThreadGroup() : super.getThreadGroup(); } @Override public Object getSecurityContext() { return this.next != null ? this.next.getSecurityContext() : super.getSecurityContext(); } protected static LicenseSecurityManager getInstance() { return LicenseSecurityManager.instance; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy