Path: blob/master/jcl/src/java.base/share/classes/java/security/AccessControlContext.java
12513 views
/*[INCLUDE-IF Sidecar18-SE]*/1/*******************************************************************************2* Copyright (c) 1998, 2021 IBM Corp. and others3*4* This program and the accompanying materials are made available under5* the terms of the Eclipse Public License 2.0 which accompanies this6* distribution and is available at https://www.eclipse.org/legal/epl-2.0/7* or the Apache License, Version 2.0 which accompanies this distribution and8* is available at https://www.apache.org/licenses/LICENSE-2.0.9*10* This Source Code may also be made available under the following11* Secondary Licenses when the conditions for such availability set12* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU13* General Public License, version 2 with the GNU Classpath14* Exception [1] and GNU General Public License, version 2 with the15* OpenJDK Assembly Exception [2].16*17* [1] https://www.gnu.org/software/classpath/license.html18* [2] http://openjdk.java.net/legal/assembly-exception.html19*20* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception21*******************************************************************************/22package java.security;2324import java.io.IOException;25import java.io.StreamTokenizer;26import java.io.StringReader;27import java.net.MalformedURLException;28import java.net.URL;29import java.util.ArrayList;30/*[IF Sidecar19-SE]*/31import sun.security.util.FilePermCompat;32/*[ENDIF] Sidecar19-SE*/33import sun.security.util.SecurityConstants;3435/**36* An AccessControlContext encapsulates the information which is needed37* by class AccessController to detect if a Permission would be granted38* at a particular point in a programs execution.39*40* @author OTI41* @version initial42*/43/*[IF JAVA_SPEC_VERSION >= 17]*/44@Deprecated(since="17", forRemoval=true)45/*[ENDIF] JAVA_SPEC_VERSION >= 17 */46public final class AccessControlContext {4748static final int STATE_NOT_AUTHORIZED = 0; // It has been confirmed that the ACC is NOT authorized49static final int STATE_AUTHORIZED = 1; // It has been confirmed that the ACC is authorized50static final int STATE_UNKNOWN = 2; // The ACC state is unknown yet.5152private static int debugSetting = -1;53private static ArrayList<String> debugPermClassArray;54private static ArrayList<String> debugPermNameArray;55private static ArrayList<String> debugPermActionsArray;56static ArrayList<URL> debugCodeBaseArray;5758/* Constants used to set the value of the debugHasCodebase field */59private static final int DEBUG_UNINITIALIZED_HASCODEBASE = 0;60private static final int DEBUG_NO_CODEBASE = 1;61private static final int DEBUG_HAS_CODEBASE = 2;6263static final int DEBUG_DISABLED = 0;64static final int DEBUG_ACCESS_DENIED = 1; // debug is enabled for access denied, and failure65static final int DEBUG_ENABLED = 2; // debug is enabled for access allowed, stacks, domains, and threads6667DomainCombiner domainCombiner;68/*[PR CMVC 111227] JDK6 expects field to be called "context" */69ProtectionDomain[] context;70/*[PR CMVC 197399] Improve checking order */71int authorizeState = STATE_UNKNOWN;72/*[PR JAZZ 66930] j.s.AccessControlContext.checkPermission() invoke untrusted ProtectionDomain.implies */73// This flag is to determine if current ACC contains privileged PDs such that74// createAccessControlContext permission need to be checked before invoking ProtectionDomain.implies()75private boolean containPrivilegedContext = false;76// This is the ProtectionDomain of the creator of this ACC77private ProtectionDomain callerPD;78AccessControlContext doPrivilegedAcc; // AccessControlContext usually coming from a doPrivileged call79boolean isLimitedContext = false; // flag to indicate if there are limited permissions80Permission[] limitedPerms; // the limited permissions when isLimitedContext is true81AccessControlContext nextStackAcc; // AccessControlContext in next call stack when isLimitedContext is true82private int debugHasCodebase; // Set to the value of DEBUG_UNINITIALIZED_HASCODEBASE be default. Cache the result of hasDebugCodeBase()8384static final int DEBUG_ACCESS = 1;85static final int DEBUG_ACCESS_STACK = 2;86static final int DEBUG_ACCESS_DOMAIN = 4;87static final int DEBUG_ACCESS_FAILURE = 8;88static final int DEBUG_ACCESS_THREAD = 0x10;89static final int DEBUG_ALL = 0xff;9091static final class AccessCache {92ProtectionDomain[] pdsImplied;93Permission[] permsImplied;94Permission[] permsNotImplied;95}9697static int debugSetting() {98if (debugSetting != -1) return debugSetting;99debugSetting = 0;100String value = com.ibm.oti.vm.VM.getVMLangAccess().internalGetProperties().getProperty("java.security.debug"); //$NON-NLS-1$101if (value == null) return debugSetting;102StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(value));103tokenizer.resetSyntax();104tokenizer.wordChars(Character.MIN_CODE_POINT, Character.MAX_CODE_POINT);105tokenizer.quoteChar('"');106tokenizer.whitespaceChars(',', ',');107108try {109while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {110String keyword = tokenizer.sval;111if (keyword.equals("all")) { //$NON-NLS-1$112debugSetting = DEBUG_ALL;113return debugSetting;114}115if (keyword.startsWith("access:")) { //$NON-NLS-1$116debugSetting |= DEBUG_ACCESS;117keyword = keyword.substring(7);118}119120if (keyword.equals("access")) { //$NON-NLS-1$121debugSetting |= DEBUG_ACCESS;122} else if (keyword.equals("stack")) { //$NON-NLS-1$123debugSetting |= DEBUG_ACCESS_STACK;124} else if (keyword.equals("domain")) { //$NON-NLS-1$125debugSetting |= DEBUG_ACCESS_DOMAIN;126} else if (keyword.equals("failure")) { //$NON-NLS-1$127debugSetting |= DEBUG_ACCESS_FAILURE;128} else if (keyword.equals("thread")) { //$NON-NLS-1$129debugSetting |= DEBUG_ACCESS_THREAD;130} else if (keyword.startsWith("permission=")) { //$NON-NLS-1$131String debugPermClass = keyword.substring(11);132if (debugPermClass.isEmpty() && tokenizer.nextToken() != StreamTokenizer.TT_EOF) {133debugPermClass = tokenizer.sval;134}135if (null == debugPermClassArray) {136debugPermClassArray = new ArrayList<>();137}138debugPermClassArray.add(debugPermClass);139} else if (keyword.startsWith("codebase=")) { //$NON-NLS-1$140String codebase = keyword.substring(9);141if (codebase.isEmpty() && tokenizer.nextToken() != StreamTokenizer.TT_EOF) {142codebase = tokenizer.sval;143}144URL debugCodeBase = null;145try {146debugCodeBase = new URL(codebase);147} catch (MalformedURLException e) {148System.err.println("Error setting -Djava.security.debug=access:codebase - " + e); //$NON-NLS-1$149}150if (null != debugCodeBase) {151if (null == debugCodeBaseArray) {152debugCodeBaseArray = new ArrayList<>();153}154debugCodeBaseArray.add(debugCodeBase);155}156} else if (keyword.startsWith("permname=")) { //$NON-NLS-1$157String debugPermName = keyword.substring(9);158if (debugPermName.isEmpty() && tokenizer.nextToken() != StreamTokenizer.TT_EOF) {159debugPermName = tokenizer.sval;160}161if (null == debugPermNameArray) {162debugPermNameArray = new ArrayList<>();163}164debugPermNameArray.add(debugPermName);165} else if (keyword.startsWith("permactions=")) { //$NON-NLS-1$166String debugPermActions = keyword.substring(12);167if (debugPermActions.isEmpty() && tokenizer.nextToken() != StreamTokenizer.TT_EOF) {168debugPermActions = tokenizer.sval;169}170if (null == debugPermActionsArray) {171debugPermActionsArray = new ArrayList<>();172}173debugPermActionsArray.add(debugPermActions);174}175}176} catch (IOException e) {177// should not happen with StringReader178}179if (0 == (debugSetting & DEBUG_ACCESS)) {180// If the access keyword is not specified, none of the other keywords have any affect181debugSetting = 0;182}183return debugSetting;184}185186/**187* Return true if the specified Permission is enabled for debug.188* @param perm a Permission instance189* @return Return true if the specified Permission is enabled for debug190*/191static boolean debugPermission(Permission perm) {192boolean result = true;193if (debugPermClassArray != null) {194result = false;195String permClassName = perm.getClass().getName();196for (String debugPermClass : debugPermClassArray) {197if (debugPermClass.equals(permClassName)) {198return true;199}200}201}202if (debugPermNameArray != null) {203result = false;204String permName = perm.getName();205for (String debugPermName : debugPermNameArray) {206if (debugPermName.equals(permName)) {207return true;208}209}210}211if (debugPermActionsArray != null) {212result = false;213String permActions = perm.getActions();214for (String debugPermActions : debugPermActionsArray) {215if (debugPermActions.equals(permActions)) {216return true;217}218}219}220return result;221}222223/**224* Check if the receiver contains a ProtectionDomain using the debugCodeBase, which225* was parsed from the java.security.debug system property.226*227* @return true if the AccessControlContext contains a ProtectionDomain which228* matches the debug codebase.229*/230boolean hasDebugCodeBase() {231if (debugHasCodebase != DEBUG_UNINITIALIZED_HASCODEBASE) {232return debugHasCodebase == DEBUG_HAS_CODEBASE ? true : false;233}234ProtectionDomain[] pds = this.context;235if (pds != null) {236for (int i = 0; i < pds.length; ++i) {237ProtectionDomain pd = this.context[i];238CodeSource cs = null == pd ? null : pd.getCodeSource();239if ((cs != null) && debugCodeBase(cs.getLocation())) {240debugHasCodebase = DEBUG_HAS_CODEBASE;241return true;242}243}244if ((this.doPrivilegedAcc != null) && this.doPrivilegedAcc.hasDebugCodeBase()) {245debugHasCodebase = DEBUG_HAS_CODEBASE;246return true;247}248if ((this.nextStackAcc != null) && this.nextStackAcc.hasDebugCodeBase()) {249debugHasCodebase = DEBUG_HAS_CODEBASE;250return true;251}252}253debugHasCodebase = DEBUG_NO_CODEBASE;254return false;255}256257/**258* Return true if the specified codebase location is enabled for debug.259* @param location a codebase URL260* @return Return true if the specified codebase location is enabled for debug261*/262static boolean debugCodeBase(URL location) {263if (location != null) {264for (URL debugCodeBase : debugCodeBaseArray) {265if (debugCodeBase.equals(location)) {266return true;267}268}269}270271return false;272}273274static void debugPrintAccess() {275System.err.print("access: "); //$NON-NLS-1$276if ((debugSetting() & DEBUG_ACCESS_THREAD) == DEBUG_ACCESS_THREAD) {277System.err.print("(" + Thread.currentThread() + ")"); //$NON-NLS-1$ //$NON-NLS-2$278}279}280281/**282* Constructs a new instance of this class given an array of283* protection domains.284*285* @param fromContext the array of ProtectionDomain286*287* @exception NullPointerException if fromContext is null288*/289public AccessControlContext(ProtectionDomain[] fromContext) {290/*[PR 94884]*/291int length = fromContext.length;292if (length == 0) {293context = null;294} else {295int domainIndex = 0;296context = new ProtectionDomain[length];297next : for (int i = 0; i < length; ++i) {298ProtectionDomain current = fromContext[i];299if (current == null) continue;300for (int j = 0; j < i; ++j)301if (current == context[j]) continue next;302context[domainIndex++] = current;303}304if (domainIndex == 0) {305context = null;306} else if (domainIndex != length) {307ProtectionDomain[] copy = new ProtectionDomain[domainIndex];308System.arraycopy(context, 0, copy, 0, domainIndex);309context = copy;310}311}312// this.containPrivilegedContext is set to false by default313// this.authorizeState is STATE_UNKNOWN by default314}315316AccessControlContext(ProtectionDomain[] context, int authorizeState) {317super();318switch (authorizeState) {319default:320// authorizeState can't be STATE_UNKNOWN, callerPD always is NULL321throw new IllegalArgumentException();322case STATE_AUTHORIZED:323case STATE_NOT_AUTHORIZED:324break;325}326this.context = context;327this.authorizeState = authorizeState;328this.containPrivilegedContext = true;329}330331AccessControlContext(AccessControlContext acc, ProtectionDomain[] context, int authorizeState) {332super();333switch (authorizeState) {334default:335// authorizeState can't be STATE_UNKNOWN, callerPD always is NULL336throw new IllegalArgumentException();337case STATE_AUTHORIZED:338if (null != acc) {339// inherit the domain combiner when authorized340this.domainCombiner = acc.domainCombiner;341}342break;343case STATE_NOT_AUTHORIZED:344break;345}346this.doPrivilegedAcc = acc;347this.context = context;348this.authorizeState = authorizeState;349this.containPrivilegedContext = true;350}351352/**353* Constructs a new instance of this class given a context354* and a DomainCombiner355*356* @param acc the AccessControlContext357* @param combiner the DomainCombiner358*359* @exception java.security.AccessControlException thrown360* when the caller doesn't have the "createAccessControlContext" SecurityPermission361* @exception NullPointerException if the provided context is null.362*/363public AccessControlContext(AccessControlContext acc, DomainCombiner combiner) {364this(acc, combiner, false);365}366367/**368* Constructs a new instance of this class given a context and a DomainCombiner369* Skip the Permission "createAccessControlContext" check if preauthorized is true370*371* @param acc the AccessControlContext372* @param combiner the DomainCombiner373* @param preauthorized the flag to indicate if the permission check can be skipped374*375* @exception java.security.AccessControlException thrown376* when the caller doesn't have the "createAccessControlContext" SecurityPermission377* @exception NullPointerException if the provided context is null.378*/379AccessControlContext(AccessControlContext acc, DomainCombiner combiner, boolean preauthorized) {380if (!preauthorized) {381@SuppressWarnings("removal")382SecurityManager security = System.getSecurityManager();383if (null != security) {384security.checkPermission(SecurityConstants.CREATE_ACC_PERMISSION);385/*[PR JAZZ 78139] java.security.AccessController.checkPermission invokes untrusted DomainCombiner.combine method */386}387}388// only AccessControlContext with STATE_AUTHORIZED authorizeState could have non-null domainCombiner389this.authorizeState = STATE_AUTHORIZED;390this.context = acc.context;391this.domainCombiner = combiner;392this.containPrivilegedContext = acc.containPrivilegedContext;393this.isLimitedContext = acc.isLimitedContext;394this.limitedPerms = acc.limitedPerms;395this.nextStackAcc = acc.nextStackAcc;396this.doPrivilegedAcc = acc.doPrivilegedAcc;397}398399/**400* Combine checked and toBeCombined401* Assuming: there are no null or dup elements in checked402* there might be nulls or dups in toBeCombined403*404* @param objPDs the flag to indicate if it is a ProtectionDomain or Permission object element405* @param checked the array of objects already checked406* @param toBeCombined the array of objects to be combined407* @param start the start position in the toBeCombined array408* @param len the number of element to be copied409* @param justCombine the flag to indicate if null/dup check is needed410*411* @return the combination of these two array412*/413private static Object[] combineObjs(boolean objPDs, Object[] checked, Object[] toBeCombined, int start, int len, boolean justCombine) {414if (null == toBeCombined) {415return checked;416}417final int lenToBeCombined = Math.min(len, toBeCombined.length - start);418if (0 == lenToBeCombined) {419return checked;420}421final int lenChecked = (null == checked) ? 0 : checked.length;422Object[] answer;423if (objPDs) {424answer = new ProtectionDomain[lenChecked + lenToBeCombined];425} else {426answer = new Permission[lenChecked + lenToBeCombined];427}428if (0 != lenChecked) {429System.arraycopy(checked, 0, answer, 0, lenChecked);430}431if (justCombine) {432// no null/dup check433System.arraycopy(toBeCombined, start, answer, lenChecked, lenToBeCombined);434} else {435// remove the null & dups436int answerLength = lenChecked;437for (int i = 0; i < lenToBeCombined; ++i) {438Object object = toBeCombined[start + i];439if (null != object) { // remove null440// check starts from newly added elements441for (int j = answerLength;;) {442j -= 1;443if (j < 0) {444answer[answerLength] = object;445answerLength += 1;446break;447} else if (object == answer[j]) {448break;449}450}451}452}453if (answerLength < answer.length) {454Object[] result;455if (objPDs) {456result = new ProtectionDomain[answerLength];457} else {458result = new Permission[answerLength];459}460System.arraycopy(answer, 0, result, 0, answerLength);461answer = result;462}463}464return answer;465}466467/**468* Combine checked and toBeCombined ProtectionDomain objects469* Assuming: there are no null or dup elements in checked470* there might be null or dups in toBeCombined471*472* @param checked the array of objects already checked473* @param toBeCombined the array of objects to be combined474*475* @return the combination of these two array476*/477static ProtectionDomain[] combinePDObjs(ProtectionDomain[] checked, Object[] toBeCombined) {478return (ProtectionDomain[]) combineObjs(true, checked, toBeCombined, 0, (null != toBeCombined) ? toBeCombined.length : 0, false);479}480481/**482* Combine checked and toBeCombined Permission objects483* Assuming: there are no null or dup elements in checked484* there might be null or dups in toBeCombined485*486* @param checked the array of objects already checked487* @param toBeCombined the array of objects to be combined488* @param start the start position in the toBeCombined array489* @param len the number of element to be copied490* @param justCombine the flag to indicate if null/dup check is needed491*492* @return the combination of these two array493*/494static Permission[] combinePermObjs(Permission[] checked, Permission[] toBeCombined, int start, int len, boolean justCombine) {495return (Permission[]) combineObjs(false, checked, toBeCombined, start, len, justCombine);496}497498/**499* Perform ProtectionDomain.implies(permission) with known ProtectionDomain objects already implied500*501* @param perm the permission to be checked502* @param toCheck the ProtectionDomain to be checked503* @param cacheChecked the cached check result which is an array with following three elements:504* ProtectionDomain[] pdsImplied, Permission[] permsImplied, Permission[] permsNotImplied505*506* @return -1 if toCheck is null, among pdsImplied or each ProtectionDomain within toCheck implies perm,507* otherwise the index of ProtectionDomain objects not implied508*/509static int checkPermWithCachedPDsImplied(Permission perm, Object[] toCheck, AccessCache cacheChecked) {510if (null == toCheck) {511return -1; // nothing to check, implied512}513ProtectionDomain[] pdsImplied = (null == cacheChecked) ? null : cacheChecked.pdsImplied;514515// in reverse order as per RI behavior516check: for (int i = toCheck.length; i > 0;) {517i -= 1;518Object domain = toCheck[i];519if (null != domain) {520if (null != pdsImplied) {521for (int j = 0; j < pdsImplied.length; ++j) {522if (domain == pdsImplied[j]) {523continue check;524}525}526}527/*[IF Sidecar19-SE]*/528if (!((ProtectionDomain) domain).impliesWithAltFilePerm(perm)) {529/*[ELSE]*/530if (!((ProtectionDomain) domain).implies(perm)) {531/*[ENDIF] Sidecar19-SE*/532return i; // NOT implied533}534}535}536if (null != cacheChecked) {537cacheChecked.pdsImplied = combinePDObjs(pdsImplied, toCheck);538}539return -1; // all implied540}541542/**543* Perform Permission.implies(permission) with known Permission objects already implied and NOT implied544*545* @param perm the permission to be checked546* @param permsLimited the limited Permission to be checked547* @param cacheChecked the cached check result which is an array with following three elements:548* ProtectionDomain[] pdsImplied, Permission[] permsImplied, Permission[] permsNotImplied549*550* @return true if there is a limited permission implied perm, otherwise false551*/552static boolean checkPermWithCachedPermImplied(Permission perm, Permission[] permsLimited, AccessCache cacheChecked) {553if (null == permsLimited) {554return false;555}556Permission[] permsImplied = null;557Permission[] permsNotImplied = null;558if (null != cacheChecked) {559permsImplied = cacheChecked.permsImplied;560permsNotImplied = cacheChecked.permsNotImplied;561}562boolean success = false;563int lenNotImplied = permsLimited.length;564for (int j = 0; j < permsLimited.length; ++j) {565if (null != permsLimited[j]) { // go through each non-null limited permission566if (null != permsImplied) {567for (int k = 0; k < permsImplied.length; ++k) {568if (permsLimited[j] == permsImplied[k]) {569success = true; // already implied before570break;571}572}573if (success) { // already implied574lenNotImplied = j;575break;576}577}578boolean notImplied = false;579if (null != permsNotImplied) {580for (int k = 0; k < permsNotImplied.length; ++k) {581if (permsLimited[j] == permsNotImplied[k]) {582notImplied = true; // already NOT implied before583lenNotImplied = j;584break;585}586}587}588/*[IF Sidecar19-SE]*/589permsLimited[j] = FilePermCompat.newPermPlusAltPath(permsLimited[j]);590/*[ENDIF] Sidecar19-SE*/591if (!notImplied && permsLimited[j].implies(perm)) {592success = true; // just implied593if (null != cacheChecked) {594cacheChecked.permsImplied = combinePermObjs(permsImplied, permsLimited, j, 1, true);595}596lenNotImplied = j;597break;598}599}600}601if (0 < lenNotImplied && null != cacheChecked) {602cacheChecked.permsNotImplied = combinePermObjs(permsNotImplied, permsLimited, 0, lenNotImplied, false);603}604return success;605}606607/**608* Checks if the permission perm is allowed as per incoming609* AccessControlContext/ProtectionDomain[]/isLimited/Permission[]610* while taking advantage cached611* ProtectionDomain[] pdsImplied, Permission[] permsImplied, Permission[] permsNotImplied612*613* @param perm the permission to be checked614* @param activeDC the DomainCombiner to be invoked615* @param accCurrent the current AccessControlContext to be checked616* @param debug debug flags617* @param pdsContext the current context to be checked618* @param isLimited the flag to indicate if there are limited permission(s)619* @param permsLimited the limited permission(s) to be checked620* @param accNext the next AccessControlContext to be checked621* @param cacheChecked the cached check result which is an array with following three elements:622* ProtectionDomain[] pdsImplied, Permission[] permsImplied, Permission[] permsNotImplied623*624* @return true if the access is granted by a limited permission, otherwise an exception is thrown or625* false is returned to indicate the access was NOT granted by any limited permission.626*/627static boolean checkPermissionWithCache(628Permission perm,629DomainCombiner activeDC,630Object[] pdsContext,631int debug,632AccessControlContext accCurrent,633boolean isLimited,634Permission[] permsLimited,635AccessControlContext accNext,636AccessCache cacheChecked637) throws AccessControlException {638if (((debug & DEBUG_ENABLED) != 0) && ((debugSetting() & DEBUG_ACCESS_DOMAIN) != 0)) {639debugPrintAccess();640if (pdsContext == null || pdsContext.length == 0) {641System.err.println("domain (context is null)"); //$NON-NLS-1$642} else {643for (int i = 0; i < pdsContext.length; ++i) {644System.err.println("domain " + i + " " + pdsContext[i]); //$NON-NLS-1$ //$NON-NLS-2$645}646}647}648if (null != pdsContext) {649int i = checkPermWithCachedPDsImplied(perm, pdsContext, cacheChecked);650if (0 <= i) {651// debug for access denied is not optional652if ((debug & DEBUG_ACCESS_DENIED) != 0) {653if ((debugSetting() & DEBUG_ACCESS) != 0) {654debugPrintAccess();655System.err.println("access denied " + perm); //$NON-NLS-1$656}657if ((debugSetting() & DEBUG_ACCESS_FAILURE) != 0) {658new Exception("Stack trace").printStackTrace(); //$NON-NLS-1$659System.err.println("domain that failed " + pdsContext[i]); //$NON-NLS-1$660}661}662/*[MSG "K002c", "Access denied {0}"]*/663throw new AccessControlException(com.ibm.oti.util.Msg.getString("K002c", perm), perm); //$NON-NLS-1$664}665}666if (null != accCurrent667&& (null != accCurrent.context || null != accCurrent.doPrivilegedAcc || null != accCurrent.limitedPerms || null != accCurrent.nextStackAcc)668) {669ProtectionDomain[] pdCombined;670if (activeDC == null) {671pdCombined = accCurrent.context;672} else {673pdCombined = activeDC.combine((ProtectionDomain[])pdsContext, accCurrent.context);674}675// accCurrent check either throwing a security exception (denied) or continue checking (the return value doesn't matter)676checkPermissionWithCache(perm, activeDC, pdCombined, debug, accCurrent.doPrivilegedAcc, accCurrent.isLimitedContext, accCurrent.limitedPerms, accCurrent.nextStackAcc, cacheChecked);677}678if (isLimited && null != permsLimited) {679if (checkPermWithCachedPermImplied(perm, permsLimited, cacheChecked)) {680return true; // implied by a limited permission681}682if (null != accNext) {683ProtectionDomain[] pdCombined;684if (activeDC == null) {685pdCombined = accNext.context;686} else {687pdCombined = activeDC.combine((ProtectionDomain[])pdsContext, accNext.context);688}689checkPermissionWithCache(perm, activeDC, pdCombined, debug, accNext.doPrivilegedAcc, accNext.isLimitedContext, accNext.limitedPerms, accNext.nextStackAcc, cacheChecked);690}691return false; // NOT implied by any limited permission692}693if ((debug & DEBUG_ENABLED) != 0) {694debugPrintAccess();695System.err.println("access allowed " + perm); //$NON-NLS-1$696}697return true;698}699700/**701* Helper to print debug information for checkPermission().702*703* @param perm the permission to check704* @return if debugging is enabled705*/706private boolean debugHelper(Permission perm) {707boolean debug = true;708if (debugCodeBaseArray != null) {709debug = hasDebugCodeBase();710}711if (debug) {712debug = debugPermission(perm);713}714if (debug && ((debugSetting() & DEBUG_ACCESS_STACK) != 0)) {715new Exception("Stack trace for " + perm).printStackTrace(); //$NON-NLS-1$716}717return debug;718}719720/**721* Checks if the permission <code>perm</code> is allowed in this context.722* All ProtectionDomains must grant the permission for it to be granted.723*724* @param perm java.security.Permission725* the permission to check726* @exception java.security.AccessControlException727* thrown when perm is not granted.728* @exception NullPointerException729* if perm is null730*/731public void checkPermission(Permission perm) throws AccessControlException {732if (perm == null) throw new NullPointerException();733if (null != context && (STATE_AUTHORIZED != authorizeState) && containPrivilegedContext && null != System.getSecurityManager()) {734// only check SecurityPermission "createAccessControlContext" when context is not null, not authorized and containPrivilegedContext.735if (STATE_UNKNOWN == authorizeState) {736if (null == callerPD || callerPD.implies(SecurityConstants.CREATE_ACC_PERMISSION)) {737authorizeState = STATE_AUTHORIZED;738} else {739authorizeState = STATE_NOT_AUTHORIZED;740}741callerPD = null;742}743if (STATE_NOT_AUTHORIZED == authorizeState) {744/*[MSG "K002d", "Access denied {0} due to untrusted AccessControlContext since {1} is denied"]*/745throw new AccessControlException(com.ibm.oti.util.Msg.getString("K002d", perm, SecurityConstants.CREATE_ACC_PERMISSION), perm); //$NON-NLS-1$746}747}748749boolean debug = (debugSetting() & DEBUG_ACCESS) != 0;750if (debug) {751debug = debugHelper(perm);752}753checkPermissionWithCache(perm, null, this.context, debug ? DEBUG_ENABLED | DEBUG_ACCESS_DENIED : DEBUG_DISABLED, this.doPrivilegedAcc,this.isLimitedContext, this.limitedPerms, this.nextStackAcc, new AccessCache());754}755756/**757* Helper method for equals() checks if the two arrays contain the same sets of objects or nulls.758* The order of the elements is not significant.759* If either of the given arrays is null it is treated as an empty array.760*761* @param s1 the first set762* @param s2 the second set763* @return true if the arrays have the same length and contain the same elements764*/765private static boolean equalSets(Object[] s1, Object[] s2) {766final int length;767768if (s1 == null || (length = s1.length) == 0) {769// the first set is empty, the second must be empty as well770return s2 == null || s2.length == 0;771}772773// the first set is not empty, the second must be the same size774if (s2 == null || length != s2.length) {775return false;776}777778next: for (int i = 0; i < length; ++i) {779Object object = s1[i];780781if (object == null) {782for (int j = 0; j < length; ++j) {783if (s2[j] == null) {784continue next;785}786}787} else {788for (int j = 0; j < length; ++j) {789if (object.equals(s2[j])) {790continue next;791}792}793}794795// object was not found in the second set796return false;797}798799return true;800}801802/**803* Compares the argument to the receiver, and answers true804* if they represent the <em>same</em> object using a class805* specific comparison. In this case, they must both be806* AccessControlContexts and contain the same protection domains.807*808* @param o the object to compare with this object809* @return <code>true</code>810* if the object is the same as this object811* <code>false</code>812* if it is different from this object813* @see #hashCode814*/815@Override816public boolean equals(Object o) {817if (this == o) return true;818if (o == null || this.getClass() != o.getClass()) return false;819AccessControlContext otherContext = (AccessControlContext) o;820/*[PR RTC 66684] j.s.AccessControlContext fields isAuthorized/domainCombiner not used in method equals() & hashCode() */821// match RI behaviors, i.e., ignore isAuthorized when performing equals822if (null != this.domainCombiner) {823if (!this.domainCombiner.equals(otherContext.domainCombiner)) {824return false;825}826} else {827if (null != otherContext.domainCombiner) {828return false;829}830}831if (isLimitedContext != otherContext.isLimitedContext) {832return false;833}834if (!equalSets(context, otherContext.context)) {835return false;836}837if (null != doPrivilegedAcc && !doPrivilegedAcc.equals(otherContext.doPrivilegedAcc)) {838return false;839}840if (isLimitedContext) {841if (!equalSets(limitedPerms, otherContext.limitedPerms)) {842return false;843}844if (null != nextStackAcc) {845return nextStackAcc.equals(otherContext.nextStackAcc);846}847}848return true;849}850851/**852* Answers an integer hash code for the receiver. Any two853* objects which answer <code>true</code> when passed to854* <code>equals</code> must answer the same value for this855* method.856*857* @return the receiver's hash858*859* @see #equals860*/861@Override862public int hashCode() {863int result = 0;864int i = context == null ? 0 : context.length;865while ((--i >= 0) && (context[i] != null)) {866result ^= context[i].hashCode();867}868869// RI equals not impacted by limited context,870// JCK still passes with following cause the AccessControlContext in question doesn't have limited context871// J9 might fail JCK test if JCK hashcode test changes872873if (null != doPrivilegedAcc) {874result ^= doPrivilegedAcc.hashCode();875}876// result = result + (this.isLimitedContext ? 1231 : 1237);877if (this.isLimitedContext) {878i = (limitedPerms == null) ? 0 : limitedPerms.length;879while (--i >= 0) {880if (null != limitedPerms[i]) {881result ^= limitedPerms[i].hashCode();882}883}884if (null != nextStackAcc) {885result ^= nextStackAcc.hashCode();886}887}888return result;889}890891/**892* Answers the DomainCombiner for the receiver.893*894* @return the DomainCombiner or null895*896* @exception java.security.AccessControlException thrown897* when the caller doesn't have the "getDomainCombiner" SecurityPermission898*/899public DomainCombiner getDomainCombiner() {900@SuppressWarnings("removal")901SecurityManager security = System.getSecurityManager();902if (security != null)903security.checkPermission(SecurityConstants.GET_COMBINER_PERMISSION);904return domainCombiner;905}906907/**908* Answers the DomainCombiner for the receiver.909* This is for internal use without checking "getDomainCombiner" SecurityPermission.910*911* @return the DomainCombiner or null912*913*/914DomainCombiner getCombiner() {915return domainCombiner;916}917918/*919* Added to resolve: S6907662, CVE-2010-4465: System clipboard should ensure access restrictions920* Used internally:921* java.awt.AWTEvent922* java.awt.Component923* java.awt.EventQueue924* java.awt.MenuComponent925* java.awt.TrayIcon926* java.security.ProtectionDomain927* javax.swing.Timer928* javax.swing.TransferHandler929*/930ProtectionDomain[] getContext() {931return context;932}933934/*935* Added to resolve: S6907662, CVE-2010-4465: System clipboard should ensure access restrictions936* Called internally from java.security.ProtectionDomain937*/938AccessControlContext(ProtectionDomain[] domains, AccessControlContext acc) {939this.context = AccessController.toArrayOfProtectionDomains(domains, acc, 0);940this.authorizeState = STATE_AUTHORIZED;941this.containPrivilegedContext = true;942if ((null != acc) && (STATE_AUTHORIZED == acc.authorizeState)) {943// inherit the domain combiner when authorized944this.domainCombiner = acc.domainCombiner;945}946}947948/*949* Added to resolve: S6907662, CVE-2010-4465: System clipboard should ensure access restrictions950* Called internally from java.security.ProtectionDomain951*/952AccessControlContext optimize() {953return this;954}955956}957958959