8296244: Alternate implementation of user-based authorization Subject APIs that doesn’t depend on Security Manager APIs

Reviewed-by: mullan
This commit is contained in:
Weijun Wang 2024-03-20 21:25:41 +00:00
parent 000f4d8d15
commit d32746ef4a
17 changed files with 591 additions and 141 deletions

View File

@ -2690,6 +2690,11 @@ public final class System {
public boolean bytesCompatible(String string, Charset charset) {
return string.bytesCompatible(charset);
}
@Override
public boolean allowSecurityManager() {
return System.allowSecurityManager();
}
});
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. 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
@ -35,6 +35,7 @@ import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionException;
import jdk.internal.access.SharedSecrets;
import sun.security.util.ResourcesMgr;
/**
@ -90,6 +91,41 @@ import sun.security.util.ResourcesMgr;
* {@code Principal} implementations associated with Subjects
* must implement {@code Serializable}.
*
* <h2>Deprecated Methods and Replacements</h2>
*
* <p> The following methods in this class for user-based authorization
* that are dependent on Security Manager APIs are deprecated for removal:
* <ul>
* <li>{@link #getSubject(AccessControlContext)}
* <li>{@link #doAs(Subject, PrivilegedAction)}
* <li>{@link #doAs(Subject, PrivilegedExceptionAction)}
* <li>{@link #doAsPrivileged(Subject, PrivilegedAction, AccessControlContext)}
* <li>{@link #doAsPrivileged(Subject, PrivilegedExceptionAction, AccessControlContext)}
* </ul>
* Methods {@link #current()} and {@link #callAs(Subject, Callable)}
* are replacements for these methods, where {@code current}
* is mostly equivalent to {@code getSubject(AccessController.getContext())}
* and {@code callAs} is similar to {@code doAs} except that the
* input type and exceptions thrown are slightly different.
*
* <p><b><a id="sm-allowed">These methods behave differently depending on
* whether a security manager is
* <a href="../../../java/lang/SecurityManager.html#set-security-manager">allowed or disallowed</a></a></b>:
* <ul>
* <li>If a security manager is allowed, which means it is either already set
* or allowed to be set dynamically, a {@code Subject} object is associated
* with an {@code AccessControlContext} through a {@code doAs} or
* {@code callAs} call, and the subject can then be retrieved using the
* {@code getSubject(AccessControlContext)} or {@code current} method.
* <li>If a security manager is not allowed, which means it is not set and
* not allowed to be set dynamically, a {@code doAs} or {@code callAs} call
* binds a {@code Subject} object to the period of execution of an action,
* and the subject can be retrieved using the {@code current} method inside
* the action. This subject can be inherited by child threads if they are
* started and terminate within the execution of its parent thread using
* structured concurrency.
* </ul>
*
* @since 1.4
* @see java.security.Principal
* @see java.security.DomainCombiner
@ -258,7 +294,9 @@ public final class Subject implements java.io.Serializable {
/**
* Get the {@code Subject} associated with the provided
* {@code AccessControlContext}.
* {@code AccessControlContext}. This method is intended to be used with
* a security manager. It throws an {@code UnsupportedOperationException}
* if a security manager is not allowed.
*
* <p> The {@code AccessControlContext} may contain many
* Subjects (from nested {@code doAs} calls).
@ -273,6 +311,9 @@ public final class Subject implements java.io.Serializable {
* if no {@code Subject} is associated
* with the provided {@code AccessControlContext}.
*
* @throws UnsupportedOperationException if a security manager is
* not allowed
*
* @throws SecurityException if a security manager is installed and the
* caller does not have an
* {@link AuthPermission#AuthPermission(String)
@ -302,36 +343,45 @@ public final class Subject implements java.io.Serializable {
Objects.requireNonNull(acc, ResourcesMgr.getString
("invalid.null.AccessControlContext.provided"));
// return the Subject from the DomainCombiner of the provided context
return AccessController.doPrivileged
(new java.security.PrivilegedAction<>() {
public Subject run() {
DomainCombiner dc = acc.getDomainCombiner();
if (!(dc instanceof SubjectDomainCombiner)) {
return null;
}
SubjectDomainCombiner sdc = (SubjectDomainCombiner)dc;
return sdc.getSubject();
}
});
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
throw new UnsupportedOperationException(
"getSubject is supported only if a security manager is allowed");
} else {
// return the Subject from the DomainCombiner of the provided context
return AccessController.doPrivileged
(new java.security.PrivilegedAction<>() {
public Subject run() {
DomainCombiner dc = acc.getDomainCombiner();
if (!(dc instanceof SubjectDomainCombiner)) {
return null;
}
SubjectDomainCombiner sdc = (SubjectDomainCombiner) dc;
return sdc.getSubject();
}
});
}
}
private static final ScopedValue<Subject> SCOPED_SUBJECT =
ScopedValue.newInstance();
/**
* Returns the current subject.
* <p>
* The current subject is installed by the {@link #callAs} method.
*
* <p> The current subject is installed by the {@link #callAs} method.
* When {@code callAs(subject, action)} is called, {@code action} is
* executed with {@code subject} as its current subject which can be
* retrieved by this method. After {@code action} is finished, the current
* subject is reset to its previous value. The current
* subject is {@code null} before the first call of {@code callAs()}.
*
* @implNote
* This method returns the same value as
* {@code Subject.getSubject(AccessController.getContext())}. This
* preserves compatibility with code that may still be calling {@code doAs}
* which installs the subject in an {@code AccessControlContext}. This
* behavior is subject to change in a future version.
* <p> If a security manager is <a href=#sm-allowed>allowed</a>, this
* method is equivalent to calling {@link #getSubject} with the current
* {@code AccessControlContext}.
*
* <p> If a security manager is not allowed, this method returns the
* {@code Subject} bound to the period of the execution of the current
* thread.
*
* @return the current subject, or {@code null} if a current subject is
* not installed or the current subject is set to {@code null}.
@ -340,23 +390,32 @@ public final class Subject implements java.io.Serializable {
*/
@SuppressWarnings("removal")
public static Subject current() {
return getSubject(AccessController.getContext());
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
return SCOPED_SUBJECT.orElse(null);
} else {
return getSubject(AccessController.getContext());
}
}
/**
* Executes a {@code Callable} with {@code subject} as the
* current subject.
*
* @implNote
* This method calls {@link #doAs(Subject, PrivilegedExceptionAction)
* Subject.doAs(subject, altAction)} which stores the subject in
* a new {@code AccessControlContext}, where {@code altAction.run()}
* is equivalent to {@code action.call()} and the exception thrown is
* modified to match the specification of this method. This preserves
* compatibility with code that may still be calling
* {@code getSubject(AccessControlContext)} which retrieves the subject
* from an {@code AccessControlContext}. This behavior is subject
* to change in a future version.
* <p> If a security manager is <a href=#sm-allowed>allowed</a>,
* this method first retrieves the current Thread's
* {@code AccessControlContext} via
* {@code AccessController.getContext},
* and then instantiates a new {@code AccessControlContext}
* using the retrieved context along with a new
* {@code SubjectDomainCombiner} (constructed using
* the provided {@code Subject}).
* Finally, this method invokes {@code AccessController.doPrivileged},
* passing it the provided {@code PrivilegedAction},
* as well as the newly constructed {@code AccessControlContext}.
*
* <p> If a security manager is not allowed,
* this method launches {@code action} and binds {@code subject} to the
* period of its execution.
*
* @param subject the {@code Subject} that the specified {@code action}
* will run as. This parameter may be {@code null}.
@ -375,22 +434,31 @@ public final class Subject implements java.io.Serializable {
public static <T> T callAs(final Subject subject,
final Callable<T> action) throws CompletionException {
Objects.requireNonNull(action);
try {
PrivilegedExceptionAction<T> pa = () -> action.call();
@SuppressWarnings("removal")
var result = doAs(subject, pa);
return result;
} catch (PrivilegedActionException e) {
throw new CompletionException(e.getCause());
} catch (Exception e) {
throw new CompletionException(e);
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
try {
return ScopedValue.callWhere(SCOPED_SUBJECT, subject, action);
} catch (Exception e) {
throw new CompletionException(e);
}
} else {
try {
PrivilegedExceptionAction<T> pa = () -> action.call();
@SuppressWarnings("removal")
var result = doAs(subject, pa);
return result;
} catch (PrivilegedActionException e) {
throw new CompletionException(e.getCause());
} catch (Exception e) {
throw new CompletionException(e);
}
}
}
/**
* Perform work as a particular {@code Subject}.
*
* <p> This method first retrieves the current Thread's
* <p> If a security manager is <a href=#sm-allowed>allowed</a>,
* this method first retrieves the current Thread's
* {@code AccessControlContext} via
* {@code AccessController.getContext},
* and then instantiates a new {@code AccessControlContext}
@ -401,6 +469,10 @@ public final class Subject implements java.io.Serializable {
* passing it the provided {@code PrivilegedAction},
* as well as the newly constructed {@code AccessControlContext}.
*
* <p> If a security manager is not allowed,
* this method launches {@code action} and binds {@code subject} to the
* period of its execution.
*
* @param subject the {@code Subject} that the specified
* {@code action} will run as. This parameter
* may be {@code null}.
@ -444,20 +516,36 @@ public final class Subject implements java.io.Serializable {
Objects.requireNonNull(action,
ResourcesMgr.getString("invalid.null.action.provided"));
// set up the new Subject-based AccessControlContext
// for doPrivileged
final AccessControlContext currentAcc = AccessController.getContext();
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
try {
return callAs(subject, action::run);
} catch (CompletionException ce) {
var cause = ce.getCause();
if (cause instanceof RuntimeException re) {
throw re;
} else if (cause instanceof Error er) {
throw er;
} else {
throw new AssertionError(ce);
}
}
} else {
// set up the new Subject-based AccessControlContext
// for doPrivileged
final AccessControlContext currentAcc = AccessController.getContext();
// call doPrivileged and push this new context on the stack
return java.security.AccessController.doPrivileged
(action,
createContext(subject, currentAcc));
// call doPrivileged and push this new context on the stack
return java.security.AccessController.doPrivileged
(action,
createContext(subject, currentAcc));
}
}
/**
* Perform work as a particular {@code Subject}.
*
* <p> This method first retrieves the current Thread's
* <p> If a security manager is <a href=#sm-allowed>allowed</a>,
* this method first retrieves the current Thread's
* {@code AccessControlContext} via
* {@code AccessController.getContext},
* and then instantiates a new {@code AccessControlContext}
@ -468,6 +556,10 @@ public final class Subject implements java.io.Serializable {
* passing it the provided {@code PrivilegedExceptionAction},
* as well as the newly constructed {@code AccessControlContext}.
*
* <p> If a security manager is not allowed,
* this method launches {@code action} and binds {@code subject} to the
* period of its execution.
* @param subject the {@code Subject} that the specified
* {@code action} will run as. This parameter
* may be {@code null}.
@ -517,19 +609,37 @@ public final class Subject implements java.io.Serializable {
Objects.requireNonNull(action,
ResourcesMgr.getString("invalid.null.action.provided"));
// set up the new Subject-based AccessControlContext for doPrivileged
final AccessControlContext currentAcc = AccessController.getContext();
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
try {
return callAs(subject, action::run);
} catch (CompletionException ce) {
var cause = ce.getCause();
if (cause instanceof RuntimeException re) {
throw re;
} else if (cause instanceof Error er) {
throw er;
} else if (cause instanceof Exception e) {
throw new PrivilegedActionException(e);
} else {
throw new PrivilegedActionException(ce);
}
}
} else {
// set up the new Subject-based AccessControlContext for doPrivileged
final AccessControlContext currentAcc = AccessController.getContext();
// call doPrivileged and push this new context on the stack
return java.security.AccessController.doPrivileged
(action,
createContext(subject, currentAcc));
// call doPrivileged and push this new context on the stack
return java.security.AccessController.doPrivileged
(action,
createContext(subject, currentAcc));
}
}
/**
* Perform privileged work as a particular {@code Subject}.
*
* <p> This method behaves exactly as {@code Subject.doAs},
* <p> If a security manager is <a href=#sm-allowed>allowed</a>,
* this method behaves exactly as {@code Subject.doAs},
* except that instead of retrieving the current Thread's
* {@code AccessControlContext}, it uses the provided
* {@code AccessControlContext}. If the provided
@ -537,6 +647,10 @@ public final class Subject implements java.io.Serializable {
* this method instantiates a new {@code AccessControlContext}
* with an empty collection of ProtectionDomains.
*
* <p> If a security manager is not allowed,
* this method ignores the {@code acc} argument, launches {@code action},
* and binds {@code subject} to the period of its execution.
*
* @param subject the {@code Subject} that the specified
* {@code action} will run as. This parameter
* may be {@code null}.
@ -583,23 +697,39 @@ public final class Subject implements java.io.Serializable {
Objects.requireNonNull(action,
ResourcesMgr.getString("invalid.null.action.provided"));
// set up the new Subject-based AccessControlContext
// for doPrivileged
final AccessControlContext callerAcc =
(acc == null ?
new AccessControlContext(NULL_PD_ARRAY) :
acc);
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
try {
return callAs(subject, action::run);
} catch (CompletionException ce) {
var cause = ce.getCause();
if (cause instanceof RuntimeException re) {
throw re;
} else if (cause instanceof Error er) {
throw er;
} else {
throw new AssertionError(ce);
}
}
} else {
// set up the new Subject-based AccessControlContext
// for doPrivileged
final AccessControlContext callerAcc =
(acc == null ?
new AccessControlContext(NULL_PD_ARRAY) :
acc);
// call doPrivileged and push this new context on the stack
return java.security.AccessController.doPrivileged
(action,
createContext(subject, callerAcc));
// call doPrivileged and push this new context on the stack
return java.security.AccessController.doPrivileged
(action,
createContext(subject, callerAcc));
}
}
/**
* Perform privileged work as a particular {@code Subject}.
*
* <p> This method behaves exactly as {@code Subject.doAs},
* <p> If a security manager is <a href=#sm-allowed>allowed</a>,
* this method behaves exactly as {@code Subject.doAs},
* except that instead of retrieving the current Thread's
* {@code AccessControlContext}, it uses the provided
* {@code AccessControlContext}. If the provided
@ -607,6 +737,10 @@ public final class Subject implements java.io.Serializable {
* this method instantiates a new {@code AccessControlContext}
* with an empty collection of ProtectionDomains.
*
* <p> If a security manager is not allowed,
* this method ignores the {@code acc} argument, launches {@code action},
* and binds {@code subject} to the period of its execution.
*
* @param subject the {@code Subject} that the specified
* {@code action} will run as. This parameter
* may be {@code null}.
@ -659,16 +793,33 @@ public final class Subject implements java.io.Serializable {
Objects.requireNonNull(action,
ResourcesMgr.getString("invalid.null.action.provided"));
// set up the new Subject-based AccessControlContext for doPrivileged
final AccessControlContext callerAcc =
(acc == null ?
new AccessControlContext(NULL_PD_ARRAY) :
acc);
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
try {
return callAs(subject, action::run);
} catch (CompletionException ce) {
var cause = ce.getCause();
if (cause instanceof RuntimeException re) {
throw re;
} else if (cause instanceof Error er) {
throw er;
} else if (cause instanceof Exception e) {
throw new PrivilegedActionException(e);
} else {
throw new PrivilegedActionException(ce);
}
}
} else {
// set up the new Subject-based AccessControlContext for doPrivileged
final AccessControlContext callerAcc =
(acc == null ?
new AccessControlContext(NULL_PD_ARRAY) :
acc);
// call doPrivileged and push this new context on the stack
return java.security.AccessController.doPrivileged
(action,
createContext(subject, callerAcc));
// call doPrivileged and push this new context on the stack
return java.security.AccessController.doPrivileged
(action,
createContext(subject, callerAcc));
}
}
@SuppressWarnings("removal")

View File

@ -592,4 +592,10 @@ public interface JavaLangAccess {
* Are the string bytes compatible with the given charset?
*/
boolean bytesCompatible(String string, Charset charset);
/**
* Is a security manager already set or allowed to be set
* (using -Djava.security.manager=allow)?
*/
boolean allowSecurityManager();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. 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
@ -30,7 +30,7 @@
*
* @run clean ThreadPoolAccTest
* @run build ThreadPoolAccTest
* @run main ThreadPoolAccTest
* @run main/othervm -Djava.security.manager=allow ThreadPoolAccTest
*/
import java.security.AccessController;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. 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
@ -30,7 +30,7 @@
* java.management/com.sun.jmx.remote.security
* @run clean NotificationAccessControllerTest
* @run build NotificationAccessControllerTest
* @run main NotificationAccessControllerTest
* @run main/othervm -Djava.security.manager=allow NotificationAccessControllerTest
*/
import com.sun.jmx.remote.security.NotificationAccessController;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2024, Oracle and/or its affiliates. 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
@ -30,7 +30,7 @@
*
* @run clean NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
* @run build NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
* @run main NonJMXPrincipalsTest
* @run main/othervm -Djava.security.manager=allow NonJMXPrincipalsTest
*/
import java.io.File;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. 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
@ -30,7 +30,7 @@
*
* @run clean PasswordAccessFileTest SimpleStandard SimpleStandardMBean
* @run build PasswordAccessFileTest SimpleStandard SimpleStandardMBean
* @run main PasswordAccessFileTest
* @run main/othervm -Djava.security.manager=allow PasswordAccessFileTest
*/
import java.io.File;

