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:
parent
000f4d8d15
commit
d32746ef4a
@ -2690,6 +2690,11 @@ public final class System {
|
|||||||
public boolean bytesCompatible(String string, Charset charset) {
|
public boolean bytesCompatible(String string, Charset charset) {
|
||||||
return string.bytesCompatible(charset);
|
return string.bytesCompatible(charset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowSecurityManager() {
|
||||||
|
return System.allowSecurityManager();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.Callable;
|
||||||
import java.util.concurrent.CompletionException;
|
import java.util.concurrent.CompletionException;
|
||||||
|
|
||||||
|
import jdk.internal.access.SharedSecrets;
|
||||||
import sun.security.util.ResourcesMgr;
|
import sun.security.util.ResourcesMgr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,6 +91,41 @@ import sun.security.util.ResourcesMgr;
|
|||||||
* {@code Principal} implementations associated with Subjects
|
* {@code Principal} implementations associated with Subjects
|
||||||
* must implement {@code Serializable}.
|
* 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
|
* @since 1.4
|
||||||
* @see java.security.Principal
|
* @see java.security.Principal
|
||||||
* @see java.security.DomainCombiner
|
* @see java.security.DomainCombiner
|
||||||
@ -258,7 +294,9 @@ public final class Subject implements java.io.Serializable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@code Subject} associated with the provided
|
* 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
|
* <p> The {@code AccessControlContext} may contain many
|
||||||
* Subjects (from nested {@code doAs} calls).
|
* Subjects (from nested {@code doAs} calls).
|
||||||
@ -273,6 +311,9 @@ public final class Subject implements java.io.Serializable {
|
|||||||
* if no {@code Subject} is associated
|
* if no {@code Subject} is associated
|
||||||
* with the provided {@code AccessControlContext}.
|
* with the provided {@code AccessControlContext}.
|
||||||
*
|
*
|
||||||
|
* @throws UnsupportedOperationException if a security manager is
|
||||||
|
* not allowed
|
||||||
|
*
|
||||||
* @throws SecurityException if a security manager is installed and the
|
* @throws SecurityException if a security manager is installed and the
|
||||||
* caller does not have an
|
* caller does not have an
|
||||||
* {@link AuthPermission#AuthPermission(String)
|
* {@link AuthPermission#AuthPermission(String)
|
||||||
@ -302,36 +343,45 @@ public final class Subject implements java.io.Serializable {
|
|||||||
Objects.requireNonNull(acc, ResourcesMgr.getString
|
Objects.requireNonNull(acc, ResourcesMgr.getString
|
||||||
("invalid.null.AccessControlContext.provided"));
|
("invalid.null.AccessControlContext.provided"));
|
||||||
|
|
||||||
// return the Subject from the DomainCombiner of the provided context
|
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
|
||||||
return AccessController.doPrivileged
|
throw new UnsupportedOperationException(
|
||||||
(new java.security.PrivilegedAction<>() {
|
"getSubject is supported only if a security manager is allowed");
|
||||||
public Subject run() {
|
} else {
|
||||||
DomainCombiner dc = acc.getDomainCombiner();
|
// return the Subject from the DomainCombiner of the provided context
|
||||||
if (!(dc instanceof SubjectDomainCombiner)) {
|
return AccessController.doPrivileged
|
||||||
return null;
|
(new java.security.PrivilegedAction<>() {
|
||||||
}
|
public Subject run() {
|
||||||
SubjectDomainCombiner sdc = (SubjectDomainCombiner)dc;
|
DomainCombiner dc = acc.getDomainCombiner();
|
||||||
return sdc.getSubject();
|
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.
|
* 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
|
* When {@code callAs(subject, action)} is called, {@code action} is
|
||||||
* executed with {@code subject} as its current subject which can be
|
* executed with {@code subject} as its current subject which can be
|
||||||
* retrieved by this method. After {@code action} is finished, the current
|
* retrieved by this method. After {@code action} is finished, the current
|
||||||
* subject is reset to its previous value. The current
|
* subject is reset to its previous value. The current
|
||||||
* subject is {@code null} before the first call of {@code callAs()}.
|
* subject is {@code null} before the first call of {@code callAs()}.
|
||||||
*
|
*
|
||||||
* @implNote
|
* <p> If a security manager is <a href=#sm-allowed>allowed</a>, this
|
||||||
* This method returns the same value as
|
* method is equivalent to calling {@link #getSubject} with the current
|
||||||
* {@code Subject.getSubject(AccessController.getContext())}. This
|
* {@code AccessControlContext}.
|
||||||
* preserves compatibility with code that may still be calling {@code doAs}
|
*
|
||||||
* which installs the subject in an {@code AccessControlContext}. This
|
* <p> If a security manager is not allowed, this method returns the
|
||||||
* behavior is subject to change in a future version.
|
* {@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
|
* @return the current subject, or {@code null} if a current subject is
|
||||||
* not installed or the current subject is set to {@code null}.
|
* 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")
|
@SuppressWarnings("removal")
|
||||||
public static Subject current() {
|
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
|
* Executes a {@code Callable} with {@code subject} as the
|
||||||
* current subject.
|
* current subject.
|
||||||
*
|
*
|
||||||
* @implNote
|
* <p> If a security manager is <a href=#sm-allowed>allowed</a>,
|
||||||
* This method calls {@link #doAs(Subject, PrivilegedExceptionAction)
|
* this method first retrieves the current Thread's
|
||||||
* Subject.doAs(subject, altAction)} which stores the subject in
|
* {@code AccessControlContext} via
|
||||||
* a new {@code AccessControlContext}, where {@code altAction.run()}
|
* {@code AccessController.getContext},
|
||||||
* is equivalent to {@code action.call()} and the exception thrown is
|
* and then instantiates a new {@code AccessControlContext}
|
||||||
* modified to match the specification of this method. This preserves
|
* using the retrieved context along with a new
|
||||||
* compatibility with code that may still be calling
|
* {@code SubjectDomainCombiner} (constructed using
|
||||||
* {@code getSubject(AccessControlContext)} which retrieves the subject
|
* the provided {@code Subject}).
|
||||||
* from an {@code AccessControlContext}. This behavior is subject
|
* Finally, this method invokes {@code AccessController.doPrivileged},
|
||||||
* to change in a future version.
|
* 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}
|
* @param subject the {@code Subject} that the specified {@code action}
|
||||||
* will run as. This parameter may be {@code null}.
|
* 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,
|
public static <T> T callAs(final Subject subject,
|
||||||
final Callable<T> action) throws CompletionException {
|
final Callable<T> action) throws CompletionException {
|
||||||
Objects.requireNonNull(action);
|
Objects.requireNonNull(action);
|
||||||
try {
|
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
|
||||||
PrivilegedExceptionAction<T> pa = () -> action.call();
|
try {
|
||||||
@SuppressWarnings("removal")
|
return ScopedValue.callWhere(SCOPED_SUBJECT, subject, action);
|
||||||
var result = doAs(subject, pa);
|
} catch (Exception e) {
|
||||||
return result;
|
throw new CompletionException(e);
|
||||||
} catch (PrivilegedActionException e) {
|
}
|
||||||
throw new CompletionException(e.getCause());
|
} else {
|
||||||
} catch (Exception e) {
|
try {
|
||||||
throw new CompletionException(e);
|
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}.
|
* 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 AccessControlContext} via
|
||||||
* {@code AccessController.getContext},
|
* {@code AccessController.getContext},
|
||||||
* and then instantiates a new {@code AccessControlContext}
|
* 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},
|
* passing it the provided {@code PrivilegedAction},
|
||||||
* as well as the newly constructed {@code AccessControlContext}.
|
* 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
|
* @param subject the {@code Subject} that the specified
|
||||||
* {@code action} will run as. This parameter
|
* {@code action} will run as. This parameter
|
||||||
* may be {@code null}.
|
* may be {@code null}.
|
||||||
@ -444,20 +516,36 @@ public final class Subject implements java.io.Serializable {
|
|||||||
Objects.requireNonNull(action,
|
Objects.requireNonNull(action,
|
||||||
ResourcesMgr.getString("invalid.null.action.provided"));
|
ResourcesMgr.getString("invalid.null.action.provided"));
|
||||||
|
|
||||||
// set up the new Subject-based AccessControlContext
|
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
|
||||||
// for doPrivileged
|
try {
|
||||||
final AccessControlContext currentAcc = AccessController.getContext();
|
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
|
// call doPrivileged and push this new context on the stack
|
||||||
return java.security.AccessController.doPrivileged
|
return java.security.AccessController.doPrivileged
|
||||||
(action,
|
(action,
|
||||||
createContext(subject, currentAcc));
|
createContext(subject, currentAcc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform work as a particular {@code Subject}.
|
* 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 AccessControlContext} via
|
||||||
* {@code AccessController.getContext},
|
* {@code AccessController.getContext},
|
||||||
* and then instantiates a new {@code AccessControlContext}
|
* 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},
|
* passing it the provided {@code PrivilegedExceptionAction},
|
||||||
* as well as the newly constructed {@code AccessControlContext}.
|
* 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
|
* @param subject the {@code Subject} that the specified
|
||||||
* {@code action} will run as. This parameter
|
* {@code action} will run as. This parameter
|
||||||
* may be {@code null}.
|
* may be {@code null}.
|
||||||
@ -517,19 +609,37 @@ public final class Subject implements java.io.Serializable {
|
|||||||
Objects.requireNonNull(action,
|
Objects.requireNonNull(action,
|
||||||
ResourcesMgr.getString("invalid.null.action.provided"));
|
ResourcesMgr.getString("invalid.null.action.provided"));
|
||||||
|
|
||||||
// set up the new Subject-based AccessControlContext for doPrivileged
|
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
|
||||||
final AccessControlContext currentAcc = AccessController.getContext();
|
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
|
// call doPrivileged and push this new context on the stack
|
||||||
return java.security.AccessController.doPrivileged
|
return java.security.AccessController.doPrivileged
|
||||||
(action,
|
(action,
|
||||||
createContext(subject, currentAcc));
|
createContext(subject, currentAcc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform privileged work as a particular {@code Subject}.
|
* 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
|
* except that instead of retrieving the current Thread's
|
||||||
* {@code AccessControlContext}, it uses the provided
|
* {@code AccessControlContext}, it uses the provided
|
||||||
* {@code AccessControlContext}. If 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}
|
* this method instantiates a new {@code AccessControlContext}
|
||||||
* with an empty collection of ProtectionDomains.
|
* 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
|
* @param subject the {@code Subject} that the specified
|
||||||
* {@code action} will run as. This parameter
|
* {@code action} will run as. This parameter
|
||||||
* may be {@code null}.
|
* may be {@code null}.
|
||||||
@ -583,23 +697,39 @@ public final class Subject implements java.io.Serializable {
|
|||||||
Objects.requireNonNull(action,
|
Objects.requireNonNull(action,
|
||||||
ResourcesMgr.getString("invalid.null.action.provided"));
|
ResourcesMgr.getString("invalid.null.action.provided"));
|
||||||
|
|
||||||
// set up the new Subject-based AccessControlContext
|
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
|
||||||
// for doPrivileged
|
try {
|
||||||
final AccessControlContext callerAcc =
|
return callAs(subject, action::run);
|
||||||
(acc == null ?
|
} catch (CompletionException ce) {
|
||||||
new AccessControlContext(NULL_PD_ARRAY) :
|
var cause = ce.getCause();
|
||||||
acc);
|
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
|
// call doPrivileged and push this new context on the stack
|
||||||
return java.security.AccessController.doPrivileged
|
return java.security.AccessController.doPrivileged
|
||||||
(action,
|
(action,
|
||||||
createContext(subject, callerAcc));
|
createContext(subject, callerAcc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform privileged work as a particular {@code Subject}.
|
* 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
|
* except that instead of retrieving the current Thread's
|
||||||
* {@code AccessControlContext}, it uses the provided
|
* {@code AccessControlContext}, it uses the provided
|
||||||
* {@code AccessControlContext}. If 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}
|
* this method instantiates a new {@code AccessControlContext}
|
||||||
* with an empty collection of ProtectionDomains.
|
* 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
|
* @param subject the {@code Subject} that the specified
|
||||||
* {@code action} will run as. This parameter
|
* {@code action} will run as. This parameter
|
||||||
* may be {@code null}.
|
* may be {@code null}.
|
||||||
@ -659,16 +793,33 @@ public final class Subject implements java.io.Serializable {
|
|||||||
Objects.requireNonNull(action,
|
Objects.requireNonNull(action,
|
||||||
ResourcesMgr.getString("invalid.null.action.provided"));
|
ResourcesMgr.getString("invalid.null.action.provided"));
|
||||||
|
|
||||||
// set up the new Subject-based AccessControlContext for doPrivileged
|
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
|
||||||
final AccessControlContext callerAcc =
|
try {
|
||||||
(acc == null ?
|
return callAs(subject, action::run);
|
||||||
new AccessControlContext(NULL_PD_ARRAY) :
|
} catch (CompletionException ce) {
|
||||||
acc);
|
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
|
// call doPrivileged and push this new context on the stack
|
||||||
return java.security.AccessController.doPrivileged
|
return java.security.AccessController.doPrivileged
|
||||||
(action,
|
(action,
|
||||||
createContext(subject, callerAcc));
|
createContext(subject, callerAcc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
@SuppressWarnings("removal")
|
||||||
|
@ -592,4 +592,10 @@ public interface JavaLangAccess {
|
|||||||
* Are the string bytes compatible with the given charset?
|
* Are the string bytes compatible with the given charset?
|
||||||
*/
|
*/
|
||||||
boolean bytesCompatible(String string, Charset 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();
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -30,7 +30,7 @@
|
|||||||
*
|
*
|
||||||
* @run clean ThreadPoolAccTest
|
* @run clean ThreadPoolAccTest
|
||||||
* @run build ThreadPoolAccTest
|
* @run build ThreadPoolAccTest
|
||||||
* @run main ThreadPoolAccTest
|
* @run main/othervm -Djava.security.manager=allow ThreadPoolAccTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -30,7 +30,7 @@
|
|||||||
* java.management/com.sun.jmx.remote.security
|
* java.management/com.sun.jmx.remote.security
|
||||||
* @run clean NotificationAccessControllerTest
|
* @run clean NotificationAccessControllerTest
|
||||||
* @run build NotificationAccessControllerTest
|
* @run build NotificationAccessControllerTest
|
||||||
* @run main NotificationAccessControllerTest
|
* @run main/othervm -Djava.security.manager=allow NotificationAccessControllerTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import com.sun.jmx.remote.security.NotificationAccessController;
|
import com.sun.jmx.remote.security.NotificationAccessController;
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -30,7 +30,7 @@
|
|||||||
*
|
*
|
||||||
* @run clean NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
|
* @run clean NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
|
||||||
* @run build NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
|
* @run build NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
|
||||||
* @run main NonJMXPrincipalsTest
|
* @run main/othervm -Djava.security.manager=allow NonJMXPrincipalsTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -30,7 +30,7 @@
|
|||||||
*
|
*
|
||||||
* @run clean PasswordAccessFileTest SimpleStandard SimpleStandardMBean
|
* @run clean PasswordAccessFileTest SimpleStandard SimpleStandardMBean
|
||||||
* @run build PasswordAccessFileTest SimpleStandard SimpleStandardMBean
|
* @run build PasswordAccessFileTest SimpleStandard SimpleStandardMBean
|
||||||
* @run main PasswordAccessFileTest
|
* @run main/othervm -Djava.security.manager=allow PasswordAccessFileTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
* java.management/com.sun.jmx.remote.security
|
* java.management/com.sun.jmx.remote.security
|
||||||
* @run clean RMIAltAuthTest
|
* @run clean RMIAltAuthTest
|
||||||
* @run build RMIAltAuthTest SimpleStandard SimpleStandardMBean
|
* @run build RMIAltAuthTest SimpleStandard SimpleStandardMBean
|
||||||
* @run main RMIAltAuthTest
|
* @run main/othervm -Djava.security.manager=allow RMIAltAuthTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
* java.management/com.sun.jmx.remote.security
|
* java.management/com.sun.jmx.remote.security
|
||||||
* @run clean RMIPasswdAuthTest
|
* @run clean RMIPasswdAuthTest
|
||||||
* @run build RMIPasswdAuthTest SimpleStandard SimpleStandardMBean
|
* @run build RMIPasswdAuthTest SimpleStandard SimpleStandardMBean
|
||||||
* @run main RMIPasswdAuthTest
|
* @run main/othervm -Djava.security.manager=allow RMIPasswdAuthTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -31,12 +31,12 @@
|
|||||||
* java.management/com.sun.jmx.remote.security
|
* java.management/com.sun.jmx.remote.security
|
||||||
* @run clean SubjectDelegation1Test SimpleStandard SimpleStandardMBean
|
* @run clean SubjectDelegation1Test SimpleStandard SimpleStandardMBean
|
||||||
* @run build SubjectDelegation1Test SimpleStandard SimpleStandardMBean
|
* @run build SubjectDelegation1Test SimpleStandard SimpleStandardMBean
|
||||||
* @run main SubjectDelegation1Test policy11 ok
|
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy11 ok
|
||||||
* @run main SubjectDelegation1Test policy12 ko
|
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy12 ko
|
||||||
* @run main SubjectDelegation1Test policy13 ko
|
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy13 ko
|
||||||
* @run main SubjectDelegation1Test policy14 ko
|
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy14 ko
|
||||||
* @run main SubjectDelegation1Test policy15 ok
|
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy15 ok
|
||||||
* @run main SubjectDelegation1Test policy16 ko
|
* @run main/othervm -Djava.security.manager=allow SubjectDelegation1Test policy16 ko
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
|
import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -29,9 +29,9 @@
|
|||||||
* @modules java.management.rmi
|
* @modules java.management.rmi
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @compile Simple.java
|
* @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 -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 -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=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=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=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=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
|
* @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
|
||||||
|
106
test/jdk/javax/security/auth/Subject/CallAsWithScopedValue.java
Normal file
106
test/jdk/javax/security/auth/Subject/CallAsWithScopedValue.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
128
test/jdk/javax/security/auth/Subject/Compat.java
Normal file
128
test/jdk/javax/security/auth/Subject/Compat.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -22,28 +22,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import javax.security.auth.Subject;
|
import javax.security.auth.Subject;
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8267108
|
* @bug 8267108
|
||||||
* @summary confirm current subject specification
|
* @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 {
|
public class CurrentSubject {
|
||||||
|
|
||||||
static transient boolean failed = false;
|
static boolean failed = false;
|
||||||
static CountDownLatch cl = new CountDownLatch(1);
|
|
||||||
static AtomicInteger count = new AtomicInteger();
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
// At the beginning, current subject is null
|
// At the beginning, current subject is null
|
||||||
test("", null);
|
test("", null);
|
||||||
cl.await();
|
|
||||||
if (failed) {
|
if (failed) {
|
||||||
throw new Exception("Failed");
|
throw new Exception("Failed");
|
||||||
}
|
}
|
||||||
@ -57,12 +53,6 @@ public class CurrentSubject {
|
|||||||
*/
|
*/
|
||||||
synchronized static void check(String label, Subject expected) {
|
synchronized static void check(String label, Subject expected) {
|
||||||
Subject cas = Subject.current();
|
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;
|
Subject interested = cas;
|
||||||
if (interested != expected) {
|
if (interested != expected) {
|
||||||
failed = true;
|
failed = true;
|
||||||
@ -89,31 +79,23 @@ public class CurrentSubject {
|
|||||||
// run with a new subject, inside current subject will be the new subject
|
// run with a new subject, inside current subject will be the new subject
|
||||||
Subject.callAs(another, () -> test(name + 'c', another));
|
Subject.callAs(another, () -> test(name + 'c', another));
|
||||||
Subject.doAs(another, (PrivilegedAction<Void>) () -> test(name + 'd', 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
|
// run with null, inside current subject will be null
|
||||||
Subject.callAs(null, () -> test(name + 'C', null));
|
Subject.callAs(null, () -> test(name + 'C', null));
|
||||||
Subject.doAs(null, (PrivilegedAction<Void>) () -> test(name + 'D', null));
|
Subject.doAs(null, (PrivilegedAction<Void>) () -> test(name + 'D', null));
|
||||||
// new thread, inside current subject is unchanged
|
Subject.doAsPrivileged(null, (PrivilegedAction<Void>) () -> test(name + 'E', null), null);
|
||||||
count.incrementAndGet();
|
try {
|
||||||
new Thread(() -> {
|
Subject.doAs(null, (PrivilegedExceptionAction<Void>) () -> test(name + 'F', null));
|
||||||
try {
|
Subject.doAsPrivileged(null, (PrivilegedExceptionAction<Void>) () -> test(name + 'G', null), null);
|
||||||
test(name + 't', expected);
|
} catch (Exception e) {
|
||||||
try {
|
throw new RuntimeException(e);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
// Now it's reset to original
|
// Now it's reset to original
|
||||||
check(" ".repeat(name.length()) + "<- " + name, expected);
|
check(" ".repeat(name.length()) + "<- " + name, expected);
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -32,7 +32,6 @@ import java.security.PrivilegedAction;
|
|||||||
* @bug 8267108
|
* @bug 8267108
|
||||||
* @summary confirm current installed subject specification
|
* @summary confirm current installed subject specification
|
||||||
* @run main/othervm -Djava.security.manager=allow FromACC
|
* @run main/othervm -Djava.security.manager=allow FromACC
|
||||||
* @run main/othervm -Djava.security.manager=disallow FromACC
|
|
||||||
*/
|
*/
|
||||||
public class FromACC {
|
public class FromACC {
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
73
test/jdk/javax/security/auth/Subject/UnsupportedSV.java
Normal file
73
test/jdk/javax/security/auth/Subject/UnsupportedSV.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -61,7 +61,7 @@ import java.util.Set;
|
|||||||
*
|
*
|
||||||
* @library /test/lib
|
* @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
|
* @library /test/lib
|
||||||
*
|
*
|
||||||
* @run main/othervm/timeout=300 RmiBootstrapTest .*_ssltest.*.in
|
* @run main/othervm/timeout=300 -Djava.security.manager=allow RmiBootstrapTest .*_ssltest.*.in
|
||||||
* */
|
* */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user