Skip to content

Commit

Permalink
Merge pull request #23934 from arjantijms/23933_fix_authorization_tck…
Browse files Browse the repository at this point in the history
…_failures

Fix #23933 by adding a proxy for the Policy when Security Managed used
  • Loading branch information
arjantijms authored May 11, 2022
2 parents bca432a + 3f52215 commit ef775ac
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 12 deletions.
4 changes: 4 additions & 0 deletions appserver/featuresets/debug/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.resolver</artifactId>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.main</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion appserver/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
<jakarta.authorization-api.version>2.1.0</jakarta.authorization-api.version>
<jakarta.authentication-api.version>3.0.0</jakarta.authentication-api.version>
<soteria.version>3.0.0-M5</soteria.version>
<exousia.version>2.1.0-M1</exousia.version>
<exousia.version>2.1.0-M2</exousia.version>
<nimbus.version>9.22</nimbus.version>
<jcip.version>1.0.2</jcip.version>

Expand Down
66 changes: 63 additions & 3 deletions appserver/tests/tck/authorization/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2021 Contributors to the Eclipse Foundation. All rights reserved.
Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -15,6 +15,43 @@
SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
-->

<!--
Usage:
Run full TCK:
mvn clean clean
Run full TCK, debugging remote GlassFish (suspends on port 9009)
mvn clean install -Dglassfish.suspend
Run full TCK, debugging client TCK
mvn clean install -Dsuspend-tck
Run full TCK with security manager (deprecated in principal, but still needed for EE 10 to pass)
mvn clean install -Dglassfish.security.manager
Run all tests in test class
mvn clean install -Drun.test="com/sun/ts/tests/el/api/jakarta_el/methodexpression/ELClient.java"
Run single test:
mvn clean install -Drun.test="com/sun/ts/tests/jacc/web/toolsContracts/Client.java#validateNoInvalidStates_from_standalone"
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
Expand Down Expand Up @@ -185,6 +222,10 @@
<replaceregexp file="${tck.home}/bin/ts.jte" byline="true"
match="work\.dir=.*"
replace="work\.dir=${tck.home}/jacctckwork/jacctck" />

<replaceregexp file="${tck.home}/bin/ts.jte" byline="true"
match="work\.dir=.*"
replace="work\.dir=${tck.home}/jacctckwork/jacctck" />

<!-- Run just selected subset tests -->
<replaceregexp file="${tck.home}/bin/build.xml" byline="true"
Expand All @@ -206,6 +247,12 @@
<exec executable="${glassfish.asadmin}" dir="${glassfish.home}/glassfish/bin">
<arg value="start-domain"/>
</exec>

<exec executable="${glassfish.asadmin}" dir="${glassfish.home}/glassfish/bin" if:set="glassfish.security.manager">
<arg value="create-jvm-options" />
<arg value="--port=${port.admin}" />
<arg value="&quot;-Djava.security.manager&quot;" />
</exec>

<if>
<isset property="jacoco.version" />
Expand Down Expand Up @@ -250,7 +297,7 @@
<goal>run</goal>
</goals>
<configuration>
<target>
<target xmlns:if="ant:if" xmlns:unless="ant:unless">
<taskdef resource="net/sf/antcontrib/antcontrib.properties"
classpathref="maven.plugin.classpath" />
<limit maxwait="20">
Expand All @@ -266,6 +313,18 @@
<arg value="enable.jacc" />
<env key="tck.home" value="${tck.home}"/>
</exec>

<!-- Restart GlassFish in debug mode if so requested -->
<sequential if:set="glassfish.suspend">
<exec executable="${glassfish.asadmin}" dir="${glassfish.home}/glassfish/bin">
<arg value="stop-domain" />
</exec>
<echo message="Starting GlassFish in suspended mode, waiting on port 9009" />
<exec executable="${glassfish.asadmin}" dir="${glassfish.home}/glassfish/bin">
<arg value="start-domain"/>
<arg value="--suspend" if:set="glassfish.suspend"/>
</exec>
</sequential>
</target>
</configuration>
</execution>
Expand All @@ -285,7 +344,8 @@
<exec executable="${ant.home}/bin/ant" dir="${tck.tests.home}" resultproperty="testResult">
<arg value="-Dmultiple.tests=${run.test}" if:set="run.test" />
<arg value="deploy"/>
<arg value="run.all"/>
<arg value="run.all" unless:set="run.test"/>
<arg value="runclient" if:set="run.test" />
<env key="LC_ALL" value="C" />
</exec>

Expand Down
5 changes: 5 additions & 0 deletions nucleus/security/core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@
<groupId>org.glassfish.gmbal</groupId>
<artifactId>gmbal</artifactId>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
</dependency>

<dependency>
<groupId>org.glassfish.annotations</groupId>
<artifactId>logging-annotation-processor</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation.
* Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand Down Expand Up @@ -27,9 +28,13 @@
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.SEVERE;
import static java.util.logging.Level.WARNING;
import static javassist.Modifier.PUBLIC;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.Permission;
import java.security.Policy;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;

