/* * Copyright (c) 2006 Mark Petrovic * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Original Author: Mark Petrovic * */ package secmgr.manager; import static java.lang.System.err; import static java.lang.System.out; import java.lang.reflect.Field; import java.net.URL; import java.security.AccessController; import java.security.AccessControlContext; import java.security.CodeSource; import java.security.Permission; import java.security.ProtectionDomain; import java.util.ArrayList; /** * ProfilingSecurityManager is a Java security manager that profiles * what resources an application accesses, and in what manner --- e.g., read, write, etc. It does not enforce a * security policy, but rather produces a starting point for crafting one. *

* It extends java.lang.SecurityManager and overrides the two forms of the checkPermission() method. * For each call to checkPermission(), ProfilingSecurityManager first guards against the * condition that it itself induced the call to checkPermission(), which would result in * unterminated recursion. If a call to checkPermission() resulted from a call outside * ProfilingSecurityManager, the current context is examined and each class found therein is * profiled as needing access to the java.security.Permission in question. * * Profiling is manifested as a writing to System.out a "grant" rule for each java.security.Permission requested * on a per CodeBase basis. * * The implementation here does some very simple rule caching. If a rule has been seen previously, it is not output to System.out. * The caching cannot prevent a security check, but it can reduce I/O during profiling. * * @author Mark S. Petrovic */ public class ProfilingSecurityManager extends SecurityManager { /* Variables of pure convenience */ final private String thisClassName; final private String thisCodeSourceURLString; final private String psmMsg = "ProfilingSecurityManager"; final private ArrayList cacheList = new ArrayList(); // --------------------------------- public ProfilingSecurityManager() { thisClassName=this.getClass().getName(); CodeSource thisCodeSource = this.getClass().getProtectionDomain().getCodeSource(); thisCodeSourceURLString = thisCodeSource.getLocation().toString(); } // ----------------- @Override public void checkPermission(final Permission permission) { final Throwable t = new Throwable("Profiler stack probe"); final StackTraceElement[] stack = t.getStackTrace(); // Avoid recursion owing to actions in this class itself inducing callbacks if( !isRecur(stack) ) { buildRules(permission, AccessController.getContext()); } } // ----------------- @Override public void checkPermission(final Permission permission, final Object context) { buildRules(permission, (AccessControlContext)context); } // ----------------- // With a Permission and an AccessControlContext, we can build and print rules private void buildRules(final Permission permission, final AccessControlContext ctx) { try { final ProtectionDomain[] protectionDomain = getProtectionDomains(ctx); if( null != protectionDomain ) { for(int i=0;i=1;--i) { final boolean c = st[i].getClassName().equals(thisClassName); final boolean m = st[i].getMethodName().equals("buildRules"); if (c && m) { v = true; break; } } return v; } // ----------------- /* Get the protection domains by Java reflection. There is no public API for this info, * making this code Sun Java 1.5 JVM implementation dependent. */ private ProtectionDomain[] getProtectionDomains(final AccessControlContext context) throws IllegalStateException { ProtectionDomain[] pda = null; try { final Field[] fields = AccessControlContext.class.getDeclaredFields(); if( null == fields ) { throw new IllegalStateException("No fields"); } for(int i=0; i