View File

@ -30,7 +30,7 @@
* java.management/com.sun.jmx.remote.security
* @run clean RMIAltAuthTest
* @run build RMIAltAuthTest SimpleStandard SimpleStandardMBean
* @run main RMIAltAuthTest
* @run main/othervm -Djava.security.manager=allow RMIAltAuthTest
*/
import java.io.File;

View File

@ -30,7 +30,7 @@
* java.management/com.sun.jmx.remote.security
* @run clean RMIPasswdAuthTest
* @run build RMIPasswdAuthTest SimpleStandard SimpleStandardMBean
* @run main RMIPasswdAuthTest
* @run main/othervm -Djava.security.manager=allow RMIPasswdAuthTest
*/
import java.io.File;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. 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
@ -31,12 +31,12 @@
* java.management/com.sun.jmx.remote.security
* @run clean SubjectDelegation1Test SimpleStandard SimpleStandardMBean
* @run build SubjectDelegation1Test SimpleStandard SimpleStandardMBean
* @run main SubjectDelegation1Test policy11 ok
* @run main SubjectDelegation1Test policy12 ko
* @run main SubjectDelegation1Test policy13 ko
* @run main SubjectDelegation1Test policy14 ko
* @run main SubjectDelegation1Test policy15 ok
* @run main SubjectDelegation1Test policy16 ko
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy11 ok
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy12 ko
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy13 ko
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy14 ko
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy15 ok
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy16 ko
*/
import com.sun.jmx.remote.security.JMXPluggableAuthenticator;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. 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
@ -29,9 +29,9 @@
* @modules java.management.rmi
* @library /test/lib
* @compile Simple.java
* @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials
* @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException
* @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
* @run main/othervm/timeout=300 -Djava.security.manager=allow -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials
* @run main/othervm/timeout=300 -Djava.security.manager=allow -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException
* @run main/othervm/timeout=300 -Djava.security.manager=allow -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials
* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username3 -Dpassword=password3 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedGetException
* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username5 -Dpassword=password5 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. 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.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8296244
* @enablePreview
* @summary Implement Subject.current and Subject.callAs using scoped values.
* Need enablePreview to use StructuredTaskScope.
* @run main/othervm -Djava.security.manager=allow CallAsWithScopedValue false
* @run main/othervm -Djava.security.manager=disallow CallAsWithScopedValue true
*/
import com.sun.security.auth.UserPrincipal;
import javax.security.auth.Subject;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.StructuredTaskScope;
public class CallAsWithScopedValue {
private static Map results = new ConcurrentHashMap<Integer,Boolean>();
public static void main(String[] args) throws Exception {
boolean usv = Boolean.parseBoolean(args[0]);
Subject subject = new Subject();
subject.getPrincipals().add(new UserPrincipal("Duke"));
// Always observable in the same thread
Subject.callAs(subject, () -> check(0, Subject.current(), "Duke"));
// Observable in a new platform thread in ACC mode, but not in the SV mode
Subject.callAs(subject, () -> {
Thread.ofPlatform().start(() -> check(1, Subject.current(), usv ? null : "Duke")).join();
return null;
});
// Never observable in a new virtual thread
Subject.callAs(subject, () -> {
Thread.ofVirtual().start(() -> check(2, Subject.current(), null)).join();
return null;
});
// Observable in structured concurrency in SV mode, but not in ACC mode
Subject.callAs(subject, () -> {
try (var scope = new StructuredTaskScope<>()) {
scope.fork(() -> check(3, Subject.current(), usv ? "Duke" : null));
scope.join();
}
return null;
});
// Suggested way to pass the current subject into arbitrary
// threads. Grab one using current() and explicitly pass it
// into the new thread.
Subject.callAs(subject, () -> {
Subject current = Subject.current();
Thread.ofPlatform().start(() -> {
Subject.callAs(current, () -> check(4, Subject.current(), "Duke"));
}).join();
return null;
});
if (results.size() != 5 || results.containsValue(false)) {
System.out.println(results);
throw new RuntimeException("Failed");
}
}
static String check(int type, Subject current, String expected) {
String actual;
if (current == null) {
actual = null;
} else {
var set = current.getPrincipals(UserPrincipal.class);
actual = set.isEmpty()
? null
: set.iterator().next().getName();
}
results.put(type, Objects.equals(actual, expected));
return actual;
}
}