Expand All @@ -48,6 +53,11 @@
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.inject.Singleton;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import javassist.util.proxy.ProxyObject;

/**
* Loads the Default Policy File into the system.
Expand All @@ -73,6 +83,7 @@ public class PolicyLoader {
private static final String POLICY_PROVIDER = "jakarta.security.jacc.policy.provider";
private static final String POLICY_CONF_FACTORY = "jakarta.security.jacc.PolicyConfigurationFactory.provider";
private static final String POLICY_PROP_PREFIX = "com.sun.enterprise.jaccprovider.property.";
private static final String POLICY_PROXY = "com.sun.enterprise.jaccprovider.proxy";
private boolean isPolicyInstalled;

/**
Expand Down Expand Up @@ -104,8 +115,6 @@ public void loadPolicy() {
javaPolicyClassName = authorizationModule.getPolicyProvider();
}

// TEMP TEMP TEMP

if (System.getProperty("simple.jacc.provider.JACCRoleMapper.class") == null) {
System.setProperty("simple.jacc.provider.JACCRoleMapper.class",
"com.sun.enterprise.security.web.integration.GlassfishRoleMapper");
Expand All @@ -117,7 +126,15 @@ public void loadPolicy() {
try {
LOGGER.log(INFO, policyLoading, javaPolicyClassName);

Policy policy = loadPolicy(javaPolicyClassName);
boolean usePolicyProxy = Boolean.parseBoolean(System.getProperty(POLICY_PROXY, "true"));

Policy policy = null;
if (usePolicyProxy && System.getSecurityManager() != null) {
policy = loadPolicyAsProxy(javaPolicyClassName);
} else {
policy = loadPolicy(javaPolicyClassName);
}

Policy.setPolicy(policy);

// TODO: causing ClassCircularity error when SM ON and
Expand All @@ -143,15 +160,92 @@ public void loadPolicy() {
}
}

private Policy loadPolicy(String javaPolicyClassName) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Object javaPolicyInstance = Thread.currentThread().getContextClassLoader().loadClass(javaPolicyClassName).getDeclaredConstructor()
.newInstance();
@SuppressWarnings("unchecked")
public static <T> T createPolicyProxy(Class<T> targetClass) throws Exception {
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(targetClass);

ProxyObject instance = (ProxyObject) factory.createClass().getDeclaredConstructor().newInstance();
instance.setHandler(new JakartaAuthenticationGuardHandler(Policy.getPolicy()));

return (T) instance;
}

private static class JakartaAuthenticationGuardHandler implements MethodHandler {

public final static Method impliesMethod = getMethod(
Policy.class, "implies", ProtectionDomain.class, Permission.class);

private final Policy javaSePolicy;

public JakartaAuthenticationGuardHandler(Policy javaSePolicy) {
this.javaSePolicy = javaSePolicy;
}

@Override
public Object invoke(Object self, Method overridden, Method forwarder, Object[] args) throws Throwable {
if (isImplementationOf(overridden, impliesMethod)) {
Permission permission = (Permission) args[1];
if (!permission.getClass().getName().startsWith("jakarta.")) {
return javaSePolicy.implies((ProtectionDomain)args[0], permission);
}
}

return forwarder.invoke(self, args);
}

public static boolean isImplementationOf(Method implementationMethod, Method interfaceMethod) {
return
interfaceMethod.getDeclaringClass().isAssignableFrom(implementationMethod.getDeclaringClass()) &&
interfaceMethod.getName().equals(implementationMethod.getName()) &&
Arrays.equals(interfaceMethod.getParameterTypes(), implementationMethod.getParameterTypes());
}

public static Method getMethod(Class<?> base, String name, Class<?>... parameterTypes) {
try {
// Method literals in Java would be nice
return base.getMethod(name, parameterTypes);
} catch (NoSuchMethodException | SecurityException e) {
throw new IllegalStateException(e);
}
}

}

private Policy loadPolicy(String javaPolicyClassName) throws ReflectiveOperationException, SecurityException {
Object javaPolicyInstance =
Thread.currentThread()
.getContextClassLoader()
.loadClass(javaPolicyClassName)
.getDeclaredConstructor()
.newInstance();

if (!(javaPolicyInstance instanceof Policy)) {
throw new RuntimeException(SM.getString("enterprise.security.plcyload.not14"));
}

return (Policy) javaPolicyInstance;
}

private Policy loadPolicyAsProxy(String javaPolicyClassName) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.get(javaPolicyClassName);
clazz.defrost();
clazz.setModifiers(PUBLIC);

Object javaPolicyInstance =
createPolicyProxy(
clazz.toClass(
Thread.currentThread()
.getContextClassLoader()
.loadClass(System.getProperty(POLICY_CONF_FACTORY))));

if (!(javaPolicyInstance instanceof Policy)) {
throw new RuntimeException(SM.getString("enterprise.security.plcyload.not14"));
}

javaPolicyInstance.toString();

return (Policy) javaPolicyInstance;
}

Expand Down

0 comments on commit ef775ac

Please sign in to comment.