1 package groovy.security; 2 3 import groovy.lang.Binding; 4 import groovy.lang.GroovyClassLoader; 5 import groovy.lang.GroovyCodeSource; 6 import groovy.lang.Script; 7 import groovy.util.GroovyTestCase; 8 9 import java.io.File ; 10 import java.io.FileNotFoundException ; 11 import java.io.PrintStream ; 12 import java.security.AccessControlException ; 13 import java.security.AccessController ; 14 import java.security.Permission ; 15 import java.security.Policy ; 16 import java.security.PrivilegedAction ; 17 import java.util.Enumeration ; 18 19 import junit.framework.TestCase; 20 import junit.framework.TestFailure; 21 import junit.framework.TestResult; 22 import junit.framework.TestSuite; 23 import junit.textui.ResultPrinter; 24 25 import org.codehaus.groovy.runtime.InvokerHelper; 26 27 30 public class SecurityTestSupport extends GroovyTestCase { 31 32 private static int counter = 0; 33 private static boolean securityDisabled; 34 private static boolean securityAvailable; 35 private static boolean securityChecked = false; 36 37 static { 38 if (System.getProperty("groovy.security.disabled") != null) { 39 securityAvailable = false; 40 securityDisabled = true; 41 } else { 42 securityDisabled = false; 43 String groovyLibDir = System.getProperty("groovy.lib"); 44 if (groovyLibDir == null) { 45 groovyLibDir = System.getProperty("user.home") + "/" + ".maven/repository"; 47 } 48 if (groovyLibDir == null) { 49 groovyLibDir = "lib"; 51 } 52 if (new File (groovyLibDir).exists()) { 53 securityAvailable = true; 54 System.setProperty("groovy.lib", groovyLibDir); 55 System.setProperty("java.security.policy", "=security/groovy.policy"); 56 } else { 57 securityAvailable = false; 58 } 59 } 60 } 61 62 public static boolean isSecurityAvailable() { 63 return securityAvailable; 64 } 65 66 public static boolean isSecurityDisabled() { 67 return securityDisabled; 68 } 69 70 public static void resetSecurityPolicy(String policyFileURL) { 71 System.setProperty("java.security.policy", policyFileURL); 72 Policy.getPolicy().refresh(); 73 } 74 75 protected class SecurityTestResultPrinter extends ResultPrinter { 76 77 public SecurityTestResultPrinter(PrintStream stream) { 78 super(stream); 79 } 80 public void print(TestResult result) { 81 getWriter().println("Security testing on a groovy test failed:"); 82 printErrors(result); 83 printFailures(result); 84 printFooter(result); 85 } 86 }; 87 88 protected GroovyClassLoader loader = (GroovyClassLoader) AccessController.doPrivileged(new PrivilegedAction () { 89 public Object run() { 90 return new GroovyClassLoader(SecurityTestSupport.class.getClassLoader()); 91 } 92 }); 93 94 private SecurityManager securityManager; 95 private ClassLoader currentClassLoader; 96 97 public SecurityTestSupport() { 98 } 99 100 104 private boolean checkSecurity() { 105 if (!securityChecked) { 106 securityChecked = true; 107 if (!isSecurityAvailable()) { 108 fail("Security is not available - skipping security tests. Ensure that groovy.lib is set and points to the groovy dependency jars."); 109 } 110 } 111 return isSecurityAvailable(); 112 } 113 114 protected void setUp() { 122 if (checkSecurity()) { 123 securityManager = System.getSecurityManager(); 124 if (securityManager == null) { 125 System.setSecurityManager(new SecurityManager ()); 126 } 127 } 128 currentClassLoader = Thread.currentThread().getContextClassLoader(); 129 AccessController.doPrivileged(new PrivilegedAction () { 130 public Object run() { 131 Thread.currentThread().setContextClassLoader(loader); 132 return null; 133 } 134 }); 135 } 136 137 protected void tearDown() { 138 AccessController.doPrivileged(new PrivilegedAction () { 139 public Object run() { 140 System.setSecurityManager(securityManager); 141 Thread.currentThread().setContextClassLoader(currentClassLoader); 142 return null; 143 } 144 }); 145 } 146 147 protected synchronized String generateClassName() { 148 return "testSecurity" + (++counter); 149 } 150 151 156 protected Class parseClass(File file) { 157 GroovyCodeSource gcs = null; 158 try { 159 gcs = new GroovyCodeSource(file); 160 } catch (FileNotFoundException fnfe) { 161 fail(fnfe.toString()); 162 } 163 return parseClass(gcs); 164 } 165 166 170 protected Class parseClass(final GroovyCodeSource gcs) { 171 Class clazz = null; 172 try { 173 clazz = loader.parseClass(gcs); 174 } catch (Exception e) { 175 fail(e.toString()); 176 } 177 return clazz; 178 } 179 180 186 private void parseAndExecute(final GroovyCodeSource gcs, Permission missingPermission) { 187 Class clazz = null; 188 try { 189 clazz = loader.parseClass(gcs); 190 } catch (Exception e) { 191 fail(e.toString()); 192 } 193 if (TestCase.class.isAssignableFrom(clazz)) { 194 executeTest(clazz, missingPermission); 195 } else { 196 executeScript(clazz, missingPermission); 197 } 198 } 199 200 protected void executeTest(Class test, Permission missingPermission) { 201 TestSuite suite = new TestSuite(); 202 suite.addTestSuite(test); 203 TestResult result = new TestResult(); 204 suite.run(result); 205 if (result.wasSuccessful()) { 206 if (missingPermission == null) { 207 return; 208 } else { 209 fail("Security test expected an AccessControlException on " + missingPermission + ", but did not receive one"); 210 } 211 } else { 212 if (missingPermission == null) { 213 new SecurityTestResultPrinter(System.out).print(result); 214 fail("Security test was expected to run successfully, but failed (results on System.out)"); 215 } else { 216 boolean otherFailure = false; 218 for (Enumeration e = result.errors(); e.hasMoreElements(); ) { 219 TestFailure failure = (TestFailure) e.nextElement(); 220 if (failure.thrownException() instanceof AccessControlException ) { 221 AccessControlException ace = (AccessControlException ) failure.thrownException(); 222 if (missingPermission.implies(ace.getPermission())) { 223 continue; 224 } 225 } 226 otherFailure = true; 227 } 228 if (otherFailure) { 229 new SecurityTestResultPrinter(System.out).print(result); 230 fail("Security test expected an AccessControlException on " + missingPermission + ", but failed for other reasons (results on System.out)"); 231 } 232 } 233 } 234 } 235 236 protected void executeScript(Class scriptClass, Permission missingPermission) { 237 try { 238 Script script = InvokerHelper.createScript(scriptClass, new Binding()); 239 script.run(); 240 } catch (AccessControlException ace) { 242 if (missingPermission != null && missingPermission.implies(ace.getPermission())) { 243 return; 244 } else { 245 fail(ace.toString()); 246 } 247 } 248 if (missingPermission != null) { 249 fail("Should catch an AccessControlException"); 250 } 251 } 252 253 258 protected void assertExecute(File file, Permission missingPermission) { 259 if (!isSecurityAvailable()) { 260 return; 261 } 262 GroovyCodeSource gcs = null; 263 try { 264 gcs = new GroovyCodeSource(file); 265 } catch (FileNotFoundException fnfe) { 266 fail(fnfe.toString()); 267 } 268 parseAndExecute(gcs, missingPermission); 269 } 270 271 276 protected void assertExecute(String scriptStr, String codeBase, Permission missingPermission) { 277 if (!isSecurityAvailable()) { 278 return; 279 } 280 if (codeBase == null) { 281 codeBase = "/groovy/security/test"; 282 } 283 parseAndExecute(new GroovyCodeSource(scriptStr, generateClassName(), codeBase), missingPermission); 284 } 285 } 286 | Popular Tags |