View File

@ -0,0 +1,128 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. 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.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.sun.security.auth.UserPrincipal;
import javax.security.auth.Subject;
import javax.security.auth.SubjectDomainCombiner;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.Objects;
/*
* @test
* @bug 8296244
* @run main/othervm -Djava.security.manager=allow Compat
* @summary ensures the old implementation still works when SM is allowed
*/
public class Compat {
static PrivilegedExceptionAction<AccessControlContext> action
= () -> AccessController.getContext();
static boolean failed = false;
public static void main(String[] args) throws Exception {
main0(null);
var t = new Thread(() -> {
try {
main0(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
t.start();
t.join();
}
public static void main0(String[] args) throws Exception {
System.out.println(">>> bare run");
run(null);
System.out.println(">>> run inside");
Subject subject = makeSubject("three");
Subject.doAs(subject, (PrivilegedExceptionAction<? extends Object>)
() -> run("three"));
if (failed) {
throw new RuntimeException();
}
}
public static Void run(String from) throws Exception {
Subject subject = makeSubject("one");
var a1 = Subject.doAs(subject, action);
Subject subject2 = makeSubject("two");
var a2 = Subject.doAs(subject2, action);
test("from ether", AccessController.getContext(), from);
test("from a1", a1, "one");
test("from a2", a2, "two");
var a3 = Subject.doAsPrivileged(subject, action, a1);
test("doAsPriv with one and a1", a3, "one");
var a4 = Subject.doAsPrivileged(subject, action, a2);
test("doAsPriv with one and a2", a4, "one");
var a5 = Subject.doAsPrivileged(null, action, a2);
test("doAsPriv with null and a2", a5, null);
var a6 = Subject.doAs(null, action);
test("doAsPriv with null and this", a6, null);
var ax = new AccessControlContext(a2, new SubjectDomainCombiner(subject));
test("a2 plus subject", ax, "one");
ax = AccessController.doPrivileged(action, a2);
test("doPriv on a2", ax, "two");
ax = AccessController.doPrivilegedWithCombiner(action);
test("doPrivWC", ax, from == null ? null : from);
ax = AccessController.doPrivilegedWithCombiner(action, a2);
test("doPrivWC on a2", ax, from == null ? "two" : from);
return null;
}
static Subject makeSubject(String name) {
Subject subject = new Subject();
subject.getPrincipals().add(new UserPrincipal(name));
return subject;
}
static String getSubject(AccessControlContext acc) {
var subj = Subject.getSubject(acc);
if (subj == null) return null;
var princ = subj.getPrincipals(UserPrincipal.class);
return (princ == null || princ.isEmpty())
? null
: princ.iterator().next().getName();
}
static void test(String label, AccessControlContext acc, String expected) {
var actual = getSubject(acc);
System.out.println(label + ": " + actual);
if (!Objects.equals(actual, expected)) {
System.out.println(" Expect " + expected + ", but see " + actual);
failed = true;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. 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
@ -22,28 +22,24 @@
*/
import javax.security.auth.Subject;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.security.PrivilegedExceptionAction;
/*
* @test
* @bug 8267108
* @summary confirm current subject specification
* @run main/othervm CurrentSubject
* @run main/othervm -Djava.security.manager=allow CurrentSubject
* @run main/othervm -Djava.security.manager=disallow CurrentSubject
*/
public class CurrentSubject {
static transient boolean failed = false;
static CountDownLatch cl = new CountDownLatch(1);
static AtomicInteger count = new AtomicInteger();
static boolean failed = false;
public static void main(String[] args) throws Exception {
// At the beginning, current subject is null
test("", null);
cl.await();
if (failed) {
throw new Exception("Failed");
}
@ -57,12 +53,6 @@ public class CurrentSubject {
*/
synchronized static void check(String label, Subject expected) {
Subject cas = Subject.current();
Subject accs = Subject.getSubject(AccessController.getContext());
if (cas != accs) {
failed = true;
System.out.println(label + ": current " + s2s(cas)
+ " but getSubject is " + s2s(accs));
}
Subject interested = cas;
if (interested != expected) {
failed = true;
@ -89,31 +79,23 @@ public class CurrentSubject {
// run with a new subject, inside current subject will be the new subject
Subject.callAs(another, () -> test(name + 'c', another));
Subject.doAs(another, (PrivilegedAction<Void>) () -> test(name + 'd', another));
Subject.doAsPrivileged(another, (PrivilegedAction<Void>) () -> test(name + 'e', another), null);
try {
Subject.doAs(another, (PrivilegedExceptionAction<Void>) () -> test(name + 'f', another));
Subject.doAsPrivileged(another, (PrivilegedExceptionAction<Void>) () -> test(name + 'g', another), null);
} catch (Exception e) {
throw new RuntimeException(e);
}
// run with null, inside current subject will be null
Subject.callAs(null, () -> test(name + 'C', null));
Subject.doAs(null, (PrivilegedAction<Void>) () -> test(name + 'D', null));
// new thread, inside current subject is unchanged
count.incrementAndGet();
new Thread(() -> {
try {
test(name + 't', expected);
try {
Thread.sleep(500);
} catch (Exception e) {
throw new AssertionError(e);
}
// by this time, parent thread should have exited the
// action and current subject reset, but here
// current subject unchanged.
test(name + 'T', expected);
} finally {
var n = count.decrementAndGet();
if (n == 0) {
cl.countDown();
}
assert n >= 0;
}
}).start();
Subject.doAsPrivileged(null, (PrivilegedAction<Void>) () -> test(name + 'E', null), null);
try {
Subject.doAs(null, (PrivilegedExceptionAction<Void>) () -> test(name + 'F', null));
Subject.doAsPrivileged(null, (PrivilegedExceptionAction<Void>) () -> test(name + 'G', null), null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// Now it's reset to original
check(" ".repeat(name.length()) + "<- " + name, expected);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. 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
@ -32,7 +32,6 @@ import java.security.PrivilegedAction;
* @bug 8267108
* @summary confirm current installed subject specification
* @run main/othervm -Djava.security.manager=allow FromACC
* @run main/othervm -Djava.security.manager=disallow FromACC
*/
public class FromACC {
public static void main(String[] args) throws Exception {

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. 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.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8296244
* @library /test/lib
* @summary Implement Subject.current and Subject.callAs using scoped values
* @run main/othervm -Djava.security.manager=disallow UnsupportedSV t1
* @run main/othervm -Djava.security.manager=allow UnsupportedSV t2
*/
import com.sun.security.auth.UserPrincipal;
import jdk.test.lib.Utils;
import javax.security.auth.Subject;
import javax.security.auth.SubjectDomainCombiner;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
public class UnsupportedSV {
public static void main(String[] args) throws Exception {
switch (args[0]) {
case "t1" -> t1();
case "t2" -> t2();
}
}
// ScopedValue-based implementation is used
static void t1() throws Exception {
AccessControlContext acc = AccessController.getContext();
Utils.runAndCheckException(() -> Subject.getSubject(acc),
UnsupportedOperationException.class);
Subject s = new Subject();
s.getPrincipals().add(new UserPrincipal("Duke"));
// TODO: Still has no way to reject the following code.
// Here, AccessController::getContext returns a plain ACC without
// the subject inside.
AccessControlContext acc2 = Subject.callAs(s, AccessController::getContext);
Subject ns = AccessController.doPrivileged(
(PrivilegedAction<Subject>) Subject::current, acc2);
System.out.println(ns);
}
// When a security manager is set, ScopedValue-based implementation
// will not be used
static void t2() {
AccessControlContext acc = AccessController.getContext();
Subject.getSubject(acc);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. 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
@ -61,7 +61,7 @@ import java.util.Set;
*
* @library /test/lib
*
* @run main/othervm/timeout=300 RmiBootstrapTest .*_test.*.in
* @run main/othervm/timeout=300 -Djava.security.manager=allow RmiBootstrapTest .*_test.*.in
* */
/*
@ -72,7 +72,7 @@ import java.util.Set;
*
* @library /test/lib
*
* @run main/othervm/timeout=300 RmiBootstrapTest .*_ssltest.*.in
* @run main/othervm/timeout=300 -Djava.security.manager=allow RmiBootstrapTest .*_ssltest.*.in
* */
/**