/* * Copyright (c) 1997, 2015, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.ArrayList; import java.util.List; import sun.security.util.Debug; import sun.security.util.SecurityConstants; /** * An AccessControlContext is used to make system resource access decisions * based on the context it encapsulates. * *

More specifically, it encapsulates a context and * has a single method, {@code checkPermission}, * that is equivalent to the {@code checkPermission} method * in the AccessController class, with one difference: The AccessControlContext * {@code checkPermission} method makes access decisions based on the * context it encapsulates, * rather than that of the current execution thread. * *

Thus, the purpose of AccessControlContext is for those situations where * a security check that should be made within a given context * actually needs to be done from within a * different context (for example, from within a worker thread). * *

An AccessControlContext is created by calling the * {@code AccessController.getContext} method. * The {@code getContext} method takes a "snapshot" * of the current calling context, and places * it in an AccessControlContext object, which it returns. A sample call is * the following: * *

 *   AccessControlContext acc = AccessController.getContext()
 * 
* *

* Code within a different context can subsequently call the * {@code checkPermission} method on the * previously-saved AccessControlContext object. A sample call is the * following: * *

 *   acc.checkPermission(permission)
 * 
* * @see AccessController * * @author Roland Schemers */ public final class AccessControlContext { private ProtectionDomain context[]; // isPrivileged and isAuthorized are referenced by the VM - do not remove // or change their names private boolean isPrivileged; private boolean isAuthorized = false; // Note: This field is directly used by the virtual machine // native codes. Don't touch it. private AccessControlContext privilegedContext; private DomainCombiner combiner = null; // limited privilege scope private Permission permissions[]; private AccessControlContext parent; private boolean isWrapped; // is constrained by limited privilege scope? private boolean isLimited; private ProtectionDomain limitedContext[]; private static boolean debugInit = false; private static Debug debug = null; static Debug getDebug() { if (debugInit) return debug; else { if (Policy.isSet()) { debug = Debug.getInstance("access"); debugInit = true; } return debug; } } /** * Create an AccessControlContext with the given array of ProtectionDomains. * Context must not be null. Duplicate domains will be removed from the * context. * * @param context the ProtectionDomains associated with this context. * The non-duplicate domains are copied from the array. Subsequent * changes to the array will not affect this AccessControlContext. * @throws NullPointerException if {@code context} is {@code null} */ public AccessControlContext(ProtectionDomain context[]) { if (context.length == 0) { this.context = null; } else if (context.length == 1) { if (context[0] != null) { this.context = context.clone(); } else { this.context = null; } } else { List v = new ArrayList<>(context.length); for (int i =0; i< context.length; i++) { if ((context[i] != null) && (!v.contains(context[i]))) v.add(context[i]); } if (!v.isEmpty()) { this.context = new ProtectionDomain[v.size()]; this.context = v.toArray(this.context); } } } /** * Create a new {@code AccessControlContext} with the given * {@code AccessControlContext} and {@code DomainCombiner}. * This constructor associates the provided * {@code DomainCombiner} with the provided * {@code AccessControlContext}. * *

* * @param acc the {@code AccessControlContext} associated * with the provided {@code DomainCombiner}. * * @param combiner the {@code DomainCombiner} to be associated * with the provided {@code AccessControlContext}. * * @exception NullPointerException if the provided * {@code context} is {@code null}. * * @exception SecurityException if a security manager is installed and the * caller does not have the "createAccessControlContext" * {@link SecurityPermission} * @since 1.3 */ public AccessControlContext(AccessControlContext acc, DomainCombiner combiner) { this(acc, combiner, false); } /** * package private to allow calls from ProtectionDomain without performing * the security check for {@linkplain SecurityConstants.CREATE_ACC_PERMISSION} * permission */ AccessControlContext(AccessControlContext acc, DomainCombiner combiner, boolean preauthorized) { if (!preauthorized) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(SecurityConstants.CREATE_ACC_PERMISSION); this.isAuthorized = true; } } else { this.isAuthorized = true; } this.context = acc.context; // we do not need to run the combine method on the // provided ACC. it was already "combined" when the // context was originally retrieved. // // at this point in time, we simply throw away the old // combiner and use the newly provided one. this.combiner = combiner; } /** * package private for AccessController * * This "argument wrapper" context will be passed as the actual context * parameter on an internal doPrivileged() call used in the implementation. */ AccessControlContext(ProtectionDomain caller, DomainCombiner combiner, AccessControlContext parent, AccessControlContext context, Permission[] perms) { /* * Combine the domains from the doPrivileged() context into our * wrapper context, if necessary. */ ProtectionDomain[] callerPDs = null; if (caller != null) { callerPDs = new ProtectionDomain[] { caller }; } if (context != null) { if (combiner != null) { this.context = combiner.combine(callerPDs, context.context); } else { this.context = combine(callerPDs, context.context); } } else { /* * Call combiner even if there is seemingly nothing to combine. */ if (combiner != null) { this.context = combiner.combine(callerPDs, null); } else { this.context = combine(callerPDs, null); } } this.combiner = combiner; Permission[] tmp = null; if (perms != null) { tmp = new Permission[perms.length]; for (int i=0; i < perms.length; i++) { if (perms[i] == null) { throw new NullPointerException("permission can't be null"); } /* * An AllPermission argument is equivalent to calling * doPrivileged() without any limit permissions. */ if (perms[i].getClass() == AllPermission.class) { parent = null; } tmp[i] = perms[i]; } } /* * For a doPrivileged() with limited privilege scope, initialize * the relevant fields. * * The limitedContext field contains the union of all domains which * are enclosed by this limited privilege scope. In other words, * it contains all of the domains which could potentially be checked * if none of the limiting permissions implied a requested permission. */ if (parent != null) { this.limitedContext = combine(parent.context, parent.limitedContext); this.isLimited = true; this.isWrapped = true; this.permissions = tmp; this.parent = parent; this.privilegedContext = context; // used in checkPermission2() } this.isAuthorized = true; } /** * package private constructor for AccessController.getContext() */ AccessControlContext(ProtectionDomain context[], boolean isPrivileged) { this.context = context; this.isPrivileged = isPrivileged; this.isAuthorized = true; } /** * Constructor for JavaSecurityAccess.doIntersectionPrivilege() */ AccessControlContext(ProtectionDomain[] context, AccessControlContext privilegedContext) { this.context = context; this.privilegedContext = privilegedContext; this.isPrivileged = true; } /** * Returns this context's context. */ ProtectionDomain[] getContext() { return context; } /** * Returns true if this context is privileged. */ boolean isPrivileged() { return isPrivileged; } /** * get the assigned combiner from the privileged or inherited context */ DomainCombiner getAssignedCombiner() { AccessControlContext acc; if (isPrivileged) { acc = privilegedContext; } else { acc = AccessController.getInheritedAccessControlContext(); } if (acc != null) { return acc.combiner; } return null; } /** * Get the {@code DomainCombiner} associated with this * {@code AccessControlContext}. * *

* * @return the {@code DomainCombiner} associated with this * {@code AccessControlContext}, or {@code null} * if there is none. * * @exception SecurityException if a security manager is installed and * the caller does not have the "getDomainCombiner" * {@link SecurityPermission} * @since 1.3 */ public DomainCombiner getDomainCombiner() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(SecurityConstants.GET_COMBINER_PERMISSION); } return getCombiner(); } /** * package private for AccessController */ DomainCombiner getCombiner() { return combiner; } boolean isAuthorized() { return isAuthorized; } /** * Determines whether the access request indicated by the * specified permission should be allowed or denied, based on * the security policy currently in effect, and the context in * this object. The request is allowed only if every ProtectionDomain * in the context implies the permission. Otherwise the request is * denied. * *

* This method quietly returns if the access request * is permitted, or throws a suitable AccessControlException otherwise. * * @param perm the requested permission. * * @exception AccessControlException if the specified permission * is not permitted, based on the current security policy and the * context encapsulated by this object. * @exception NullPointerException if the permission to check for is null. */ public void checkPermission(Permission perm) throws AccessControlException { boolean dumpDebug = false; if (perm == null) { throw new NullPointerException("permission can't be null"); } if (getDebug() != null) { // If "codebase" is not specified, we dump the info by default. dumpDebug = !Debug.isOn("codebase="); if (!dumpDebug) { // If "codebase" is specified, only dump if the specified code // value is in the stack. for (int i = 0; context != null && i < context.length; i++) { if (context[i].getCodeSource() != null && context[i].getCodeSource().getLocation() != null && Debug.isOn("codebase=" + context[i].getCodeSource().getLocation().toString())) { dumpDebug = true; break; } } } dumpDebug &= !Debug.isOn("permission=") || Debug.isOn("permission=" + perm.getClass().getCanonicalName()); if (dumpDebug && Debug.isOn("stack")) { Thread.dumpStack(); } if (dumpDebug && Debug.isOn("domain")) { if (context == null) { debug.println("domain (context is null)"); } else { for (int i=0; i< context.length; i++) { debug.println("domain "+i+" "+context[i]); } } } } /* * iterate through the ProtectionDomains in the context. * Stop at the first one that doesn't allow the * requested permission (throwing an exception). * */ /* if ctxt is null, all we had on the stack were system domains, or the first domain was a Privileged system domain. This is to make the common case for system code very fast */ if (context == null) { checkPermission2(perm); return; } for (int i=0; i< context.length; i++) { if (context[i] != null && !context[i].implies(perm)) { if (dumpDebug) { debug.println("access denied " + perm); } if (Debug.isOn("failure") && debug != null) { // Want to make sure this is always displayed for failure, // but do not want to display again if already displayed // above. if (!dumpDebug) { debug.println("access denied " + perm); } Thread.dumpStack(); final ProtectionDomain pd = context[i]; final Debug db = debug; AccessController.doPrivileged (new PrivilegedAction() { public Void run() { db.println("domain that failed "+pd); return null; } }); } throw new AccessControlException("access denied "+perm, perm); } } // allow if all of them allowed access if (dumpDebug) { debug.println("access allowed "+perm); } checkPermission2(perm); } /* * Check the domains associated with the limited privilege scope. */ private void checkPermission2(Permission perm) { if (!isLimited) { return; } /* * Check the doPrivileged() context parameter, if present. */ if (privilegedContext != null) { privilegedContext.checkPermission2(perm); } /* * Ignore the limited permissions and parent fields of a wrapper * context since they were already carried down into the unwrapped * context. */ if (isWrapped) { return; } /* * Try to match any limited privilege scope. */ if (permissions != null) { Class permClass = perm.getClass(); for (int i=0; i < permissions.length; i++) { Permission limit = permissions[i]; if (limit.getClass().equals(permClass) && limit.implies(perm)) { return; } } } /* * Check the limited privilege scope up the call stack or the inherited * parent thread call stack of this ACC. */ if (parent != null) { /* * As an optimization, if the parent context is the inherited call * stack context from a parent thread then checking the protection * domains of the parent context is redundant since they have * already been merged into the child thread's context by * optimize(). When parent is set to an inherited context this * context was not directly created by a limited scope * doPrivileged() and it does not have its own limited permissions. */ if (permissions == null) { parent.checkPermission2(perm); } else { parent.checkPermission(perm); } } } /** * Take the stack-based context (this) and combine it with the * privileged or inherited context, if need be. Any limited * privilege scope is flagged regardless of whether the assigned * context comes from an immediately enclosing limited doPrivileged(). * The limited privilege scope can indirectly flow from the inherited * parent thread or an assigned context previously captured by getContext(). */ AccessControlContext optimize() { // the assigned (privileged or inherited) context AccessControlContext acc; DomainCombiner combiner = null; AccessControlContext parent = null; Permission[] permissions = null; if (isPrivileged) { acc = privilegedContext; if (acc != null) { /* * If the context is from a limited scope doPrivileged() then * copy the permissions and parent fields out of the wrapper * context that was created to hold them. */ if (acc.isWrapped) { permissions = acc.permissions; parent = acc.parent; } } } else { acc = AccessController.getInheritedAccessControlContext(); if (acc != null) { /* * If the inherited context is constrained by a limited scope * doPrivileged() then set it as our parent so we will process * the non-domain-related state. */ if (acc.isLimited) { parent = acc; } } } // this.context could be null if only system code is on the stack; // in that case, ignore the stack context boolean skipStack = (context == null); // acc.context could be null if only system code was involved; // in that case, ignore the assigned context boolean skipAssigned = (acc == null || acc.context == null); ProtectionDomain[] assigned = (skipAssigned) ? null : acc.context; ProtectionDomain[] pd; // if there is no enclosing limited privilege scope on the stack or // inherited from a parent thread boolean skipLimited = ((acc == null || !acc.isWrapped) && parent == null); if (acc != null && acc.combiner != null) { // let the assigned acc's combiner do its thing if (getDebug() != null) { debug.println("AccessControlContext invoking the Combiner"); } // No need to clone current and assigned.context // combine() will not update them combiner = acc.combiner; pd = combiner.combine(context, assigned); } else { if (skipStack) { if (skipAssigned) { calculateFields(acc, parent, permissions); return this; } else if (skipLimited) { return acc; } } else if (assigned != null) { if (skipLimited) { // optimization: if there is a single stack domain and // that domain is already in the assigned context; no // need to combine if (context.length == 1 && context[0] == assigned[0]) { return acc; } } } pd = combine(context, assigned); if (skipLimited && !skipAssigned && pd == assigned) { return acc; } else if (skipAssigned && pd == context) { calculateFields(acc, parent, permissions); return this; } } // Reuse existing ACC this.context = pd; this.combiner = combiner; this.isPrivileged = false; calculateFields(acc, parent, permissions); return this; } /* * Combine the current (stack) and assigned domains. */ private static ProtectionDomain[] combine(ProtectionDomain[]current, ProtectionDomain[] assigned) { // current could be null if only system code is on the stack; // in that case, ignore the stack context boolean skipStack = (current == null); // assigned could be null if only system code was involved; // in that case, ignore the assigned context boolean skipAssigned = (assigned == null); int slen = (skipStack) ? 0 : current.length; // optimization: if there is no assigned context and the stack length // is less then or equal to two; there is no reason to compress the // stack context, it already is if (skipAssigned && slen <= 2) { return current; } int n = (skipAssigned) ? 0 : assigned.length; // now we combine both of them, and create a new context ProtectionDomain pd[] = new ProtectionDomain[slen + n]; // first copy in the assigned context domains, no need to compress if (!skipAssigned) { System.arraycopy(assigned, 0, pd, 0, n); } // now add the stack context domains, discarding nulls and duplicates outer: for (int i = 0; i < slen; i++) { ProtectionDomain sd = current[i]; if (sd != null) { for (int j = 0; j < n; j++) { if (sd == pd[j]) { continue outer; } } pd[n++] = sd; } } // if length isn't equal, we need to shorten the array if (n != pd.length) { // optimization: if we didn't really combine anything if (!skipAssigned && n == assigned.length) { return assigned; } else if (skipAssigned && n == slen) { return current; } ProtectionDomain tmp[] = new ProtectionDomain[n]; System.arraycopy(pd, 0, tmp, 0, n); pd = tmp; } return pd; } /* * Calculate the additional domains that could potentially be reached via * limited privilege scope. Mark the context as being subject to limited * privilege scope unless the reachable domains (if any) are already * contained in this domain context (in which case any limited * privilege scope checking would be redundant). */ private void calculateFields(AccessControlContext assigned, AccessControlContext parent, Permission[] permissions) { ProtectionDomain[] parentLimit = null; ProtectionDomain[] assignedLimit = null; ProtectionDomain[] newLimit; parentLimit = (parent != null)? parent.limitedContext: null; assignedLimit = (assigned != null)? assigned.limitedContext: null; newLimit = combine(parentLimit, assignedLimit); if (newLimit != null) { if (context == null || !containsAllPDs(newLimit, context)) { this.limitedContext = newLimit; this.permissions = permissions; this.parent = parent; this.isLimited = true; } } } /** * Checks two AccessControlContext objects for equality. * Checks that obj is * an AccessControlContext and has the same set of ProtectionDomains * as this context. *

* @param obj the object we are testing for equality with this object. * @return true if obj is an AccessControlContext, and has the * same set of ProtectionDomains as this context, false otherwise. */ public boolean equals(Object obj) { if (obj == this) return true; if (! (obj instanceof AccessControlContext)) return false; AccessControlContext that = (AccessControlContext) obj; if (!equalContext(that)) return false; if (!equalLimitedContext(that)) return false; return true; } /* * Compare for equality based on state that is free of limited * privilege complications. */ private boolean equalContext(AccessControlContext that) { if (!equalPDs(this.context, that.context)) return false; if (this.combiner == null && that.combiner != null) return false; if (this.combiner != null && !this.combiner.equals(that.combiner)) return false; return true; } private boolean equalPDs(ProtectionDomain[] a, ProtectionDomain[] b) { if (a == null) { return (b == null); } if (b == null) return false; if (!(containsAllPDs(a, b) && containsAllPDs(b, a))) return false; return true; } /* * Compare for equality based on state that is captured during a * call to AccessController.getContext() when a limited privilege * scope is in effect. */ private boolean equalLimitedContext(AccessControlContext that) { if (that == null) return false; /* * If neither instance has limited privilege scope then we're done. */ if (!this.isLimited && !that.isLimited) return true; /* * If only one instance has limited privilege scope then we're done. */ if (!(this.isLimited && that.isLimited)) return false; /* * Wrapped instances should never escape outside the implementation * this class and AccessController so this will probably never happen * but it only makes any sense to compare if they both have the same * isWrapped state. */ if ((this.isWrapped && !that.isWrapped) || (!this.isWrapped && that.isWrapped)) { return false; } if (this.permissions == null && that.permissions != null) return false; if (this.permissions != null && that.permissions == null) return false; if (!(this.containsAllLimits(that) && that.containsAllLimits(this))) return false; /* * Skip through any wrapped contexts. */ AccessControlContext thisNextPC = getNextPC(this); AccessControlContext thatNextPC = getNextPC(that); /* * The protection domains and combiner of a privilegedContext are * not relevant because they have already been included in the context * of this instance by optimize() so we only care about any limited * privilege state they may have. */ if (thisNextPC == null && thatNextPC != null && thatNextPC.isLimited) return false; if (thisNextPC != null && !thisNextPC.equalLimitedContext(thatNextPC)) return false; if (this.parent == null && that.parent != null) return false; if (this.parent != null && !this.parent.equals(that.parent)) return false; return true; } /* * Follow the privilegedContext link making our best effort to skip * through any wrapper contexts. */ private static AccessControlContext getNextPC(AccessControlContext acc) { while (acc != null && acc.privilegedContext != null) { acc = acc.privilegedContext; if (!acc.isWrapped) return acc; } return null; } private static boolean containsAllPDs(ProtectionDomain[] thisContext, ProtectionDomain[] thatContext) { boolean match = false; // // ProtectionDomains within an ACC currently cannot be null // and this is enforced by the constructor and the various // optimize methods. However, historically this logic made attempts // to support the notion of a null PD and therefore this logic continues // to support that notion. ProtectionDomain thisPd; for (int i = 0; i < thisContext.length; i++) { match = false; if ((thisPd = thisContext[i]) == null) { for (int j = 0; (j < thatContext.length) && !match; j++) { match = (thatContext[j] == null); } } else { Class thisPdClass = thisPd.getClass(); ProtectionDomain thatPd; for (int j = 0; (j < thatContext.length) && !match; j++) { thatPd = thatContext[j]; // Class check required to avoid PD exposure (4285406) match = (thatPd != null && thisPdClass == thatPd.getClass() && thisPd.equals(thatPd)); } } if (!match) return false; } return match; } private boolean containsAllLimits(AccessControlContext that) { boolean match = false; Permission thisPerm; if (this.permissions == null && that.permissions == null) return true; for (int i = 0; i < this.permissions.length; i++) { Permission limit = this.permissions[i]; Class limitClass = limit.getClass(); match = false; for (int j = 0; (j < that.permissions.length) && !match; j++) { Permission perm = that.permissions[j]; match = (limitClass.equals(perm.getClass()) && limit.equals(perm)); } if (!match) return false; } return match; } /** * Returns the hash code value for this context. The hash code * is computed by exclusive or-ing the hash code of all the protection * domains in the context together. * * @return a hash code value for this context. */ public int hashCode() { int hashCode = 0; if (context == null) return hashCode; for (int i =0; i < context.length; i++) { if (context[i] != null) hashCode ^= context[i].hashCode(); } return hashCode; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2900 Content-Disposition: inline; filename="AccessControlException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "a4f2a7803adbbc264355da9c017cf13f05f4969d" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** *

This exception is thrown by the AccessController to indicate * that a requested access (to a critical system resource such as the * file system or the network) is denied. * *

The reason to deny access can vary. For example, the requested * permission might be of an incorrect type, contain an invalid * value, or request access that is not allowed according to the * security policy. Such information should be given whenever * possible at the time the exception is thrown. * * @author Li Gong * @author Roland Schemers */ public class AccessControlException extends SecurityException { private static final long serialVersionUID = 5138225684096988535L; // the permission that caused the exception to be thrown. private Permission perm; /** * Constructs an {@code AccessControlException} with the * specified, detailed message. * * @param s the detail message. */ public AccessControlException(String s) { super(s); } /** * Constructs an {@code AccessControlException} with the * specified, detailed message, and the requested permission that caused * the exception. * * @param s the detail message. * @param p the permission that caused the exception. */ public AccessControlException(String s, Permission p) { super(s); perm = p; } /** * Gets the Permission object associated with this exception, or * null if there was no corresponding Permission object. * * @return the Permission object. */ public Permission getPermission() { return perm; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 37103 Content-Disposition: inline; filename="AccessController.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "00e084ca96b8821a6e4cf6bccf6cd1672dd89150" /* * Copyright (c) 1997, 2019, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import sun.security.util.Debug; import sun.reflect.CallerSensitive; import sun.reflect.Reflection; /** *

The AccessController class is used for access control operations * and decisions. * *

More specifically, the AccessController class is used for * three purposes: * *

* *

The {@link #checkPermission(Permission) checkPermission} method * determines whether the access request indicated by a specified * permission should be granted or denied. A sample call appears * below. In this example, {@code checkPermission} will determine * whether or not to grant "read" access to the file named "testFile" in * the "/temp" directory. * *

 *
 * FilePermission perm = new FilePermission("/temp/testFile", "read");
 * AccessController.checkPermission(perm);
 *
 * 
* *

If a requested access is allowed, * {@code checkPermission} returns quietly. If denied, an * AccessControlException is * thrown. AccessControlException can also be thrown if the requested * permission is of an incorrect type or contains an invalid value. * Such information is given whenever possible. * * Suppose the current thread traversed m callers, in the order of caller 1 * to caller 2 to caller m. Then caller m invoked the * {@code checkPermission} method. * The {@code checkPermission} method determines whether access * is granted or denied based on the following algorithm: * *

 {@code
 * for (int i = m; i > 0; i--) {
 *
 *     if (caller i's domain does not have the permission)
 *         throw AccessControlException
 *
 *     else if (caller i is marked as privileged) {
 *         if (a context was specified in the call to doPrivileged)
 *             context.checkPermission(permission)
 *         if (limited permissions were specified in the call to doPrivileged) {
 *             for (each limited permission) {
 *                 if (the limited permission implies the requested permission)
 *                     return;
 *             }
 *         } else
 *             return;
 *     }
 * }
 *
 * // Next, check the context inherited when the thread was created.
 * // Whenever a new thread is created, the AccessControlContext at
 * // that time is stored and associated with the new thread, as the
 * // "inherited" context.
 *
 * inheritedContext.checkPermission(permission);
 * }
* *

A caller can be marked as being "privileged" * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below). * When making access control decisions, the {@code checkPermission} * method stops checking if it reaches a caller that * was marked as "privileged" via a {@code doPrivileged} * call without a context argument (see below for information about a * context argument). If that caller's domain has the * specified permission and at least one limiting permission argument (if any) * implies the requested permission, no further checking is done and * {@code checkPermission} * returns quietly, indicating that the requested access is allowed. * If that domain does not have the specified permission, an exception * is thrown, as usual. If the caller's domain had the specified permission * but it was not implied by any limiting permission arguments given in the call * to {@code doPrivileged} then the permission checking continues * until there are no more callers or another {@code doPrivileged} * call matches the requested permission and returns normally. * *

The normal use of the "privileged" feature is as follows. If you * don't need to return a value from within the "privileged" block, do * the following: * *

 {@code
 * somemethod() {
 *     ...normal code here...
 *     AccessController.doPrivileged(new PrivilegedAction() {
 *         public Void run() {
 *             // privileged code goes here, for example:
 *             System.loadLibrary("awt");
 *             return null; // nothing to return
 *         }
 *     });
 *     ...normal code here...
 * }}
* *

* PrivilegedAction is an interface with a single method, named * {@code run}. * The above example shows creation of an implementation * of that interface; a concrete implementation of the * {@code run} method is supplied. * When the call to {@code doPrivileged} is made, an * instance of the PrivilegedAction implementation is passed * to it. The {@code doPrivileged} method calls the * {@code run} method from the PrivilegedAction * implementation after enabling privileges, and returns the * {@code run} method's return value as the * {@code doPrivileged} return value (which is * ignored in this example). * *

If you need to return a value, you can do something like the following: * *

 {@code
 * somemethod() {
 *     ...normal code here...
 *     String user = AccessController.doPrivileged(
 *         new PrivilegedAction() {
 *         public String run() {
 *             return System.getProperty("user.name");
 *             }
 *         });
 *     ...normal code here...
 * }}
* *

If the action performed in your {@code run} method could * throw a "checked" exception (those listed in the {@code throws} clause * of a method), then you need to use the * {@code PrivilegedExceptionAction} interface instead of the * {@code PrivilegedAction} interface: * *

 {@code
 * somemethod() throws FileNotFoundException {
 *     ...normal code here...
 *     try {
 *         FileInputStream fis = AccessController.doPrivileged(
 *         new PrivilegedExceptionAction() {
 *             public FileInputStream run() throws FileNotFoundException {
 *                 return new FileInputStream("someFile");
 *             }
 *         });
 *     } catch (PrivilegedActionException e) {
 *         // e.getException() should be an instance of FileNotFoundException,
 *         // as only "checked" exceptions will be "wrapped" in a
 *         // PrivilegedActionException.
 *         throw (FileNotFoundException) e.getException();
 *     }
 *     ...normal code here...
 *  }}
* *

Be *very* careful in your use of the "privileged" construct, and * always remember to make the privileged code section as small as possible. * You can pass {@code Permission} arguments to further limit the * scope of the "privilege" (see below). * * *

Note that {@code checkPermission} always performs security checks * within the context of the currently executing thread. * Sometimes a security check that should be made within a given context * will actually need to be done from within a * different context (for example, from within a worker thread). * The {@link #getContext() getContext} method and * AccessControlContext class are provided * for this situation. The {@code getContext} method takes a "snapshot" * of the current calling context, and places * it in an AccessControlContext object, which it returns. A sample call is * the following: * *

 *
 * AccessControlContext acc = AccessController.getContext()
 *
 * 
* *

* AccessControlContext itself has a {@code checkPermission} method * that makes access decisions based on the context it encapsulates, * rather than that of the current execution thread. * Code within a different context can thus call that method on the * previously-saved AccessControlContext object. A sample call is the * following: * *

 *
 * acc.checkPermission(permission)
 *
 * 
* *

There are also times where you don't know a priori which permissions * to check the context against. In these cases you can use the * doPrivileged method that takes a context. You can also limit the scope * of the privileged code by passing additional {@code Permission} * parameters. * *

 {@code
 * somemethod() {
 *     AccessController.doPrivileged(new PrivilegedAction() {
 *         public Object run() {
 *             // Code goes here. Any permission checks within this
 *             // run method will require that the intersection of the
 *             // caller's protection domain and the snapshot's
 *             // context have the desired permission. If a requested
 *             // permission is not implied by the limiting FilePermission
 *             // argument then checking of the thread continues beyond the
 *             // caller of doPrivileged.
 *         }
 *     }, acc, new FilePermission("/temp/*", read));
 *     ...normal code here...
 * }}
 * 

Passing a limiting {@code Permission} argument of an instance of * {@code AllPermission} is equivalent to calling the equivalent * {@code doPrivileged} method without limiting {@code Permission} * arguments. Passing a zero length array of {@code Permission} disables * the code privileges so that checking always continues beyond the caller of * that {@code doPrivileged} method. * * @see AccessControlContext * * @author Li Gong * @author Roland Schemers */ public final class AccessController { /** * Don't allow anyone to instantiate an AccessController */ private AccessController() { } /** * Performs the specified {@code PrivilegedAction} with privileges * enabled. The action is performed with all of the permissions * possessed by the caller's protection domain. * *

If the action's {@code run} method throws an (unchecked) * exception, it will propagate through this method. * *

Note that any DomainCombiner associated with the current * AccessControlContext will be ignored while the action is performed. * * @param the type of the value returned by the PrivilegedAction's * {@code run} method. * * @param action the action to be performed. * * @return the value returned by the action's {@code run} method. * * @exception NullPointerException if the action is {@code null} * * @see #doPrivileged(PrivilegedAction,AccessControlContext) * @see #doPrivileged(PrivilegedExceptionAction) * @see #doPrivilegedWithCombiner(PrivilegedAction) * @see java.security.DomainCombiner */ @CallerSensitive public static native T doPrivileged(PrivilegedAction action); /** * Performs the specified {@code PrivilegedAction} with privileges * enabled. The action is performed with all of the permissions * possessed by the caller's protection domain. * *

If the action's {@code run} method throws an (unchecked) * exception, it will propagate through this method. * *

This method preserves the current AccessControlContext's * DomainCombiner (which may be null) while the action is performed. * * @param the type of the value returned by the PrivilegedAction's * {@code run} method. * * @param action the action to be performed. * * @return the value returned by the action's {@code run} method. * * @exception NullPointerException if the action is {@code null} * * @see #doPrivileged(PrivilegedAction) * @see java.security.DomainCombiner * * @since 1.6 */ @CallerSensitive public static T doPrivilegedWithCombiner(PrivilegedAction action) { AccessControlContext acc = getStackAccessControlContext(); if (acc == null) { return AccessController.doPrivileged(action); } DomainCombiner dc = acc.getAssignedCombiner(); return AccessController.doPrivileged(action, preserveCombiner(dc, Reflection.getCallerClass())); } /** * Performs the specified {@code PrivilegedAction} with privileges * enabled and restricted by the specified {@code AccessControlContext}. * The action is performed with the intersection of the permissions * possessed by the caller's protection domain, and those possessed * by the domains represented by the specified {@code AccessControlContext}. *

* If the action's {@code run} method throws an (unchecked) exception, * it will propagate through this method. *

* If a security manager is installed and the specified * {@code AccessControlContext} was not created by system code and the * caller's {@code ProtectionDomain} has not been granted the * {@literal "createAccessControlContext"} * {@link java.security.SecurityPermission}, then the action is performed * with no permissions. * * @param the type of the value returned by the PrivilegedAction's * {@code run} method. * @param action the action to be performed. * @param context an access control context * representing the restriction to be applied to the * caller's domain's privileges before performing * the specified action. If the context is * {@code null}, then no additional restriction is applied. * * @return the value returned by the action's {@code run} method. * * @exception NullPointerException if the action is {@code null} * * @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) */ @CallerSensitive public static native T doPrivileged(PrivilegedAction action, AccessControlContext context); /** * Performs the specified {@code PrivilegedAction} with privileges * enabled and restricted by the specified * {@code AccessControlContext} and with a privilege scope limited * by specified {@code Permission} arguments. * * The action is performed with the intersection of the permissions * possessed by the caller's protection domain, and those possessed * by the domains represented by the specified * {@code AccessControlContext}. *

* If the action's {@code run} method throws an (unchecked) exception, * it will propagate through this method. *

* If a security manager is installed and the specified * {@code AccessControlContext} was not created by system code and the * caller's {@code ProtectionDomain} has not been granted the * {@literal "createAccessControlContext"} * {@link java.security.SecurityPermission}, then the action is performed * with no permissions. * * @param the type of the value returned by the PrivilegedAction's * {@code run} method. * @param action the action to be performed. * @param context an access control context * representing the restriction to be applied to the * caller's domain's privileges before performing * the specified action. If the context is * {@code null}, * then no additional restriction is applied. * @param perms the {@code Permission} arguments which limit the * scope of the caller's privileges. The number of arguments * is variable. * * @return the value returned by the action's {@code run} method. * * @throws NullPointerException if action or perms or any element of * perms is {@code null} * * @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) * * @since 1.8 */ @CallerSensitive public static T doPrivileged(PrivilegedAction action, AccessControlContext context, Permission... perms) { AccessControlContext parent = getContext(); if (perms == null) { throw new NullPointerException("null permissions parameter"); } Class caller = Reflection.getCallerClass(); DomainCombiner dc = (context == null) ? null : context.getCombiner(); return AccessController.doPrivileged(action, createWrapper(dc, caller, parent, context, perms)); } /** * Performs the specified {@code PrivilegedAction} with privileges * enabled and restricted by the specified * {@code AccessControlContext} and with a privilege scope limited * by specified {@code Permission} arguments. * * The action is performed with the intersection of the permissions * possessed by the caller's protection domain, and those possessed * by the domains represented by the specified * {@code AccessControlContext}. *

* If the action's {@code run} method throws an (unchecked) exception, * it will propagate through this method. * *

This method preserves the current AccessControlContext's * DomainCombiner (which may be null) while the action is performed. *

* If a security manager is installed and the specified * {@code AccessControlContext} was not created by system code and the * caller's {@code ProtectionDomain} has not been granted the * {@literal "createAccessControlContext"} * {@link java.security.SecurityPermission}, then the action is performed * with no permissions. * * @param the type of the value returned by the PrivilegedAction's * {@code run} method. * @param action the action to be performed. * @param context an access control context * representing the restriction to be applied to the * caller's domain's privileges before performing * the specified action. If the context is * {@code null}, * then no additional restriction is applied. * @param perms the {@code Permission} arguments which limit the * scope of the caller's privileges. The number of arguments * is variable. * * @return the value returned by the action's {@code run} method. * * @throws NullPointerException if action or perms or any element of * perms is {@code null} * * @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) * @see java.security.DomainCombiner * * @since 1.8 */ @CallerSensitive public static T doPrivilegedWithCombiner(PrivilegedAction action, AccessControlContext context, Permission... perms) { AccessControlContext parent = getContext(); DomainCombiner dc = parent.getCombiner(); if (dc == null && context != null) { dc = context.getCombiner(); } if (perms == null) { throw new NullPointerException("null permissions parameter"); } Class caller = Reflection.getCallerClass(); return AccessController.doPrivileged(action, createWrapper(dc, caller, parent, context, perms)); } /** * Performs the specified {@code PrivilegedExceptionAction} with * privileges enabled. The action is performed with all of the * permissions possessed by the caller's protection domain. * *

If the action's {@code run} method throws an unchecked * exception, it will propagate through this method. * *

Note that any DomainCombiner associated with the current * AccessControlContext will be ignored while the action is performed. * * @param the type of the value returned by the * PrivilegedExceptionAction's {@code run} method. * * @param action the action to be performed * * @return the value returned by the action's {@code run} method * * @exception PrivilegedActionException if the specified action's * {@code run} method threw a checked exception * @exception NullPointerException if the action is {@code null} * * @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction) * @see java.security.DomainCombiner */ @CallerSensitive public static native T doPrivileged(PrivilegedExceptionAction action) throws PrivilegedActionException; /** * Performs the specified {@code PrivilegedExceptionAction} with * privileges enabled. The action is performed with all of the * permissions possessed by the caller's protection domain. * *

If the action's {@code run} method throws an unchecked * exception, it will propagate through this method. * *

This method preserves the current AccessControlContext's * DomainCombiner (which may be null) while the action is performed. * * @param the type of the value returned by the * PrivilegedExceptionAction's {@code run} method. * * @param action the action to be performed. * * @return the value returned by the action's {@code run} method * * @exception PrivilegedActionException if the specified action's * {@code run} method threw a checked exception * @exception NullPointerException if the action is {@code null} * * @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) * @see java.security.DomainCombiner * * @since 1.6 */ @CallerSensitive public static T doPrivilegedWithCombiner(PrivilegedExceptionAction action) throws PrivilegedActionException { AccessControlContext acc = getStackAccessControlContext(); if (acc == null) { return AccessController.doPrivileged(action); } DomainCombiner dc = acc.getAssignedCombiner(); return AccessController.doPrivileged(action, preserveCombiner(dc, Reflection.getCallerClass())); } /** * preserve the combiner across the doPrivileged call */ private static AccessControlContext preserveCombiner(DomainCombiner combiner, Class caller) { return createWrapper(combiner, caller, null, null, null); } /** * Create a wrapper to contain the limited privilege scope data. */ private static AccessControlContext createWrapper(DomainCombiner combiner, Class caller, AccessControlContext parent, AccessControlContext context, Permission[] perms) { ProtectionDomain callerPD = getCallerPD(caller); // check if caller is authorized to create context if (context != null && !context.isAuthorized() && System.getSecurityManager() != null && !callerPD.impliesCreateAccessControlContext()) { ProtectionDomain nullPD = new ProtectionDomain(null, null); return new AccessControlContext(new ProtectionDomain[] { nullPD }); } else { return new AccessControlContext(callerPD, combiner, parent, context, perms); } } private static ProtectionDomain getCallerPD(final Class caller) { ProtectionDomain callerPd = doPrivileged (new PrivilegedAction() { public ProtectionDomain run() { return caller.getProtectionDomain(); } }); return callerPd; } /** * Performs the specified {@code PrivilegedExceptionAction} with * privileges enabled and restricted by the specified * {@code AccessControlContext}. The action is performed with the * intersection of the permissions possessed by the caller's * protection domain, and those possessed by the domains represented by the * specified {@code AccessControlContext}. *

* If the action's {@code run} method throws an unchecked * exception, it will propagate through this method. *

* If a security manager is installed and the specified * {@code AccessControlContext} was not created by system code and the * caller's {@code ProtectionDomain} has not been granted the * {@literal "createAccessControlContext"} * {@link java.security.SecurityPermission}, then the action is performed * with no permissions. * * @param the type of the value returned by the * PrivilegedExceptionAction's {@code run} method. * @param action the action to be performed * @param context an access control context * representing the restriction to be applied to the * caller's domain's privileges before performing * the specified action. If the context is * {@code null}, then no additional restriction is applied. * * @return the value returned by the action's {@code run} method * * @exception PrivilegedActionException if the specified action's * {@code run} method threw a checked exception * @exception NullPointerException if the action is {@code null} * * @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedAction,AccessControlContext) */ @CallerSensitive public static native T doPrivileged(PrivilegedExceptionAction action, AccessControlContext context) throws PrivilegedActionException; /** * Performs the specified {@code PrivilegedExceptionAction} with * privileges enabled and restricted by the specified * {@code AccessControlContext} and with a privilege scope limited by * specified {@code Permission} arguments. * * The action is performed with the intersection of the permissions * possessed by the caller's protection domain, and those possessed * by the domains represented by the specified * {@code AccessControlContext}. *

* If the action's {@code run} method throws an (unchecked) exception, * it will propagate through this method. *

* If a security manager is installed and the specified * {@code AccessControlContext} was not created by system code and the * caller's {@code ProtectionDomain} has not been granted the * {@literal "createAccessControlContext"} * {@link java.security.SecurityPermission}, then the action is performed * with no permissions. * * @param the type of the value returned by the * PrivilegedExceptionAction's {@code run} method. * @param action the action to be performed. * @param context an access control context * representing the restriction to be applied to the * caller's domain's privileges before performing * the specified action. If the context is * {@code null}, * then no additional restriction is applied. * @param perms the {@code Permission} arguments which limit the * scope of the caller's privileges. The number of arguments * is variable. * * @return the value returned by the action's {@code run} method. * * @throws PrivilegedActionException if the specified action's * {@code run} method threw a checked exception * @throws NullPointerException if action or perms or any element of * perms is {@code null} * * @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedAction,AccessControlContext) * * @since 1.8 */ @CallerSensitive public static T doPrivileged(PrivilegedExceptionAction action, AccessControlContext context, Permission... perms) throws PrivilegedActionException { AccessControlContext parent = getContext(); if (perms == null) { throw new NullPointerException("null permissions parameter"); } Class caller = Reflection.getCallerClass(); DomainCombiner dc = (context == null) ? null : context.getCombiner(); return AccessController.doPrivileged(action, createWrapper(dc, caller, parent, context, perms)); } /** * Performs the specified {@code PrivilegedExceptionAction} with * privileges enabled and restricted by the specified * {@code AccessControlContext} and with a privilege scope limited by * specified {@code Permission} arguments. * * The action is performed with the intersection of the permissions * possessed by the caller's protection domain, and those possessed * by the domains represented by the specified * {@code AccessControlContext}. *

* If the action's {@code run} method throws an (unchecked) exception, * it will propagate through this method. * *

This method preserves the current AccessControlContext's * DomainCombiner (which may be null) while the action is performed. *

* If a security manager is installed and the specified * {@code AccessControlContext} was not created by system code and the * caller's {@code ProtectionDomain} has not been granted the * {@literal "createAccessControlContext"} * {@link java.security.SecurityPermission}, then the action is performed * with no permissions. * * @param the type of the value returned by the * PrivilegedExceptionAction's {@code run} method. * @param action the action to be performed. * @param context an access control context * representing the restriction to be applied to the * caller's domain's privileges before performing * the specified action. If the context is * {@code null}, * then no additional restriction is applied. * @param perms the {@code Permission} arguments which limit the * scope of the caller's privileges. The number of arguments * is variable. * * @return the value returned by the action's {@code run} method. * * @throws PrivilegedActionException if the specified action's * {@code run} method threw a checked exception * @throws NullPointerException if action or perms or any element of * perms is {@code null} * * @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedAction,AccessControlContext) * @see java.security.DomainCombiner * * @since 1.8 */ @CallerSensitive public static T doPrivilegedWithCombiner(PrivilegedExceptionAction action, AccessControlContext context, Permission... perms) throws PrivilegedActionException { AccessControlContext parent = getContext(); DomainCombiner dc = parent.getCombiner(); if (dc == null && context != null) { dc = context.getCombiner(); } if (perms == null) { throw new NullPointerException("null permissions parameter"); } Class caller = Reflection.getCallerClass(); return AccessController.doPrivileged(action, createWrapper(dc, caller, parent, context, perms)); } /** * Returns the AccessControl context. i.e., it gets * the protection domains of all the callers on the stack, * starting at the first class with a non-null * ProtectionDomain. * * @return the access control context based on the current stack or * null if there was only privileged system code. */ private static native AccessControlContext getStackAccessControlContext(); /** * Returns the "inherited" AccessControl context. This is the context * that existed when the thread was created. Package private so * AccessControlContext can use it. */ static native AccessControlContext getInheritedAccessControlContext(); /** * This method takes a "snapshot" of the current calling context, which * includes the current Thread's inherited AccessControlContext and any * limited privilege scope, and places it in an AccessControlContext object. * This context may then be checked at a later point, possibly in another thread. * * @see AccessControlContext * * @return the AccessControlContext based on the current context. */ public static AccessControlContext getContext() { AccessControlContext acc = getStackAccessControlContext(); if (acc == null) { // all we had was privileged system code. We don't want // to return null though, so we construct a real ACC. return new AccessControlContext(null, true); } else { return acc.optimize(); } } /** * Determines whether the access request indicated by the * specified permission should be allowed or denied, based on * the current AccessControlContext and security policy. * This method quietly returns if the access request * is permitted, or throws an AccessControlException otherwise. The * getPermission method of the AccessControlException returns the * {@code perm} Permission object instance. * * @param perm the requested permission. * * @exception AccessControlException if the specified permission * is not permitted, based on the current security policy. * @exception NullPointerException if the specified permission * is {@code null} and is checked based on the * security policy currently in effect. */ public static void checkPermission(Permission perm) throws AccessControlException { //System.err.println("checkPermission "+perm); //Thread.currentThread().dumpStack(); if (perm == null) { throw new NullPointerException("permission can't be null"); } AccessControlContext stack = getStackAccessControlContext(); // if context is null, we had privileged system code on the stack. if (stack == null) { Debug debug = AccessControlContext.getDebug(); boolean dumpDebug = false; if (debug != null) { dumpDebug = !Debug.isOn("codebase="); dumpDebug &= !Debug.isOn("permission=") || Debug.isOn("permission=" + perm.getClass().getCanonicalName()); } if (dumpDebug && Debug.isOn("stack")) { Thread.dumpStack(); } if (dumpDebug && Debug.isOn("domain")) { debug.println("domain (context is null)"); } if (dumpDebug) { debug.println("access allowed "+perm); } return; } AccessControlContext acc = stack.optimize(); acc.checkPermission(perm); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 4242 Content-Disposition: inline; filename="AlgorithmConstraints.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "7341603dc7cf65d3941cee8dce0e38194ed1a560" /* * Copyright (c) 2010, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.Set; /** * This interface specifies constraints for cryptographic algorithms, * keys (key sizes), and other algorithm parameters. *

* {@code AlgorithmConstraints} objects are immutable. An implementation * of this interface should not provide methods that can change the state * of an instance once it has been created. *

* Note that {@code AlgorithmConstraints} can be used to represent the * restrictions described by the security properties * {@code jdk.certpath.disabledAlgorithms} and * {@code jdk.tls.disabledAlgorithms}, or could be used by a * concrete {@code PKIXCertPathChecker} to check whether a specified * certificate in the certification path contains the required algorithm * constraints. * * @see javax.net.ssl.SSLParameters#getAlgorithmConstraints * @see javax.net.ssl.SSLParameters#setAlgorithmConstraints(AlgorithmConstraints) * * @since 1.7 */ public interface AlgorithmConstraints { /** * Determines whether an algorithm is granted permission for the * specified cryptographic primitives. * * @param primitives a set of cryptographic primitives * @param algorithm the algorithm name * @param parameters the algorithm parameters, or null if no additional * parameters * * @return true if the algorithm is permitted and can be used for all * of the specified cryptographic primitives * * @throws IllegalArgumentException if primitives or algorithm is null * or empty */ public boolean permits(Set primitives, String algorithm, AlgorithmParameters parameters); /** * Determines whether a key is granted permission for the specified * cryptographic primitives. *

* This method is usually used to check key size and key usage. * * @param primitives a set of cryptographic primitives * @param key the key * * @return true if the key can be used for all of the specified * cryptographic primitives * * @throws IllegalArgumentException if primitives is null or empty, * or the key is null */ public boolean permits(Set primitives, Key key); /** * Determines whether an algorithm and the corresponding key are granted * permission for the specified cryptographic primitives. * * @param primitives a set of cryptographic primitives * @param algorithm the algorithm name * @param key the key * @param parameters the algorithm parameters, or null if no additional * parameters * * @return true if the key and the algorithm can be used for all of the * specified cryptographic primitives * * @throws IllegalArgumentException if primitives or algorithm is null * or empty, or the key is null */ public boolean permits(Set primitives, String algorithm, Key key, AlgorithmParameters parameters); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 13966 Content-Disposition: inline; filename="AlgorithmParameterGenerator.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "7f9c7cbf4abfd86fca25ea9707d8bf522dfe16b4" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.security.spec.AlgorithmParameterSpec; /** * The {@code AlgorithmParameterGenerator} class is used to generate a * set of * parameters to be used with a certain algorithm. Parameter generators * are constructed using the {@code getInstance} factory methods * (static methods that return instances of a given class). * *

The object that will generate the parameters can be initialized * in two different ways: in an algorithm-independent manner, or in an * algorithm-specific manner: * *

    *
  • The algorithm-independent approach uses the fact that all parameter * generators share the concept of a "size" and a * source of randomness. The measure of size is universally shared * by all algorithm parameters, though it is interpreted differently * for different algorithms. For example, in the case of parameters for * the DSA algorithm, "size" corresponds to the size * of the prime modulus (in bits). * When using this approach, algorithm-specific parameter generation * values - if any - default to some standard values, unless they can be * derived from the specified size. * *
  • The other approach initializes a parameter generator object * using algorithm-specific semantics, which are represented by a set of * algorithm-specific parameter generation values. To generate * Diffie-Hellman system parameters, for example, the parameter generation * values usually * consist of the size of the prime modulus and the size of the * random exponent, both specified in number of bits. *
* *

In case the client does not explicitly initialize the * AlgorithmParameterGenerator * (via a call to an {@code init} method), each provider must supply (and * document) a default initialization. For example, the Sun provider uses a * default modulus prime size of 1024 bits for the generation of DSA * parameters. * *

Every implementation of the Java platform is required to support the * following standard {@code AlgorithmParameterGenerator} algorithms and * keysizes in parentheses: *

    *
  • {@code DiffieHellman} (1024)
  • *
  • {@code DSA} (1024)
  • *
* These algorithms are described in the * AlgorithmParameterGenerator section of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * Consult the release documentation for your implementation to see if any * other algorithms are supported. * * @author Jan Luehe * * * @see AlgorithmParameters * @see java.security.spec.AlgorithmParameterSpec * * @since 1.2 */ public class AlgorithmParameterGenerator { // The provider private Provider provider; // The provider implementation (delegate) private AlgorithmParameterGeneratorSpi paramGenSpi; // The algorithm private String algorithm; /** * Creates an AlgorithmParameterGenerator object. * * @param paramGenSpi the delegate * @param provider the provider * @param algorithm the algorithm */ protected AlgorithmParameterGenerator (AlgorithmParameterGeneratorSpi paramGenSpi, Provider provider, String algorithm) { this.paramGenSpi = paramGenSpi; this.provider = provider; this.algorithm = algorithm; } /** * Returns the standard name of the algorithm this parameter * generator is associated with. * * @return the string name of the algorithm. */ public final String getAlgorithm() { return this.algorithm; } /** * Returns an AlgorithmParameterGenerator object for generating * a set of parameters to be used with the specified algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new AlgorithmParameterGenerator object encapsulating the * AlgorithmParameterGeneratorSpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm this * parameter generator is associated with. * See the AlgorithmParameterGenerator section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the new AlgorithmParameterGenerator object. * * @exception NoSuchAlgorithmException if no Provider supports an * AlgorithmParameterGeneratorSpi implementation for the * specified algorithm. * * @see Provider */ public static AlgorithmParameterGenerator getInstance(String algorithm) throws NoSuchAlgorithmException { try { Object[] objs = Security.getImpl(algorithm, "AlgorithmParameterGenerator", (String)null); return new AlgorithmParameterGenerator ((AlgorithmParameterGeneratorSpi)objs[0], (Provider)objs[1], algorithm); } catch(NoSuchProviderException e) { throw new NoSuchAlgorithmException(algorithm + " not found"); } } /** * Returns an AlgorithmParameterGenerator object for generating * a set of parameters to be used with the specified algorithm. * *

A new AlgorithmParameterGenerator object encapsulating the * AlgorithmParameterGeneratorSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm this * parameter generator is associated with. * See the AlgorithmParameterGenerator section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the string name of the Provider. * * @return the new AlgorithmParameterGenerator object. * * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider name is null * or empty. * * @see Provider */ public static AlgorithmParameterGenerator getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { if (provider == null || provider.length() == 0) throw new IllegalArgumentException("missing provider"); Object[] objs = Security.getImpl(algorithm, "AlgorithmParameterGenerator", provider); return new AlgorithmParameterGenerator ((AlgorithmParameterGeneratorSpi)objs[0], (Provider)objs[1], algorithm); } /** * Returns an AlgorithmParameterGenerator object for generating * a set of parameters to be used with the specified algorithm. * *

A new AlgorithmParameterGenerator object encapsulating the * AlgorithmParameterGeneratorSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the string name of the algorithm this * parameter generator is associated with. * See the AlgorithmParameterGenerator section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the Provider object. * * @return the new AlgorithmParameterGenerator object. * * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the specified provider is null. * * @see Provider * * @since 1.4 */ public static AlgorithmParameterGenerator getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { if (provider == null) throw new IllegalArgumentException("missing provider"); Object[] objs = Security.getImpl(algorithm, "AlgorithmParameterGenerator", provider); return new AlgorithmParameterGenerator ((AlgorithmParameterGeneratorSpi)objs[0], (Provider)objs[1], algorithm); } /** * Returns the provider of this algorithm parameter generator object. * * @return the provider of this algorithm parameter generator object */ public final Provider getProvider() { return this.provider; } /** * Initializes this parameter generator for a certain size. * To create the parameters, the {@code SecureRandom} * implementation of the highest-priority installed provider is used as * the source of randomness. * (If none of the installed providers supply an implementation of * {@code SecureRandom}, a system-provided source of randomness is * used.) * * @param size the size (number of bits). */ public final void init(int size) { paramGenSpi.engineInit(size, new SecureRandom()); } /** * Initializes this parameter generator for a certain size and source * of randomness. * * @param size the size (number of bits). * @param random the source of randomness. */ public final void init(int size, SecureRandom random) { paramGenSpi.engineInit(size, random); } /** * Initializes this parameter generator with a set of algorithm-specific * parameter generation values. * To generate the parameters, the {@code SecureRandom} * implementation of the highest-priority installed provider is used as * the source of randomness. * (If none of the installed providers supply an implementation of * {@code SecureRandom}, a system-provided source of randomness is * used.) * * @param genParamSpec the set of algorithm-specific parameter generation values. * * @exception InvalidAlgorithmParameterException if the given parameter * generation values are inappropriate for this parameter generator. */ public final void init(AlgorithmParameterSpec genParamSpec) throws InvalidAlgorithmParameterException { paramGenSpi.engineInit(genParamSpec, new SecureRandom()); } /** * Initializes this parameter generator with a set of algorithm-specific * parameter generation values. * * @param genParamSpec the set of algorithm-specific parameter generation values. * @param random the source of randomness. * * @exception InvalidAlgorithmParameterException if the given parameter * generation values are inappropriate for this parameter generator. */ public final void init(AlgorithmParameterSpec genParamSpec, SecureRandom random) throws InvalidAlgorithmParameterException { paramGenSpi.engineInit(genParamSpec, random); } /** * Generates the parameters. * * @return the new AlgorithmParameters object. */ public final AlgorithmParameters generateParameters() { return paramGenSpi.engineGenerateParameters(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3344 Content-Disposition: inline; filename="AlgorithmParameterGeneratorSpi.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "721fb52ac180726506bf4a263a6d2e821203346a" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.security.spec.AlgorithmParameterSpec; /** * This class defines the Service Provider Interface (SPI) * for the {@code AlgorithmParameterGenerator} class, which * is used to generate a set of parameters to be used with a certain algorithm. * *

All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a parameter generator for a particular algorithm. * *

In case the client does not explicitly initialize the * AlgorithmParameterGenerator (via a call to an {@code engineInit} * method), each provider must supply (and document) a default initialization. * For example, the Sun provider uses a default modulus prime size of 1024 * bits for the generation of DSA parameters. * * @author Jan Luehe * * * @see AlgorithmParameterGenerator * @see AlgorithmParameters * @see java.security.spec.AlgorithmParameterSpec * * @since 1.2 */ public abstract class AlgorithmParameterGeneratorSpi { /** * Initializes this parameter generator for a certain size * and source of randomness. * * @param size the size (number of bits). * @param random the source of randomness. */ protected abstract void engineInit(int size, SecureRandom random); /** * Initializes this parameter generator with a set of * algorithm-specific parameter generation values. * * @param genParamSpec the set of algorithm-specific parameter generation values. * @param random the source of randomness. * * @exception InvalidAlgorithmParameterException if the given parameter * generation values are inappropriate for this parameter generator. */ protected abstract void engineInit(AlgorithmParameterSpec genParamSpec, SecureRandom random) throws InvalidAlgorithmParameterException; /** * Generates the parameters. * * @return the new AlgorithmParameters object. */ protected abstract AlgorithmParameters engineGenerateParameters(); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 15314 Content-Disposition: inline; filename="AlgorithmParameters.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "b548fcb64c8a9c0e438dc81f3565ad32dfa50d00" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.*; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidParameterSpecException; /** * This class is used as an opaque representation of cryptographic parameters. * *

An {@code AlgorithmParameters} object for managing the parameters * for a particular algorithm can be obtained by * calling one of the {@code getInstance} factory methods * (static methods that return instances of a given class). * *

Once an {@code AlgorithmParameters} object is obtained, it must be * initialized via a call to {@code init}, using an appropriate parameter * specification or parameter encoding. * *

A transparent parameter specification is obtained from an * {@code AlgorithmParameters} object via a call to * {@code getParameterSpec}, and a byte encoding of the parameters is * obtained via a call to {@code getEncoded}. * *

Every implementation of the Java platform is required to support the * following standard {@code AlgorithmParameters} algorithms: *

    *
  • {@code AES}
  • *
  • {@code DES}
  • *
  • {@code DESede}
  • *
  • {@code DiffieHellman}
  • *
  • {@code DSA}
  • *
* These algorithms are described in the * AlgorithmParameters section of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * Consult the release documentation for your implementation to see if any * other algorithms are supported. * * @author Jan Luehe * * * @see java.security.spec.AlgorithmParameterSpec * @see java.security.spec.DSAParameterSpec * @see KeyPairGenerator * * @since 1.2 */ public class AlgorithmParameters { // The provider private Provider provider; // The provider implementation (delegate) private AlgorithmParametersSpi paramSpi; // The algorithm private String algorithm; // Has this object been initialized? private boolean initialized = false; /** * Creates an AlgorithmParameters object. * * @param paramSpi the delegate * @param provider the provider * @param algorithm the algorithm */ protected AlgorithmParameters(AlgorithmParametersSpi paramSpi, Provider provider, String algorithm) { this.paramSpi = paramSpi; this.provider = provider; this.algorithm = algorithm; } /** * Returns the name of the algorithm associated with this parameter object. * * @return the algorithm name. */ public final String getAlgorithm() { return this.algorithm; } /** * Returns a parameter object for the specified algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new AlgorithmParameters object encapsulating the * AlgorithmParametersSpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * *

The returned parameter object must be initialized via a call to * {@code init}, using an appropriate parameter specification or * parameter encoding. * * @param algorithm the name of the algorithm requested. * See the AlgorithmParameters section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the new parameter object. * * @exception NoSuchAlgorithmException if no Provider supports an * AlgorithmParametersSpi implementation for the * specified algorithm. * * @see Provider */ public static AlgorithmParameters getInstance(String algorithm) throws NoSuchAlgorithmException { try { Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters", (String)null); return new AlgorithmParameters((AlgorithmParametersSpi)objs[0], (Provider)objs[1], algorithm); } catch(NoSuchProviderException e) { throw new NoSuchAlgorithmException(algorithm + " not found"); } } /** * Returns a parameter object for the specified algorithm. * *

A new AlgorithmParameters object encapsulating the * AlgorithmParametersSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * *

The returned parameter object must be initialized via a call to * {@code init}, using an appropriate parameter specification or * parameter encoding. * * @param algorithm the name of the algorithm requested. * See the AlgorithmParameters section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the name of the provider. * * @return the new parameter object. * * @exception NoSuchAlgorithmException if an AlgorithmParametersSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider name is null * or empty. * * @see Provider */ public static AlgorithmParameters getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { if (provider == null || provider.length() == 0) throw new IllegalArgumentException("missing provider"); Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters", provider); return new AlgorithmParameters((AlgorithmParametersSpi)objs[0], (Provider)objs[1], algorithm); } /** * Returns a parameter object for the specified algorithm. * *

A new AlgorithmParameters object encapsulating the * AlgorithmParametersSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * *

The returned parameter object must be initialized via a call to * {@code init}, using an appropriate parameter specification or * parameter encoding. * * @param algorithm the name of the algorithm requested. * See the AlgorithmParameters section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the name of the provider. * * @return the new parameter object. * * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the provider is null. * * @see Provider * * @since 1.4 */ public static AlgorithmParameters getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { if (provider == null) throw new IllegalArgumentException("missing provider"); Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters", provider); return new AlgorithmParameters((AlgorithmParametersSpi)objs[0], (Provider)objs[1], algorithm); } /** * Returns the provider of this parameter object. * * @return the provider of this parameter object */ public final Provider getProvider() { return this.provider; } /** * Initializes this parameter object using the parameters * specified in {@code paramSpec}. * * @param paramSpec the parameter specification. * * @exception InvalidParameterSpecException if the given parameter * specification is inappropriate for the initialization of this parameter * object, or if this parameter object has already been initialized. */ public final void init(AlgorithmParameterSpec paramSpec) throws InvalidParameterSpecException { if (this.initialized) throw new InvalidParameterSpecException("already initialized"); paramSpi.engineInit(paramSpec); this.initialized = true; } /** * Imports the specified parameters and decodes them according to the * primary decoding format for parameters. The primary decoding * format for parameters is ASN.1, if an ASN.1 specification for this type * of parameters exists. * * @param params the encoded parameters. * * @exception IOException on decoding errors, or if this parameter object * has already been initialized. */ public final void init(byte[] params) throws IOException { if (this.initialized) throw new IOException("already initialized"); paramSpi.engineInit(params); this.initialized = true; } /** * Imports the parameters from {@code params} and decodes them * according to the specified decoding scheme. * If {@code format} is null, the * primary decoding format for parameters is used. The primary decoding * format is ASN.1, if an ASN.1 specification for these parameters * exists. * * @param params the encoded parameters. * * @param format the name of the decoding scheme. * * @exception IOException on decoding errors, or if this parameter object * has already been initialized. */ public final void init(byte[] params, String format) throws IOException { if (this.initialized) throw new IOException("already initialized"); paramSpi.engineInit(params, format); this.initialized = true; } /** * Returns a (transparent) specification of this parameter object. * {@code paramSpec} identifies the specification class in which * the parameters should be returned. It could, for example, be * {@code DSAParameterSpec.class}, to indicate that the * parameters should be returned in an instance of the * {@code DSAParameterSpec} class. * * @param the type of the parameter specification to be returrned * @param paramSpec the specification class in which * the parameters should be returned. * * @return the parameter specification. * * @exception InvalidParameterSpecException if the requested parameter * specification is inappropriate for this parameter object, or if this * parameter object has not been initialized. */ public final T getParameterSpec(Class paramSpec) throws InvalidParameterSpecException { if (this.initialized == false) { throw new InvalidParameterSpecException("not initialized"); } return paramSpi.engineGetParameterSpec(paramSpec); } /** * Returns the parameters in their primary encoding format. * The primary encoding format for parameters is ASN.1, if an ASN.1 * specification for this type of parameters exists. * * @return the parameters encoded using their primary encoding format. * * @exception IOException on encoding errors, or if this parameter object * has not been initialized. */ public final byte[] getEncoded() throws IOException { if (this.initialized == false) { throw new IOException("not initialized"); } return paramSpi.engineGetEncoded(); } /** * Returns the parameters encoded in the specified scheme. * If {@code format} is null, the * primary encoding format for parameters is used. The primary encoding * format is ASN.1, if an ASN.1 specification for these parameters * exists. * * @param format the name of the encoding format. * * @return the parameters encoded using the specified encoding scheme. * * @exception IOException on encoding errors, or if this parameter object * has not been initialized. */ public final byte[] getEncoded(String format) throws IOException { if (this.initialized == false) { throw new IOException("not initialized"); } return paramSpi.engineGetEncoded(format); } /** * Returns a formatted string describing the parameters. * * @return a formatted string describing the parameters, or null if this * parameter object has not been initialized. */ public final String toString() { if (this.initialized == false) { return null; } return paramSpi.engineToString(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5593 Content-Disposition: inline; filename="AlgorithmParametersSpi.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "282493b97b9728467d14f3ba1c06ed4e032dcacc" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.*; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidParameterSpecException; /** * This class defines the Service Provider Interface (SPI) * for the {@code AlgorithmParameters} class, which is used to manage * algorithm parameters. * *

All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply parameter management * for a particular algorithm. * * @author Jan Luehe * * * @see AlgorithmParameters * @see java.security.spec.AlgorithmParameterSpec * @see java.security.spec.DSAParameterSpec * * @since 1.2 */ public abstract class AlgorithmParametersSpi { /** * Initializes this parameters object using the parameters * specified in {@code paramSpec}. * * @param paramSpec the parameter specification. * * @exception InvalidParameterSpecException if the given parameter * specification is inappropriate for the initialization of this parameter * object. */ protected abstract void engineInit(AlgorithmParameterSpec paramSpec) throws InvalidParameterSpecException; /** * Imports the specified parameters and decodes them * according to the primary decoding format for parameters. * The primary decoding format for parameters is ASN.1, if an ASN.1 * specification for this type of parameters exists. * * @param params the encoded parameters. * * @exception IOException on decoding errors */ protected abstract void engineInit(byte[] params) throws IOException; /** * Imports the parameters from {@code params} and * decodes them according to the specified decoding format. * If {@code format} is null, the * primary decoding format for parameters is used. The primary decoding * format is ASN.1, if an ASN.1 specification for these parameters * exists. * * @param params the encoded parameters. * * @param format the name of the decoding format. * * @exception IOException on decoding errors */ protected abstract void engineInit(byte[] params, String format) throws IOException; /** * Returns a (transparent) specification of this parameters * object. * {@code paramSpec} identifies the specification class in which * the parameters should be returned. It could, for example, be * {@code DSAParameterSpec.class}, to indicate that the * parameters should be returned in an instance of the * {@code DSAParameterSpec} class. * * @param the type of the parameter specification to be returned * * @param paramSpec the specification class in which * the parameters should be returned. * * @return the parameter specification. * * @exception InvalidParameterSpecException if the requested parameter * specification is inappropriate for this parameter object. */ protected abstract T engineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException; /** * Returns the parameters in their primary encoding format. * The primary encoding format for parameters is ASN.1, if an ASN.1 * specification for this type of parameters exists. * * @return the parameters encoded using their primary encoding format. * * @exception IOException on encoding errors. */ protected abstract byte[] engineGetEncoded() throws IOException; /** * Returns the parameters encoded in the specified format. * If {@code format} is null, the * primary encoding format for parameters is used. The primary encoding * format is ASN.1, if an ASN.1 specification for these parameters * exists. * * @param format the name of the encoding format. * * @return the parameters encoded using the specified encoding scheme. * * @exception IOException on encoding errors. */ protected abstract byte[] engineGetEncoded(String format) throws IOException; /** * Returns a formatted string describing the parameters. * * @return a formatted string describing the parameters. */ protected abstract String engineToString(); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 6852 Content-Disposition: inline; filename="AllPermission.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "c01b134f074cd08794215fce520e91e2f3a771a1" /* * Copyright (c) 1998, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.security.*; import java.util.Enumeration; import java.util.Hashtable; import java.util.StringTokenizer; import sun.security.util.SecurityConstants; /** * The AllPermission is a permission that implies all other permissions. *

* Note: Granting AllPermission should be done with extreme care, * as it implies all other permissions. Thus, it grants code the ability * to run with security * disabled. Extreme caution should be taken before granting such * a permission to code. This permission should be used only during testing, * or in extremely rare cases where an application or applet is * completely trusted and adding the necessary permissions to the policy * is prohibitively cumbersome. * * @see java.security.Permission * @see java.security.AccessController * @see java.security.Permissions * @see java.security.PermissionCollection * @see java.lang.SecurityManager * * * @author Roland Schemers * * @serial exclude */ public final class AllPermission extends Permission { private static final long serialVersionUID = -2916474571451318075L; /** * Creates a new AllPermission object. */ public AllPermission() { super(""); } /** * Creates a new AllPermission object. This * constructor exists for use by the {@code Policy} object * to instantiate new Permission objects. * * @param name ignored * @param actions ignored. */ public AllPermission(String name, String actions) { this(); } /** * Checks if the specified permission is "implied" by * this object. This method always returns true. * * @param p the permission to check against. * * @return return */ public boolean implies(Permission p) { return true; } /** * Checks two AllPermission objects for equality. Two AllPermission * objects are always equal. * * @param obj the object we are testing for equality with this object. * @return true if obj is an AllPermission, false otherwise. */ public boolean equals(Object obj) { return (obj instanceof AllPermission); } /** * Returns the hash code value for this object. * * @return a hash code value for this object. */ public int hashCode() { return 1; } /** * Returns the canonical string representation of the actions. * * @return the actions. */ public String getActions() { return ""; } /** * Returns a new PermissionCollection object for storing AllPermission * objects. *

* * @return a new PermissionCollection object suitable for * storing AllPermissions. */ public PermissionCollection newPermissionCollection() { return new AllPermissionCollection(); } } /** * A AllPermissionCollection stores a collection * of AllPermission permissions. AllPermission objects * must be stored in a manner that allows them to be inserted in any * order, but enable the implies function to evaluate the implies * method in an efficient (and consistent) manner. * * @see java.security.Permission * @see java.security.Permissions * * * @author Roland Schemers * * @serial include */ final class AllPermissionCollection extends PermissionCollection implements java.io.Serializable { // use serialVersionUID from JDK 1.2.2 for interoperability private static final long serialVersionUID = -4023755556366636806L; private boolean all_allowed; // true if any all permissions have been added /** * Create an empty AllPermissions object. * */ public AllPermissionCollection() { all_allowed = false; } /** * Adds a permission to the AllPermissions. The key for the hash is * permission.path. * * @param permission the Permission object to add. * * @exception IllegalArgumentException - if the permission is not a * AllPermission * * @exception SecurityException - if this AllPermissionCollection object * has been marked readonly */ public void add(Permission permission) { if (! (permission instanceof AllPermission)) throw new IllegalArgumentException("invalid permission: "+ permission); if (isReadOnly()) throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection"); all_allowed = true; // No sync; staleness OK } /** * Check and see if this set of permissions implies the permissions * expressed in "permission". * * @param permission the Permission object to compare * * @return always returns true. */ public boolean implies(Permission permission) { return all_allowed; // No sync; staleness OK } /** * Returns an enumeration of all the AllPermission objects in the * container. * * @return an enumeration of all the AllPermission objects. */ public Enumeration elements() { return new Enumeration() { private boolean hasMore = all_allowed; public boolean hasMoreElements() { return hasMore; } public Permission nextElement() { hasMore = false; return SecurityConstants.ALL_PERMISSION; } }; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5375 Content-Disposition: inline; filename="AuthProvider.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "571a1fe085f40c04b8b3fe544b311f0280a5f57f" /* * Copyright (c) 2003, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import javax.security.auth.Subject; import javax.security.auth.login.LoginException; import javax.security.auth.callback.CallbackHandler; /** * This class defines login and logout methods for a provider. * *

While callers may invoke {@code login} directly, * the provider may also invoke {@code login} on behalf of callers * if it determines that a login must be performed * prior to certain operations. * * @since 1.5 */ public abstract class AuthProvider extends Provider { private static final long serialVersionUID = 4197859053084546461L; /** * Constructs a provider with the specified name, version number, * and information. * * @param name the provider name. * @param version the provider version number. * @param info a description of the provider and its services. */ protected AuthProvider(String name, double version, String info) { super(name, version, info); } /** * Log in to this provider. * *

The provider relies on a {@code CallbackHandler} * to obtain authentication information from the caller * (a PIN, for example). If the caller passes a {@code null} * handler to this method, the provider uses the handler set in the * {@code setCallbackHandler} method. * If no handler was set in that method, the provider queries the * auth.login.defaultCallbackHandler security property * for the fully qualified class name of a default handler implementation. * If the security property is not set, * the provider is assumed to have alternative means * for obtaining authentication information. * * @param subject the {@code Subject} which may contain * principals/credentials used for authentication, * or may be populated with additional principals/credentials * after successful authentication has completed. * This parameter may be {@code null}. * @param handler the {@code CallbackHandler} used by * this provider to obtain authentication information * from the caller, which may be {@code null} * * @exception LoginException if the login operation fails * @exception SecurityException if the caller does not pass a * security check for * {@code SecurityPermission("authProvider.name")}, * where {@code name} is the value returned by * this provider's {@code getName} method */ public abstract void login(Subject subject, CallbackHandler handler) throws LoginException; /** * Log out from this provider. * * @exception LoginException if the logout operation fails * @exception SecurityException if the caller does not pass a * security check for * {@code SecurityPermission("authProvider.name")}, * where {@code name} is the value returned by * this provider's {@code getName} method */ public abstract void logout() throws LoginException; /** * Set a {@code CallbackHandler}. * *

The provider uses this handler if one is not passed to the * {@code login} method. The provider also uses this handler * if it invokes {@code login} on behalf of callers. * In either case if a handler is not set via this method, * the provider queries the * auth.login.defaultCallbackHandler security property * for the fully qualified class name of a default handler implementation. * If the security property is not set, * the provider is assumed to have alternative means * for obtaining authentication information. * * @param handler a {@code CallbackHandler} for obtaining * authentication information, which may be {@code null} * * @exception SecurityException if the caller does not pass a * security check for * {@code SecurityPermission("authProvider.name")}, * where {@code name} is the value returned by * this provider's {@code getName} method */ public abstract void setCallbackHandler(CallbackHandler handler); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 18383 Content-Disposition: inline; filename="BasicPermission.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "89cc2f921524934d96b40f05b96ef1bc1e7621f1" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.Enumeration; import java.util.Map; import java.util.HashMap; import java.util.Hashtable; import java.util.Collections; import java.io.ObjectStreamField; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.IOException; /** * The BasicPermission class extends the Permission class, and * can be used as the base class for permissions that want to * follow the same naming convention as BasicPermission. *

* The name for a BasicPermission is the name of the given permission * (for example, "exit", * "setFactory", "print.queueJob", etc). The naming * convention follows the hierarchical property naming convention. * An asterisk may appear by itself, or if immediately preceded by a "." * may appear at the end of the name, to signify a wildcard match. * For example, "*" and "java.*" signify a wildcard match, while "*java", "a*b", * and "java*" do not. *

* The action string (inherited from Permission) is unused. * Thus, BasicPermission is commonly used as the base class for * "named" permissions * (ones that contain a name but no actions list; you either have the * named permission or you don't.) * Subclasses may implement actions on top of BasicPermission, * if desired. *

* @see java.security.Permission * @see java.security.Permissions * @see java.security.PermissionCollection * @see java.lang.SecurityManager * * @author Marianne Mueller * @author Roland Schemers */ public abstract class BasicPermission extends Permission implements java.io.Serializable { private static final long serialVersionUID = 6279438298436773498L; // does this permission have a wildcard at the end? private transient boolean wildcard; // the name without the wildcard on the end private transient String path; // is this permission the old-style exitVM permission (pre JDK 1.6)? private transient boolean exitVM; /** * initialize a BasicPermission object. Common to all constructors. */ private void init(String name) { if (name == null) throw new NullPointerException("name can't be null"); int len = name.length(); if (len == 0) { throw new IllegalArgumentException("name can't be empty"); } char last = name.charAt(len - 1); // Is wildcard or ends with ".*"? if (last == '*' && (len == 1 || name.charAt(len - 2) == '.')) { wildcard = true; if (len == 1) { path = ""; } else { path = name.substring(0, len - 1); } } else { if (name.equals("exitVM")) { wildcard = true; path = "exitVM."; exitVM = true; } else { path = name; } } } /** * Creates a new BasicPermission with the specified name. * Name is the symbolic name of the permission, such as * "setFactory", * "print.queueJob", or "topLevelWindow", etc. * * @param name the name of the BasicPermission. * * @throws NullPointerException if {@code name} is {@code null}. * @throws IllegalArgumentException if {@code name} is empty. */ public BasicPermission(String name) { super(name); init(name); } /** * Creates a new BasicPermission object with the specified name. * The name is the symbolic name of the BasicPermission, and the * actions String is currently unused. * * @param name the name of the BasicPermission. * @param actions ignored. * * @throws NullPointerException if {@code name} is {@code null}. * @throws IllegalArgumentException if {@code name} is empty. */ public BasicPermission(String name, String actions) { super(name); init(name); } /** * Checks if the specified permission is "implied" by * this object. *

* More specifically, this method returns true if: *

    *
  • p's class is the same as this object's class, and *
  • p's name equals or (in the case of wildcards) * is implied by this object's * name. For example, "a.b.*" implies "a.b.c". *
* * @param p the permission to check against. * * @return true if the passed permission is equal to or * implied by this permission, false otherwise. */ public boolean implies(Permission p) { if ((p == null) || (p.getClass() != getClass())) return false; BasicPermission that = (BasicPermission) p; if (this.wildcard) { if (that.wildcard) { // one wildcard can imply another return that.path.startsWith(path); } else { // make sure ap.path is longer so a.b.* doesn't imply a.b return (that.path.length() > this.path.length()) && that.path.startsWith(this.path); } } else { if (that.wildcard) { // a non-wildcard can't imply a wildcard return false; } else { return this.path.equals(that.path); } } } /** * Checks two BasicPermission objects for equality. * Checks that obj's class is the same as this object's class * and has the same name as this object. *

* @param obj the object we are testing for equality with this object. * @return true if obj's class is the same as this object's class * and has the same name as this BasicPermission object, false otherwise. */ public boolean equals(Object obj) { if (obj == this) return true; if ((obj == null) || (obj.getClass() != getClass())) return false; BasicPermission bp = (BasicPermission) obj; return getName().equals(bp.getName()); } /** * Returns the hash code value for this object. * The hash code used is the hash code of the name, that is, * {@code getName().hashCode()}, where {@code getName} is * from the Permission superclass. * * @return a hash code value for this object. */ public int hashCode() { return this.getName().hashCode(); } /** * Returns the canonical string representation of the actions, * which currently is the empty string "", since there are no actions for * a BasicPermission. * * @return the empty string "". */ public String getActions() { return ""; } /** * Returns a new PermissionCollection object for storing BasicPermission * objects. * *

BasicPermission objects must be stored in a manner that allows them * to be inserted in any order, but that also enables the * PermissionCollection {@code implies} method * to be implemented in an efficient (and consistent) manner. * * @return a new PermissionCollection object suitable for * storing BasicPermissions. */ public PermissionCollection newPermissionCollection() { return new BasicPermissionCollection(this.getClass()); } /** * readObject is called to restore the state of the BasicPermission from * a stream. */ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); // init is called to initialize the rest of the values. init(getName()); } /** * Returns the canonical name of this BasicPermission. * All internal invocations of getName should invoke this method, so * that the pre-JDK 1.6 "exitVM" and current "exitVM.*" permission are * equivalent in equals/hashCode methods. * * @return the canonical name of this BasicPermission. */ final String getCanonicalName() { return exitVM ? "exitVM.*" : getName(); } } /** * A BasicPermissionCollection stores a collection * of BasicPermission permissions. BasicPermission objects * must be stored in a manner that allows them to be inserted in any * order, but enable the implies function to evaluate the implies * method in an efficient (and consistent) manner. * * A BasicPermissionCollection handles comparing a permission like "a.b.c.d.e" * with a Permission such as "a.b.*", or "*". * * @see java.security.Permission * @see java.security.Permissions * * * @author Roland Schemers * * @serial include */ final class BasicPermissionCollection extends PermissionCollection implements java.io.Serializable { private static final long serialVersionUID = 739301742472979399L; /** * Key is name, value is permission. All permission objects in * collection must be of the same type. * Not serialized; see serialization section at end of class. */ private transient Map perms; /** * This is set to {@code true} if this BasicPermissionCollection * contains a BasicPermission with '*' as its permission name. * * @see #serialPersistentFields */ private boolean all_allowed; /** * The class to which all BasicPermissions in this * BasicPermissionCollection belongs. * * @see #serialPersistentFields */ private Class permClass; /** * Create an empty BasicPermissionCollection object. * */ public BasicPermissionCollection(Class clazz) { perms = new HashMap(11); all_allowed = false; permClass = clazz; } /** * Adds a permission to the BasicPermissions. The key for the hash is * permission.path. * * @param permission the Permission object to add. * * @exception IllegalArgumentException - if the permission is not a * BasicPermission, or if * the permission is not of the * same Class as the other * permissions in this collection. * * @exception SecurityException - if this BasicPermissionCollection object * has been marked readonly */ public void add(Permission permission) { if (! (permission instanceof BasicPermission)) throw new IllegalArgumentException("invalid permission: "+ permission); if (isReadOnly()) throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection"); BasicPermission bp = (BasicPermission) permission; // make sure we only add new BasicPermissions of the same class // Also check null for compatibility with deserialized form from // previous versions. if (permClass == null) { // adding first permission permClass = bp.getClass(); } else { if (bp.getClass() != permClass) throw new IllegalArgumentException("invalid permission: " + permission); } synchronized (this) { perms.put(bp.getCanonicalName(), permission); } // No sync on all_allowed; staleness OK if (!all_allowed) { if (bp.getCanonicalName().equals("*")) all_allowed = true; } } /** * Check and see if this set of permissions implies the permissions * expressed in "permission". * * @param permission the Permission object to compare * * @return true if "permission" is a proper subset of a permission in * the set, false if not. */ public boolean implies(Permission permission) { if (! (permission instanceof BasicPermission)) return false; BasicPermission bp = (BasicPermission) permission; // random subclasses of BasicPermission do not imply each other if (bp.getClass() != permClass) return false; // short circuit if the "*" Permission was added if (all_allowed) return true; // strategy: // Check for full match first. Then work our way up the // path looking for matches on a.b..* String path = bp.getCanonicalName(); //System.out.println("check "+path); Permission x; synchronized (this) { x = perms.get(path); } if (x != null) { // we have a direct hit! return x.implies(permission); } // work our way up the tree... int last, offset; offset = path.length()-1; while ((last = path.lastIndexOf(".", offset)) != -1) { path = path.substring(0, last+1) + "*"; //System.out.println("check "+path); synchronized (this) { x = perms.get(path); } if (x != null) { return x.implies(permission); } offset = last -1; } // we don't have to check for "*" as it was already checked // at the top (all_allowed), so we just return false return false; } /** * Returns an enumeration of all the BasicPermission objects in the * container. * * @return an enumeration of all the BasicPermission objects. */ public Enumeration elements() { // Convert Iterator of Map values into an Enumeration synchronized (this) { return Collections.enumeration(perms.values()); } } // Need to maintain serialization interoperability with earlier releases, // which had the serializable field: // // @serial the Hashtable is indexed by the BasicPermission name // // private Hashtable permissions; /** * @serialField permissions java.util.Hashtable * The BasicPermissions in this BasicPermissionCollection. * All BasicPermissions in the collection must belong to the same class. * The Hashtable is indexed by the BasicPermission name; the value * of the Hashtable entry is the permission. * @serialField all_allowed boolean * This is set to {@code true} if this BasicPermissionCollection * contains a BasicPermission with '*' as its permission name. * @serialField permClass java.lang.Class * The class to which all BasicPermissions in this * BasicPermissionCollection belongs. */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("permissions", Hashtable.class), new ObjectStreamField("all_allowed", Boolean.TYPE), new ObjectStreamField("permClass", Class.class), }; /** * @serialData Default fields. */ /* * Writes the contents of the perms field out as a Hashtable for * serialization compatibility with earlier releases. all_allowed * and permClass unchanged. */ private void writeObject(ObjectOutputStream out) throws IOException { // Don't call out.defaultWriteObject() // Copy perms into a Hashtable Hashtable permissions = new Hashtable<>(perms.size()*2); synchronized (this) { permissions.putAll(perms); } // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); pfields.put("all_allowed", all_allowed); pfields.put("permissions", permissions); pfields.put("permClass", permClass); out.writeFields(); } /** * readObject is called to restore the state of the * BasicPermissionCollection from a stream. */ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { // Don't call defaultReadObject() // Read in serialized fields ObjectInputStream.GetField gfields = in.readFields(); // Get permissions // writeObject writes a Hashtable for the // permissions key, so this cast is safe, unless the data is corrupt. @SuppressWarnings("unchecked") Hashtable permissions = (Hashtable)gfields.get("permissions", null); perms = new HashMap(permissions.size()*2); perms.putAll(permissions); // Get all_allowed all_allowed = gfields.get("all_allowed", false); // Get permClass permClass = (Class) gfields.get("permClass", null); if (permClass == null) { // set permClass Enumeration e = permissions.elements(); if (e.hasMoreElements()) { Permission p = e.nextElement(); permClass = p.getClass(); } } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 6091 Content-Disposition: inline; filename="Certificate.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "489c6d620afae5424699ae3cfc6626b9a0c65b07" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.*; import java.util.Date; /** *

This is an interface of abstract methods for managing a * variety of identity certificates. * An identity certificate is a guarantee by a principal that * a public key is that of another principal. (A principal represents * an entity such as an individual user, a group, or a corporation.) * *

In particular, this interface is intended to be a common * abstraction for constructs that have different formats but * important common uses. For example, different types of * certificates, such as X.509 certificates and PGP certificates, * share general certificate functionality (the need to encode and * decode certificates) and some types of information, such as a * public key, the principal whose key it is, and the guarantor * guaranteeing that the public key is that of the specified * principal. So an implementation of X.509 certificates and an * implementation of PGP certificates can both utilize the Certificate * interface, even though their formats and additional types and * amounts of information stored are different. * *

Important: This interface is useful for cataloging and * grouping objects sharing certain common uses. It does not have any * semantics of its own. In particular, a Certificate object does not * make any statement as to the validity of the binding. It is * the duty of the application implementing this interface to verify * the certificate and satisfy itself of its validity. * * @author Benjamin Renaud * @deprecated A new certificate handling package is created in the Java platform. * This Certificate interface is entirely deprecated and * is here to allow for a smooth transition to the new * package. * @see java.security.cert.Certificate */ @Deprecated public interface Certificate { /** * Returns the guarantor of the certificate, that is, the principal * guaranteeing that the public key associated with this certificate * is that of the principal associated with this certificate. For X.509 * certificates, the guarantor will typically be a Certificate Authority * (such as the United States Postal Service or Verisign, Inc.). * * @return the guarantor which guaranteed the principal-key * binding. */ public abstract Principal getGuarantor(); /** * Returns the principal of the principal-key pair being guaranteed by * the guarantor. * * @return the principal to which this certificate is bound. */ public abstract Principal getPrincipal(); /** * Returns the key of the principal-key pair being guaranteed by * the guarantor. * * @return the public key that this certificate certifies belongs * to a particular principal. */ public abstract PublicKey getPublicKey(); /** * Encodes the certificate to an output stream in a format that can * be decoded by the {@code decode} method. * * @param stream the output stream to which to encode the * certificate. * * @exception KeyException if the certificate is not * properly initialized, or data is missing, etc. * * @exception IOException if a stream exception occurs while * trying to output the encoded certificate to the output stream. * * @see #decode * @see #getFormat */ public abstract void encode(OutputStream stream) throws KeyException, IOException; /** * Decodes a certificate from an input stream. The format should be * that returned by {@code getFormat} and produced by * {@code encode}. * * @param stream the input stream from which to fetch the data * being decoded. * * @exception KeyException if the certificate is not properly initialized, * or data is missing, etc. * * @exception IOException if an exception occurs while trying to input * the encoded certificate from the input stream. * * @see #encode * @see #getFormat */ public abstract void decode(InputStream stream) throws KeyException, IOException; /** * Returns the name of the coding format. This is used as a hint to find * an appropriate parser. It could be "X.509", "PGP", etc. This is * the format produced and understood by the {@code encode} * and {@code decode} methods. * * @return the name of the coding format. */ public abstract String getFormat(); /** * Returns a string that represents the contents of the certificate. * * @param detailed whether or not to give detailed information * about the certificate * * @return a string representing the contents of the certificate */ public String toString(boolean detailed); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5270 Content-Disposition: inline; filename="CodeSigner.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "37c12b153b3d8d06097c397c9f12ce80e420cef4" /* * Copyright (c) 2003, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.*; import java.security.cert.CertPath; /** * This class encapsulates information about a code signer. * It is immutable. * * @since 1.5 * @author Vincent Ryan */ public final class CodeSigner implements Serializable { private static final long serialVersionUID = 6819288105193937581L; /** * The signer's certificate path. * * @serial */ private CertPath signerCertPath; /* * The signature timestamp. * * @serial */ private Timestamp timestamp; /* * Hash code for this code signer. */ private transient int myhash = -1; /** * Constructs a CodeSigner object. * * @param signerCertPath The signer's certificate path. * It must not be {@code null}. * @param timestamp A signature timestamp. * If {@code null} then no timestamp was generated * for the signature. * @throws NullPointerException if {@code signerCertPath} is * {@code null}. */ public CodeSigner(CertPath signerCertPath, Timestamp timestamp) { if (signerCertPath == null) { throw new NullPointerException(); } this.signerCertPath = signerCertPath; this.timestamp = timestamp; } /** * Returns the signer's certificate path. * * @return A certificate path. */ public CertPath getSignerCertPath() { return signerCertPath; } /** * Returns the signature timestamp. * * @return The timestamp or {@code null} if none is present. */ public Timestamp getTimestamp() { return timestamp; } /** * Returns the hash code value for this code signer. * The hash code is generated using the signer's certificate path and the * timestamp, if present. * * @return a hash code value for this code signer. */ public int hashCode() { if (myhash == -1) { if (timestamp == null) { myhash = signerCertPath.hashCode(); } else { myhash = signerCertPath.hashCode() + timestamp.hashCode(); } } return myhash; } /** * Tests for equality between the specified object and this * code signer. Two code signers are considered equal if their * signer certificate paths are equal and if their timestamps are equal, * if present in both. * * @param obj the object to test for equality with this object. * * @return true if the objects are considered equal, false otherwise. */ public boolean equals(Object obj) { if (obj == null || (!(obj instanceof CodeSigner))) { return false; } CodeSigner that = (CodeSigner)obj; if (this == that) { return true; } Timestamp thatTimestamp = that.getTimestamp(); if (timestamp == null) { if (thatTimestamp != null) { return false; } } else { if (thatTimestamp == null || (! timestamp.equals(thatTimestamp))) { return false; } } return signerCertPath.equals(that.getSignerCertPath()); } /** * Returns a string describing this code signer. * * @return A string comprising the signer's certificate and a timestamp, * if present. */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append("("); sb.append("Signer: " + signerCertPath.getCertificates().get(0)); if (timestamp != null) { sb.append("timestamp: " + timestamp); } sb.append(")"); return sb.toString(); } // Explicitly reset hash code value to -1 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); myhash = -1; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 23248 Content-Disposition: inline; filename="CodeSource.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "e2ca471360ad9f5826c5a668a1fac71e32561128" /* * Copyright (c) 1997, 2017, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.net.URL; import java.net.SocketPermission; import java.util.ArrayList; import java.util.List; import java.util.Hashtable; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.cert.*; import sun.misc.IOUtils; /** * *

This class extends the concept of a codebase to * encapsulate not only the location (URL) but also the certificate chains * that were used to verify signed code originating from that location. * * @author Li Gong * @author Roland Schemers */ public class CodeSource implements java.io.Serializable { private static final long serialVersionUID = 4977541819976013951L; /** * The code location. * * @serial */ private URL location; /* * The code signers. */ private transient CodeSigner[] signers = null; /* * The code signers. Certificate chains are concatenated. */ private transient java.security.cert.Certificate certs[] = null; // cached SocketPermission used for matchLocation private transient SocketPermission sp; // for generating cert paths private transient CertificateFactory factory = null; /** * Constructs a CodeSource and associates it with the specified * location and set of certificates. * * @param url the location (URL). * * @param certs the certificate(s). It may be null. The contents of the * array are copied to protect against subsequent modification. */ public CodeSource(URL url, java.security.cert.Certificate certs[]) { this.location = url; // Copy the supplied certs if (certs != null) { this.certs = certs.clone(); } } /** * Constructs a CodeSource and associates it with the specified * location and set of code signers. * * @param url the location (URL). * @param signers the code signers. It may be null. The contents of the * array are copied to protect against subsequent modification. * * @since 1.5 */ public CodeSource(URL url, CodeSigner[] signers) { this.location = url; // Copy the supplied signers if (signers != null) { this.signers = signers.clone(); } } /** * Returns the hash code value for this object. * * @return a hash code value for this object. */ @Override public int hashCode() { if (location != null) return location.hashCode(); else return 0; } /** * Tests for equality between the specified object and this * object. Two CodeSource objects are considered equal if their * locations are of identical value and if their signer certificate * chains are of identical value. It is not required that * the certificate chains be in the same order. * * @param obj the object to test for equality with this object. * * @return true if the objects are considered equal, false otherwise. */ @Override public boolean equals(Object obj) { if (obj == this) return true; // objects types must be equal if (!(obj instanceof CodeSource)) return false; CodeSource cs = (CodeSource) obj; // URLs must match if (location == null) { // if location is null, then cs.location must be null as well if (cs.location != null) return false; } else { // if location is not null, then it must equal cs.location if (!location.equals(cs.location)) return false; } // certs must match return matchCerts(cs, true); } /** * Returns the location associated with this CodeSource. * * @return the location (URL). */ public final URL getLocation() { /* since URL is practically immutable, returning itself is not a security problem */ return this.location; } /** * Returns the certificates associated with this CodeSource. *

* If this CodeSource object was created using the * {@link #CodeSource(URL url, CodeSigner[] signers)} * constructor then its certificate chains are extracted and used to * create an array of Certificate objects. Each signer certificate is * followed by its supporting certificate chain (which may be empty). * Each signer certificate and its supporting certificate chain is ordered * bottom-to-top (i.e., with the signer certificate first and the (root) * certificate authority last). * * @return A copy of the certificates array, or null if there is none. */ public final java.security.cert.Certificate[] getCertificates() { if (certs != null) { return certs.clone(); } else if (signers != null) { // Convert the code signers to certs ArrayList certChains = new ArrayList<>(); for (int i = 0; i < signers.length; i++) { certChains.addAll( signers[i].getSignerCertPath().getCertificates()); } certs = certChains.toArray( new java.security.cert.Certificate[certChains.size()]); return certs.clone(); } else { return null; } } /** * Returns the code signers associated with this CodeSource. *

* If this CodeSource object was created using the * {@link #CodeSource(URL url, java.security.cert.Certificate[] certs)} * constructor then its certificate chains are extracted and used to * create an array of CodeSigner objects. Note that only X.509 certificates * are examined - all other certificate types are ignored. * * @return A copy of the code signer array, or null if there is none. * * @since 1.5 */ public final CodeSigner[] getCodeSigners() { if (signers != null) { return signers.clone(); } else if (certs != null) { // Convert the certs to code signers signers = convertCertArrayToSignerArray(certs); return signers.clone(); } else { return null; } } /** * Returns true if this CodeSource object "implies" the specified CodeSource. *

* More specifically, this method makes the following checks. * If any fail, it returns false. If they all succeed, it returns true. *

    *
  • codesource must not be null. *
  • If this object's certificates are not null, then all * of this object's certificates must be present in codesource's * certificates. *
  • If this object's location (getLocation()) is not null, then the * following checks are made against this object's location and * codesource's: *
      *
    • codesource's location must not be null. * *
    • If this object's location * equals codesource's location, then return true. * *
    • This object's protocol (getLocation().getProtocol()) must be * equal to codesource's protocol, ignoring case. * *
    • If this object's host (getLocation().getHost()) is not null, * then the SocketPermission * constructed with this object's host must imply the * SocketPermission constructed with codesource's host. * *
    • If this object's port (getLocation().getPort()) is not * equal to -1 (that is, if a port is specified), it must equal * codesource's port or default port * (codesource.getLocation().getDefaultPort()). * *
    • If this object's file (getLocation().getFile()) doesn't equal * codesource's file, then the following checks are made: * If this object's file ends with "/-", * then codesource's file must start with this object's * file (exclusive the trailing "-"). * If this object's file ends with a "/*", * then codesource's file must start with this object's * file and must not have any further "/" separators. * If this object's file doesn't end with a "/", * then codesource's file must match this object's * file with a '/' appended. * *
    • If this object's reference (getLocation().getRef()) is * not null, it must equal codesource's reference. * *
    *
*

* For example, the codesource objects with the following locations * and null certificates all imply * the codesource with the location "http://java.sun.com/classes/foo.jar" * and null certificates: *

     *     http:
     *     http://*.sun.com/classes/*
     *     http://java.sun.com/classes/-
     *     http://java.sun.com/classes/foo.jar
     * 
* * Note that if this CodeSource has a null location and a null * certificate chain, then it implies every other CodeSource. * * @param codesource CodeSource to compare against. * * @return true if the specified codesource is implied by this codesource, * false if not. */ public boolean implies(CodeSource codesource) { if (codesource == null) return false; return matchCerts(codesource, false) && matchLocation(codesource); } /** * Returns true if all the certs in this * CodeSource are also in that. * * @param that the CodeSource to check against. * @param strict If true then a strict equality match is performed. * Otherwise a subset match is performed. */ private boolean matchCerts(CodeSource that, boolean strict) { boolean match; // match any key if (certs == null && signers == null) { if (strict) { return (that.certs == null && that.signers == null); } else { return true; } // both have signers } else if (signers != null && that.signers != null) { if (strict && signers.length != that.signers.length) { return false; } for (int i = 0; i < signers.length; i++) { match = false; for (int j = 0; j < that.signers.length; j++) { if (signers[i].equals(that.signers[j])) { match = true; break; } } if (!match) return false; } return true; // both have certs } else if (certs != null && that.certs != null) { if (strict && certs.length != that.certs.length) { return false; } for (int i = 0; i < certs.length; i++) { match = false; for (int j = 0; j < that.certs.length; j++) { if (certs[i].equals(that.certs[j])) { match = true; break; } } if (!match) return false; } return true; } return false; } /** * Returns true if two CodeSource's have the "same" location. * * @param that CodeSource to compare against */ private boolean matchLocation(CodeSource that) { if (location == null) return true; if ((that == null) || (that.location == null)) return false; if (location.equals(that.location)) return true; if (!location.getProtocol().equalsIgnoreCase(that.location.getProtocol())) return false; int thisPort = location.getPort(); if (thisPort != -1) { int thatPort = that.location.getPort(); int port = thatPort != -1 ? thatPort : that.location.getDefaultPort(); if (thisPort != port) return false; } if (location.getFile().endsWith("/-")) { // Matches the directory and (recursively) all files // and subdirectories contained in that directory. // For example, "/a/b/-" implies anything that starts with // "/a/b/" String thisPath = location.getFile().substring(0, location.getFile().length()-1); if (!that.location.getFile().startsWith(thisPath)) return false; } else if (location.getFile().endsWith("/*")) { // Matches the directory and all the files contained in that // directory. // For example, "/a/b/*" implies anything that starts with // "/a/b/" but has no further slashes int last = that.location.getFile().lastIndexOf('/'); if (last == -1) return false; String thisPath = location.getFile().substring(0, location.getFile().length()-1); String thatPath = that.location.getFile().substring(0, last+1); if (!thatPath.equals(thisPath)) return false; } else { // Exact matches only. // For example, "/a/b" and "/a/b/" both imply "/a/b/" if ((!that.location.getFile().equals(location.getFile())) && (!that.location.getFile().equals(location.getFile()+"/"))) { return false; } } if (location.getRef() != null && !location.getRef().equals(that.location.getRef())) { return false; } String thisHost = location.getHost(); String thatHost = that.location.getHost(); if (thisHost != null) { if (("".equals(thisHost) || "localhost".equals(thisHost)) && ("".equals(thatHost) || "localhost".equals(thatHost))) { // ok } else if (!thisHost.equals(thatHost)) { if (thatHost == null) { return false; } if (this.sp == null) { this.sp = new SocketPermission(thisHost, "resolve"); } if (that.sp == null) { that.sp = new SocketPermission(thatHost, "resolve"); } if (!this.sp.implies(that.sp)) { return false; } } } // everything matches return true; } /** * Returns a string describing this CodeSource, telling its * URL and certificates. * * @return information about this CodeSource. */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("("); sb.append(this.location); if (this.certs != null && this.certs.length > 0) { for (int i = 0; i < this.certs.length; i++) { sb.append( " " + this.certs[i]); } } else if (this.signers != null && this.signers.length > 0) { for (int i = 0; i < this.signers.length; i++) { sb.append( " " + this.signers[i]); } } else { sb.append(" "); } sb.append(")"); return sb.toString(); } /** * Writes this object out to a stream (i.e., serializes it). * * @serialData An initial {@code URL} is followed by an * {@code int} indicating the number of certificates to follow * (a value of "zero" denotes that there are no certificates associated * with this object). * Each certificate is written out starting with a {@code String} * denoting the certificate type, followed by an * {@code int} specifying the length of the certificate encoding, * followed by the certificate encoding itself which is written out as an * array of bytes. Finally, if any code signers are present then the array * of code signers is serialized and written out too. */ private void writeObject(java.io.ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); // location // Serialize the array of certs if (certs == null || certs.length == 0) { oos.writeInt(0); } else { // write out the total number of certs oos.writeInt(certs.length); // write out each cert, including its type for (int i = 0; i < certs.length; i++) { java.security.cert.Certificate cert = certs[i]; try { oos.writeUTF(cert.getType()); byte[] encoded = cert.getEncoded(); oos.writeInt(encoded.length); oos.write(encoded); } catch (CertificateEncodingException cee) { throw new IOException(cee.getMessage()); } } } // Serialize the array of code signers (if any) if (signers != null && signers.length > 0) { oos.writeObject(signers); } } /** * Restores this object from a stream (i.e., deserializes it). */ private void readObject(java.io.ObjectInputStream ois) throws IOException, ClassNotFoundException { CertificateFactory cf; Hashtable cfs = null; List certList = null; ois.defaultReadObject(); // location // process any new-style certs in the stream (if present) int size = ois.readInt(); if (size > 0) { // we know of 3 different cert types: X.509, PGP, SDSI, which // could all be present in the stream at the same time cfs = new Hashtable(3); certList = new ArrayList<>(size > 20 ? 20 : size); } else if (size < 0) { throw new IOException("size cannot be negative"); } for (int i = 0; i < size; i++) { // read the certificate type, and instantiate a certificate // factory of that type (reuse existing factory if possible) String certType = ois.readUTF(); if (cfs.containsKey(certType)) { // reuse certificate factory cf = cfs.get(certType); } else { // create new certificate factory try { cf = CertificateFactory.getInstance(certType); } catch (CertificateException ce) { throw new ClassNotFoundException ("Certificate factory for " + certType + " not found"); } // store the certificate factory so we can reuse it later cfs.put(certType, cf); } // parse the certificate byte[] encoded = IOUtils.readExactlyNBytes(ois, ois.readInt()); ByteArrayInputStream bais = new ByteArrayInputStream(encoded); try { certList.add(cf.generateCertificate(bais)); } catch (CertificateException ce) { throw new IOException(ce.getMessage()); } bais.close(); } if (certList != null) { this.certs = certList.toArray( new java.security.cert.Certificate[size]); } // Deserialize array of code signers (if any) try { this.signers = ((CodeSigner[])ois.readObject()).clone(); } catch (IOException ioe) { // no signers present } } /* * Convert an array of certificates to an array of code signers. * The array of certificates is a concatenation of certificate chains * where the initial certificate in each chain is the end-entity cert. * * @return An array of code signers or null if none are generated. */ private CodeSigner[] convertCertArrayToSignerArray( java.security.cert.Certificate[] certs) { if (certs == null) { return null; } try { // Initialize certificate factory if (factory == null) { factory = CertificateFactory.getInstance("X.509"); } // Iterate through all the certificates int i = 0; List signers = new ArrayList<>(); while (i < certs.length) { List certChain = new ArrayList<>(); certChain.add(certs[i++]); // first cert is an end-entity cert int j = i; // Extract chain of certificates // (loop while certs are not end-entity certs) while (j < certs.length && certs[j] instanceof X509Certificate && ((X509Certificate)certs[j]).getBasicConstraints() != -1) { certChain.add(certs[j]); j++; } i = j; CertPath certPath = factory.generateCertPath(certChain); signers.add(new CodeSigner(certPath, null)); } if (signers.isEmpty()) { return null; } else { return signers.toArray(new CodeSigner[signers.size()]); } } catch (CertificateException e) { return null; //TODO - may be better to throw an ex. here } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2147 Content-Disposition: inline; filename="CryptoPrimitive.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "158643b9574cac1cc2ab55c068490b73a969d20f" /* * Copyright (c) 2010, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * An enumeration of cryptographic primitives. * * @since 1.7 */ public enum CryptoPrimitive { /** * Hash function */ MESSAGE_DIGEST, /** * Cryptographic random number generator */ SECURE_RANDOM, /** * Symmetric primitive: block cipher */ BLOCK_CIPHER, /** * Symmetric primitive: stream cipher */ STREAM_CIPHER, /** * Symmetric primitive: message authentication code */ MAC, /** * Symmetric primitive: key wrap */ KEY_WRAP, /** * Asymmetric primitive: public key encryption */ PUBLIC_KEY_ENCRYPTION, /** * Asymmetric primitive: signature scheme */ SIGNATURE, /** * Asymmetric primitive: key encapsulation mechanism */ KEY_ENCAPSULATION, /** * Asymmetric primitive: key agreement and key distribution */ KEY_AGREEMENT } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3128 Content-Disposition: inline; filename="DigestException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "2327c982845abcc481da62838903b6037883cd42" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This is the generic Message Digest exception. * * @author Benjamin Renaud */ public class DigestException extends GeneralSecurityException { private static final long serialVersionUID = 5821450303093652515L; /** * Constructs a DigestException with no detail message. (A * detail message is a String that describes this particular * exception.) */ public DigestException() { super(); } /** * Constructs a DigestException with the specified detail * message. (A detail message is a String that describes this * particular exception.) * * @param msg the detail message. */ public DigestException(String msg) { super(msg); } /** * Creates a {@code DigestException} with the specified * detail message and cause. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public DigestException(String message, Throwable cause) { super(message, cause); } /** * Creates a {@code DigestException} with the specified cause * and a detail message of {@code (cause==null ? null : cause.toString())} * (which typically contains the class and detail message of * {@code cause}). * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public DigestException(Throwable cause) { super(cause); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 6526 Content-Disposition: inline; filename="DigestInputStream.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "a1bf55ac9e7b4d9ce9a96f70047f1fab986f015c" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.IOException; import java.io.EOFException; import java.io.InputStream; import java.io.FilterInputStream; import java.io.PrintStream; import java.io.ByteArrayInputStream; /** * A transparent stream that updates the associated message digest using * the bits going through the stream. * *

To complete the message digest computation, call one of the * {@code digest} methods on the associated message * digest after your calls to one of this digest input stream's * {@link #read() read} methods. * *

It is possible to turn this stream on or off (see * {@link #on(boolean) on}). When it is on, a call to one of the * {@code read} methods * results in an update on the message digest. But when it is off, * the message digest is not updated. The default is for the stream * to be on. * *

Note that digest objects can compute only one digest (see * {@link MessageDigest}), * so that in order to compute intermediate digests, a caller should * retain a handle onto the digest object, and clone it for each * digest to be computed, leaving the orginal digest untouched. * * @see MessageDigest * * @see DigestOutputStream * * @author Benjamin Renaud */ public class DigestInputStream extends FilterInputStream { /* NOTE: This should be made a generic UpdaterInputStream */ /* Are we on or off? */ private boolean on = true; /** * The message digest associated with this stream. */ protected MessageDigest digest; /** * Creates a digest input stream, using the specified input stream * and message digest. * * @param stream the input stream. * * @param digest the message digest to associate with this stream. */ public DigestInputStream(InputStream stream, MessageDigest digest) { super(stream); setMessageDigest(digest); } /** * Returns the message digest associated with this stream. * * @return the message digest associated with this stream. * @see #setMessageDigest(java.security.MessageDigest) */ public MessageDigest getMessageDigest() { return digest; } /** * Associates the specified message digest with this stream. * * @param digest the message digest to be associated with this stream. * @see #getMessageDigest() */ public void setMessageDigest(MessageDigest digest) { this.digest = digest; } /** * Reads a byte, and updates the message digest (if the digest * function is on). That is, this method reads a byte from the * input stream, blocking until the byte is actually read. If the * digest function is on (see {@link #on(boolean) on}), this method * will then call {@code update} on the message digest associated * with this stream, passing it the byte read. * * @return the byte read. * * @exception IOException if an I/O error occurs. * * @see MessageDigest#update(byte) */ public int read() throws IOException { int ch = in.read(); if (on && ch != -1) { digest.update((byte)ch); } return ch; } /** * Reads into a byte array, and updates the message digest (if the * digest function is on). That is, this method reads up to * {@code len} bytes from the input stream into the array * {@code b}, starting at offset {@code off}. This method * blocks until the data is actually * read. If the digest function is on (see * {@link #on(boolean) on}), this method will then call {@code update} * on the message digest associated with this stream, passing it * the data. * * @param b the array into which the data is read. * * @param off the starting offset into {@code b} of where the * data should be placed. * * @param len the maximum number of bytes to be read from the input * stream into b, starting at offset {@code off}. * * @return the actual number of bytes read. This is less than * {@code len} if the end of the stream is reached prior to * reading {@code len} bytes. -1 is returned if no bytes were * read because the end of the stream had already been reached when * the call was made. * * @exception IOException if an I/O error occurs. * * @see MessageDigest#update(byte[], int, int) */ public int read(byte[] b, int off, int len) throws IOException { int result = in.read(b, off, len); if (on && result != -1) { digest.update(b, off, result); } return result; } /** * Turns the digest function on or off. The default is on. When * it is on, a call to one of the {@code read} methods results in an * update on the message digest. But when it is off, the message * digest is not updated. * * @param on true to turn the digest function on, false to turn * it off. */ public void on(boolean on) { this.on = on; } /** * Prints a string representation of this digest input stream and * its associated message digest object. */ public String toString() { return "[Digest Input Stream] " + digest.toString(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5967 Content-Disposition: inline; filename="DigestOutputStream.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "51db133a5f67279a8c1685f3cefc73428235c827" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.IOException; import java.io.EOFException; import java.io.OutputStream; import java.io.FilterOutputStream; import java.io.PrintStream; import java.io.ByteArrayOutputStream; /** * A transparent stream that updates the associated message digest using * the bits going through the stream. * *

To complete the message digest computation, call one of the * {@code digest} methods on the associated message * digest after your calls to one of this digest output stream's * {@link #write(int) write} methods. * *

It is possible to turn this stream on or off (see * {@link #on(boolean) on}). When it is on, a call to one of the * {@code write} methods results in * an update on the message digest. But when it is off, the message * digest is not updated. The default is for the stream to be on. * * @see MessageDigest * @see DigestInputStream * * @author Benjamin Renaud */ public class DigestOutputStream extends FilterOutputStream { private boolean on = true; /** * The message digest associated with this stream. */ protected MessageDigest digest; /** * Creates a digest output stream, using the specified output stream * and message digest. * * @param stream the output stream. * * @param digest the message digest to associate with this stream. */ public DigestOutputStream(OutputStream stream, MessageDigest digest) { super(stream); setMessageDigest(digest); } /** * Returns the message digest associated with this stream. * * @return the message digest associated with this stream. * @see #setMessageDigest(java.security.MessageDigest) */ public MessageDigest getMessageDigest() { return digest; } /** * Associates the specified message digest with this stream. * * @param digest the message digest to be associated with this stream. * @see #getMessageDigest() */ public void setMessageDigest(MessageDigest digest) { this.digest = digest; } /** * Updates the message digest (if the digest function is on) using * the specified byte, and in any case writes the byte * to the output stream. That is, if the digest function is on * (see {@link #on(boolean) on}), this method calls * {@code update} on the message digest associated with this * stream, passing it the byte {@code b}. This method then * writes the byte to the output stream, blocking until the byte * is actually written. * * @param b the byte to be used for updating and writing to the * output stream. * * @exception IOException if an I/O error occurs. * * @see MessageDigest#update(byte) */ public void write(int b) throws IOException { out.write(b); if (on) { digest.update((byte)b); } } /** * Updates the message digest (if the digest function is on) using * the specified subarray, and in any case writes the subarray to * the output stream. That is, if the digest function is on (see * {@link #on(boolean) on}), this method calls {@code update} * on the message digest associated with this stream, passing it * the subarray specifications. This method then writes the subarray * bytes to the output stream, blocking until the bytes are actually * written. * * @param b the array containing the subarray to be used for updating * and writing to the output stream. * * @param off the offset into {@code b} of the first byte to * be updated and written. * * @param len the number of bytes of data to be updated and written * from {@code b}, starting at offset {@code off}. * * @exception IOException if an I/O error occurs. * * @see MessageDigest#update(byte[], int, int) */ public void write(byte[] b, int off, int len) throws IOException { out.write(b, off, len); if (on) { digest.update(b, off, len); } } /** * Turns the digest function on or off. The default is on. When * it is on, a call to one of the {@code write} methods results in an * update on the message digest. But when it is off, the message * digest is not updated. * * @param on true to turn the digest function on, false to turn it * off. */ public void on(boolean on) { this.on = on; } /** * Prints a string representation of this digest output stream and * its associated message digest object. */ public String toString() { return "[Digest Output Stream] " + digest.toString(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5518 Content-Disposition: inline; filename="DomainCombiner.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "7aadc7e7b2f3135871ff7af78db8813ddf9a9c3c" /* * Copyright (c) 1999, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * A {@code DomainCombiner} provides a means to dynamically * update the ProtectionDomains associated with the current * {@code AccessControlContext}. * *

A {@code DomainCombiner} is passed as a parameter to the * appropriate constructor for {@code AccessControlContext}. * The newly constructed context is then passed to the * {@code AccessController.doPrivileged(..., context)} method * to bind the provided context (and associated {@code DomainCombiner}) * with the current execution Thread. Subsequent calls to * {@code AccessController.getContext} or * {@code AccessController.checkPermission} * cause the {@code DomainCombiner.combine} to get invoked. * *

The combine method takes two arguments. The first argument represents * an array of ProtectionDomains from the current execution Thread, * since the most recent call to {@code AccessController.doPrivileged}. * If no call to doPrivileged was made, then the first argument will contain * all the ProtectionDomains from the current execution Thread. * The second argument represents an array of inherited ProtectionDomains, * which may be {@code null}. ProtectionDomains may be inherited * from a parent Thread, or from a privileged context. If no call to * doPrivileged was made, then the second argument will contain the * ProtectionDomains inherited from the parent Thread. If one or more calls * to doPrivileged were made, and the most recent call was to * doPrivileged(action, context), then the second argument will contain the * ProtectionDomains from the privileged context. If the most recent call * was to doPrivileged(action), then there is no privileged context, * and the second argument will be {@code null}. * *

The {@code combine} method investigates the two input arrays * of ProtectionDomains and returns a single array containing the updated * ProtectionDomains. In the simplest case, the {@code combine} * method merges the two stacks into one. In more complex cases, * the {@code combine} method returns a modified * stack of ProtectionDomains. The modification may have added new * ProtectionDomains, removed certain ProtectionDomains, or simply * updated existing ProtectionDomains. Re-ordering and other optimizations * to the ProtectionDomains are also permitted. Typically the * {@code combine} method bases its updates on the information * encapsulated in the {@code DomainCombiner}. * *

After the {@code AccessController.getContext} method * receives the combined stack of ProtectionDomains back from * the {@code DomainCombiner}, it returns a new * AccessControlContext that has both the combined ProtectionDomains * as well as the {@code DomainCombiner}. * * @see AccessController * @see AccessControlContext * @since 1.3 */ public interface DomainCombiner { /** * Modify or update the provided ProtectionDomains. * ProtectionDomains may be added to or removed from the given * ProtectionDomains. The ProtectionDomains may be re-ordered. * Individual ProtectionDomains may be modified (with a new * set of Permissions, for example). * *

* * @param currentDomains the ProtectionDomains associated with the * current execution Thread, up to the most recent * privileged {@code ProtectionDomain}. * The ProtectionDomains are are listed in order of execution, * with the most recently executing {@code ProtectionDomain} * residing at the beginning of the array. This parameter may * be {@code null} if the current execution Thread * has no associated ProtectionDomains.

* * @param assignedDomains an array of inherited ProtectionDomains. * ProtectionDomains may be inherited from a parent Thread, * or from a privileged {@code AccessControlContext}. * This parameter may be {@code null} * if there are no inherited ProtectionDomains. * * @return a new array consisting of the updated ProtectionDomains, * or {@code null}. */ ProtectionDomain[] combine(ProtectionDomain[] currentDomains, ProtectionDomain[] assignedDomains); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 6879 Content-Disposition: inline; filename="DomainLoadStoreParameter.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "bc9697597e50633c0801777a957831e1d8709f06" /* * Copyright (c) 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.net.URI; import java.util.*; import static java.security.KeyStore.*; /** * Configuration data that specifies the keystores in a keystore domain. * A keystore domain is a collection of keystores that are presented as a * single logical keystore. The configuration data is used during * {@code KeyStore} * {@link KeyStore#load(KeyStore.LoadStoreParameter) load} and * {@link KeyStore#store(KeyStore.LoadStoreParameter) store} operations. *

* The following syntax is supported for configuration data: *

{@code
 *     domain  [ ...] {
 *         keystore  [ ...] ;
 *         ...
 *     };
 *     ...
 * }
* where {@code domainName} and {@code keystoreName} are identifiers * and {@code property} is a key/value pairing. The key and value are * separated by an 'equals' symbol and the value is enclosed in double * quotes. A property value may be either a printable string or a binary * string of colon-separated pairs of hexadecimal digits. Multi-valued * properties are represented as a comma-separated list of values, * enclosed in square brackets. * See {@link Arrays#toString(java.lang.Object[])}. *

* To ensure that keystore entries are uniquely identified, each * entry's alias is prefixed by its {@code keystoreName} followed * by the entry name separator and each {@code keystoreName} must be * unique within its domain. Entry name prefixes are omitted when * storing a keystore. *

* Properties are context-sensitive: properties that apply to * all the keystores in a domain are located in the domain clause, * and properties that apply only to a specific keystore are located * in that keystore's clause. * Unless otherwise specified, a property in a keystore clause overrides * a property of the same name in the domain clause. All property names * are case-insensitive. The following properties are supported: *

*
{@code keystoreType=""}
*
The keystore type.
*
{@code keystoreURI=""}
*
The keystore location.
*
{@code keystoreProviderName=""}
*
The name of the keystore's JCE provider.
*
{@code keystorePasswordEnv=""}
*
The environment variable that stores a keystore password. * Alternatively, passwords may be supplied to the constructor * method in a {@code Map}.
*
{@code entryNameSeparator=""}
*
The separator between a keystore name prefix and an entry name. * When specified, it applies to all the entries in a domain. * Its default value is a space.
*
*

* For example, configuration data for a simple keystore domain * comprising three keystores is shown below: *

 *
 * domain app1 {
 *     keystore app1-truststore
 *         keystoreURI="file:///app1/etc/truststore.jks";
 *
 *     keystore system-truststore
 *         keystoreURI="${java.home}/lib/security/cacerts";
 *
 *     keystore app1-keystore
 *         keystoreType="PKCS12"
 *         keystoreURI="file:///app1/etc/keystore.p12";
 * };
 *
 * 
* @since 1.8 */ public final class DomainLoadStoreParameter implements LoadStoreParameter { private final URI configuration; private final Map protectionParams; /** * Constructs a DomainLoadStoreParameter for a keystore domain with * the parameters used to protect keystore data. * * @param configuration identifier for the domain configuration data. * The name of the target domain should be specified in the * {@code java.net.URI} fragment component when it is necessary * to distinguish between several domain configurations at the * same location. * * @param protectionParams the map from keystore name to the parameter * used to protect keystore data. * A {@code java.util.Collections.EMPTY_MAP} should be used * when protection parameters are not required or when they have * been specified by properties in the domain configuration data. * It is cloned to prevent subsequent modification. * * @exception NullPointerException if {@code configuration} or * {@code protectionParams} is {@code null} */ public DomainLoadStoreParameter(URI configuration, Map protectionParams) { if (configuration == null || protectionParams == null) { throw new NullPointerException("invalid null input"); } this.configuration = configuration; this.protectionParams = Collections.unmodifiableMap(new HashMap<>(protectionParams)); } /** * Gets the identifier for the domain configuration data. * * @return the identifier for the configuration data */ public URI getConfiguration() { return configuration; } /** * Gets the keystore protection parameters for keystores in this * domain. * * @return an unmodifiable map of keystore names to protection * parameters */ public Map getProtectionParams() { return protectionParams; } /** * Gets the keystore protection parameters for this domain. * Keystore domains do not support a protection parameter. * * @return always returns {@code null} */ @Override public KeyStore.ProtectionParameter getProtectionParameter() { return null; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3241 Content-Disposition: inline; filename="GeneralSecurityException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "dc9ea06ecce6edb19a75dba3a85be73c774bfb43" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * The {@code GeneralSecurityException} class is a generic * security exception class that provides type safety for all the * security-related exception classes that extend from it. * * @author Jan Luehe */ public class GeneralSecurityException extends Exception { private static final long serialVersionUID = 894798122053539237L; /** * Constructs a GeneralSecurityException with no detail message. */ public GeneralSecurityException() { super(); } /** * Constructs a GeneralSecurityException with the specified detail * message. * A detail message is a String that describes this particular * exception. * * @param msg the detail message. */ public GeneralSecurityException(String msg) { super(msg); } /** * Creates a {@code GeneralSecurityException} with the specified * detail message and cause. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public GeneralSecurityException(String message, Throwable cause) { super(message, cause); } /** * Creates a {@code GeneralSecurityException} with the specified cause * and a detail message of {@code (cause==null ? null : cause.toString())} * (which typically contains the class and detail message of * {@code cause}). * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public GeneralSecurityException(Throwable cause) { super(cause); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2114 Content-Disposition: inline; filename="Guard.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "abafb5886594fb136aafe386e3433f1bf47a8b3e" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** *

This interface represents a guard, which is an object that is used * to protect access to another object. * *

This interface contains a single method, {@code checkGuard}, * with a single {@code object} argument. {@code checkGuard} is * invoked (by the GuardedObject {@code getObject} method) * to determine whether or not to allow access to the object. * * @see GuardedObject * * @author Roland Schemers * @author Li Gong */ public interface Guard { /** * Determines whether or not to allow access to the guarded object * {@code object}. Returns silently if access is allowed. * Otherwise, throws a SecurityException. * * @param object the object being protected by the guard. * * @exception SecurityException if access is denied. * */ void checkGuard(Object object) throws SecurityException; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3320 Content-Disposition: inline; filename="GuardedObject.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "a275ddf043ee593eaf04a311b8682676e0993ff1" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * A GuardedObject is an object that is used to protect access to * another object. * *

A GuardedObject encapsulates a target object and a Guard object, * such that access to the target object is possible * only if the Guard object allows it. * Once an object is encapsulated by a GuardedObject, * access to that object is controlled by the {@code getObject} * method, which invokes the * {@code checkGuard} method on the Guard object that is * guarding access. If access is not allowed, * an exception is thrown. * * @see Guard * @see Permission * * @author Roland Schemers * @author Li Gong */ public class GuardedObject implements java.io.Serializable { private static final long serialVersionUID = -5240450096227834308L; private Object object; // the object we are guarding private Guard guard; // the guard /** * Constructs a GuardedObject using the specified object and guard. * If the Guard object is null, then no restrictions will * be placed on who can access the object. * * @param object the object to be guarded. * * @param guard the Guard object that guards access to the object. */ public GuardedObject(Object object, Guard guard) { this.guard = guard; this.object = object; } /** * Retrieves the guarded object, or throws an exception if access * to the guarded object is denied by the guard. * * @return the guarded object. * * @exception SecurityException if access to the guarded object is * denied. */ public Object getObject() throws SecurityException { if (guard != null) guard.checkGuard(object); return object; } /** * Writes this object out to a stream (i.e., serializes it). * We check the guard if there is one. */ private void writeObject(java.io.ObjectOutputStream oos) throws java.io.IOException { if (guard != null) guard.checkGuard(object); oos.defaultWriteObject(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 15805 Content-Disposition: inline; filename="Identity.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "6eada6d9fd798e30c20c0a4027365671aeac2198" /* * Copyright (c) 1996, 2015, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.Serializable; import java.util.*; /** *

This class represents identities: real-world objects such as people, * companies or organizations whose identities can be authenticated using * their public keys. Identities may also be more abstract (or concrete) * constructs, such as daemon threads or smart cards. * *

All Identity objects have a name and a public key. Names are * immutable. Identities may also be scoped. That is, if an Identity is * specified to have a particular scope, then the name and public * key of the Identity are unique within that scope. * *

An Identity also has a set of certificates (all certifying its own * public key). The Principal names specified in these certificates need * not be the same, only the key. * *

An Identity can be subclassed, to include postal and email addresses, * telephone numbers, images of faces and logos, and so on. * * @see IdentityScope * @see Signer * @see Principal * * @author Benjamin Renaud * @deprecated This class is no longer used. Its functionality has been * replaced by {@code java.security.KeyStore}, the * {@code java.security.cert} package, and * {@code java.security.Principal}. */ @Deprecated public abstract class Identity implements Principal, Serializable { /** use serialVersionUID from JDK 1.1.x for interoperability */ private static final long serialVersionUID = 3609922007826600659L; /** * The name for this identity. * * @serial */ private String name; /** * The public key for this identity. * * @serial */ private PublicKey publicKey; /** * Generic, descriptive information about the identity. * * @serial */ String info = "No further information available."; /** * The scope of the identity. * * @serial */ IdentityScope scope; /** * The certificates for this identity. * * @serial */ Vector certificates; /** * Constructor for serialization only. */ protected Identity() { this("restoring..."); } /** * Constructs an identity with the specified name and scope. * * @param name the identity name. * @param scope the scope of the identity. * * @exception KeyManagementException if there is already an identity * with the same name in the scope. */ public Identity(String name, IdentityScope scope) throws KeyManagementException { this(name); if (scope != null) { scope.addIdentity(this); } this.scope = scope; } /** * Constructs an identity with the specified name and no scope. * * @param name the identity name. */ public Identity(String name) { this.name = name; } /** * Returns this identity's name. * * @return the name of this identity. */ public final String getName() { return name; } /** * Returns this identity's scope. * * @return the scope of this identity. */ public final IdentityScope getScope() { return scope; } /** * Returns this identity's public key. * * @return the public key for this identity. * * @see #setPublicKey */ public PublicKey getPublicKey() { return publicKey; } /** * Sets this identity's public key. The old key and all of this * identity's certificates are removed by this operation. * *

First, if there is a security manager, its {@code checkSecurityAccess} * method is called with {@code "setIdentityPublicKey"} * as its argument to see if it's ok to set the public key. * * @param key the public key for this identity. * * @exception KeyManagementException if another identity in the * identity's scope has the same public key, or if another exception occurs. * * @exception SecurityException if a security manager exists and its * {@code checkSecurityAccess} method doesn't allow * setting the public key. * * @see #getPublicKey * @see SecurityManager#checkSecurityAccess */ /* Should we throw an exception if this is already set? */ public void setPublicKey(PublicKey key) throws KeyManagementException { check("setIdentityPublicKey"); this.publicKey = key; certificates = new Vector(); } /** * Specifies a general information string for this identity. * *

First, if there is a security manager, its {@code checkSecurityAccess} * method is called with {@code "setIdentityInfo"} * as its argument to see if it's ok to specify the information string. * * @param info the information string. * * @exception SecurityException if a security manager exists and its * {@code checkSecurityAccess} method doesn't allow * setting the information string. * * @see #getInfo * @see SecurityManager#checkSecurityAccess */ public void setInfo(String info) { check("setIdentityInfo"); this.info = info; } /** * Returns general information previously specified for this identity. * * @return general information about this identity. * * @see #setInfo */ public String getInfo() { return info; } /** * Adds a certificate for this identity. If the identity has a public * key, the public key in the certificate must be the same, and if * the identity does not have a public key, the identity's * public key is set to be that specified in the certificate. * *

First, if there is a security manager, its {@code checkSecurityAccess} * method is called with {@code "addIdentityCertificate"} * as its argument to see if it's ok to add a certificate. * * @param certificate the certificate to be added. * * @exception KeyManagementException if the certificate is not valid, * if the public key in the certificate being added conflicts with * this identity's public key, or if another exception occurs. * * @exception SecurityException if a security manager exists and its * {@code checkSecurityAccess} method doesn't allow * adding a certificate. * * @see SecurityManager#checkSecurityAccess */ public void addCertificate(Certificate certificate) throws KeyManagementException { check("addIdentityCertificate"); if (certificates == null) { certificates = new Vector(); } if (publicKey != null) { if (!keyEquals(publicKey, certificate.getPublicKey())) { throw new KeyManagementException( "public key different from cert public key"); } } else { publicKey = certificate.getPublicKey(); } certificates.addElement(certificate); } private boolean keyEquals(PublicKey aKey, PublicKey anotherKey) { String aKeyFormat = aKey.getFormat(); String anotherKeyFormat = anotherKey.getFormat(); if ((aKeyFormat == null) ^ (anotherKeyFormat == null)) return false; if (aKeyFormat != null && anotherKeyFormat != null) if (!aKeyFormat.equalsIgnoreCase(anotherKeyFormat)) return false; return java.util.Arrays.equals(aKey.getEncoded(), anotherKey.getEncoded()); } /** * Removes a certificate from this identity. * *

First, if there is a security manager, its {@code checkSecurityAccess} * method is called with {@code "removeIdentityCertificate"} * as its argument to see if it's ok to remove a certificate. * * @param certificate the certificate to be removed. * * @exception KeyManagementException if the certificate is * missing, or if another exception occurs. * * @exception SecurityException if a security manager exists and its * {@code checkSecurityAccess} method doesn't allow * removing a certificate. * * @see SecurityManager#checkSecurityAccess */ public void removeCertificate(Certificate certificate) throws KeyManagementException { check("removeIdentityCertificate"); if (certificates != null) { certificates.removeElement(certificate); } } /** * Returns a copy of all the certificates for this identity. * * @return a copy of all the certificates for this identity. */ public Certificate[] certificates() { if (certificates == null) { return new Certificate[0]; } int len = certificates.size(); Certificate[] certs = new Certificate[len]; certificates.copyInto(certs); return certs; } /** * Tests for equality between the specified object and this identity. * This first tests to see if the entities actually refer to the same * object, in which case it returns true. Next, it checks to see if * the entities have the same name and the same scope. If they do, * the method returns true. Otherwise, it calls * {@link #identityEquals(Identity) identityEquals}, which subclasses should * override. * * @param identity the object to test for equality with this identity. * * @return true if the objects are considered equal, false otherwise. * * @see #identityEquals */ public final boolean equals(Object identity) { if (identity == this) { return true; } if (identity instanceof Identity) { Identity i = (Identity)identity; if (this.fullName().equals(i.fullName())) { return true; } else { return identityEquals(i); } } return false; } /** * Tests for equality between the specified identity and this identity. * This method should be overriden by subclasses to test for equality. * The default behavior is to return true if the names and public keys * are equal. * * @param identity the identity to test for equality with this identity. * * @return true if the identities are considered equal, false * otherwise. * * @see #equals */ protected boolean identityEquals(Identity identity) { if (!name.equalsIgnoreCase(identity.name)) return false; if ((publicKey == null) ^ (identity.publicKey == null)) return false; if (publicKey != null && identity.publicKey != null) if (!publicKey.equals(identity.publicKey)) return false; return true; } /** * Returns a parsable name for identity: identityName.scopeName */ String fullName() { String parsable = name; if (scope != null) { parsable += "." + scope.getName(); } return parsable; } /** * Returns a short string describing this identity, telling its * name and its scope (if any). * *

First, if there is a security manager, its {@code checkSecurityAccess} * method is called with {@code "printIdentity"} * as its argument to see if it's ok to return the string. * * @return information about this identity, such as its name and the * name of its scope (if any). * * @exception SecurityException if a security manager exists and its * {@code checkSecurityAccess} method doesn't allow * returning a string describing this identity. * * @see SecurityManager#checkSecurityAccess */ public String toString() { check("printIdentity"); String printable = name; if (scope != null) { printable += "[" + scope.getName() + "]"; } return printable; } /** * Returns a string representation of this identity, with * optionally more details than that provided by the * {@code toString} method without any arguments. * *

First, if there is a security manager, its {@code checkSecurityAccess} * method is called with {@code "printIdentity"} * as its argument to see if it's ok to return the string. * * @param detailed whether or not to provide detailed information. * * @return information about this identity. If {@code detailed} * is true, then this method returns more information than that * provided by the {@code toString} method without any arguments. * * @exception SecurityException if a security manager exists and its * {@code checkSecurityAccess} method doesn't allow * returning a string describing this identity. * * @see #toString * @see SecurityManager#checkSecurityAccess */ public String toString(boolean detailed) { String out = toString(); if (detailed) { out += "\n"; out += printKeys(); out += "\n" + printCertificates(); if (info != null) { out += "\n\t" + info; } else { out += "\n\tno additional information available."; } } return out; } String printKeys() { String key = ""; if (publicKey != null) { key = "\tpublic key initialized"; } else { key = "\tno public key"; } return key; } String printCertificates() { String out = ""; if (certificates == null) { return "\tno certificates"; } else { out += "\tcertificates: \n"; int i = 1; for (Certificate cert : certificates) { out += "\tcertificate " + i++ + "\tfor : " + cert.getPrincipal() + "\n"; out += "\t\t\tfrom : " + cert.getGuarantor() + "\n"; } } return out; } /** * Returns a hashcode for this identity. * * @return a hashcode for this identity. */ public int hashCode() { return name.hashCode(); } private static void check(String directive) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkSecurityAccess(directive); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 8445 Content-Disposition: inline; filename="IdentityScope.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "7b18387a353c1c9979c9857e0bb5aa7f5f066d2b" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.Serializable; import java.util.Enumeration; import java.util.Properties; /** *

This class represents a scope for identities. It is an Identity * itself, and therefore has a name and can have a scope. It can also * optionally have a public key and associated certificates. * *

An IdentityScope can contain Identity objects of all kinds, including * Signers. All types of Identity objects can be retrieved, added, and * removed using the same methods. Note that it is possible, and in fact * expected, that different types of identity scopes will * apply different policies for their various operations on the * various types of Identities. * *

There is a one-to-one mapping between keys and identities, and * there can only be one copy of one key per scope. For example, suppose * Acme Software, Inc is a software publisher known to a user. * Suppose it is an Identity, that is, it has a public key, and a set of * associated certificates. It is named in the scope using the name * "Acme Software". No other named Identity in the scope has the same * public key. Of course, none has the same name as well. * * @see Identity * @see Signer * @see Principal * @see Key * * @author Benjamin Renaud * * @deprecated This class is no longer used. Its functionality has been * replaced by {@code java.security.KeyStore}, the * {@code java.security.cert} package, and * {@code java.security.Principal}. */ @Deprecated public abstract class IdentityScope extends Identity { private static final long serialVersionUID = -2337346281189773310L; /* The system's scope */ private static IdentityScope scope; // initialize the system scope private static void initializeSystemScope() { String classname = AccessController.doPrivileged( new PrivilegedAction() { public String run() { return Security.getProperty("system.scope"); } }); if (classname == null) { return; } else { try { Class.forName(classname); } catch (ClassNotFoundException e) { System.err.println("unable to establish a system scope from " + classname); e.printStackTrace(); } } } /** * This constructor is used for serialization only and should not * be used by subclasses. */ protected IdentityScope() { this("restoring..."); } /** * Constructs a new identity scope with the specified name. * * @param name the scope name. */ public IdentityScope(String name) { super(name); } /** * Constructs a new identity scope with the specified name and scope. * * @param name the scope name. * @param scope the scope for the new identity scope. * * @exception KeyManagementException if there is already an identity * with the same name in the scope. */ public IdentityScope(String name, IdentityScope scope) throws KeyManagementException { super(name, scope); } /** * Returns the system's identity scope. * * @return the system's identity scope, or {@code null} if none has been * set. * * @see #setSystemScope */ public static IdentityScope getSystemScope() { if (scope == null) { initializeSystemScope(); } return scope; } /** * Sets the system's identity scope. * *

First, if there is a security manager, its * {@code checkSecurityAccess} * method is called with {@code "setSystemScope"} * as its argument to see if it's ok to set the identity scope. * * @param scope the scope to set. * * @exception SecurityException if a security manager exists and its * {@code checkSecurityAccess} method doesn't allow * setting the identity scope. * * @see #getSystemScope * @see SecurityManager#checkSecurityAccess */ protected static void setSystemScope(IdentityScope scope) { check("setSystemScope"); IdentityScope.scope = scope; } /** * Returns the number of identities within this identity scope. * * @return the number of identities within this identity scope. */ public abstract int size(); /** * Returns the identity in this scope with the specified name (if any). * * @param name the name of the identity to be retrieved. * * @return the identity named {@code name}, or null if there are * no identities named {@code name} in this scope. */ public abstract Identity getIdentity(String name); /** * Retrieves the identity whose name is the same as that of the * specified principal. (Note: Identity implements Principal.) * * @param principal the principal corresponding to the identity * to be retrieved. * * @return the identity whose name is the same as that of the * principal, or null if there are no identities of the same name * in this scope. */ public Identity getIdentity(Principal principal) { return getIdentity(principal.getName()); } /** * Retrieves the identity with the specified public key. * * @param key the public key for the identity to be returned. * * @return the identity with the given key, or null if there are * no identities in this scope with that key. */ public abstract Identity getIdentity(PublicKey key); /** * Adds an identity to this identity scope. * * @param identity the identity to be added. * * @exception KeyManagementException if the identity is not * valid, a name conflict occurs, another identity has the same * public key as the identity being added, or another exception * occurs. */ public abstract void addIdentity(Identity identity) throws KeyManagementException; /** * Removes an identity from this identity scope. * * @param identity the identity to be removed. * * @exception KeyManagementException if the identity is missing, * or another exception occurs. */ public abstract void removeIdentity(Identity identity) throws KeyManagementException; /** * Returns an enumeration of all identities in this identity scope. * * @return an enumeration of all identities in this identity scope. */ public abstract Enumeration identities(); /** * Returns a string representation of this identity scope, including * its name, its scope name, and the number of identities in this * identity scope. * * @return a string representation of this identity scope. */ public String toString() { return super.toString() + "[" + size() + "]"; } private static void check(String directive) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkSecurityAccess(directive); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3441 Content-Disposition: inline; filename="InvalidAlgorithmParameterException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "559a8beed09daf8f22e0b0b7a884373132431b99" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This is the exception for invalid or inappropriate algorithm parameters. * * @author Jan Luehe * * * @see AlgorithmParameters * @see java.security.spec.AlgorithmParameterSpec * * @since 1.2 */ public class InvalidAlgorithmParameterException extends GeneralSecurityException { private static final long serialVersionUID = 2864672297499471472L; /** * Constructs an InvalidAlgorithmParameterException with no detail * message. * A detail message is a String that describes this particular * exception. */ public InvalidAlgorithmParameterException() { super(); } /** * Constructs an InvalidAlgorithmParameterException with the specified * detail message. * A detail message is a String that describes this * particular exception. * * @param msg the detail message. */ public InvalidAlgorithmParameterException(String msg) { super(msg); } /** * Creates a {@code InvalidAlgorithmParameterException} with the * specified detail message and cause. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public InvalidAlgorithmParameterException(String message, Throwable cause) { super(message, cause); } /** * Creates a {@code InvalidAlgorithmParameterException} with the * specified cause and a detail message of * {@code (cause==null ? null : cause.toString())} * (which typically contains the class and detail message of * {@code cause}). * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public InvalidAlgorithmParameterException(Throwable cause) { super(cause); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3202 Content-Disposition: inline; filename="InvalidKeyException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "35fc64c3d9e90ed7c55a5a3074a3dece5bca3eb9" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This is the exception for invalid Keys (invalid encoding, wrong * length, uninitialized, etc). * * @author Benjamin Renaud */ public class InvalidKeyException extends KeyException { private static final long serialVersionUID = 5698479920593359816L; /** * Constructs an InvalidKeyException with no detail message. A * detail message is a String that describes this particular * exception. */ public InvalidKeyException() { super(); } /** * Constructs an InvalidKeyException with the specified detail * message. A detail message is a String that describes this * particular exception. * * @param msg the detail message. */ public InvalidKeyException(String msg) { super(msg); } /** * Creates a {@code InvalidKeyException} with the specified * detail message and cause. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public InvalidKeyException(String message, Throwable cause) { super(message, cause); } /** * Creates a {@code InvalidKeyException} with the specified cause * and a detail message of {@code (cause==null ? null : cause.toString())} * (which typically contains the class and detail message of * {@code cause}). * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public InvalidKeyException(Throwable cause) { super(cause); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2101 Content-Disposition: inline; filename="InvalidParameterException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "a095f90de36f5a905f0bff89005191b7940c0976" /* * Copyright (c) 1996, 2003, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This exception, designed for use by the JCA/JCE engine classes, * is thrown when an invalid parameter is passed * to a method. * * @author Benjamin Renaud */ public class InvalidParameterException extends IllegalArgumentException { private static final long serialVersionUID = -857968536935667808L; /** * Constructs an InvalidParameterException with no detail message. * A detail message is a String that describes this particular * exception. */ public InvalidParameterException() { super(); } /** * Constructs an InvalidParameterException with the specified * detail message. A detail message is a String that describes * this particular exception. * * @param msg the detail message. */ public InvalidParameterException(String msg) { super(msg); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5644 Content-Disposition: inline; filename="Key.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "09542e394a25f3722aa4a43701ef8e17b28a14c4" /* * Copyright (c) 1996, 2014, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * The Key interface is the top-level interface for all keys. It * defines the functionality shared by all key objects. All keys * have three characteristics: * *

    * *
  • An Algorithm * *

    This is the key algorithm for that key. The key algorithm is usually * an encryption or asymmetric operation algorithm (such as DSA or * RSA), which will work with those algorithms and with related * algorithms (such as MD5 with RSA, SHA-1 with RSA, Raw DSA, etc.) * The name of the algorithm of a key is obtained using the * {@link #getAlgorithm() getAlgorithm} method. * *

  • An Encoded Form * *

    This is an external encoded form for the key used when a standard * representation of the key is needed outside the Java Virtual Machine, * as when transmitting the key to some other party. The key * is encoded according to a standard format (such as * X.509 {@code SubjectPublicKeyInfo} or PKCS#8), and * is returned using the {@link #getEncoded() getEncoded} method. * Note: The syntax of the ASN.1 type {@code SubjectPublicKeyInfo} * is defined as follows: * *

     * SubjectPublicKeyInfo ::= SEQUENCE {
     *   algorithm AlgorithmIdentifier,
     *   subjectPublicKey BIT STRING }
     *
     * AlgorithmIdentifier ::= SEQUENCE {
     *   algorithm OBJECT IDENTIFIER,
     *   parameters ANY DEFINED BY algorithm OPTIONAL }
     * 
    * * For more information, see * RFC 5280: * Internet X.509 Public Key Infrastructure Certificate and CRL Profile. * *
  • A Format * *

    This is the name of the format of the encoded key. It is returned * by the {@link #getFormat() getFormat} method. * *

* * Keys are generally obtained through key generators, certificates, * or various Identity classes used to manage keys. * Keys may also be obtained from key specifications (transparent * representations of the underlying key material) through the use of a key * factory (see {@link KeyFactory}). * *

A Key should use KeyRep as its serialized representation. * Note that a serialized Key may contain sensitive information * which should not be exposed in untrusted environments. See the * * Security Appendix * of the Serialization Specification for more information. * * @see PublicKey * @see PrivateKey * @see KeyPair * @see KeyPairGenerator * @see KeyFactory * @see KeyRep * @see java.security.spec.KeySpec * @see Identity * @see Signer * * @author Benjamin Renaud */ public interface Key extends java.io.Serializable { // Declare serialVersionUID to be compatible with JDK1.1 /** * The class fingerprint that is set to indicate * serialization compatibility with a previous * version of the class. */ static final long serialVersionUID = 6603384152749567654L; /** * Returns the standard algorithm name for this key. For * example, "DSA" would indicate that this key is a DSA key. * See Appendix A in the * Java Cryptography Architecture API Specification & Reference * for information about standard algorithm names. * * @return the name of the algorithm associated with this key. */ public String getAlgorithm(); /** * Returns the name of the primary encoding format of this key, * or null if this key does not support encoding. * The primary encoding format is * named in terms of the appropriate ASN.1 data format, if an * ASN.1 specification for this key exists. * For example, the name of the ASN.1 data format for public * keys is SubjectPublicKeyInfo, as * defined by the X.509 standard; in this case, the returned format is * {@code "X.509"}. Similarly, * the name of the ASN.1 data format for private keys is * PrivateKeyInfo, * as defined by the PKCS #8 standard; in this case, the returned format is * {@code "PKCS#8"}. * * @return the primary encoding format of the key. */ public String getFormat(); /** * Returns the key in its primary encoding format, or null * if this key does not support encoding. * * @return the encoded key, or null if the key does not support * encoding. */ public byte[] getEncoded(); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3153 Content-Disposition: inline; filename="KeyException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "59cdd6f3ab515be6ac0e660827d189b3b4d7fcf5" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This is the basic key exception. * * @see Key * @see InvalidKeyException * @see KeyManagementException * * @author Benjamin Renaud */ public class KeyException extends GeneralSecurityException { private static final long serialVersionUID = -7483676942812432108L; /** * Constructs a KeyException with no detail message. A detail * message is a String that describes this particular exception. */ public KeyException() { super(); } /** * Constructs a KeyException with the specified detail message. * A detail message is a String that describes this particular * exception. * * @param msg the detail message. */ public KeyException(String msg) { super(msg); } /** * Creates a {@code KeyException} with the specified * detail message and cause. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public KeyException(String message, Throwable cause) { super(message, cause); } /** * Creates a {@code KeyException} with the specified cause * and a detail message of {@code (cause==null ? null : cause.toString())} * (which typically contains the class and detail message of * {@code cause}). * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public KeyException(Throwable cause) { super(cause); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 17406 Content-Disposition: inline; filename="KeyFactory.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "8e761ff41f727d3311f897d60d4e9b1d42cfe5ba" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.*; import java.security.Provider.Service; import java.security.spec.KeySpec; import java.security.spec.InvalidKeySpecException; import sun.security.util.Debug; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; /** * Key factories are used to convert keys (opaque * cryptographic keys of type {@code Key}) into key specifications * (transparent representations of the underlying key material), and vice * versa. * *

Key factories are bi-directional. That is, they allow you to build an * opaque key object from a given key specification (key material), or to * retrieve the underlying key material of a key object in a suitable format. * *

Multiple compatible key specifications may exist for the same key. * For example, a DSA public key may be specified using * {@code DSAPublicKeySpec} or * {@code X509EncodedKeySpec}. A key factory can be used to translate * between compatible key specifications. * *

The following is an example of how to use a key factory in order to * instantiate a DSA public key from its encoding. * Assume Alice has received a digital signature from Bob. * Bob also sent her his public key (in encoded format) to verify * his signature. Alice then performs the following actions: * *

 * X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);
 * KeyFactory keyFactory = KeyFactory.getInstance("DSA");
 * PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);
 * Signature sig = Signature.getInstance("DSA");
 * sig.initVerify(bobPubKey);
 * sig.update(data);
 * sig.verify(signature);
 * 
* *

Every implementation of the Java platform is required to support the * following standard {@code KeyFactory} algorithms: *

    *
  • {@code DiffieHellman}
  • *
  • {@code DSA}
  • *
  • {@code RSA}
  • *
* These algorithms are described in the * KeyFactory section of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * Consult the release documentation for your implementation to see if any * other algorithms are supported. * * @author Jan Luehe * * @see Key * @see PublicKey * @see PrivateKey * @see java.security.spec.KeySpec * @see java.security.spec.DSAPublicKeySpec * @see java.security.spec.X509EncodedKeySpec * * @since 1.2 */ public class KeyFactory { private static final Debug debug = Debug.getInstance("jca", "KeyFactory"); // The algorithm associated with this key factory private final String algorithm; // The provider private Provider provider; // The provider implementation (delegate) private volatile KeyFactorySpi spi; // lock for mutex during provider selection private final Object lock = new Object(); // remaining services to try in provider selection // null once provider is selected private Iterator serviceIterator; /** * Creates a KeyFactory object. * * @param keyFacSpi the delegate * @param provider the provider * @param algorithm the name of the algorithm * to associate with this {@code KeyFactory} */ protected KeyFactory(KeyFactorySpi keyFacSpi, Provider provider, String algorithm) { this.spi = keyFacSpi; this.provider = provider; this.algorithm = algorithm; } private KeyFactory(String algorithm) throws NoSuchAlgorithmException { this.algorithm = algorithm; List list = GetInstance.getServices("KeyFactory", algorithm); serviceIterator = list.iterator(); // fetch and instantiate initial spi if (nextSpi(null) == null) { throw new NoSuchAlgorithmException (algorithm + " KeyFactory not available"); } } /** * Returns a KeyFactory object that converts * public/private keys of the specified algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new KeyFactory object encapsulating the * KeyFactorySpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the requested key algorithm. * See the KeyFactory section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the new KeyFactory object. * * @exception NoSuchAlgorithmException if no Provider supports a * KeyFactorySpi implementation for the * specified algorithm. * * @see Provider */ public static KeyFactory getInstance(String algorithm) throws NoSuchAlgorithmException { return new KeyFactory(algorithm); } /** * Returns a KeyFactory object that converts * public/private keys of the specified algorithm. * *

A new KeyFactory object encapsulating the * KeyFactorySpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the requested key algorithm. * See the KeyFactory section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the name of the provider. * * @return the new KeyFactory object. * * @exception NoSuchAlgorithmException if a KeyFactorySpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider name is null * or empty. * * @see Provider */ public static KeyFactory getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Instance instance = GetInstance.getInstance("KeyFactory", KeyFactorySpi.class, algorithm, provider); return new KeyFactory((KeyFactorySpi)instance.impl, instance.provider, algorithm); } /** * Returns a KeyFactory object that converts * public/private keys of the specified algorithm. * *

A new KeyFactory object encapsulating the * KeyFactorySpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the name of the requested key algorithm. * See the KeyFactory section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the provider. * * @return the new KeyFactory object. * * @exception NoSuchAlgorithmException if a KeyFactorySpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the specified provider is null. * * @see Provider * * @since 1.4 */ public static KeyFactory getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { Instance instance = GetInstance.getInstance("KeyFactory", KeyFactorySpi.class, algorithm, provider); return new KeyFactory((KeyFactorySpi)instance.impl, instance.provider, algorithm); } /** * Returns the provider of this key factory object. * * @return the provider of this key factory object */ public final Provider getProvider() { synchronized (lock) { // disable further failover after this call serviceIterator = null; return provider; } } /** * Gets the name of the algorithm * associated with this {@code KeyFactory}. * * @return the name of the algorithm associated with this * {@code KeyFactory} */ public final String getAlgorithm() { return this.algorithm; } /** * Update the active KeyFactorySpi of this class and return the next * implementation for failover. If no more implemenations are * available, this method returns null. However, the active spi of * this class is never set to null. */ private KeyFactorySpi nextSpi(KeyFactorySpi oldSpi) { synchronized (lock) { // somebody else did a failover concurrently // try that spi now if ((oldSpi != null) && (oldSpi != spi)) { return spi; } if (serviceIterator == null) { return null; } while (serviceIterator.hasNext()) { Service s = serviceIterator.next(); try { Object obj = s.newInstance(null); if (obj instanceof KeyFactorySpi == false) { continue; } KeyFactorySpi spi = (KeyFactorySpi)obj; provider = s.getProvider(); this.spi = spi; return spi; } catch (NoSuchAlgorithmException e) { // ignore } } serviceIterator = null; return null; } } /** * Generates a public key object from the provided key specification * (key material). * * @param keySpec the specification (key material) of the public key. * * @return the public key. * * @exception InvalidKeySpecException if the given key specification * is inappropriate for this key factory to produce a public key. */ public final PublicKey generatePublic(KeySpec keySpec) throws InvalidKeySpecException { if (serviceIterator == null) { return spi.engineGeneratePublic(keySpec); } Exception failure = null; KeyFactorySpi mySpi = spi; do { try { return mySpi.engineGeneratePublic(keySpec); } catch (Exception e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi); } } while (mySpi != null); if (failure instanceof RuntimeException) { throw (RuntimeException)failure; } if (failure instanceof InvalidKeySpecException) { throw (InvalidKeySpecException)failure; } throw new InvalidKeySpecException ("Could not generate public key", failure); } /** * Generates a private key object from the provided key specification * (key material). * * @param keySpec the specification (key material) of the private key. * * @return the private key. * * @exception InvalidKeySpecException if the given key specification * is inappropriate for this key factory to produce a private key. */ public final PrivateKey generatePrivate(KeySpec keySpec) throws InvalidKeySpecException { if (serviceIterator == null) { return spi.engineGeneratePrivate(keySpec); } Exception failure = null; KeyFactorySpi mySpi = spi; do { try { return mySpi.engineGeneratePrivate(keySpec); } catch (Exception e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi); } } while (mySpi != null); if (failure instanceof RuntimeException) { throw (RuntimeException)failure; } if (failure instanceof InvalidKeySpecException) { throw (InvalidKeySpecException)failure; } throw new InvalidKeySpecException ("Could not generate private key", failure); } /** * Returns a specification (key material) of the given key object. * {@code keySpec} identifies the specification class in which * the key material should be returned. It could, for example, be * {@code DSAPublicKeySpec.class}, to indicate that the * key material should be returned in an instance of the * {@code DSAPublicKeySpec} class. * * @param the type of the key specification to be returned * * @param key the key. * * @param keySpec the specification class in which * the key material should be returned. * * @return the underlying key specification (key material) in an instance * of the requested specification class. * * @exception InvalidKeySpecException if the requested key specification is * inappropriate for the given key, or the given key cannot be processed * (e.g., the given key has an unrecognized algorithm or format). */ public final T getKeySpec(Key key, Class keySpec) throws InvalidKeySpecException { if (serviceIterator == null) { return spi.engineGetKeySpec(key, keySpec); } Exception failure = null; KeyFactorySpi mySpi = spi; do { try { return mySpi.engineGetKeySpec(key, keySpec); } catch (Exception e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi); } } while (mySpi != null); if (failure instanceof RuntimeException) { throw (RuntimeException)failure; } if (failure instanceof InvalidKeySpecException) { throw (InvalidKeySpecException)failure; } throw new InvalidKeySpecException ("Could not get key spec", failure); } /** * Translates a key object, whose provider may be unknown or potentially * untrusted, into a corresponding key object of this key factory. * * @param key the key whose provider is unknown or untrusted. * * @return the translated key. * * @exception InvalidKeyException if the given key cannot be processed * by this key factory. */ public final Key translateKey(Key key) throws InvalidKeyException { if (serviceIterator == null) { return spi.engineTranslateKey(key); } Exception failure = null; KeyFactorySpi mySpi = spi; do { try { return mySpi.engineTranslateKey(key); } catch (Exception e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi); } } while (mySpi != null); if (failure instanceof RuntimeException) { throw (RuntimeException)failure; } if (failure instanceof InvalidKeyException) { throw (InvalidKeyException)failure; } throw new InvalidKeyException ("Could not translate key", failure); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5313 Content-Disposition: inline; filename="KeyFactorySpi.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "5ee7f4589315d84a1f4d2e600cda21427eb973f2" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.security.spec.KeySpec; import java.security.spec.InvalidKeySpecException; /** * This class defines the Service Provider Interface (SPI) * for the {@code KeyFactory} class. * All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a key factory for a particular algorithm. * *

Key factories are used to convert keys (opaque * cryptographic keys of type {@code Key}) into key specifications * (transparent representations of the underlying key material), and vice * versa. * *

Key factories are bi-directional. That is, they allow you to build an * opaque key object from a given key specification (key material), or to * retrieve the underlying key material of a key object in a suitable format. * *

Multiple compatible key specifications may exist for the same key. * For example, a DSA public key may be specified using * {@code DSAPublicKeySpec} or * {@code X509EncodedKeySpec}. A key factory can be used to translate * between compatible key specifications. * *

A provider should document all the key specifications supported by its * key factory. * * @author Jan Luehe * * * @see KeyFactory * @see Key * @see PublicKey * @see PrivateKey * @see java.security.spec.KeySpec * @see java.security.spec.DSAPublicKeySpec * @see java.security.spec.X509EncodedKeySpec * * @since 1.2 */ public abstract class KeyFactorySpi { /** * Generates a public key object from the provided key * specification (key material). * * @param keySpec the specification (key material) of the public key. * * @return the public key. * * @exception InvalidKeySpecException if the given key specification * is inappropriate for this key factory to produce a public key. */ protected abstract PublicKey engineGeneratePublic(KeySpec keySpec) throws InvalidKeySpecException; /** * Generates a private key object from the provided key * specification (key material). * * @param keySpec the specification (key material) of the private key. * * @return the private key. * * @exception InvalidKeySpecException if the given key specification * is inappropriate for this key factory to produce a private key. */ protected abstract PrivateKey engineGeneratePrivate(KeySpec keySpec) throws InvalidKeySpecException; /** * Returns a specification (key material) of the given key * object. * {@code keySpec} identifies the specification class in which * the key material should be returned. It could, for example, be * {@code DSAPublicKeySpec.class}, to indicate that the * key material should be returned in an instance of the * {@code DSAPublicKeySpec} class. * * @param the type of the key specification to be returned * * @param key the key. * * @param keySpec the specification class in which * the key material should be returned. * * @return the underlying key specification (key material) in an instance * of the requested specification class. * @exception InvalidKeySpecException if the requested key specification is * inappropriate for the given key, or the given key cannot be dealt with * (e.g., the given key has an unrecognized format). */ protected abstract T engineGetKeySpec(Key key, Class keySpec) throws InvalidKeySpecException; /** * Translates a key object, whose provider may be unknown or * potentially untrusted, into a corresponding key object of this key * factory. * * @param key the key whose provider is unknown or untrusted. * * @return the translated key. * * @exception InvalidKeyException if the given key cannot be processed * by this key factory. */ protected abstract Key engineTranslateKey(Key key) throws InvalidKeyException; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3514 Content-Disposition: inline; filename="KeyManagementException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "be212b9fdc16c612c3ae9aac49509d7e0d018107" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This is the general key management exception for all operations * dealing with key management. Examples of subclasses of * KeyManagementException that developers might create for * giving more detailed information could include: * *

    *
  • KeyIDConflictException *
  • KeyAuthorizationFailureException *
  • ExpiredKeyException *
* * @author Benjamin Renaud * * @see Key * @see KeyException */ public class KeyManagementException extends KeyException { private static final long serialVersionUID = 947674216157062695L; /** * Constructs a KeyManagementException with no detail message. A * detail message is a String that describes this particular * exception. */ public KeyManagementException() { super(); } /** * Constructs a KeyManagementException with the specified detail * message. A detail message is a String that describes this * particular exception. * * @param msg the detail message. */ public KeyManagementException(String msg) { super(msg); } /** * Creates a {@code KeyManagementException} with the specified * detail message and cause. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public KeyManagementException(String message, Throwable cause) { super(message, cause); } /** * Creates a {@code KeyManagementException} with the specified cause * and a detail message of {@code (cause==null ? null : cause.toString())} * (which typically contains the class and detail message of * {@code cause}). * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public KeyManagementException(Throwable cause) { super(cause); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2686 Content-Disposition: inline; filename="KeyPair.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "6147a16aa59be2cab7a0a603c8ead27502f5a726" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.*; /** * This class is a simple holder for a key pair (a public key and a * private key). It does not enforce any security, and, when initialized, * should be treated like a PrivateKey. * * @see PublicKey * @see PrivateKey * * @author Benjamin Renaud */ public final class KeyPair implements java.io.Serializable { private static final long serialVersionUID = -7565189502268009837L; private PrivateKey privateKey; private PublicKey publicKey; /** * Constructs a key pair from the given public key and private key. * *

Note that this constructor only stores references to the public * and private key components in the generated key pair. This is safe, * because {@code Key} objects are immutable. * * @param publicKey the public key. * * @param privateKey the private key. */ public KeyPair(PublicKey publicKey, PrivateKey privateKey) { this.publicKey = publicKey; this.privateKey = privateKey; } /** * Returns a reference to the public key component of this key pair. * * @return a reference to the public key. */ public PublicKey getPublic() { return publicKey; } /** * Returns a reference to the private key component of this key pair. * * @return a reference to the private key. */ public PrivateKey getPrivate() { return privateKey; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 28793 Content-Disposition: inline; filename="KeyPairGenerator.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "2056768893917b4d7c3df482a17f968e37c64d5a" /* * Copyright (c) 1997, 2014, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.*; import java.security.spec.AlgorithmParameterSpec; import java.security.Provider.Service; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; import sun.security.util.Debug; /** * The KeyPairGenerator class is used to generate pairs of * public and private keys. Key pair generators are constructed using the * {@code getInstance} factory methods (static methods that * return instances of a given class). * *

A Key pair generator for a particular algorithm creates a public/private * key pair that can be used with this algorithm. It also associates * algorithm-specific parameters with each of the generated keys. * *

There are two ways to generate a key pair: in an algorithm-independent * manner, and in an algorithm-specific manner. * The only difference between the two is the initialization of the object: * *

    *
  • Algorithm-Independent Initialization *

    All key pair generators share the concepts of a keysize and a * source of randomness. The keysize is interpreted differently for different * algorithms (e.g., in the case of the DSA algorithm, the keysize * corresponds to the length of the modulus). * There is an * {@link #initialize(int, java.security.SecureRandom) initialize} * method in this KeyPairGenerator class that takes these two universally * shared types of arguments. There is also one that takes just a * {@code keysize} argument, and uses the {@code SecureRandom} * implementation of the highest-priority installed provider as the source * of randomness. (If none of the installed providers supply an implementation * of {@code SecureRandom}, a system-provided source of randomness is * used.) * *

    Since no other parameters are specified when you call the above * algorithm-independent {@code initialize} methods, it is up to the * provider what to do about the algorithm-specific parameters (if any) to be * associated with each of the keys. * *

    If the algorithm is the DSA algorithm, and the keysize (modulus * size) is 512, 768, or 1024, then the Sun provider uses a set of * precomputed values for the {@code p}, {@code q}, and * {@code g} parameters. If the modulus size is not one of the above * values, the Sun provider creates a new set of parameters. Other * providers might have precomputed parameter sets for more than just the * three modulus sizes mentioned above. Still others might not have a list of * precomputed parameters at all and instead always create new parameter sets. * *

  • Algorithm-Specific Initialization *

    For situations where a set of algorithm-specific parameters already * exists (e.g., so-called community parameters in DSA), there are two * {@link #initialize(java.security.spec.AlgorithmParameterSpec) * initialize} methods that have an {@code AlgorithmParameterSpec} * argument. One also has a {@code SecureRandom} argument, while the * the other uses the {@code SecureRandom} * implementation of the highest-priority installed provider as the source * of randomness. (If none of the installed providers supply an implementation * of {@code SecureRandom}, a system-provided source of randomness is * used.) *

* *

In case the client does not explicitly initialize the KeyPairGenerator * (via a call to an {@code initialize} method), each provider must * supply (and document) a default initialization. * For example, the Sun provider uses a default modulus size (keysize) * of 1024 bits. * *

Note that this class is abstract and extends from * {@code KeyPairGeneratorSpi} for historical reasons. * Application developers should only take notice of the methods defined in * this {@code KeyPairGenerator} class; all the methods in * the superclass are intended for cryptographic service providers who wish to * supply their own implementations of key pair generators. * *

Every implementation of the Java platform is required to support the * following standard {@code KeyPairGenerator} algorithms and keysizes in * parentheses: *

    *
  • {@code DiffieHellman} (1024)
  • *
  • {@code DSA} (1024)
  • *
  • {@code RSA} (1024, 2048)
  • *
* These algorithms are described in the * KeyPairGenerator section of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * Consult the release documentation for your implementation to see if any * other algorithms are supported. * * @author Benjamin Renaud * * @see java.security.spec.AlgorithmParameterSpec */ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { private static final Debug pdebug = Debug.getInstance("provider", "Provider"); private static final boolean skipDebug = Debug.isOn("engine=") && !Debug.isOn("keypairgenerator"); private final String algorithm; // The provider Provider provider; /** * Creates a KeyPairGenerator object for the specified algorithm. * * @param algorithm the standard string name of the algorithm. * See the KeyPairGenerator section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. */ protected KeyPairGenerator(String algorithm) { this.algorithm = algorithm; } /** * Returns the standard name of the algorithm for this key pair generator. * See the KeyPairGenerator section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the standard string name of the algorithm. */ public String getAlgorithm() { return this.algorithm; } private static KeyPairGenerator getInstance(Instance instance, String algorithm) { KeyPairGenerator kpg; if (instance.impl instanceof KeyPairGenerator) { kpg = (KeyPairGenerator)instance.impl; } else { KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)instance.impl; kpg = new Delegate(spi, algorithm); } kpg.provider = instance.provider; if (!skipDebug && pdebug != null) { pdebug.println("KeyPairGenerator." + algorithm + " algorithm from: " + kpg.provider.getName()); } return kpg; } /** * Returns a KeyPairGenerator object that generates public/private * key pairs for the specified algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new KeyPairGenerator object encapsulating the * KeyPairGeneratorSpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard string name of the algorithm. * See the KeyPairGenerator section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the new KeyPairGenerator object. * * @exception NoSuchAlgorithmException if no Provider supports a * KeyPairGeneratorSpi implementation for the * specified algorithm. * * @see Provider */ public static KeyPairGenerator getInstance(String algorithm) throws NoSuchAlgorithmException { List list = GetInstance.getServices("KeyPairGenerator", algorithm); Iterator t = list.iterator(); if (t.hasNext() == false) { throw new NoSuchAlgorithmException (algorithm + " KeyPairGenerator not available"); } // find a working Spi or KeyPairGenerator subclass NoSuchAlgorithmException failure = null; do { Service s = t.next(); try { Instance instance = GetInstance.getInstance(s, KeyPairGeneratorSpi.class); if (instance.impl instanceof KeyPairGenerator) { return getInstance(instance, algorithm); } else { return new Delegate(instance, t, algorithm); } } catch (NoSuchAlgorithmException e) { if (failure == null) { failure = e; } } } while (t.hasNext()); throw failure; } /** * Returns a KeyPairGenerator object that generates public/private * key pairs for the specified algorithm. * *

A new KeyPairGenerator object encapsulating the * KeyPairGeneratorSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard string name of the algorithm. * See the KeyPairGenerator section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the string name of the provider. * * @return the new KeyPairGenerator object. * * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider name is null * or empty. * * @see Provider */ public static KeyPairGenerator getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Instance instance = GetInstance.getInstance("KeyPairGenerator", KeyPairGeneratorSpi.class, algorithm, provider); return getInstance(instance, algorithm); } /** * Returns a KeyPairGenerator object that generates public/private * key pairs for the specified algorithm. * *

A new KeyPairGenerator object encapsulating the * KeyPairGeneratorSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the standard string name of the algorithm. * See the KeyPairGenerator section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the provider. * * @return the new KeyPairGenerator object. * * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the specified provider is null. * * @see Provider * * @since 1.4 */ public static KeyPairGenerator getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { Instance instance = GetInstance.getInstance("KeyPairGenerator", KeyPairGeneratorSpi.class, algorithm, provider); return getInstance(instance, algorithm); } /** * Returns the provider of this key pair generator object. * * @return the provider of this key pair generator object */ public final Provider getProvider() { disableFailover(); return this.provider; } void disableFailover() { // empty, overridden in Delegate } /** * Initializes the key pair generator for a certain keysize using * a default parameter set and the {@code SecureRandom} * implementation of the highest-priority installed provider as the source * of randomness. * (If none of the installed providers supply an implementation of * {@code SecureRandom}, a system-provided source of randomness is * used.) * * @param keysize the keysize. This is an * algorithm-specific metric, such as modulus length, specified in * number of bits. * * @exception InvalidParameterException if the {@code keysize} is not * supported by this KeyPairGenerator object. */ public void initialize(int keysize) { initialize(keysize, JCAUtil.getSecureRandom()); } /** * Initializes the key pair generator for a certain keysize with * the given source of randomness (and a default parameter set). * * @param keysize the keysize. This is an * algorithm-specific metric, such as modulus length, specified in * number of bits. * @param random the source of randomness. * * @exception InvalidParameterException if the {@code keysize} is not * supported by this KeyPairGenerator object. * * @since 1.2 */ public void initialize(int keysize, SecureRandom random) { // This does nothing, because either // 1. the implementation object returned by getInstance() is an // instance of KeyPairGenerator which has its own // initialize(keysize, random) method, so the application would // be calling that method directly, or // 2. the implementation returned by getInstance() is an instance // of Delegate, in which case initialize(keysize, random) is // overridden to call the corresponding SPI method. // (This is a special case, because the API and SPI method have the // same name.) } /** * Initializes the key pair generator using the specified parameter * set and the {@code SecureRandom} * implementation of the highest-priority installed provider as the source * of randomness. * (If none of the installed providers supply an implementation of * {@code SecureRandom}, a system-provided source of randomness is * used.). * *

This concrete method has been added to this previously-defined * abstract class. * This method calls the KeyPairGeneratorSpi * {@link KeyPairGeneratorSpi#initialize( * java.security.spec.AlgorithmParameterSpec, * java.security.SecureRandom) initialize} method, * passing it {@code params} and a source of randomness (obtained * from the highest-priority installed provider or system-provided if none * of the installed providers supply one). * That {@code initialize} method always throws an * UnsupportedOperationException if it is not overridden by the provider. * * @param params the parameter set used to generate the keys. * * @exception InvalidAlgorithmParameterException if the given parameters * are inappropriate for this key pair generator. * * @since 1.2 */ public void initialize(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { initialize(params, JCAUtil.getSecureRandom()); } /** * Initializes the key pair generator with the given parameter * set and source of randomness. * *

This concrete method has been added to this previously-defined * abstract class. * This method calls the KeyPairGeneratorSpi {@link * KeyPairGeneratorSpi#initialize( * java.security.spec.AlgorithmParameterSpec, * java.security.SecureRandom) initialize} method, * passing it {@code params} and {@code random}. * That {@code initialize} * method always throws an * UnsupportedOperationException if it is not overridden by the provider. * * @param params the parameter set used to generate the keys. * @param random the source of randomness. * * @exception InvalidAlgorithmParameterException if the given parameters * are inappropriate for this key pair generator. * * @since 1.2 */ public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { // This does nothing, because either // 1. the implementation object returned by getInstance() is an // instance of KeyPairGenerator which has its own // initialize(params, random) method, so the application would // be calling that method directly, or // 2. the implementation returned by getInstance() is an instance // of Delegate, in which case initialize(params, random) is // overridden to call the corresponding SPI method. // (This is a special case, because the API and SPI method have the // same name.) } /** * Generates a key pair. * *

If this KeyPairGenerator has not been initialized explicitly, * provider-specific defaults will be used for the size and other * (algorithm-specific) values of the generated keys. * *

This will generate a new key pair every time it is called. * *

This method is functionally equivalent to * {@link #generateKeyPair() generateKeyPair}. * * @return the generated key pair * * @since 1.2 */ public final KeyPair genKeyPair() { return generateKeyPair(); } /** * Generates a key pair. * *

If this KeyPairGenerator has not been initialized explicitly, * provider-specific defaults will be used for the size and other * (algorithm-specific) values of the generated keys. * *

This will generate a new key pair every time it is called. * *

This method is functionally equivalent to * {@link #genKeyPair() genKeyPair}. * * @return the generated key pair */ public KeyPair generateKeyPair() { // This does nothing (except returning null), because either: // // 1. the implementation object returned by getInstance() is an // instance of KeyPairGenerator which has its own implementation // of generateKeyPair (overriding this one), so the application // would be calling that method directly, or // // 2. the implementation returned by getInstance() is an instance // of Delegate, in which case generateKeyPair is // overridden to invoke the corresponding SPI method. // // (This is a special case, because in JDK 1.1.x the generateKeyPair // method was used both as an API and a SPI method.) return null; } /* * The following class allows providers to extend from KeyPairGeneratorSpi * rather than from KeyPairGenerator. It represents a KeyPairGenerator * with an encapsulated, provider-supplied SPI object (of type * KeyPairGeneratorSpi). * If the provider implementation is an instance of KeyPairGeneratorSpi, * the getInstance() methods above return an instance of this class, with * the SPI object encapsulated. * * Note: All SPI methods from the original KeyPairGenerator class have been * moved up the hierarchy into a new class (KeyPairGeneratorSpi), which has * been interposed in the hierarchy between the API (KeyPairGenerator) * and its original parent (Object). */ // // error failover notes: // // . we failover if the implementation throws an error during init // by retrying the init on other providers // // . we also failover if the init succeeded but the subsequent call // to generateKeyPair() fails. In order for this to work, we need // to remember the parameters to the last successful call to init // and initialize() the next spi using them. // // . although not specified, KeyPairGenerators could be thread safe, // so we make sure we do not interfere with that // // . failover is not available, if: // . getInstance(algorithm, provider) was used // . a provider extends KeyPairGenerator rather than // KeyPairGeneratorSpi (JDK 1.1 style) // . once getProvider() is called // private static final class Delegate extends KeyPairGenerator { // The provider implementation (delegate) private volatile KeyPairGeneratorSpi spi; private final Object lock = new Object(); private Iterator serviceIterator; private final static int I_NONE = 1; private final static int I_SIZE = 2; private final static int I_PARAMS = 3; private int initType; private int initKeySize; private AlgorithmParameterSpec initParams; private SecureRandom initRandom; // constructor Delegate(KeyPairGeneratorSpi spi, String algorithm) { super(algorithm); this.spi = spi; } Delegate(Instance instance, Iterator serviceIterator, String algorithm) { super(algorithm); spi = (KeyPairGeneratorSpi)instance.impl; provider = instance.provider; this.serviceIterator = serviceIterator; initType = I_NONE; if (!skipDebug && pdebug != null) { pdebug.println("KeyPairGenerator." + algorithm + " algorithm from: " + provider.getName()); } } /** * Update the active spi of this class and return the next * implementation for failover. If no more implemenations are * available, this method returns null. However, the active spi of * this class is never set to null. */ private KeyPairGeneratorSpi nextSpi(KeyPairGeneratorSpi oldSpi, boolean reinit) { synchronized (lock) { // somebody else did a failover concurrently // try that spi now if ((oldSpi != null) && (oldSpi != spi)) { return spi; } if (serviceIterator == null) { return null; } while (serviceIterator.hasNext()) { Service s = serviceIterator.next(); try { Object inst = s.newInstance(null); // ignore non-spis if (inst instanceof KeyPairGeneratorSpi == false) { continue; } if (inst instanceof KeyPairGenerator) { continue; } KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)inst; if (reinit) { if (initType == I_SIZE) { spi.initialize(initKeySize, initRandom); } else if (initType == I_PARAMS) { spi.initialize(initParams, initRandom); } else if (initType != I_NONE) { throw new AssertionError ("KeyPairGenerator initType: " + initType); } } provider = s.getProvider(); this.spi = spi; return spi; } catch (Exception e) { // ignore } } disableFailover(); return null; } } void disableFailover() { serviceIterator = null; initType = 0; initParams = null; initRandom = null; } // engine method public void initialize(int keysize, SecureRandom random) { if (serviceIterator == null) { spi.initialize(keysize, random); return; } RuntimeException failure = null; KeyPairGeneratorSpi mySpi = spi; do { try { mySpi.initialize(keysize, random); initType = I_SIZE; initKeySize = keysize; initParams = null; initRandom = random; return; } catch (RuntimeException e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi, false); } } while (mySpi != null); throw failure; } // engine method public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { if (serviceIterator == null) { spi.initialize(params, random); return; } Exception failure = null; KeyPairGeneratorSpi mySpi = spi; do { try { mySpi.initialize(params, random); initType = I_PARAMS; initKeySize = 0; initParams = params; initRandom = random; return; } catch (Exception e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi, false); } } while (mySpi != null); if (failure instanceof RuntimeException) { throw (RuntimeException)failure; } // must be an InvalidAlgorithmParameterException throw (InvalidAlgorithmParameterException)failure; } // engine method public KeyPair generateKeyPair() { if (serviceIterator == null) { return spi.generateKeyPair(); } RuntimeException failure = null; KeyPairGeneratorSpi mySpi = spi; do { try { return mySpi.generateKeyPair(); } catch (RuntimeException e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi, true); } } while (mySpi != null); throw failure; } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 4199 Content-Disposition: inline; filename="KeyPairGeneratorSpi.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "dfe8c04218dc1f0f734a06e7df94c6f2b651693e" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.security.spec.AlgorithmParameterSpec; /** *

This class defines the Service Provider Interface (SPI) * for the {@code KeyPairGenerator} class, which is used to generate * pairs of public and private keys. * *

All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a key pair generator for a particular algorithm. * *

In case the client does not explicitly initialize the KeyPairGenerator * (via a call to an {@code initialize} method), each provider must * supply (and document) a default initialization. * For example, the Sun provider uses a default modulus size (keysize) * of 1024 bits. * * @author Benjamin Renaud * * * @see KeyPairGenerator * @see java.security.spec.AlgorithmParameterSpec */ public abstract class KeyPairGeneratorSpi { /** * Initializes the key pair generator for a certain keysize, using * the default parameter set. * * @param keysize the keysize. This is an * algorithm-specific metric, such as modulus length, specified in * number of bits. * * @param random the source of randomness for this generator. * * @exception InvalidParameterException if the {@code keysize} is not * supported by this KeyPairGeneratorSpi object. */ public abstract void initialize(int keysize, SecureRandom random); /** * Initializes the key pair generator using the specified parameter * set and user-provided source of randomness. * *

This concrete method has been added to this previously-defined * abstract class. (For backwards compatibility, it cannot be abstract.) * It may be overridden by a provider to initialize the key pair * generator. Such an override * is expected to throw an InvalidAlgorithmParameterException if * a parameter is inappropriate for this key pair generator. * If this method is not overridden, it always throws an * UnsupportedOperationException. * * @param params the parameter set used to generate the keys. * * @param random the source of randomness for this generator. * * @exception InvalidAlgorithmParameterException if the given parameters * are inappropriate for this key pair generator. * * @since 1.2 */ public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { throw new UnsupportedOperationException(); } /** * Generates a key pair. Unless an initialization method is called * using a KeyPairGenerator interface, algorithm-specific defaults * will be used. This will generate a new key pair every time it * is called. * * @return the newly generated {@code KeyPair} */ public abstract KeyPair generateKeyPair(); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 6397 Content-Disposition: inline; filename="KeyRep.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "0b1412c1563c15e843d18d07b5b76b9fe5a81434" /* * Copyright (c) 2003, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.*; import java.util.Locale; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.security.spec.InvalidKeySpecException; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.SecretKeySpec; /** * Standardized representation for serialized Key objects. * *

* * Note that a serialized Key may contain sensitive information * which should not be exposed in untrusted environments. See the * * Security Appendix * of the Serialization Specification for more information. * * @see Key * @see KeyFactory * @see javax.crypto.spec.SecretKeySpec * @see java.security.spec.X509EncodedKeySpec * @see java.security.spec.PKCS8EncodedKeySpec * * @since 1.5 */ public class KeyRep implements Serializable { private static final long serialVersionUID = -4757683898830641853L; /** * Key type. * * @since 1.5 */ public static enum Type { /** Type for secret keys. */ SECRET, /** Type for public keys. */ PUBLIC, /** Type for private keys. */ PRIVATE, } private static final String PKCS8 = "PKCS#8"; private static final String X509 = "X.509"; private static final String RAW = "RAW"; /** * Either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE * * @serial */ private Type type; /** * The Key algorithm * * @serial */ private String algorithm; /** * The Key encoding format * * @serial */ private String format; /** * The encoded Key bytes * * @serial */ private byte[] encoded; /** * Construct the alternate Key class. * *

* * @param type either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE * @param algorithm the algorithm returned from * {@code Key.getAlgorithm()} * @param format the encoding format returned from * {@code Key.getFormat()} * @param encoded the encoded bytes returned from * {@code Key.getEncoded()} * * @exception NullPointerException * if type is {@code null}, * if algorithm is {@code null}, * if format is {@code null}, * or if encoded is {@code null} */ public KeyRep(Type type, String algorithm, String format, byte[] encoded) { if (type == null || algorithm == null || format == null || encoded == null) { throw new NullPointerException("invalid null input(s)"); } this.type = type; this.algorithm = algorithm; this.format = format.toUpperCase(Locale.ENGLISH); this.encoded = encoded.clone(); } /** * Resolve the Key object. * *

This method supports three Type/format combinations: *

    *
  • Type.SECRET/"RAW" - returns a SecretKeySpec object * constructed using encoded key bytes and algorithm *
  • Type.PUBLIC/"X.509" - gets a KeyFactory instance for * the key algorithm, constructs an X509EncodedKeySpec with the * encoded key bytes, and generates a public key from the spec *
  • Type.PRIVATE/"PKCS#8" - gets a KeyFactory instance for * the key algorithm, constructs a PKCS8EncodedKeySpec with the * encoded key bytes, and generates a private key from the spec *
* *

* * @return the resolved Key object * * @exception ObjectStreamException if the Type/format * combination is unrecognized, if the algorithm, key format, or * encoded key bytes are unrecognized/invalid, of if the * resolution of the key fails for any reason */ protected Object readResolve() throws ObjectStreamException { try { if (type == Type.SECRET && RAW.equals(format)) { return new SecretKeySpec(encoded, algorithm); } else if (type == Type.PUBLIC && X509.equals(format)) { KeyFactory f = KeyFactory.getInstance(algorithm); return f.generatePublic(new X509EncodedKeySpec(encoded)); } else if (type == Type.PRIVATE && PKCS8.equals(format)) { KeyFactory f = KeyFactory.getInstance(algorithm); return f.generatePrivate(new PKCS8EncodedKeySpec(encoded)); } else { throw new NotSerializableException ("unrecognized type/format combination: " + type + "/" + format); } } catch (NotSerializableException nse) { throw nse; } catch (Exception e) { NotSerializableException nse = new NotSerializableException ("java.security.Key: " + "[" + type + "] " + "[" + algorithm + "] " + "[" + format + "]"); nse.initCause(e); throw nse; } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 76179 Content-Disposition: inline; filename="KeyStore.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "4278369e8be966cc596d4e9f21f28602479b1248" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.*; import java.net.URI; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; import java.security.spec.AlgorithmParameterSpec; import java.util.*; import javax.crypto.SecretKey; import javax.security.auth.DestroyFailedException; import javax.security.auth.callback.*; import sun.security.util.Debug; /** * This class represents a storage facility for cryptographic * keys and certificates. * *

A {@code KeyStore} manages different types of entries. * Each type of entry implements the {@code KeyStore.Entry} interface. * Three basic {@code KeyStore.Entry} implementations are provided: * *

    *
  • KeyStore.PrivateKeyEntry *

    This type of entry holds a cryptographic {@code PrivateKey}, * which is optionally stored in a protected format to prevent * unauthorized access. It is also accompanied by a certificate chain * for the corresponding public key. * *

    Private keys and certificate chains are used by a given entity for * self-authentication. Applications for this authentication include software * distribution organizations which sign JAR files as part of releasing * and/or licensing software. * *

  • KeyStore.SecretKeyEntry *

    This type of entry holds a cryptographic {@code SecretKey}, * which is optionally stored in a protected format to prevent * unauthorized access. * *

  • KeyStore.TrustedCertificateEntry *

    This type of entry contains a single public key {@code Certificate} * belonging to another party. It is called a trusted certificate * because the keystore owner trusts that the public key in the certificate * indeed belongs to the identity identified by the subject (owner) * of the certificate. * *

    This type of entry can be used to authenticate other parties. *

* *

Each entry in a keystore is identified by an "alias" string. In the * case of private keys and their associated certificate chains, these strings * distinguish among the different ways in which the entity may authenticate * itself. For example, the entity may authenticate itself using different * certificate authorities, or using different public key algorithms. * *

Whether aliases are case sensitive is implementation dependent. In order * to avoid problems, it is recommended not to use aliases in a KeyStore that * only differ in case. * *

Whether keystores are persistent, and the mechanisms used by the * keystore if it is persistent, are not specified here. This allows * use of a variety of techniques for protecting sensitive (e.g., private or * secret) keys. Smart cards or other integrated cryptographic engines * (SafeKeyper) are one option, and simpler mechanisms such as files may also * be used (in a variety of formats). * *

Typical ways to request a KeyStore object include * relying on the default type and providing a specific keystore type. * *

    *
  • To rely on the default type: *
     *    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
     * 
    * The system will return a keystore implementation for the default type. * *
  • To provide a specific keystore type: *
     *      KeyStore ks = KeyStore.getInstance("JKS");
     * 
    * The system will return the most preferred implementation of the * specified keystore type available in the environment.

    *

* *

Before a keystore can be accessed, it must be * {@link #load(java.io.InputStream, char[]) loaded}. *

 *    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
 *
 *    // get user password and file input stream
 *    char[] password = getPassword();
 *
 *    try (FileInputStream fis = new FileInputStream("keyStoreName")) {
 *        ks.load(fis, password);
 *    }
 * 
* * To create an empty keystore using the above {@code load} method, * pass {@code null} as the {@code InputStream} argument. * *

Once the keystore has been loaded, it is possible * to read existing entries from the keystore, or to write new entries * into the keystore: *

 *    KeyStore.ProtectionParameter protParam =
 *        new KeyStore.PasswordProtection(password);
 *
 *    // get my private key
 *    KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
 *        ks.getEntry("privateKeyAlias", protParam);
 *    PrivateKey myPrivateKey = pkEntry.getPrivateKey();
 *
 *    // save my secret key
 *    javax.crypto.SecretKey mySecretKey;
 *    KeyStore.SecretKeyEntry skEntry =
 *        new KeyStore.SecretKeyEntry(mySecretKey);
 *    ks.setEntry("secretKeyAlias", skEntry, protParam);
 *
 *    // store away the keystore
 *    try (FileOutputStream fos = new FileOutputStream("newKeyStoreName")) {
 *        ks.store(fos, password);
 *    }
 * 
* * Note that although the same password may be used to * load the keystore, to protect the private key entry, * to protect the secret key entry, and to store the keystore * (as is shown in the sample code above), * different passwords or other protection parameters * may also be used. * *

Every implementation of the Java platform is required to support * the following standard {@code KeyStore} type: *

    *
  • {@code PKCS12}
  • *
* This type is described in the * KeyStore section of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * Consult the release documentation for your implementation to see if any * other types are supported. * * @author Jan Luehe * * @see java.security.PrivateKey * @see javax.crypto.SecretKey * @see java.security.cert.Certificate * * @since 1.2 */ public class KeyStore { private static final Debug pdebug = Debug.getInstance("provider", "Provider"); private static final boolean skipDebug = Debug.isOn("engine=") && !Debug.isOn("keystore"); /* * Constant to lookup in the Security properties file to determine * the default keystore type. * In the Security properties file, the default keystore type is given as: *
     * keystore.type=jks
     * 
*/ private static final String KEYSTORE_TYPE = "keystore.type"; // The keystore type private String type; // The provider private Provider provider; // The provider implementation private KeyStoreSpi keyStoreSpi; // Has this keystore been initialized (loaded)? private boolean initialized = false; /** * A marker interface for {@code KeyStore} * {@link #load(KeyStore.LoadStoreParameter) load} * and * {@link #store(KeyStore.LoadStoreParameter) store} * parameters. * * @since 1.5 */ public static interface LoadStoreParameter { /** * Gets the parameter used to protect keystore data. * * @return the parameter used to protect keystore data, or null */ public ProtectionParameter getProtectionParameter(); } /** * A marker interface for keystore protection parameters. * *

The information stored in a {@code ProtectionParameter} * object protects the contents of a keystore. * For example, protection parameters may be used to check * the integrity of keystore data, or to protect the * confidentiality of sensitive keystore data * (such as a {@code PrivateKey}). * * @since 1.5 */ public static interface ProtectionParameter { } /** * A password-based implementation of {@code ProtectionParameter}. * * @since 1.5 */ public static class PasswordProtection implements ProtectionParameter, javax.security.auth.Destroyable { private final char[] password; private final String protectionAlgorithm; private final AlgorithmParameterSpec protectionParameters; private volatile boolean destroyed = false; /** * Creates a password parameter. * *

The specified {@code password} is cloned before it is stored * in the new {@code PasswordProtection} object. * * @param password the password, which may be {@code null} */ public PasswordProtection(char[] password) { this.password = (password == null) ? null : password.clone(); this.protectionAlgorithm = null; this.protectionParameters = null; } /** * Creates a password parameter and specifies the protection algorithm * and associated parameters to use when encrypting a keystore entry. *

* The specified {@code password} is cloned before it is stored in the * new {@code PasswordProtection} object. * * @param password the password, which may be {@code null} * @param protectionAlgorithm the encryption algorithm name, for * example, {@code PBEWithHmacSHA256AndAES_256}. * See the Cipher section in the * Java Cryptography Architecture Standard Algorithm Name * Documentation * for information about standard encryption algorithm names. * @param protectionParameters the encryption algorithm parameter * specification, which may be {@code null} * @exception NullPointerException if {@code protectionAlgorithm} is * {@code null} * * @since 1.8 */ public PasswordProtection(char[] password, String protectionAlgorithm, AlgorithmParameterSpec protectionParameters) { if (protectionAlgorithm == null) { throw new NullPointerException("invalid null input"); } this.password = (password == null) ? null : password.clone(); this.protectionAlgorithm = protectionAlgorithm; this.protectionParameters = protectionParameters; } /** * Gets the name of the protection algorithm. * If none was set then the keystore provider will use its default * protection algorithm. The name of the default protection algorithm * for a given keystore type is set using the * {@code 'keystore..keyProtectionAlgorithm'} security property. * For example, the * {@code keystore.PKCS12.keyProtectionAlgorithm} property stores the * name of the default key protection algorithm used for PKCS12 * keystores. If the security property is not set, an * implementation-specific algorithm will be used. * * @return the algorithm name, or {@code null} if none was set * * @since 1.8 */ public String getProtectionAlgorithm() { return protectionAlgorithm; } /** * Gets the parameters supplied for the protection algorithm. * * @return the algorithm parameter specification, or {@code null}, * if none was set * * @since 1.8 */ public AlgorithmParameterSpec getProtectionParameters() { return protectionParameters; } /** * Gets the password. * *

Note that this method returns a reference to the password. * If a clone of the array is created it is the caller's * responsibility to zero out the password information * after it is no longer needed. * * @see #destroy() * @return the password, which may be {@code null} * @exception IllegalStateException if the password has * been cleared (destroyed) */ public synchronized char[] getPassword() { if (destroyed) { throw new IllegalStateException("password has been cleared"); } return password; } /** * Clears the password. * * @exception DestroyFailedException if this method was unable * to clear the password */ public synchronized void destroy() throws DestroyFailedException { destroyed = true; if (password != null) { Arrays.fill(password, ' '); } } /** * Determines if password has been cleared. * * @return true if the password has been cleared, false otherwise */ public synchronized boolean isDestroyed() { return destroyed; } } /** * A ProtectionParameter encapsulating a CallbackHandler. * * @since 1.5 */ public static class CallbackHandlerProtection implements ProtectionParameter { private final CallbackHandler handler; /** * Constructs a new CallbackHandlerProtection from a * CallbackHandler. * * @param handler the CallbackHandler * @exception NullPointerException if handler is null */ public CallbackHandlerProtection(CallbackHandler handler) { if (handler == null) { throw new NullPointerException("handler must not be null"); } this.handler = handler; } /** * Returns the CallbackHandler. * * @return the CallbackHandler. */ public CallbackHandler getCallbackHandler() { return handler; } } /** * A marker interface for {@code KeyStore} entry types. * * @since 1.5 */ public static interface Entry { /** * Retrieves the attributes associated with an entry. *

* The default implementation returns an empty {@code Set}. * * @return an unmodifiable {@code Set} of attributes, possibly empty * * @since 1.8 */ public default Set getAttributes() { return Collections.emptySet(); } /** * An attribute associated with a keystore entry. * It comprises a name and one or more values. * * @since 1.8 */ public interface Attribute { /** * Returns the attribute's name. * * @return the attribute name */ public String getName(); /** * Returns the attribute's value. * Multi-valued attributes encode their values as a single string. * * @return the attribute value */ public String getValue(); } } /** * A {@code KeyStore} entry that holds a {@code PrivateKey} * and corresponding certificate chain. * * @since 1.5 */ public static final class PrivateKeyEntry implements Entry { private final PrivateKey privKey; private final Certificate[] chain; private final Set attributes; /** * Constructs a {@code PrivateKeyEntry} with a * {@code PrivateKey} and corresponding certificate chain. * *

The specified {@code chain} is cloned before it is stored * in the new {@code PrivateKeyEntry} object. * * @param privateKey the {@code PrivateKey} * @param chain an array of {@code Certificate}s * representing the certificate chain. * The chain must be ordered and contain a * {@code Certificate} at index 0 * corresponding to the private key. * * @exception NullPointerException if * {@code privateKey} or {@code chain} * is {@code null} * @exception IllegalArgumentException if the specified chain has a * length of 0, if the specified chain does not contain * {@code Certificate}s of the same type, * or if the {@code PrivateKey} algorithm * does not match the algorithm of the {@code PublicKey} * in the end entity {@code Certificate} (at index 0) */ public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain) { this(privateKey, chain, Collections.emptySet()); } /** * Constructs a {@code PrivateKeyEntry} with a {@code PrivateKey} and * corresponding certificate chain and associated entry attributes. * *

The specified {@code chain} and {@code attributes} are cloned * before they are stored in the new {@code PrivateKeyEntry} object. * * @param privateKey the {@code PrivateKey} * @param chain an array of {@code Certificate}s * representing the certificate chain. * The chain must be ordered and contain a * {@code Certificate} at index 0 * corresponding to the private key. * @param attributes the attributes * * @exception NullPointerException if {@code privateKey}, {@code chain} * or {@code attributes} is {@code null} * @exception IllegalArgumentException if the specified chain has a * length of 0, if the specified chain does not contain * {@code Certificate}s of the same type, * or if the {@code PrivateKey} algorithm * does not match the algorithm of the {@code PublicKey} * in the end entity {@code Certificate} (at index 0) * * @since 1.8 */ public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain, Set attributes) { if (privateKey == null || chain == null || attributes == null) { throw new NullPointerException("invalid null input"); } if (chain.length == 0) { throw new IllegalArgumentException ("invalid zero-length input chain"); } Certificate[] clonedChain = chain.clone(); String certType = clonedChain[0].getType(); for (int i = 1; i < clonedChain.length; i++) { if (!certType.equals(clonedChain[i].getType())) { throw new IllegalArgumentException ("chain does not contain certificates " + "of the same type"); } } if (!privateKey.getAlgorithm().equals (clonedChain[0].getPublicKey().getAlgorithm())) { throw new IllegalArgumentException ("private key algorithm does not match " + "algorithm of public key in end entity " + "certificate (at index 0)"); } this.privKey = privateKey; if (clonedChain[0] instanceof X509Certificate && !(clonedChain instanceof X509Certificate[])) { this.chain = new X509Certificate[clonedChain.length]; System.arraycopy(clonedChain, 0, this.chain, 0, clonedChain.length); } else { this.chain = clonedChain; } this.attributes = Collections.unmodifiableSet(new HashSet<>(attributes)); } /** * Gets the {@code PrivateKey} from this entry. * * @return the {@code PrivateKey} from this entry */ public PrivateKey getPrivateKey() { return privKey; } /** * Gets the {@code Certificate} chain from this entry. * *

The stored chain is cloned before being returned. * * @return an array of {@code Certificate}s corresponding * to the certificate chain for the public key. * If the certificates are of type X.509, * the runtime type of the returned array is * {@code X509Certificate[]}. */ public Certificate[] getCertificateChain() { return chain.clone(); } /** * Gets the end entity {@code Certificate} * from the certificate chain in this entry. * * @return the end entity {@code Certificate} (at index 0) * from the certificate chain in this entry. * If the certificate is of type X.509, * the runtime type of the returned certificate is * {@code X509Certificate}. */ public Certificate getCertificate() { return chain[0]; } /** * Retrieves the attributes associated with an entry. *

* * @return an unmodifiable {@code Set} of attributes, possibly empty * * @since 1.8 */ @Override public Set getAttributes() { return attributes; } /** * Returns a string representation of this PrivateKeyEntry. * @return a string representation of this PrivateKeyEntry. */ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Private key entry and certificate chain with " + chain.length + " elements:\r\n"); for (Certificate cert : chain) { sb.append(cert); sb.append("\r\n"); } return sb.toString(); } } /** * A {@code KeyStore} entry that holds a {@code SecretKey}. * * @since 1.5 */ public static final class SecretKeyEntry implements Entry { private final SecretKey sKey; private final Set attributes; /** * Constructs a {@code SecretKeyEntry} with a * {@code SecretKey}. * * @param secretKey the {@code SecretKey} * * @exception NullPointerException if {@code secretKey} * is {@code null} */ public SecretKeyEntry(SecretKey secretKey) { if (secretKey == null) { throw new NullPointerException("invalid null input"); } this.sKey = secretKey; this.attributes = Collections.emptySet(); } /** * Constructs a {@code SecretKeyEntry} with a {@code SecretKey} and * associated entry attributes. * *

The specified {@code attributes} is cloned before it is stored * in the new {@code SecretKeyEntry} object. * * @param secretKey the {@code SecretKey} * @param attributes the attributes * * @exception NullPointerException if {@code secretKey} or * {@code attributes} is {@code null} * * @since 1.8 */ public SecretKeyEntry(SecretKey secretKey, Set attributes) { if (secretKey == null || attributes == null) { throw new NullPointerException("invalid null input"); } this.sKey = secretKey; this.attributes = Collections.unmodifiableSet(new HashSet<>(attributes)); } /** * Gets the {@code SecretKey} from this entry. * * @return the {@code SecretKey} from this entry */ public SecretKey getSecretKey() { return sKey; } /** * Retrieves the attributes associated with an entry. *

* * @return an unmodifiable {@code Set} of attributes, possibly empty * * @since 1.8 */ @Override public Set getAttributes() { return attributes; } /** * Returns a string representation of this SecretKeyEntry. * @return a string representation of this SecretKeyEntry. */ public String toString() { return "Secret key entry with algorithm " + sKey.getAlgorithm(); } } /** * A {@code KeyStore} entry that holds a trusted * {@code Certificate}. * * @since 1.5 */ public static final class TrustedCertificateEntry implements Entry { private final Certificate cert; private final Set attributes; /** * Constructs a {@code TrustedCertificateEntry} with a * trusted {@code Certificate}. * * @param trustedCert the trusted {@code Certificate} * * @exception NullPointerException if * {@code trustedCert} is {@code null} */ public TrustedCertificateEntry(Certificate trustedCert) { if (trustedCert == null) { throw new NullPointerException("invalid null input"); } this.cert = trustedCert; this.attributes = Collections.emptySet(); } /** * Constructs a {@code TrustedCertificateEntry} with a * trusted {@code Certificate} and associated entry attributes. * *

The specified {@code attributes} is cloned before it is stored * in the new {@code TrustedCertificateEntry} object. * * @param trustedCert the trusted {@code Certificate} * @param attributes the attributes * * @exception NullPointerException if {@code trustedCert} or * {@code attributes} is {@code null} * * @since 1.8 */ public TrustedCertificateEntry(Certificate trustedCert, Set attributes) { if (trustedCert == null || attributes == null) { throw new NullPointerException("invalid null input"); } this.cert = trustedCert; this.attributes = Collections.unmodifiableSet(new HashSet<>(attributes)); } /** * Gets the trusted {@code Certficate} from this entry. * * @return the trusted {@code Certificate} from this entry */ public Certificate getTrustedCertificate() { return cert; } /** * Retrieves the attributes associated with an entry. *

* * @return an unmodifiable {@code Set} of attributes, possibly empty * * @since 1.8 */ @Override public Set getAttributes() { return attributes; } /** * Returns a string representation of this TrustedCertificateEntry. * @return a string representation of this TrustedCertificateEntry. */ public String toString() { return "Trusted certificate entry:\r\n" + cert.toString(); } } /** * Creates a KeyStore object of the given type, and encapsulates the given * provider implementation (SPI object) in it. * * @param keyStoreSpi the provider implementation. * @param provider the provider. * @param type the keystore type. */ protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type) { this.keyStoreSpi = keyStoreSpi; this.provider = provider; this.type = type; if (!skipDebug && pdebug != null) { pdebug.println("KeyStore." + type.toUpperCase() + " type from: " + this.provider.getName()); } } /** * Returns a keystore object of the specified type. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new KeyStore object encapsulating the * KeyStoreSpi implementation from the first * Provider that supports the specified type is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param type the type of keystore. * See the KeyStore section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard keystore types. * * @return a keystore object of the specified type. * * @exception KeyStoreException if no Provider supports a * KeyStoreSpi implementation for the * specified type. * * @see Provider */ public static KeyStore getInstance(String type) throws KeyStoreException { try { Object[] objs = Security.getImpl(type, "KeyStore", (String)null); return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); } catch (NoSuchAlgorithmException nsae) { throw new KeyStoreException(type + " not found", nsae); } catch (NoSuchProviderException nspe) { throw new KeyStoreException(type + " not found", nspe); } } /** * Returns a keystore object of the specified type. * *

A new KeyStore object encapsulating the * KeyStoreSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param type the type of keystore. * See the KeyStore section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard keystore types. * * @param provider the name of the provider. * * @return a keystore object of the specified type. * * @exception KeyStoreException if a KeyStoreSpi * implementation for the specified type is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider name is null * or empty. * * @see Provider */ public static KeyStore getInstance(String type, String provider) throws KeyStoreException, NoSuchProviderException { if (provider == null || provider.length() == 0) throw new IllegalArgumentException("missing provider"); try { Object[] objs = Security.getImpl(type, "KeyStore", provider); return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); } catch (NoSuchAlgorithmException nsae) { throw new KeyStoreException(type + " not found", nsae); } } /** * Returns a keystore object of the specified type. * *

A new KeyStore object encapsulating the * KeyStoreSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param type the type of keystore. * See the KeyStore section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard keystore types. * * @param provider the provider. * * @return a keystore object of the specified type. * * @exception KeyStoreException if KeyStoreSpi * implementation for the specified type is not available * from the specified Provider object. * * @exception IllegalArgumentException if the specified provider is null. * * @see Provider * * @since 1.4 */ public static KeyStore getInstance(String type, Provider provider) throws KeyStoreException { if (provider == null) throw new IllegalArgumentException("missing provider"); try { Object[] objs = Security.getImpl(type, "KeyStore", provider); return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); } catch (NoSuchAlgorithmException nsae) { throw new KeyStoreException(type + " not found", nsae); } } /** * Returns the default keystore type as specified by the * {@code keystore.type} security property, or the string * {@literal "jks"} (acronym for {@literal "Java keystore"}) * if no such property exists. * *

The default keystore type can be used by applications that do not * want to use a hard-coded keystore type when calling one of the * {@code getInstance} methods, and want to provide a default keystore * type in case a user does not specify its own. * *

The default keystore type can be changed by setting the value of the * {@code keystore.type} security property to the desired keystore type. * * @return the default keystore type as specified by the * {@code keystore.type} security property, or the string {@literal "jks"} * if no such property exists. * @see java.security.Security security properties */ public final static String getDefaultType() { String kstype; kstype = AccessController.doPrivileged(new PrivilegedAction() { public String run() { return Security.getProperty(KEYSTORE_TYPE); } }); if (kstype == null) { kstype = "jks"; } return kstype; } /** * Returns the provider of this keystore. * * @return the provider of this keystore. */ public final Provider getProvider() { return this.provider; } /** * Returns the type of this keystore. * * @return the type of this keystore. */ public final String getType() { return this.type; } /** * Returns the key associated with the given alias, using the given * password to recover it. The key must have been associated with * the alias by a call to {@code setKeyEntry}, * or by a call to {@code setEntry} with a * {@code PrivateKeyEntry} or {@code SecretKeyEntry}. * * @param alias the alias name * @param password the password for recovering the key * * @return the requested key, or null if the given alias does not exist * or does not identify a key-related entry. * * @exception KeyStoreException if the keystore has not been initialized * (loaded). * @exception NoSuchAlgorithmException if the algorithm for recovering the * key cannot be found * @exception UnrecoverableKeyException if the key cannot be recovered * (e.g., the given password is wrong). */ public final Key getKey(String alias, char[] password) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineGetKey(alias, password); } /** * Returns the certificate chain associated with the given alias. * The certificate chain must have been associated with the alias * by a call to {@code setKeyEntry}, * or by a call to {@code setEntry} with a * {@code PrivateKeyEntry}. * * @param alias the alias name * * @return the certificate chain (ordered with the user's certificate first * followed by zero or more certificate authorities), or null if the given alias * does not exist or does not contain a certificate chain * * @exception KeyStoreException if the keystore has not been initialized * (loaded). */ public final Certificate[] getCertificateChain(String alias) throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineGetCertificateChain(alias); } /** * Returns the certificate associated with the given alias. * *

If the given alias name identifies an entry * created by a call to {@code setCertificateEntry}, * or created by a call to {@code setEntry} with a * {@code TrustedCertificateEntry}, * then the trusted certificate contained in that entry is returned. * *

If the given alias name identifies an entry * created by a call to {@code setKeyEntry}, * or created by a call to {@code setEntry} with a * {@code PrivateKeyEntry}, * then the first element of the certificate chain in that entry * is returned. * * @param alias the alias name * * @return the certificate, or null if the given alias does not exist or * does not contain a certificate. * * @exception KeyStoreException if the keystore has not been initialized * (loaded). */ public final Certificate getCertificate(String alias) throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineGetCertificate(alias); } /** * Returns the creation date of the entry identified by the given alias. * * @param alias the alias name * * @return the creation date of this entry, or null if the given alias does * not exist * * @exception KeyStoreException if the keystore has not been initialized * (loaded). */ public final Date getCreationDate(String alias) throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineGetCreationDate(alias); } /** * Assigns the given key to the given alias, protecting it with the given * password. * *

If the given key is of type {@code java.security.PrivateKey}, * it must be accompanied by a certificate chain certifying the * corresponding public key. * *

If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key to be associated with the alias * @param password the password to protect the key * @param chain the certificate chain for the corresponding public * key (only required if the given key is of type * {@code java.security.PrivateKey}). * * @exception KeyStoreException if the keystore has not been initialized * (loaded), the given key cannot be protected, or this operation fails * for some other reason */ public final void setKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } if ((key instanceof PrivateKey) && (chain == null || chain.length == 0)) { throw new IllegalArgumentException("Private key must be " + "accompanied by certificate " + "chain"); } keyStoreSpi.engineSetKeyEntry(alias, key, password, chain); } /** * Assigns the given key (that has already been protected) to the given * alias. * *

If the protected key is of type * {@code java.security.PrivateKey}, it must be accompanied by a * certificate chain certifying the corresponding public key. If the * underlying keystore implementation is of type {@code jks}, * {@code key} must be encoded as an * {@code EncryptedPrivateKeyInfo} as defined in the PKCS #8 standard. * *

If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key (in protected format) to be associated with the alias * @param chain the certificate chain for the corresponding public * key (only useful if the protected key is of type * {@code java.security.PrivateKey}). * * @exception KeyStoreException if the keystore has not been initialized * (loaded), or if this operation fails for some other reason. */ public final void setKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } keyStoreSpi.engineSetKeyEntry(alias, key, chain); } /** * Assigns the given trusted certificate to the given alias. * *

If the given alias identifies an existing entry * created by a call to {@code setCertificateEntry}, * or created by a call to {@code setEntry} with a * {@code TrustedCertificateEntry}, * the trusted certificate in the existing entry * is overridden by the given certificate. * * @param alias the alias name * @param cert the certificate * * @exception KeyStoreException if the keystore has not been initialized, * or the given alias already exists and does not identify an * entry containing a trusted certificate, * or this operation fails for some other reason. */ public final void setCertificateEntry(String alias, Certificate cert) throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } keyStoreSpi.engineSetCertificateEntry(alias, cert); } /** * Deletes the entry identified by the given alias from this keystore. * * @param alias the alias name * * @exception KeyStoreException if the keystore has not been initialized, * or if the entry cannot be removed. */ public final void deleteEntry(String alias) throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } keyStoreSpi.engineDeleteEntry(alias); } /** * Lists all the alias names of this keystore. * * @return enumeration of the alias names * * @exception KeyStoreException if the keystore has not been initialized * (loaded). */ public final Enumeration aliases() throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineAliases(); } /** * Checks if the given alias exists in this keystore. * * @param alias the alias name * * @return true if the alias exists, false otherwise * * @exception KeyStoreException if the keystore has not been initialized * (loaded). */ public final boolean containsAlias(String alias) throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineContainsAlias(alias); } /** * Retrieves the number of entries in this keystore. * * @return the number of entries in this keystore * * @exception KeyStoreException if the keystore has not been initialized * (loaded). */ public final int size() throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineSize(); } /** * Returns true if the entry identified by the given alias * was created by a call to {@code setKeyEntry}, * or created by a call to {@code setEntry} with a * {@code PrivateKeyEntry} or a {@code SecretKeyEntry}. * * @param alias the alias for the keystore entry to be checked * * @return true if the entry identified by the given alias is a * key-related entry, false otherwise. * * @exception KeyStoreException if the keystore has not been initialized * (loaded). */ public final boolean isKeyEntry(String alias) throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineIsKeyEntry(alias); } /** * Returns true if the entry identified by the given alias * was created by a call to {@code setCertificateEntry}, * or created by a call to {@code setEntry} with a * {@code TrustedCertificateEntry}. * * @param alias the alias for the keystore entry to be checked * * @return true if the entry identified by the given alias contains a * trusted certificate, false otherwise. * * @exception KeyStoreException if the keystore has not been initialized * (loaded). */ public final boolean isCertificateEntry(String alias) throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineIsCertificateEntry(alias); } /** * Returns the (alias) name of the first keystore entry whose certificate * matches the given certificate. * *

This method attempts to match the given certificate with each * keystore entry. If the entry being considered was * created by a call to {@code setCertificateEntry}, * or created by a call to {@code setEntry} with a * {@code TrustedCertificateEntry}, * then the given certificate is compared to that entry's certificate. * *

If the entry being considered was * created by a call to {@code setKeyEntry}, * or created by a call to {@code setEntry} with a * {@code PrivateKeyEntry}, * then the given certificate is compared to the first * element of that entry's certificate chain. * * @param cert the certificate to match with. * * @return the alias name of the first entry with a matching certificate, * or null if no such entry exists in this keystore. * * @exception KeyStoreException if the keystore has not been initialized * (loaded). */ public final String getCertificateAlias(Certificate cert) throws KeyStoreException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineGetCertificateAlias(cert); } /** * Stores this keystore to the given output stream, and protects its * integrity with the given password. * * @param stream the output stream to which this keystore is written. * @param password the password to generate the keystore integrity check * * @exception KeyStoreException if the keystore has not been initialized * (loaded). * @exception IOException if there was an I/O problem with data * @exception NoSuchAlgorithmException if the appropriate data integrity * algorithm could not be found * @exception CertificateException if any of the certificates included in * the keystore data could not be stored */ public final void store(OutputStream stream, char[] password) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } keyStoreSpi.engineStore(stream, password); } /** * Stores this keystore using the given {@code LoadStoreParameter}. * * @param param the {@code LoadStoreParameter} * that specifies how to store the keystore, * which may be {@code null} * * @exception IllegalArgumentException if the given * {@code LoadStoreParameter} * input is not recognized * @exception KeyStoreException if the keystore has not been initialized * (loaded) * @exception IOException if there was an I/O problem with data * @exception NoSuchAlgorithmException if the appropriate data integrity * algorithm could not be found * @exception CertificateException if any of the certificates included in * the keystore data could not be stored * * @since 1.5 */ public final void store(LoadStoreParameter param) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } keyStoreSpi.engineStore(param); } /** * Loads this KeyStore from the given input stream. * *

A password may be given to unlock the keystore * (e.g. the keystore resides on a hardware token device), * or to check the integrity of the keystore data. * If a password is not given for integrity checking, * then integrity checking is not performed. * *

In order to create an empty keystore, or if the keystore cannot * be initialized from a stream, pass {@code null} * as the {@code stream} argument. * *

Note that if this keystore has already been loaded, it is * reinitialized and loaded again from the given input stream. * * @param stream the input stream from which the keystore is loaded, * or {@code null} * @param password the password used to check the integrity of * the keystore, the password used to unlock the keystore, * or {@code null} * * @exception IOException if there is an I/O or format problem with the * keystore data, if a password is required but not given, * or if the given password was incorrect. If the error is due to a * wrong password, the {@link Throwable#getCause cause} of the * {@code IOException} should be an * {@code UnrecoverableKeyException} * @exception NoSuchAlgorithmException if the algorithm used to check * the integrity of the keystore cannot be found * @exception CertificateException if any of the certificates in the * keystore could not be loaded */ public final void load(InputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException { keyStoreSpi.engineLoad(stream, password); initialized = true; } /** * Loads this keystore using the given {@code LoadStoreParameter}. * *

Note that if this KeyStore has already been loaded, it is * reinitialized and loaded again from the given parameter. * * @param param the {@code LoadStoreParameter} * that specifies how to load the keystore, * which may be {@code null} * * @exception IllegalArgumentException if the given * {@code LoadStoreParameter} * input is not recognized * @exception IOException if there is an I/O or format problem with the * keystore data. If the error is due to an incorrect * {@code ProtectionParameter} (e.g. wrong password) * the {@link Throwable#getCause cause} of the * {@code IOException} should be an * {@code UnrecoverableKeyException} * @exception NoSuchAlgorithmException if the algorithm used to check * the integrity of the keystore cannot be found * @exception CertificateException if any of the certificates in the * keystore could not be loaded * * @since 1.5 */ public final void load(LoadStoreParameter param) throws IOException, NoSuchAlgorithmException, CertificateException { keyStoreSpi.engineLoad(param); initialized = true; } /** * Gets a keystore {@code Entry} for the specified alias * with the specified protection parameter. * * @param alias get the keystore {@code Entry} for this alias * @param protParam the {@code ProtectionParameter} * used to protect the {@code Entry}, * which may be {@code null} * * @return the keystore {@code Entry} for the specified alias, * or {@code null} if there is no such entry * * @exception NullPointerException if * {@code alias} is {@code null} * @exception NoSuchAlgorithmException if the algorithm for recovering the * entry cannot be found * @exception UnrecoverableEntryException if the specified * {@code protParam} were insufficient or invalid * @exception UnrecoverableKeyException if the entry is a * {@code PrivateKeyEntry} or {@code SecretKeyEntry} * and the specified {@code protParam} does not contain * the information needed to recover the key (e.g. wrong password) * @exception KeyStoreException if the keystore has not been initialized * (loaded). * @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter) * * @since 1.5 */ public final Entry getEntry(String alias, ProtectionParameter protParam) throws NoSuchAlgorithmException, UnrecoverableEntryException, KeyStoreException { if (alias == null) { throw new NullPointerException("invalid null input"); } if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineGetEntry(alias, protParam); } /** * Saves a keystore {@code Entry} under the specified alias. * The protection parameter is used to protect the * {@code Entry}. * *

If an entry already exists for the specified alias, * it is overridden. * * @param alias save the keystore {@code Entry} under this alias * @param entry the {@code Entry} to save * @param protParam the {@code ProtectionParameter} * used to protect the {@code Entry}, * which may be {@code null} * * @exception NullPointerException if * {@code alias} or {@code entry} * is {@code null} * @exception KeyStoreException if the keystore has not been initialized * (loaded), or if this operation fails for some other reason * * @see #getEntry(String, KeyStore.ProtectionParameter) * * @since 1.5 */ public final void setEntry(String alias, Entry entry, ProtectionParameter protParam) throws KeyStoreException { if (alias == null || entry == null) { throw new NullPointerException("invalid null input"); } if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } keyStoreSpi.engineSetEntry(alias, entry, protParam); } /** * Determines if the keystore {@code Entry} for the specified * {@code alias} is an instance or subclass of the specified * {@code entryClass}. * * @param alias the alias name * @param entryClass the entry class * * @return true if the keystore {@code Entry} for the specified * {@code alias} is an instance or subclass of the * specified {@code entryClass}, false otherwise * * @exception NullPointerException if * {@code alias} or {@code entryClass} * is {@code null} * @exception KeyStoreException if the keystore has not been * initialized (loaded) * * @since 1.5 */ public final boolean entryInstanceOf(String alias, Class entryClass) throws KeyStoreException { if (alias == null || entryClass == null) { throw new NullPointerException("invalid null input"); } if (!initialized) { throw new KeyStoreException("Uninitialized keystore"); } return keyStoreSpi.engineEntryInstanceOf(alias, entryClass); } /** * A description of a to-be-instantiated KeyStore object. * *

An instance of this class encapsulates the information needed to * instantiate and initialize a KeyStore object. That process is * triggered when the {@linkplain #getKeyStore} method is called. * *

This makes it possible to decouple configuration from KeyStore * object creation and e.g. delay a password prompt until it is * needed. * * @see KeyStore * @see javax.net.ssl.KeyStoreBuilderParameters * @since 1.5 */ public static abstract class Builder { // maximum times to try the callbackhandler if the password is wrong static final int MAX_CALLBACK_TRIES = 3; /** * Construct a new Builder. */ protected Builder() { // empty } /** * Returns the KeyStore described by this object. * * @return the {@code KeyStore} described by this object * @exception KeyStoreException if an error occurred during the * operation, for example if the KeyStore could not be * instantiated or loaded */ public abstract KeyStore getKeyStore() throws KeyStoreException; /** * Returns the ProtectionParameters that should be used to obtain * the {@link KeyStore.Entry Entry} with the given alias. * The {@code getKeyStore} method must be invoked before this * method may be called. * * @return the ProtectionParameters that should be used to obtain * the {@link KeyStore.Entry Entry} with the given alias. * @param alias the alias of the KeyStore entry * @throws NullPointerException if alias is null * @throws KeyStoreException if an error occurred during the * operation * @throws IllegalStateException if the getKeyStore method has * not been invoked prior to calling this method */ public abstract ProtectionParameter getProtectionParameter(String alias) throws KeyStoreException; /** * Returns a new Builder that encapsulates the given KeyStore. * The {@linkplain #getKeyStore} method of the returned object * will return {@code keyStore}, the {@linkplain * #getProtectionParameter getProtectionParameter()} method will * return {@code protectionParameters}. * *

This is useful if an existing KeyStore object needs to be * used with Builder-based APIs. * * @return a new Builder object * @param keyStore the KeyStore to be encapsulated * @param protectionParameter the ProtectionParameter used to * protect the KeyStore entries * @throws NullPointerException if keyStore or * protectionParameters is null * @throws IllegalArgumentException if the keyStore has not been * initialized */ public static Builder newInstance(final KeyStore keyStore, final ProtectionParameter protectionParameter) { if ((keyStore == null) || (protectionParameter == null)) { throw new NullPointerException(); } if (keyStore.initialized == false) { throw new IllegalArgumentException("KeyStore not initialized"); } return new Builder() { private volatile boolean getCalled; public KeyStore getKeyStore() { getCalled = true; return keyStore; } public ProtectionParameter getProtectionParameter(String alias) { if (alias == null) { throw new NullPointerException(); } if (getCalled == false) { throw new IllegalStateException ("getKeyStore() must be called first"); } return protectionParameter; } }; } /** * Returns a new Builder object. * *

The first call to the {@link #getKeyStore} method on the returned * builder will create a KeyStore of type {@code type} and call * its {@link KeyStore#load load()} method. * The {@code inputStream} argument is constructed from * {@code file}. * If {@code protection} is a * {@code PasswordProtection}, the password is obtained by * calling the {@code getPassword} method. * Otherwise, if {@code protection} is a * {@code CallbackHandlerProtection}, the password is obtained * by invoking the CallbackHandler. * *

Subsequent calls to {@link #getKeyStore} return the same object * as the initial call. If the initial call to failed with a * KeyStoreException, subsequent calls also throw a * KeyStoreException. * *

The KeyStore is instantiated from {@code provider} if * non-null. Otherwise, all installed providers are searched. * *

Calls to {@link #getProtectionParameter getProtectionParameter()} * will return a {@link KeyStore.PasswordProtection PasswordProtection} * object encapsulating the password that was used to invoke the * {@code load} method. * *

Note that the {@link #getKeyStore} method is executed * within the {@link AccessControlContext} of the code invoking this * method. * * @return a new Builder object * @param type the type of KeyStore to be constructed * @param provider the provider from which the KeyStore is to * be instantiated (or null) * @param file the File that contains the KeyStore data * @param protection the ProtectionParameter securing the KeyStore data * @throws NullPointerException if type, file or protection is null * @throws IllegalArgumentException if protection is not an instance * of either PasswordProtection or CallbackHandlerProtection; or * if file does not exist or does not refer to a normal file */ public static Builder newInstance(String type, Provider provider, File file, ProtectionParameter protection) { if ((type == null) || (file == null) || (protection == null)) { throw new NullPointerException(); } if ((protection instanceof PasswordProtection == false) && (protection instanceof CallbackHandlerProtection == false)) { throw new IllegalArgumentException ("Protection must be PasswordProtection or " + "CallbackHandlerProtection"); } if (file.isFile() == false) { throw new IllegalArgumentException ("File does not exist or it does not refer " + "to a normal file: " + file); } return new FileBuilder(type, provider, file, protection, AccessController.getContext()); } private static final class FileBuilder extends Builder { private final String type; private final Provider provider; private final File file; private ProtectionParameter protection; private ProtectionParameter keyProtection; private final AccessControlContext context; private KeyStore keyStore; private Throwable oldException; FileBuilder(String type, Provider provider, File file, ProtectionParameter protection, AccessControlContext context) { this.type = type; this.provider = provider; this.file = file; this.protection = protection; this.context = context; } public synchronized KeyStore getKeyStore() throws KeyStoreException { if (keyStore != null) { return keyStore; } if (oldException != null) { throw new KeyStoreException ("Previous KeyStore instantiation failed", oldException); } PrivilegedExceptionAction action = new PrivilegedExceptionAction() { public KeyStore run() throws Exception { if (protection instanceof CallbackHandlerProtection == false) { return run0(); } // when using a CallbackHandler, // reprompt if the password is wrong int tries = 0; while (true) { tries++; try { return run0(); } catch (IOException e) { if ((tries < MAX_CALLBACK_TRIES) && (e.getCause() instanceof UnrecoverableKeyException)) { continue; } throw e; } } } public KeyStore run0() throws Exception { KeyStore ks; if (provider == null) { ks = KeyStore.getInstance(type); } else { ks = KeyStore.getInstance(type, provider); } InputStream in = null; char[] password = null; try { in = new FileInputStream(file); if (protection instanceof PasswordProtection) { password = ((PasswordProtection)protection).getPassword(); keyProtection = protection; } else { CallbackHandler handler = ((CallbackHandlerProtection)protection) .getCallbackHandler(); PasswordCallback callback = new PasswordCallback ("Password for keystore " + file.getName(), false); handler.handle(new Callback[] {callback}); password = callback.getPassword(); if (password == null) { throw new KeyStoreException("No password" + " provided"); } callback.clearPassword(); keyProtection = new PasswordProtection(password); } ks.load(in, password); return ks; } finally { if (in != null) { in.close(); } } } }; try { keyStore = AccessController.doPrivileged(action, context); return keyStore; } catch (PrivilegedActionException e) { oldException = e.getCause(); throw new KeyStoreException ("KeyStore instantiation failed", oldException); } } public synchronized ProtectionParameter getProtectionParameter(String alias) { if (alias == null) { throw new NullPointerException(); } if (keyStore == null) { throw new IllegalStateException ("getKeyStore() must be called first"); } return keyProtection; } } /** * Returns a new Builder object. * *

Each call to the {@link #getKeyStore} method on the returned * builder will return a new KeyStore object of type {@code type}. * Its {@link KeyStore#load(KeyStore.LoadStoreParameter) load()} * method is invoked using a * {@code LoadStoreParameter} that encapsulates * {@code protection}. * *

The KeyStore is instantiated from {@code provider} if * non-null. Otherwise, all installed providers are searched. * *

Calls to {@link #getProtectionParameter getProtectionParameter()} * will return {@code protection}. * *

Note that the {@link #getKeyStore} method is executed * within the {@link AccessControlContext} of the code invoking this * method. * * @return a new Builder object * @param type the type of KeyStore to be constructed * @param provider the provider from which the KeyStore is to * be instantiated (or null) * @param protection the ProtectionParameter securing the Keystore * @throws NullPointerException if type or protection is null */ public static Builder newInstance(final String type, final Provider provider, final ProtectionParameter protection) { if ((type == null) || (protection == null)) { throw new NullPointerException(); } final AccessControlContext context = AccessController.getContext(); return new Builder() { private volatile boolean getCalled; private IOException oldException; private final PrivilegedExceptionAction action = new PrivilegedExceptionAction() { public KeyStore run() throws Exception { KeyStore ks; if (provider == null) { ks = KeyStore.getInstance(type); } else { ks = KeyStore.getInstance(type, provider); } LoadStoreParameter param = new SimpleLoadStoreParameter(protection); if (protection instanceof CallbackHandlerProtection == false) { ks.load(param); } else { // when using a CallbackHandler, // reprompt if the password is wrong int tries = 0; while (true) { tries++; try { ks.load(param); break; } catch (IOException e) { if (e.getCause() instanceof UnrecoverableKeyException) { if (tries < MAX_CALLBACK_TRIES) { continue; } else { oldException = e; } } throw e; } } } getCalled = true; return ks; } }; public synchronized KeyStore getKeyStore() throws KeyStoreException { if (oldException != null) { throw new KeyStoreException ("Previous KeyStore instantiation failed", oldException); } try { return AccessController.doPrivileged(action, context); } catch (PrivilegedActionException e) { Throwable cause = e.getCause(); throw new KeyStoreException ("KeyStore instantiation failed", cause); } } public ProtectionParameter getProtectionParameter(String alias) { if (alias == null) { throw new NullPointerException(); } if (getCalled == false) { throw new IllegalStateException ("getKeyStore() must be called first"); } return protection; } }; } } static class SimpleLoadStoreParameter implements LoadStoreParameter { private final ProtectionParameter protection; SimpleLoadStoreParameter(ProtectionParameter protection) { this.protection = protection; } public ProtectionParameter getProtectionParameter() { return protection; } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3156 Content-Disposition: inline; filename="KeyStoreException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "cf56d6aa54264bc2e26195db4ea43e170b935103" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This is the generic KeyStore exception. * * @author Jan Luehe * * * @since 1.2 */ public class KeyStoreException extends GeneralSecurityException { private static final long serialVersionUID = -1119353179322377262L; /** * Constructs a KeyStoreException with no detail message. (A * detail message is a String that describes this particular * exception.) */ public KeyStoreException() { super(); } /** * Constructs a KeyStoreException with the specified detail * message. (A detail message is a String that describes this * particular exception.) * * @param msg the detail message. */ public KeyStoreException(String msg) { super(msg); } /** * Creates a {@code KeyStoreException} with the specified * detail message and cause. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public KeyStoreException(String message, Throwable cause) { super(message, cause); } /** * Creates a {@code KeyStoreException} with the specified cause * and a detail message of {@code (cause==null ? null : cause.toString())} * (which typically contains the class and detail message of * {@code cause}). * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public KeyStoreException(Throwable cause) { super(cause); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 23643 Content-Disposition: inline; filename="KeyStoreSpi.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "f71aed439e31eaec5235cafbbc74f313dd6b022a" /* * Copyright (c) 1998, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.*; import java.util.*; import java.security.KeyStore.*; import java.security.cert.Certificate; import java.security.cert.CertificateException; import javax.crypto.SecretKey; import javax.security.auth.callback.*; /** * This class defines the Service Provider Interface (SPI) * for the {@code KeyStore} class. * All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a keystore for a particular keystore type. * * @author Jan Luehe * * * @see KeyStore * * @since 1.2 */ public abstract class KeyStoreSpi { /** * Returns the key associated with the given alias, using the given * password to recover it. The key must have been associated with * the alias by a call to {@code setKeyEntry}, * or by a call to {@code setEntry} with a * {@code PrivateKeyEntry} or {@code SecretKeyEntry}. * * @param alias the alias name * @param password the password for recovering the key * * @return the requested key, or null if the given alias does not exist * or does not identify a key-related entry. * * @exception NoSuchAlgorithmException if the algorithm for recovering the * key cannot be found * @exception UnrecoverableKeyException if the key cannot be recovered * (e.g., the given password is wrong). */ public abstract Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException; /** * Returns the certificate chain associated with the given alias. * The certificate chain must have been associated with the alias * by a call to {@code setKeyEntry}, * or by a call to {@code setEntry} with a * {@code PrivateKeyEntry}. * * @param alias the alias name * * @return the certificate chain (ordered with the user's certificate first * and the root certificate authority last), or null if the given alias * does not exist or does not contain a certificate chain */ public abstract Certificate[] engineGetCertificateChain(String alias); /** * Returns the certificate associated with the given alias. * *

If the given alias name identifies an entry * created by a call to {@code setCertificateEntry}, * or created by a call to {@code setEntry} with a * {@code TrustedCertificateEntry}, * then the trusted certificate contained in that entry is returned. * *

If the given alias name identifies an entry * created by a call to {@code setKeyEntry}, * or created by a call to {@code setEntry} with a * {@code PrivateKeyEntry}, * then the first element of the certificate chain in that entry * (if a chain exists) is returned. * * @param alias the alias name * * @return the certificate, or null if the given alias does not exist or * does not contain a certificate. */ public abstract Certificate engineGetCertificate(String alias); /** * Returns the creation date of the entry identified by the given alias. * * @param alias the alias name * * @return the creation date of this entry, or null if the given alias does * not exist */ public abstract Date engineGetCreationDate(String alias); /** * Assigns the given key to the given alias, protecting it with the given * password. * *

If the given key is of type {@code java.security.PrivateKey}, * it must be accompanied by a certificate chain certifying the * corresponding public key. * *

If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key to be associated with the alias * @param password the password to protect the key * @param chain the certificate chain for the corresponding public * key (only required if the given key is of type * {@code java.security.PrivateKey}). * * @exception KeyStoreException if the given key cannot be protected, or * this operation fails for some other reason */ public abstract void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException; /** * Assigns the given key (that has already been protected) to the given * alias. * *

If the protected key is of type * {@code java.security.PrivateKey}, * it must be accompanied by a certificate chain certifying the * corresponding public key. * *

If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key (in protected format) to be associated with the alias * @param chain the certificate chain for the corresponding public * key (only useful if the protected key is of type * {@code java.security.PrivateKey}). * * @exception KeyStoreException if this operation fails. */ public abstract void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException; /** * Assigns the given certificate to the given alias. * *

If the given alias identifies an existing entry * created by a call to {@code setCertificateEntry}, * or created by a call to {@code setEntry} with a * {@code TrustedCertificateEntry}, * the trusted certificate in the existing entry * is overridden by the given certificate. * * @param alias the alias name * @param cert the certificate * * @exception KeyStoreException if the given alias already exists and does * not identify an entry containing a trusted certificate, * or this operation fails for some other reason. */ public abstract void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException; /** * Deletes the entry identified by the given alias from this keystore. * * @param alias the alias name * * @exception KeyStoreException if the entry cannot be removed. */ public abstract void engineDeleteEntry(String alias) throws KeyStoreException; /** * Lists all the alias names of this keystore. * * @return enumeration of the alias names */ public abstract Enumeration engineAliases(); /** * Checks if the given alias exists in this keystore. * * @param alias the alias name * * @return true if the alias exists, false otherwise */ public abstract boolean engineContainsAlias(String alias); /** * Retrieves the number of entries in this keystore. * * @return the number of entries in this keystore */ public abstract int engineSize(); /** * Returns true if the entry identified by the given alias * was created by a call to {@code setKeyEntry}, * or created by a call to {@code setEntry} with a * {@code PrivateKeyEntry} or a {@code SecretKeyEntry}. * * @param alias the alias for the keystore entry to be checked * * @return true if the entry identified by the given alias is a * key-related, false otherwise. */ public abstract boolean engineIsKeyEntry(String alias); /** * Returns true if the entry identified by the given alias * was created by a call to {@code setCertificateEntry}, * or created by a call to {@code setEntry} with a * {@code TrustedCertificateEntry}. * * @param alias the alias for the keystore entry to be checked * * @return true if the entry identified by the given alias contains a * trusted certificate, false otherwise. */ public abstract boolean engineIsCertificateEntry(String alias); /** * Returns the (alias) name of the first keystore entry whose certificate * matches the given certificate. * *

This method attempts to match the given certificate with each * keystore entry. If the entry being considered was * created by a call to {@code setCertificateEntry}, * or created by a call to {@code setEntry} with a * {@code TrustedCertificateEntry}, * then the given certificate is compared to that entry's certificate. * *

If the entry being considered was * created by a call to {@code setKeyEntry}, * or created by a call to {@code setEntry} with a * {@code PrivateKeyEntry}, * then the given certificate is compared to the first * element of that entry's certificate chain. * * @param cert the certificate to match with. * * @return the alias name of the first entry with matching certificate, * or null if no such entry exists in this keystore. */ public abstract String engineGetCertificateAlias(Certificate cert); /** * Stores this keystore to the given output stream, and protects its * integrity with the given password. * * @param stream the output stream to which this keystore is written. * @param password the password to generate the keystore integrity check * * @exception IOException if there was an I/O problem with data * @exception NoSuchAlgorithmException if the appropriate data integrity * algorithm could not be found * @exception CertificateException if any of the certificates included in * the keystore data could not be stored */ public abstract void engineStore(OutputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException; /** * Stores this keystore using the given * {@code KeyStore.LoadStoreParmeter}. * * @param param the {@code KeyStore.LoadStoreParmeter} * that specifies how to store the keystore, * which may be {@code null} * * @exception IllegalArgumentException if the given * {@code KeyStore.LoadStoreParmeter} * input is not recognized * @exception IOException if there was an I/O problem with data * @exception NoSuchAlgorithmException if the appropriate data integrity * algorithm could not be found * @exception CertificateException if any of the certificates included in * the keystore data could not be stored * * @since 1.5 */ public void engineStore(KeyStore.LoadStoreParameter param) throws IOException, NoSuchAlgorithmException, CertificateException { throw new UnsupportedOperationException(); } /** * Loads the keystore from the given input stream. * *

A password may be given to unlock the keystore * (e.g. the keystore resides on a hardware token device), * or to check the integrity of the keystore data. * If a password is not given for integrity checking, * then integrity checking is not performed. * * @param stream the input stream from which the keystore is loaded, * or {@code null} * @param password the password used to check the integrity of * the keystore, the password used to unlock the keystore, * or {@code null} * * @exception IOException if there is an I/O or format problem with the * keystore data, if a password is required but not given, * or if the given password was incorrect. If the error is due to a * wrong password, the {@link Throwable#getCause cause} of the * {@code IOException} should be an * {@code UnrecoverableKeyException} * @exception NoSuchAlgorithmException if the algorithm used to check * the integrity of the keystore cannot be found * @exception CertificateException if any of the certificates in the * keystore could not be loaded */ public abstract void engineLoad(InputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException; /** * Loads the keystore using the given * {@code KeyStore.LoadStoreParameter}. * *

Note that if this KeyStore has already been loaded, it is * reinitialized and loaded again from the given parameter. * * @param param the {@code KeyStore.LoadStoreParameter} * that specifies how to load the keystore, * which may be {@code null} * * @exception IllegalArgumentException if the given * {@code KeyStore.LoadStoreParameter} * input is not recognized * @exception IOException if there is an I/O or format problem with the * keystore data. If the error is due to an incorrect * {@code ProtectionParameter} (e.g. wrong password) * the {@link Throwable#getCause cause} of the * {@code IOException} should be an * {@code UnrecoverableKeyException} * @exception NoSuchAlgorithmException if the algorithm used to check * the integrity of the keystore cannot be found * @exception CertificateException if any of the certificates in the * keystore could not be loaded * * @since 1.5 */ public void engineLoad(KeyStore.LoadStoreParameter param) throws IOException, NoSuchAlgorithmException, CertificateException { if (param == null) { engineLoad((InputStream)null, (char[])null); return; } if (param instanceof KeyStore.SimpleLoadStoreParameter) { ProtectionParameter protection = param.getProtectionParameter(); char[] password; if (protection instanceof PasswordProtection) { password = ((PasswordProtection)protection).getPassword(); } else if (protection instanceof CallbackHandlerProtection) { CallbackHandler handler = ((CallbackHandlerProtection)protection).getCallbackHandler(); PasswordCallback callback = new PasswordCallback("Password: ", false); try { handler.handle(new Callback[] {callback}); } catch (UnsupportedCallbackException e) { throw new NoSuchAlgorithmException ("Could not obtain password", e); } password = callback.getPassword(); callback.clearPassword(); if (password == null) { throw new NoSuchAlgorithmException ("No password provided"); } } else { throw new NoSuchAlgorithmException("ProtectionParameter must" + " be PasswordProtection or CallbackHandlerProtection"); } engineLoad(null, password); return; } throw new UnsupportedOperationException(); } /** * Gets a {@code KeyStore.Entry} for the specified alias * with the specified protection parameter. * * @param alias get the {@code KeyStore.Entry} for this alias * @param protParam the {@code ProtectionParameter} * used to protect the {@code Entry}, * which may be {@code null} * * @return the {@code KeyStore.Entry} for the specified alias, * or {@code null} if there is no such entry * * @exception KeyStoreException if the operation failed * @exception NoSuchAlgorithmException if the algorithm for recovering the * entry cannot be found * @exception UnrecoverableEntryException if the specified * {@code protParam} were insufficient or invalid * @exception UnrecoverableKeyException if the entry is a * {@code PrivateKeyEntry} or {@code SecretKeyEntry} * and the specified {@code protParam} does not contain * the information needed to recover the key (e.g. wrong password) * * @since 1.5 */ public KeyStore.Entry engineGetEntry(String alias, KeyStore.ProtectionParameter protParam) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException { if (!engineContainsAlias(alias)) { return null; } if (protParam == null) { if (engineIsCertificateEntry(alias)) { return new KeyStore.TrustedCertificateEntry (engineGetCertificate(alias)); } else { throw new UnrecoverableKeyException ("requested entry requires a password"); } } if (protParam instanceof KeyStore.PasswordProtection) { if (engineIsCertificateEntry(alias)) { throw new UnsupportedOperationException ("trusted certificate entries are not password-protected"); } else if (engineIsKeyEntry(alias)) { KeyStore.PasswordProtection pp = (KeyStore.PasswordProtection)protParam; char[] password = pp.getPassword(); Key key = engineGetKey(alias, password); if (key instanceof PrivateKey) { Certificate[] chain = engineGetCertificateChain(alias); return new KeyStore.PrivateKeyEntry((PrivateKey)key, chain); } else if (key instanceof SecretKey) { return new KeyStore.SecretKeyEntry((SecretKey)key); } } } throw new UnsupportedOperationException(); } /** * Saves a {@code KeyStore.Entry} under the specified alias. * The specified protection parameter is used to protect the * {@code Entry}. * *

If an entry already exists for the specified alias, * it is overridden. * * @param alias save the {@code KeyStore.Entry} under this alias * @param entry the {@code Entry} to save * @param protParam the {@code ProtectionParameter} * used to protect the {@code Entry}, * which may be {@code null} * * @exception KeyStoreException if this operation fails * * @since 1.5 */ public void engineSetEntry(String alias, KeyStore.Entry entry, KeyStore.ProtectionParameter protParam) throws KeyStoreException { // get password if (protParam != null && !(protParam instanceof KeyStore.PasswordProtection)) { throw new KeyStoreException("unsupported protection parameter"); } KeyStore.PasswordProtection pProtect = null; if (protParam != null) { pProtect = (KeyStore.PasswordProtection)protParam; } // set entry if (entry instanceof KeyStore.TrustedCertificateEntry) { if (protParam != null && pProtect.getPassword() != null) { // pre-1.5 style setCertificateEntry did not allow password throw new KeyStoreException ("trusted certificate entries are not password-protected"); } else { KeyStore.TrustedCertificateEntry tce = (KeyStore.TrustedCertificateEntry)entry; engineSetCertificateEntry(alias, tce.getTrustedCertificate()); return; } } else if (entry instanceof KeyStore.PrivateKeyEntry) { if (pProtect == null || pProtect.getPassword() == null) { // pre-1.5 style setKeyEntry required password throw new KeyStoreException ("non-null password required to create PrivateKeyEntry"); } else { engineSetKeyEntry (alias, ((KeyStore.PrivateKeyEntry)entry).getPrivateKey(), pProtect.getPassword(), ((KeyStore.PrivateKeyEntry)entry).getCertificateChain()); return; } } else if (entry instanceof KeyStore.SecretKeyEntry) { if (pProtect == null || pProtect.getPassword() == null) { // pre-1.5 style setKeyEntry required password throw new KeyStoreException ("non-null password required to create SecretKeyEntry"); } else { engineSetKeyEntry (alias, ((KeyStore.SecretKeyEntry)entry).getSecretKey(), pProtect.getPassword(), (Certificate[])null); return; } } throw new KeyStoreException ("unsupported entry type: " + entry.getClass().getName()); } /** * Determines if the keystore {@code Entry} for the specified * {@code alias} is an instance or subclass of the specified * {@code entryClass}. * * @param alias the alias name * @param entryClass the entry class * * @return true if the keystore {@code Entry} for the specified * {@code alias} is an instance or subclass of the * specified {@code entryClass}, false otherwise * * @since 1.5 */ public boolean engineEntryInstanceOf(String alias, Class entryClass) { if (entryClass == KeyStore.TrustedCertificateEntry.class) { return engineIsCertificateEntry(alias); } if (entryClass == KeyStore.PrivateKeyEntry.class) { return engineIsKeyEntry(alias) && engineGetCertificate(alias) != null; } if (entryClass == KeyStore.SecretKeyEntry.class) { return engineIsKeyEntry(alias) && engineGetCertificate(alias) == null; } return false; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 21630 Content-Disposition: inline; filename="MessageDigest.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "a72de0ca21a715b87595d4dad19cb55389604c96" /* * Copyright (c) 1996, 2017, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.*; import java.lang.*; import java.io.IOException; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.io.InputStream; import java.io.ByteArrayInputStream; import java.nio.ByteBuffer; import sun.security.util.Debug; /** * This MessageDigest class provides applications the functionality of a * message digest algorithm, such as SHA-1 or SHA-256. * Message digests are secure one-way hash functions that take arbitrary-sized * data and output a fixed-length hash value. * *

A MessageDigest object starts out initialized. The data is * processed through it using the {@link #update(byte) update} * methods. At any point {@link #reset() reset} can be called * to reset the digest. Once all the data to be updated has been * updated, one of the {@link #digest() digest} methods should * be called to complete the hash computation. * *

The {@code digest} method can be called once for a given number * of updates. After {@code digest} has been called, the MessageDigest * object is reset to its initialized state. * *

Implementations are free to implement the Cloneable interface. * Client applications can test cloneability by attempting cloning * and catching the CloneNotSupportedException: * *

{@code
 * MessageDigest md = MessageDigest.getInstance("SHA-256");
 *
 * try {
 *     md.update(toChapter1);
 *     MessageDigest tc1 = md.clone();
 *     byte[] toChapter1Digest = tc1.digest();
 *     md.update(toChapter2);
 *     ...etc.
 * } catch (CloneNotSupportedException cnse) {
 *     throw new DigestException("couldn't make digest of partial content");
 * }
 * }
* *

Note that if a given implementation is not cloneable, it is * still possible to compute intermediate digests by instantiating * several instances, if the number of digests is known in advance. * *

Note that this class is abstract and extends from * {@code MessageDigestSpi} for historical reasons. * Application developers should only take notice of the methods defined in * this {@code MessageDigest} class; all the methods in * the superclass are intended for cryptographic service providers who wish to * supply their own implementations of message digest algorithms. * *

Every implementation of the Java platform is required to support * the following standard {@code MessageDigest} algorithms: *

    *
  • {@code MD5}
  • *
  • {@code SHA-1}
  • *
  • {@code SHA-256}
  • *
* These algorithms are described in the * MessageDigest section of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * Consult the release documentation for your implementation to see if any * other algorithms are supported. * * @author Benjamin Renaud * * @see DigestInputStream * @see DigestOutputStream */ public abstract class MessageDigest extends MessageDigestSpi { private static final Debug pdebug = Debug.getInstance("provider", "Provider"); private static final boolean skipDebug = Debug.isOn("engine=") && !Debug.isOn("messagedigest"); private String algorithm; // The state of this digest private static final int INITIAL = 0; private static final int IN_PROGRESS = 1; private int state = INITIAL; // The provider private Provider provider; /** * Creates a message digest with the specified algorithm name. * * @param algorithm the standard name of the digest algorithm. * See the MessageDigest section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. */ protected MessageDigest(String algorithm) { this.algorithm = algorithm; } /** * Returns a MessageDigest object that implements the specified digest * algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new MessageDigest object encapsulating the * MessageDigestSpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm requested. * See the MessageDigest section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return a Message Digest object that implements the specified algorithm. * * @exception NoSuchAlgorithmException if no Provider supports a * MessageDigestSpi implementation for the * specified algorithm. * * @see Provider */ public static MessageDigest getInstance(String algorithm) throws NoSuchAlgorithmException { try { MessageDigest md; Object[] objs = Security.getImpl(algorithm, "MessageDigest", (String)null); if (objs[0] instanceof MessageDigest) { md = (MessageDigest)objs[0]; } else { md = new Delegate((MessageDigestSpi)objs[0], algorithm); } md.provider = (Provider)objs[1]; if (!skipDebug && pdebug != null) { pdebug.println("MessageDigest." + algorithm + " algorithm from: " + md.provider.getName()); } return md; } catch(NoSuchProviderException e) { throw new NoSuchAlgorithmException(algorithm + " not found"); } } /** * Returns a MessageDigest object that implements the specified digest * algorithm. * *

A new MessageDigest object encapsulating the * MessageDigestSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm requested. * See the MessageDigest section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the name of the provider. * * @return a MessageDigest object that implements the specified algorithm. * * @exception NoSuchAlgorithmException if a MessageDigestSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider name is null * or empty. * * @see Provider */ public static MessageDigest getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { if (provider == null || provider.length() == 0) throw new IllegalArgumentException("missing provider"); Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider); if (objs[0] instanceof MessageDigest) { MessageDigest md = (MessageDigest)objs[0]; md.provider = (Provider)objs[1]; return md; } else { MessageDigest delegate = new Delegate((MessageDigestSpi)objs[0], algorithm); delegate.provider = (Provider)objs[1]; return delegate; } } /** * Returns a MessageDigest object that implements the specified digest * algorithm. * *

A new MessageDigest object encapsulating the * MessageDigestSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the name of the algorithm requested. * See the MessageDigest section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the provider. * * @return a MessageDigest object that implements the specified algorithm. * * @exception NoSuchAlgorithmException if a MessageDigestSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the specified provider is null. * * @see Provider * * @since 1.4 */ public static MessageDigest getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { if (provider == null) throw new IllegalArgumentException("missing provider"); Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider); if (objs[0] instanceof MessageDigest) { MessageDigest md = (MessageDigest)objs[0]; md.provider = (Provider)objs[1]; return md; } else { MessageDigest delegate = new Delegate((MessageDigestSpi)objs[0], algorithm); delegate.provider = (Provider)objs[1]; return delegate; } } /** * Returns the provider of this message digest object. * * @return the provider of this message digest object */ public final Provider getProvider() { return this.provider; } /** * Updates the digest using the specified byte. * * @param input the byte with which to update the digest. */ public void update(byte input) { engineUpdate(input); state = IN_PROGRESS; } /** * Updates the digest using the specified array of bytes, starting * at the specified offset. * * @param input the array of bytes. * * @param offset the offset to start from in the array of bytes. * * @param len the number of bytes to use, starting at * {@code offset}. */ public void update(byte[] input, int offset, int len) { if (input == null) { throw new IllegalArgumentException("No input buffer given"); } if (input.length - offset < len) { throw new IllegalArgumentException("Input buffer too short"); } engineUpdate(input, offset, len); state = IN_PROGRESS; } /** * Updates the digest using the specified array of bytes. * * @param input the array of bytes. */ public void update(byte[] input) { engineUpdate(input, 0, input.length); state = IN_PROGRESS; } /** * Update the digest using the specified ByteBuffer. The digest is * updated using the {@code input.remaining()} bytes starting * at {@code input.position()}. * Upon return, the buffer's position will be equal to its limit; * its limit will not have changed. * * @param input the ByteBuffer * @since 1.5 */ public final void update(ByteBuffer input) { if (input == null) { throw new NullPointerException(); } engineUpdate(input); state = IN_PROGRESS; } /** * Completes the hash computation by performing final operations * such as padding. The digest is reset after this call is made. * * @return the array of bytes for the resulting hash value. */ public byte[] digest() { /* Resetting is the responsibility of implementors. */ byte[] result = engineDigest(); state = INITIAL; return result; } /** * Completes the hash computation by performing final operations * such as padding. The digest is reset after this call is made. * * @param buf output buffer for the computed digest * * @param offset offset into the output buffer to begin storing the digest * * @param len number of bytes within buf allotted for the digest * * @return the number of bytes placed into {@code buf} * * @exception DigestException if an error occurs. */ public int digest(byte[] buf, int offset, int len) throws DigestException { if (buf == null) { throw new IllegalArgumentException("No output buffer given"); } if (buf.length - offset < len) { throw new IllegalArgumentException ("Output buffer too small for specified offset and length"); } int numBytes = engineDigest(buf, offset, len); state = INITIAL; return numBytes; } /** * Performs a final update on the digest using the specified array * of bytes, then completes the digest computation. That is, this * method first calls {@link #update(byte[]) update(input)}, * passing the input array to the {@code update} method, * then calls {@link #digest() digest()}. * * @param input the input to be updated before the digest is * completed. * * @return the array of bytes for the resulting hash value. */ public byte[] digest(byte[] input) { update(input); return digest(); } /** * Returns a string representation of this message digest object. */ public String toString() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream p = new PrintStream(baos); p.print(algorithm+" Message Digest from "+provider.getName()+", "); switch (state) { case INITIAL: p.print(""); break; case IN_PROGRESS: p.print(""); break; } p.println(); return (baos.toString()); } /** * Compares two digests for equality. Does a simple byte compare. * * @param digesta one of the digests to compare. * * @param digestb the other digest to compare. * * @return true if the digests are equal, false otherwise. */ public static boolean isEqual(byte[] digesta, byte[] digestb) { if (digesta == digestb) return true; if (digesta == null || digestb == null) { return false; } if (digesta.length != digestb.length) { return false; } int result = 0; // time-constant comparison for (int i = 0; i < digesta.length; i++) { result |= digesta[i] ^ digestb[i]; } return result == 0; } /** * Resets the digest for further use. */ public void reset() { engineReset(); state = INITIAL; } /** * Returns a string that identifies the algorithm, independent of * implementation details. The name should be a standard * Java Security name (such as "SHA-256"). * See the MessageDigest section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the name of the algorithm */ public final String getAlgorithm() { return this.algorithm; } /** * Returns the length of the digest in bytes, or 0 if this operation is * not supported by the provider and the implementation is not cloneable. * * @return the digest length in bytes, or 0 if this operation is not * supported by the provider and the implementation is not cloneable. * * @since 1.2 */ public final int getDigestLength() { int digestLen = engineGetDigestLength(); if (digestLen == 0) { try { MessageDigest md = (MessageDigest)clone(); byte[] digest = md.digest(); return digest.length; } catch (CloneNotSupportedException e) { return digestLen; } } return digestLen; } /** * Returns a clone if the implementation is cloneable. * * @return a clone if the implementation is cloneable. * * @exception CloneNotSupportedException if this is called on an * implementation that does not support {@code Cloneable}. */ public Object clone() throws CloneNotSupportedException { if (this instanceof Cloneable) { return super.clone(); } else { throw new CloneNotSupportedException(); } } /* * The following class allows providers to extend from MessageDigestSpi * rather than from MessageDigest. It represents a MessageDigest with an * encapsulated, provider-supplied SPI object (of type MessageDigestSpi). * If the provider implementation is an instance of MessageDigestSpi, * the getInstance() methods above return an instance of this class, with * the SPI object encapsulated. * * Note: All SPI methods from the original MessageDigest class have been * moved up the hierarchy into a new class (MessageDigestSpi), which has * been interposed in the hierarchy between the API (MessageDigest) * and its original parent (Object). */ static class Delegate extends MessageDigest { // The provider implementation (delegate) private MessageDigestSpi digestSpi; // constructor public Delegate(MessageDigestSpi digestSpi, String algorithm) { super(algorithm); this.digestSpi = digestSpi; } /** * Returns a clone if the delegate is cloneable. * * @return a clone if the delegate is cloneable. * * @exception CloneNotSupportedException if this is called on a * delegate that does not support {@code Cloneable}. */ public Object clone() throws CloneNotSupportedException { if (digestSpi instanceof Cloneable) { MessageDigestSpi digestSpiClone = (MessageDigestSpi)digestSpi.clone(); // Because 'algorithm', 'provider', and 'state' are private // members of our supertype, we must perform a cast to // access them. MessageDigest that = new Delegate(digestSpiClone, ((MessageDigest)this).algorithm); that.provider = ((MessageDigest)this).provider; that.state = ((MessageDigest)this).state; return that; } else { throw new CloneNotSupportedException(); } } protected int engineGetDigestLength() { return digestSpi.engineGetDigestLength(); } protected void engineUpdate(byte input) { digestSpi.engineUpdate(input); } protected void engineUpdate(byte[] input, int offset, int len) { digestSpi.engineUpdate(input, offset, len); } protected void engineUpdate(ByteBuffer input) { digestSpi.engineUpdate(input); } protected byte[] engineDigest() { return digestSpi.engineDigest(); } protected int engineDigest(byte[] buf, int offset, int len) throws DigestException { return digestSpi.engineDigest(buf, offset, len); } protected void engineReset() { digestSpi.engineReset(); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7327 Content-Disposition: inline; filename="MessageDigestSpi.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "0d5ace1f7bfa1b84b33b4de497a9ae93921310c8" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.nio.ByteBuffer; import sun.security.jca.JCAUtil; /** * This class defines the Service Provider Interface (SPI) * for the {@code MessageDigest} class, which provides the functionality * of a message digest algorithm, such as MD5 or SHA. Message digests are * secure one-way hash functions that take arbitrary-sized data and output a * fixed-length hash value. * *

All the abstract methods in this class must be implemented by a * cryptographic service provider who wishes to supply the implementation * of a particular message digest algorithm. * *

Implementations are free to implement the Cloneable interface. * * @author Benjamin Renaud * * * @see MessageDigest */ public abstract class MessageDigestSpi { // for re-use in engineUpdate(ByteBuffer input) private byte[] tempArray; /** * Returns the digest length in bytes. * *

This concrete method has been added to this previously-defined * abstract class. (For backwards compatibility, it cannot be abstract.) * *

The default behavior is to return 0. * *

This method may be overridden by a provider to return the digest * length. * * @return the digest length in bytes. * * @since 1.2 */ protected int engineGetDigestLength() { return 0; } /** * Updates the digest using the specified byte. * * @param input the byte to use for the update. */ protected abstract void engineUpdate(byte input); /** * Updates the digest using the specified array of bytes, * starting at the specified offset. * * @param input the array of bytes to use for the update. * * @param offset the offset to start from in the array of bytes. * * @param len the number of bytes to use, starting at * {@code offset}. */ protected abstract void engineUpdate(byte[] input, int offset, int len); /** * Update the digest using the specified ByteBuffer. The digest is * updated using the {@code input.remaining()} bytes starting * at {@code input.position()}. * Upon return, the buffer's position will be equal to its limit; * its limit will not have changed. * * @param input the ByteBuffer * @since 1.5 */ protected void engineUpdate(ByteBuffer input) { if (input.hasRemaining() == false) { return; } if (input.hasArray()) { byte[] b = input.array(); int ofs = input.arrayOffset(); int pos = input.position(); int lim = input.limit(); engineUpdate(b, ofs + pos, lim - pos); input.position(lim); } else { int len = input.remaining(); int n = JCAUtil.getTempArraySize(len); if ((tempArray == null) || (n > tempArray.length)) { tempArray = new byte[n]; } while (len > 0) { int chunk = Math.min(len, tempArray.length); input.get(tempArray, 0, chunk); engineUpdate(tempArray, 0, chunk); len -= chunk; } } } /** * Completes the hash computation by performing final * operations such as padding. Once {@code engineDigest} has * been called, the engine should be reset (see * {@link #engineReset() engineReset}). * Resetting is the responsibility of the * engine implementor. * * @return the array of bytes for the resulting hash value. */ protected abstract byte[] engineDigest(); /** * Completes the hash computation by performing final * operations such as padding. Once {@code engineDigest} has * been called, the engine should be reset (see * {@link #engineReset() engineReset}). * Resetting is the responsibility of the * engine implementor. * * This method should be abstract, but we leave it concrete for * binary compatibility. Knowledgeable providers should override this * method. * * @param buf the output buffer in which to store the digest * * @param offset offset to start from in the output buffer * * @param len number of bytes within buf allotted for the digest. * Both this default implementation and the SUN provider do not * return partial digests. The presence of this parameter is solely * for consistency in our API's. If the value of this parameter is less * than the actual digest length, the method will throw a DigestException. * This parameter is ignored if its value is greater than or equal to * the actual digest length. * * @return the length of the digest stored in the output buffer. * * @exception DigestException if an error occurs. * * @since 1.2 */ protected int engineDigest(byte[] buf, int offset, int len) throws DigestException { byte[] digest = engineDigest(); if (len < digest.length) throw new DigestException("partial digests not returned"); if (buf.length - offset < digest.length) throw new DigestException("insufficient space in the output " + "buffer to store the digest"); System.arraycopy(digest, 0, buf, offset, digest.length); return digest.length; } /** * Resets the digest for further use. */ protected abstract void engineReset(); /** * Returns a clone if the implementation is cloneable. * * @return a clone if the implementation is cloneable. * * @exception CloneNotSupportedException if this is called on an * implementation that does not support {@code Cloneable}. */ public Object clone() throws CloneNotSupportedException { if (this instanceof Cloneable) { return super.clone(); } else { throw new CloneNotSupportedException(); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3358 Content-Disposition: inline; filename="NoSuchAlgorithmException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "951e44e41dcb031fc49db62aca2bc8ae249014d9" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This exception is thrown when a particular cryptographic algorithm is * requested but is not available in the environment. * * @author Benjamin Renaud */ public class NoSuchAlgorithmException extends GeneralSecurityException { private static final long serialVersionUID = -7443947487218346562L; /** * Constructs a NoSuchAlgorithmException with no detail * message. A detail message is a String that describes this * particular exception. */ public NoSuchAlgorithmException() { super(); } /** * Constructs a NoSuchAlgorithmException with the specified * detail message. A detail message is a String that describes * this particular exception, which may, for example, specify which * algorithm is not available. * * @param msg the detail message. */ public NoSuchAlgorithmException(String msg) { super(msg); } /** * Creates a {@code NoSuchAlgorithmException} with the specified * detail message and cause. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public NoSuchAlgorithmException(String message, Throwable cause) { super(message, cause); } /** * Creates a {@code NoSuchAlgorithmException} with the specified cause * and a detail message of {@code (cause==null ? null : cause.toString())} * (which typically contains the class and detail message of * {@code cause}). * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public NoSuchAlgorithmException(Throwable cause) { super(cause); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2077 Content-Disposition: inline; filename="NoSuchProviderException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "9874adb145e3f03321837a2a81f4a5ebc1ad7396" /* * Copyright (c) 1996, 2003, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This exception is thrown when a particular security provider is * requested but is not available in the environment. * * @author Benjamin Renaud */ public class NoSuchProviderException extends GeneralSecurityException { private static final long serialVersionUID = 8488111756688534474L; /** * Constructs a NoSuchProviderException with no detail message. A * detail message is a String that describes this particular * exception. */ public NoSuchProviderException() { super(); } /** * Constructs a NoSuchProviderException with the specified detail * message. A detail message is a String that describes this * particular exception. * * @param msg the detail message. */ public NoSuchProviderException(String msg) { super(msg); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 10302 Content-Disposition: inline; filename="PKCS12Attribute.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "e3898628820fed51cd73575de5c11c4c7b4cb0b5" /* * Copyright (c) 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.IOException; import java.math.BigInteger; import java.util.Arrays; import java.util.regex.Pattern; import sun.security.util.*; /** * An attribute associated with a PKCS12 keystore entry. * The attribute name is an ASN.1 Object Identifier and the attribute * value is a set of ASN.1 types. * * @since 1.8 */ public final class PKCS12Attribute implements KeyStore.Entry.Attribute { private static final Pattern COLON_SEPARATED_HEX_PAIRS = Pattern.compile("^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2})+$"); private String name; private String value; private byte[] encoded; private int hashValue = -1; /** * Constructs a PKCS12 attribute from its name and value. * The name is an ASN.1 Object Identifier represented as a list of * dot-separated integers. * A string value is represented as the string itself. * A binary value is represented as a string of colon-separated * pairs of hexadecimal digits. * Multi-valued attributes are represented as a comma-separated * list of values, enclosed in square brackets. See * {@link Arrays#toString(java.lang.Object[])}. *

* A string value will be DER-encoded as an ASN.1 UTF8String and a * binary value will be DER-encoded as an ASN.1 Octet String. * * @param name the attribute's identifier * @param value the attribute's value * * @exception NullPointerException if {@code name} or {@code value} * is {@code null} * @exception IllegalArgumentException if {@code name} or * {@code value} is incorrectly formatted */ public PKCS12Attribute(String name, String value) { if (name == null || value == null) { throw new NullPointerException(); } // Validate name ObjectIdentifier type; try { type = new ObjectIdentifier(name); } catch (IOException e) { throw new IllegalArgumentException("Incorrect format: name", e); } this.name = name; // Validate value int length = value.length(); String[] values; if (value.charAt(0) == '[' && value.charAt(length - 1) == ']') { values = value.substring(1, length - 1).split(", "); } else { values = new String[]{ value }; } this.value = value; try { this.encoded = encode(type, values); } catch (IOException e) { throw new IllegalArgumentException("Incorrect format: value", e); } } /** * Constructs a PKCS12 attribute from its ASN.1 DER encoding. * The DER encoding is specified by the following ASN.1 definition: *

     *
     * Attribute ::= SEQUENCE {
     *     type   AttributeType,
     *     values SET OF AttributeValue
     * }
     * AttributeType ::= OBJECT IDENTIFIER
     * AttributeValue ::= ANY defined by type
     *
     * 
* * @param encoded the attribute's ASN.1 DER encoding. It is cloned * to prevent subsequent modificaion. * * @exception NullPointerException if {@code encoded} is * {@code null} * @exception IllegalArgumentException if {@code encoded} is * incorrectly formatted */ public PKCS12Attribute(byte[] encoded) { if (encoded == null) { throw new NullPointerException(); } this.encoded = encoded.clone(); try { parse(encoded); } catch (IOException e) { throw new IllegalArgumentException("Incorrect format: encoded", e); } } /** * Returns the attribute's ASN.1 Object Identifier represented as a * list of dot-separated integers. * * @return the attribute's identifier */ @Override public String getName() { return name; } /** * Returns the attribute's ASN.1 DER-encoded value as a string. * An ASN.1 DER-encoded value is returned in one of the following * {@code String} formats: *
    *
  • the DER encoding of a basic ASN.1 type that has a natural * string representation is returned as the string itself. * Such types are currently limited to BOOLEAN, INTEGER, * OBJECT IDENTIFIER, UTCTime, GeneralizedTime and the * following six ASN.1 string types: UTF8String, * PrintableString, T61String, IA5String, BMPString and * GeneralString. *
  • the DER encoding of any other ASN.1 type is not decoded but * returned as a binary string of colon-separated pairs of * hexadecimal digits. *
* Multi-valued attributes are represented as a comma-separated * list of values, enclosed in square brackets. See * {@link Arrays#toString(java.lang.Object[])}. * * @return the attribute value's string encoding */ @Override public String getValue() { return value; } /** * Returns the attribute's ASN.1 DER encoding. * * @return a clone of the attribute's DER encoding */ public byte[] getEncoded() { return encoded.clone(); } /** * Compares this {@code PKCS12Attribute} and a specified object for * equality. * * @param obj the comparison object * * @return true if {@code obj} is a {@code PKCS12Attribute} and * their DER encodings are equal. */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof PKCS12Attribute)) { return false; } return Arrays.equals(encoded, ((PKCS12Attribute) obj).getEncoded()); } /** * Returns the hashcode for this {@code PKCS12Attribute}. * The hash code is computed from its DER encoding. * * @return the hash code */ @Override public int hashCode() { if (hashValue == -1) { Arrays.hashCode(encoded); } return hashValue; } /** * Returns a string representation of this {@code PKCS12Attribute}. * * @return a name/value pair separated by an 'equals' symbol */ @Override public String toString() { return (name + "=" + value); } private byte[] encode(ObjectIdentifier type, String[] values) throws IOException { DerOutputStream attribute = new DerOutputStream(); attribute.putOID(type); DerOutputStream attrContent = new DerOutputStream(); for (String value : values) { if (COLON_SEPARATED_HEX_PAIRS.matcher(value).matches()) { byte[] bytes = new BigInteger(value.replace(":", ""), 16).toByteArray(); if (bytes[0] == 0) { bytes = Arrays.copyOfRange(bytes, 1, bytes.length); } attrContent.putOctetString(bytes); } else { attrContent.putUTF8String(value); } } attribute.write(DerValue.tag_Set, attrContent); DerOutputStream attributeValue = new DerOutputStream(); attributeValue.write(DerValue.tag_Sequence, attribute); return attributeValue.toByteArray(); } private void parse(byte[] encoded) throws IOException { DerInputStream attributeValue = new DerInputStream(encoded); DerValue[] attrSeq = attributeValue.getSequence(2); ObjectIdentifier type = attrSeq[0].getOID(); DerInputStream attrContent = new DerInputStream(attrSeq[1].toByteArray()); DerValue[] attrValueSet = attrContent.getSet(1); String[] values = new String[attrValueSet.length]; String printableString; for (int i = 0; i < attrValueSet.length; i++) { if (attrValueSet[i].tag == DerValue.tag_OctetString) { values[i] = Debug.toString(attrValueSet[i].getOctetString()); } else if ((printableString = attrValueSet[i].getAsString()) != null) { values[i] = printableString; } else if (attrValueSet[i].tag == DerValue.tag_ObjectId) { values[i] = attrValueSet[i].getOID().toString(); } else if (attrValueSet[i].tag == DerValue.tag_GeneralizedTime) { values[i] = attrValueSet[i].getGeneralizedTime().toString(); } else if (attrValueSet[i].tag == DerValue.tag_UtcTime) { values[i] = attrValueSet[i].getUTCTime().toString(); } else if (attrValueSet[i].tag == DerValue.tag_Integer) { values[i] = attrValueSet[i].getBigInteger().toString(); } else if (attrValueSet[i].tag == DerValue.tag_Boolean) { values[i] = String.valueOf(attrValueSet[i].getBoolean()); } else { values[i] = Debug.toString(attrValueSet[i].getDataBytes()); } } this.name = type.toString(); this.value = values.length == 1 ? values[0] : Arrays.toString(values); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 8560 Content-Disposition: inline; filename="Permission.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "088f97c35a608deb8b27d53563e9f2d83d03a0e6" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * Abstract class for representing access to a system resource. * All permissions have a name (whose interpretation depends on the subclass), * as well as abstract functions for defining the semantics of the * particular Permission subclass. * *

Most Permission objects also include an "actions" list that tells the actions * that are permitted for the object. For example, * for a {@code java.io.FilePermission} object, the permission name is * the pathname of a file (or directory), and the actions list * (such as "read, write") specifies which actions are granted for the * specified file (or for files in the specified directory). * The actions list is optional for Permission objects, such as * {@code java.lang.RuntimePermission}, * that don't need such a list; you either have the named permission (such * as "system.exit") or you don't. * *

An important method that must be implemented by each subclass is * the {@code implies} method to compare Permissions. Basically, * "permission p1 implies permission p2" means that * if one is granted permission p1, one is naturally granted permission p2. * Thus, this is not an equality test, but rather more of a * subset test. * *

Permission objects are similar to String objects in that they * are immutable once they have been created. Subclasses should not * provide methods that can change the state of a permission * once it has been created. * * @see Permissions * @see PermissionCollection * * * @author Marianne Mueller * @author Roland Schemers */ public abstract class Permission implements Guard, java.io.Serializable { private static final long serialVersionUID = -5636570222231596674L; private String name; /** * Constructs a permission with the specified name. * * @param name name of the Permission object being created. * */ public Permission(String name) { this.name = name; } /** * Implements the guard interface for a permission. The * {@code SecurityManager.checkPermission} method is called, * passing this permission object as the permission to check. * Returns silently if access is granted. Otherwise, throws * a SecurityException. * * @param object the object being guarded (currently ignored). * * @throws SecurityException * if a security manager exists and its * {@code checkPermission} method doesn't allow access. * * @see Guard * @see GuardedObject * @see SecurityManager#checkPermission * */ public void checkGuard(Object object) throws SecurityException { SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkPermission(this); } /** * Checks if the specified permission's actions are "implied by" * this object's actions. *

* This must be implemented by subclasses of Permission, as they are the * only ones that can impose semantics on a Permission object. * *

The {@code implies} method is used by the AccessController to determine * whether or not a requested permission is implied by another permission that * is known to be valid in the current execution context. * * @param permission the permission to check against. * * @return true if the specified permission is implied by this object, * false if not. */ public abstract boolean implies(Permission permission); /** * Checks two Permission objects for equality. *

* Do not use the {@code equals} method for making access control * decisions; use the {@code implies} method. * * @param obj the object we are testing for equality with this object. * * @return true if both Permission objects are equivalent. */ public abstract boolean equals(Object obj); /** * Returns the hash code value for this Permission object. *

* The required {@code hashCode} behavior for Permission Objects is * the following: *

    *
  • Whenever it is invoked on the same Permission object more than * once during an execution of a Java application, the * {@code hashCode} method * must consistently return the same integer. This integer need not * remain consistent from one execution of an application to another * execution of the same application. *
  • If two Permission objects are equal according to the * {@code equals} * method, then calling the {@code hashCode} method on each of the * two Permission objects must produce the same integer result. *
* * @return a hash code value for this object. */ public abstract int hashCode(); /** * Returns the name of this Permission. * For example, in the case of a {@code java.io.FilePermission}, * the name will be a pathname. * * @return the name of this Permission. * */ public final String getName() { return name; } /** * Returns the actions as a String. This is abstract * so subclasses can defer creating a String representation until * one is needed. Subclasses should always return actions in what they * consider to be their * canonical form. For example, two FilePermission objects created via * the following: * *
     *   perm1 = new FilePermission(p1,"read,write");
     *   perm2 = new FilePermission(p2,"write,read");
     * 
* * both return * "read,write" when the {@code getActions} method is invoked. * * @return the actions of this Permission. * */ public abstract String getActions(); /** * Returns an empty PermissionCollection for a given Permission object, or null if * one is not defined. Subclasses of class Permission should * override this if they need to store their permissions in a particular * PermissionCollection object in order to provide the correct semantics * when the {@code PermissionCollection.implies} method is called. * If null is returned, * then the caller of this method is free to store permissions of this * type in any PermissionCollection they choose (one that uses a Hashtable, * one that uses a Vector, etc). * * @return a new PermissionCollection object for this type of Permission, or * null if one is not defined. */ public PermissionCollection newPermissionCollection() { return null; } /** * Returns a string describing this Permission. The convention is to * specify the class name, the permission name, and the actions in * the following format: '("ClassName" "name" "actions")', or * '("ClassName" "name")' if actions list is null or empty. * * @return information about this Permission. */ public String toString() { String actions = getActions(); if ((actions == null) || (actions.length() == 0)) { // OPTIONAL return "(\"" + getClass().getName() + "\" \"" + name + "\")"; } else { return "(\"" + getClass().getName() + "\" \"" + name + "\" \"" + actions + "\")"; } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7984 Content-Disposition: inline; filename="PermissionCollection.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "3f13b9f93d52c5b97e312e4d1bef137f0d91cd7c" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.*; /** * Abstract class representing a collection of Permission objects. * *

With a PermissionCollection, you can: *

    *
  • add a permission to the collection using the {@code add} method. *
  • check to see if a particular permission is implied in the * collection, using the {@code implies} method. *
  • enumerate all the permissions, using the {@code elements} method. *
* *

When it is desirable to group together a number of Permission objects * of the same type, the {@code newPermissionCollection} method on that * particular type of Permission object should first be called. The default * behavior (from the Permission class) is to simply return null. * Subclasses of class Permission override the method if they need to store * their permissions in a particular PermissionCollection object in order * to provide the correct semantics when the * {@code PermissionCollection.implies} method is called. * If a non-null value is returned, that PermissionCollection must be used. * If null is returned, then the caller of {@code newPermissionCollection} * is free to store permissions of the * given type in any PermissionCollection they choose * (one that uses a Hashtable, one that uses a Vector, etc). * *

The PermissionCollection returned by the * {@code Permission.newPermissionCollection} * method is a homogeneous collection, which stores only Permission objects * for a given Permission type. A PermissionCollection may also be * heterogeneous. For example, Permissions is a PermissionCollection * subclass that represents a collection of PermissionCollections. * That is, its members are each a homogeneous PermissionCollection. * For example, a Permissions object might have a FilePermissionCollection * for all the FilePermission objects, a SocketPermissionCollection for all the * SocketPermission objects, and so on. Its {@code add} method adds a * permission to the appropriate collection. * *

Whenever a permission is added to a heterogeneous PermissionCollection * such as Permissions, and the PermissionCollection doesn't yet contain a * PermissionCollection of the specified permission's type, the * PermissionCollection should call * the {@code newPermissionCollection} method on the permission's class * to see if it requires a special PermissionCollection. If * {@code newPermissionCollection} * returns null, the PermissionCollection * is free to store the permission in any type of PermissionCollection it * desires (one using a Hashtable, one using a Vector, etc.). For example, * the Permissions object uses a default PermissionCollection implementation * that stores the permission objects in a Hashtable. * *

Subclass implementations of PermissionCollection should assume * that they may be called simultaneously from multiple threads, * and therefore should be synchronized properly. Furthermore, * Enumerations returned via the {@code elements} method are * not fail-fast. Modifications to a collection should not be * performed while enumerating over that collection. * * @see Permission * @see Permissions * * * @author Roland Schemers */ public abstract class PermissionCollection implements java.io.Serializable { private static final long serialVersionUID = -6727011328946861783L; // when set, add will throw an exception. private volatile boolean readOnly; /** * Adds a permission object to the current collection of permission objects. * * @param permission the Permission object to add. * * @exception SecurityException - if this PermissionCollection object * has been marked readonly * @exception IllegalArgumentException - if this PermissionCollection * object is a homogeneous collection and the permission * is not of the correct type. */ public abstract void add(Permission permission); /** * Checks to see if the specified permission is implied by * the collection of Permission objects held in this PermissionCollection. * * @param permission the Permission object to compare. * * @return true if "permission" is implied by the permissions in * the collection, false if not. */ public abstract boolean implies(Permission permission); /** * Returns an enumeration of all the Permission objects in the collection. * * @return an enumeration of all the Permissions. */ public abstract Enumeration elements(); /** * Marks this PermissionCollection object as "readonly". After * a PermissionCollection object * is marked as readonly, no new Permission objects can be added to it * using {@code add}. */ public void setReadOnly() { readOnly = true; } /** * Returns true if this PermissionCollection object is marked as readonly. * If it is readonly, no new Permission objects can be added to it * using {@code add}. * *

By default, the object is not readonly. It can be set to * readonly by a call to {@code setReadOnly}. * * @return true if this PermissionCollection object is marked as readonly, * false otherwise. */ public boolean isReadOnly() { return readOnly; } /** * Returns a string describing this PermissionCollection object, * providing information about all the permissions it contains. * The format is: *

     * super.toString() (
     *   // enumerate all the Permission
     *   // objects and call toString() on them,
     *   // one per line..
     * )
* * {@code super.toString} is a call to the {@code toString} * method of this * object's superclass, which is Object. The result is * this PermissionCollection's type name followed by this object's * hashcode, thus enabling clients to differentiate different * PermissionCollections object, even if they contain the same permissions. * * @return information about this PermissionCollection object, * as described above. * */ public String toString() { Enumeration enum_ = elements(); StringBuilder sb = new StringBuilder(); sb.append(super.toString()+" (\n"); while (enum_.hasMoreElements()) { try { sb.append(" "); sb.append(enum_.nextElement().toString()); sb.append("\n"); } catch (NoSuchElementException e){ // ignore } } sb.append(")\n"); return sb.toString(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 21160 Content-Disposition: inline; filename="Permissions.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "cce9f5f56f3d5b804a5595002435db3274657b1a" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.Enumeration; import java.util.Hashtable; import java.util.NoSuchElementException; import java.util.Map; import java.util.HashMap; import java.util.List; import java.util.Iterator; import java.util.Collections; import java.io.Serializable; import java.io.ObjectStreamField; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.IOException; /** * This class represents a heterogeneous collection of Permissions. That is, * it contains different types of Permission objects, organized into * PermissionCollections. For example, if any * {@code java.io.FilePermission} objects are added to an instance of * this class, they are all stored in a single * PermissionCollection. It is the PermissionCollection returned by a call to * the {@code newPermissionCollection} method in the FilePermission class. * Similarly, any {@code java.lang.RuntimePermission} objects are * stored in the PermissionCollection returned by a call to the * {@code newPermissionCollection} method in the * RuntimePermission class. Thus, this class represents a collection of * PermissionCollections. * *

When the {@code add} method is called to add a Permission, the * Permission is stored in the appropriate PermissionCollection. If no such * collection exists yet, the Permission object's class is determined and the * {@code newPermissionCollection} method is called on that class to create * the PermissionCollection and add it to the Permissions object. If * {@code newPermissionCollection} returns null, then a default * PermissionCollection that uses a hashtable will be created and used. Each * hashtable entry stores a Permission object as both the key and the value. * *

Enumerations returned via the {@code elements} method are * not fail-fast. Modifications to a collection should not be * performed while enumerating over that collection. * * @see Permission * @see PermissionCollection * @see AllPermission * * * @author Marianne Mueller * @author Roland Schemers * * @serial exclude */ public final class Permissions extends PermissionCollection implements Serializable { /** * Key is permissions Class, value is PermissionCollection for that class. * Not serialized; see serialization section at end of class. */ private transient Map, PermissionCollection> permsMap; // optimization. keep track of whether unresolved permissions need to be // checked private transient boolean hasUnresolved = false; // optimization. keep track of the AllPermission collection // - package private for ProtectionDomain optimization PermissionCollection allPermission; /** * Creates a new Permissions object containing no PermissionCollections. */ public Permissions() { permsMap = new HashMap, PermissionCollection>(11); allPermission = null; } /** * Adds a permission object to the PermissionCollection for the class the * permission belongs to. For example, if permission is a * FilePermission, it is added to the FilePermissionCollection stored * in this Permissions object. * * This method creates * a new PermissionCollection object (and adds the permission to it) * if an appropriate collection does not yet exist.

* * @param permission the Permission object to add. * * @exception SecurityException if this Permissions object is * marked as readonly. * * @see PermissionCollection#isReadOnly() */ public void add(Permission permission) { if (isReadOnly()) throw new SecurityException( "attempt to add a Permission to a readonly Permissions object"); PermissionCollection pc; synchronized (this) { pc = getPermissionCollection(permission, true); pc.add(permission); } // No sync; staleness -> optimizations delayed, which is OK if (permission instanceof AllPermission) { allPermission = pc; } if (permission instanceof UnresolvedPermission) { hasUnresolved = true; } } /** * Checks to see if this object's PermissionCollection for permissions of * the specified permission's class implies the permissions * expressed in the permission object. Returns true if the * combination of permissions in the appropriate PermissionCollection * (e.g., a FilePermissionCollection for a FilePermission) together * imply the specified permission. * *

For example, suppose there is a FilePermissionCollection in this * Permissions object, and it contains one FilePermission that specifies * "read" access for all files in all subdirectories of the "/tmp" * directory, and another FilePermission that specifies "write" access * for all files in the "/tmp/scratch/foo" directory. * Then if the {@code implies} method * is called with a permission specifying both "read" and "write" access * to files in the "/tmp/scratch/foo" directory, {@code true} is * returned. * *

Additionally, if this PermissionCollection contains the * AllPermission, this method will always return true. *

* @param permission the Permission object to check. * * @return true if "permission" is implied by the permissions in the * PermissionCollection it * belongs to, false if not. */ public boolean implies(Permission permission) { // No sync; staleness -> skip optimization, which is OK if (allPermission != null) { return true; // AllPermission has already been added } else { synchronized (this) { PermissionCollection pc = getPermissionCollection(permission, false); if (pc != null) { return pc.implies(permission); } else { // none found return false; } } } } /** * Returns an enumeration of all the Permission objects in all the * PermissionCollections in this Permissions object. * * @return an enumeration of all the Permissions. */ public Enumeration elements() { // go through each Permissions in the hash table // and call their elements() function. synchronized (this) { return new PermissionsEnumerator(permsMap.values().iterator()); } } /** * Gets the PermissionCollection in this Permissions object for * permissions whose type is the same as that of p. * For example, if p is a FilePermission, * the FilePermissionCollection * stored in this Permissions object will be returned. * * If createEmpty is true, * this method creates a new PermissionCollection object for the specified * type of permission objects if one does not yet exist. * To do so, it first calls the {@code newPermissionCollection} method * on p. Subclasses of class Permission * override that method if they need to store their permissions in a * particular PermissionCollection object in order to provide the * correct semantics when the {@code PermissionCollection.implies} * method is called. * If the call returns a PermissionCollection, that collection is stored * in this Permissions object. If the call returns null and createEmpty * is true, then * this method instantiates and stores a default PermissionCollection * that uses a hashtable to store its permission objects. * * createEmpty is ignored when creating empty PermissionCollection * for unresolved permissions because of the overhead of determining the * PermissionCollection to use. * * createEmpty should be set to false when this method is invoked from * implies() because it incurs the additional overhead of creating and * adding an empty PermissionCollection that will just return false. * It should be set to true when invoked from add(). */ private PermissionCollection getPermissionCollection(Permission p, boolean createEmpty) { Class c = p.getClass(); PermissionCollection pc = permsMap.get(c); if (!hasUnresolved && !createEmpty) { return pc; } else if (pc == null) { // Check for unresolved permissions pc = (hasUnresolved ? getUnresolvedPermissions(p) : null); // if still null, create a new collection if (pc == null && createEmpty) { pc = p.newPermissionCollection(); // still no PermissionCollection? // We'll give them a PermissionsHash. if (pc == null) pc = new PermissionsHash(); } if (pc != null) { permsMap.put(c, pc); } } return pc; } /** * Resolves any unresolved permissions of type p. * * @param p the type of unresolved permission to resolve * * @return PermissionCollection containing the unresolved permissions, * or null if there were no unresolved permissions of type p. * */ private PermissionCollection getUnresolvedPermissions(Permission p) { // Called from within synchronized method so permsMap doesn't need lock UnresolvedPermissionCollection uc = (UnresolvedPermissionCollection) permsMap.get(UnresolvedPermission.class); // we have no unresolved permissions if uc is null if (uc == null) return null; List unresolvedPerms = uc.getUnresolvedPermissions(p); // we have no unresolved permissions of this type if unresolvedPerms is null if (unresolvedPerms == null) return null; java.security.cert.Certificate certs[] = null; Object signers[] = p.getClass().getSigners(); int n = 0; if (signers != null) { for (int j=0; j < signers.length; j++) { if (signers[j] instanceof java.security.cert.Certificate) { n++; } } certs = new java.security.cert.Certificate[n]; n = 0; for (int j=0; j < signers.length; j++) { if (signers[j] instanceof java.security.cert.Certificate) { certs[n++] = (java.security.cert.Certificate)signers[j]; } } } PermissionCollection pc = null; synchronized (unresolvedPerms) { int len = unresolvedPerms.size(); for (int i = 0; i < len; i++) { UnresolvedPermission up = unresolvedPerms.get(i); Permission perm = up.resolve(p, certs); if (perm != null) { if (pc == null) { pc = p.newPermissionCollection(); if (pc == null) pc = new PermissionsHash(); } pc.add(perm); } } } return pc; } private static final long serialVersionUID = 4858622370623524688L; // Need to maintain serialization interoperability with earlier releases, // which had the serializable field: // private Hashtable perms; /** * @serialField perms java.util.Hashtable * A table of the Permission classes and PermissionCollections. * @serialField allPermission java.security.PermissionCollection */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("perms", Hashtable.class), new ObjectStreamField("allPermission", PermissionCollection.class), }; /** * @serialData Default fields. */ /* * Writes the contents of the permsMap field out as a Hashtable for * serialization compatibility with earlier releases. allPermission * unchanged. */ private void writeObject(ObjectOutputStream out) throws IOException { // Don't call out.defaultWriteObject() // Copy perms into a Hashtable Hashtable, PermissionCollection> perms = new Hashtable<>(permsMap.size()*2); // no sync; estimate synchronized (this) { perms.putAll(permsMap); } // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); pfields.put("allPermission", allPermission); // no sync; staleness OK pfields.put("perms", perms); out.writeFields(); } /* * Reads in a Hashtable of Class/PermissionCollections and saves them in the * permsMap field. Reads in allPermission. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // Don't call defaultReadObject() // Read in serialized fields ObjectInputStream.GetField gfields = in.readFields(); // Get allPermission allPermission = (PermissionCollection) gfields.get("allPermission", null); // Get permissions // writeObject writes a Hashtable, PermissionCollection> for // the perms key, so this cast is safe, unless the data is corrupt. @SuppressWarnings("unchecked") Hashtable, PermissionCollection> perms = (Hashtable, PermissionCollection>)gfields.get("perms", null); permsMap = new HashMap, PermissionCollection>(perms.size()*2); permsMap.putAll(perms); // Set hasUnresolved UnresolvedPermissionCollection uc = (UnresolvedPermissionCollection) permsMap.get(UnresolvedPermission.class); hasUnresolved = (uc != null && uc.elements().hasMoreElements()); } } final class PermissionsEnumerator implements Enumeration { // all the perms private Iterator perms; // the current set private Enumeration permset; PermissionsEnumerator(Iterator e) { perms = e; permset = getNextEnumWithMore(); } // No need to synchronize; caller should sync on object as required public boolean hasMoreElements() { // if we enter with permissionimpl null, we know // there are no more left. if (permset == null) return false; // try to see if there are any left in the current one if (permset.hasMoreElements()) return true; // get the next one that has something in it... permset = getNextEnumWithMore(); // if it is null, we are done! return (permset != null); } // No need to synchronize; caller should sync on object as required public Permission nextElement() { // hasMoreElements will update permset to the next permset // with something in it... if (hasMoreElements()) { return permset.nextElement(); } else { throw new NoSuchElementException("PermissionsEnumerator"); } } private Enumeration getNextEnumWithMore() { while (perms.hasNext()) { PermissionCollection pc = perms.next(); Enumeration next =pc.elements(); if (next.hasMoreElements()) return next; } return null; } } /** * A PermissionsHash stores a homogeneous set of permissions in a hashtable. * * @see Permission * @see Permissions * * * @author Roland Schemers * * @serial include */ final class PermissionsHash extends PermissionCollection implements Serializable { /** * Key and value are (same) permissions objects. * Not serialized; see serialization section at end of class. */ private transient Map permsMap; /** * Create an empty PermissionsHash object. */ PermissionsHash() { permsMap = new HashMap(11); } /** * Adds a permission to the PermissionsHash. * * @param permission the Permission object to add. */ public void add(Permission permission) { synchronized (this) { permsMap.put(permission, permission); } } /** * Check and see if this set of permissions implies the permissions * expressed in "permission". * * @param permission the Permission object to compare * * @return true if "permission" is a proper subset of a permission in * the set, false if not. */ public boolean implies(Permission permission) { // attempt a fast lookup and implies. If that fails // then enumerate through all the permissions. synchronized (this) { Permission p = permsMap.get(permission); // If permission is found, then p.equals(permission) if (p == null) { for (Permission p_ : permsMap.values()) { if (p_.implies(permission)) return true; } return false; } else { return true; } } } /** * Returns an enumeration of all the Permission objects in the container. * * @return an enumeration of all the Permissions. */ public Enumeration elements() { // Convert Iterator of Map values into an Enumeration synchronized (this) { return Collections.enumeration(permsMap.values()); } } private static final long serialVersionUID = -8491988220802933440L; // Need to maintain serialization interoperability with earlier releases, // which had the serializable field: // private Hashtable perms; /** * @serialField perms java.util.Hashtable * A table of the Permissions (both key and value are same). */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("perms", Hashtable.class), }; /** * @serialData Default fields. */ /* * Writes the contents of the permsMap field out as a Hashtable for * serialization compatibility with earlier releases. */ private void writeObject(ObjectOutputStream out) throws IOException { // Don't call out.defaultWriteObject() // Copy perms into a Hashtable Hashtable perms = new Hashtable<>(permsMap.size()*2); synchronized (this) { perms.putAll(permsMap); } // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); pfields.put("perms", perms); out.writeFields(); } /* * Reads in a Hashtable of Permission/Permission and saves them in the * permsMap field. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // Don't call defaultReadObject() // Read in serialized fields ObjectInputStream.GetField gfields = in.readFields(); // Get permissions // writeObject writes a Hashtable, PermissionCollection> for // the perms key, so this cast is safe, unless the data is corrupt. @SuppressWarnings("unchecked") Hashtable perms = (Hashtable)gfields.get("perms", null); permsMap = new HashMap(perms.size()*2); permsMap.putAll(perms); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 32774 Content-Disposition: inline; filename="Policy.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "ffbcb44cf3f00a6659b0a26696604f2faf3d5529" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.Enumeration; import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicReference; import sun.security.jca.GetInstance; import sun.security.util.Debug; import sun.security.util.SecurityConstants; /** * A Policy object is responsible for determining whether code executing * in the Java runtime environment has permission to perform a * security-sensitive operation. * *

There is only one Policy object installed in the runtime at any * given time. A Policy object can be installed by calling the * {@code setPolicy} method. The installed Policy object can be * obtained by calling the {@code getPolicy} method. * *

If no Policy object has been installed in the runtime, a call to * {@code getPolicy} installs an instance of the default Policy * implementation (a default subclass implementation of this abstract class). * The default Policy implementation can be changed by setting the value * of the {@code policy.provider} security property to the fully qualified * name of the desired Policy subclass implementation. * *

Application code can directly subclass Policy to provide a custom * implementation. In addition, an instance of a Policy object can be * constructed by invoking one of the {@code getInstance} factory methods * with a standard type. The default policy type is "JavaPolicy". * *

Once a Policy instance has been installed (either by default, or by * calling {@code setPolicy}), the Java runtime invokes its * {@code implies} method when it needs to * determine whether executing code (encapsulated in a ProtectionDomain) * can perform SecurityManager-protected operations. How a Policy object * retrieves its policy data is up to the Policy implementation itself. * The policy data may be stored, for example, in a flat ASCII file, * in a serialized binary file of the Policy class, or in a database. * *

The {@code refresh} method causes the policy object to * refresh/reload its data. This operation is implementation-dependent. * For example, if the policy object stores its data in configuration files, * calling {@code refresh} will cause it to re-read the configuration * policy files. If a refresh operation is not supported, this method does * nothing. Note that refreshed policy may not have an effect on classes * in a particular ProtectionDomain. This is dependent on the Policy * provider's implementation of the {@code implies} * method and its PermissionCollection caching strategy. * * @author Roland Schemers * @author Gary Ellison * @see java.security.Provider * @see java.security.ProtectionDomain * @see java.security.Permission * @see java.security.Security security properties */ public abstract class Policy { /** * A read-only empty PermissionCollection instance. * @since 1.6 */ public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION = new UnsupportedEmptyCollection(); // Information about the system-wide policy. private static class PolicyInfo { // the system-wide policy final Policy policy; // a flag indicating if the system-wide policy has been initialized final boolean initialized; PolicyInfo(Policy policy, boolean initialized) { this.policy = policy; this.initialized = initialized; } } // PolicyInfo is stored in an AtomicReference private static AtomicReference policy = new AtomicReference<>(new PolicyInfo(null, false)); private static final Debug debug = Debug.getInstance("policy"); // Cache mapping ProtectionDomain.Key to PermissionCollection private WeakHashMap pdMapping; /** package private for AccessControlContext and ProtectionDomain */ static boolean isSet() { PolicyInfo pi = policy.get(); return pi.policy != null && pi.initialized == true; } private static void checkPermission(String type) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new SecurityPermission("createPolicy." + type)); } } /** * Returns the installed Policy object. This value should not be cached, * as it may be changed by a call to {@code setPolicy}. * This method first calls * {@code SecurityManager.checkPermission} with a * {@code SecurityPermission("getPolicy")} permission * to ensure it's ok to get the Policy object. * * @return the installed Policy. * * @throws SecurityException * if a security manager exists and its * {@code checkPermission} method doesn't allow * getting the Policy object. * * @see SecurityManager#checkPermission(Permission) * @see #setPolicy(java.security.Policy) */ public static Policy getPolicy() { SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION); return getPolicyNoCheck(); } /** * Returns the installed Policy object, skipping the security check. * Used by ProtectionDomain and getPolicy. * * @return the installed Policy. */ static Policy getPolicyNoCheck() { PolicyInfo pi = policy.get(); // Use double-check idiom to avoid locking if system-wide policy is // already initialized if (pi.initialized == false || pi.policy == null) { synchronized (Policy.class) { PolicyInfo pinfo = policy.get(); if (pinfo.policy == null) { String policy_class = AccessController.doPrivileged( new PrivilegedAction() { public String run() { return Security.getProperty("policy.provider"); } }); if (policy_class == null) { policy_class = "sun.security.provider.PolicyFile"; } try { pinfo = new PolicyInfo( (Policy) Class.forName(policy_class).newInstance(), true); } catch (Exception e) { /* * The policy_class seems to be an extension * so we have to bootstrap loading it via a policy * provider that is on the bootclasspath. * If it loads then shift gears to using the configured * provider. */ // install the bootstrap provider to avoid recursion Policy polFile = new sun.security.provider.PolicyFile(); pinfo = new PolicyInfo(polFile, false); policy.set(pinfo); final String pc = policy_class; Policy pol = AccessController.doPrivileged( new PrivilegedAction() { public Policy run() { try { ClassLoader cl = ClassLoader.getSystemClassLoader(); // we want the extension loader ClassLoader extcl = null; while (cl != null) { extcl = cl; cl = cl.getParent(); } return (extcl != null ? (Policy)Class.forName( pc, true, extcl).newInstance() : null); } catch (Exception e) { if (debug != null) { debug.println("policy provider " + pc + " not available"); e.printStackTrace(); } return null; } } }); /* * if it loaded install it as the policy provider. Otherwise * continue to use the system default implementation */ if (pol != null) { pinfo = new PolicyInfo(pol, true); } else { if (debug != null) { debug.println("using sun.security.provider.PolicyFile"); } pinfo = new PolicyInfo(polFile, true); } } policy.set(pinfo); } return pinfo.policy; } } return pi.policy; } /** * Sets the system-wide Policy object. This method first calls * {@code SecurityManager.checkPermission} with a * {@code SecurityPermission("setPolicy")} * permission to ensure it's ok to set the Policy. * * @param p the new system Policy object. * * @throws SecurityException * if a security manager exists and its * {@code checkPermission} method doesn't allow * setting the Policy. * * @see SecurityManager#checkPermission(Permission) * @see #getPolicy() * */ public static void setPolicy(Policy p) { SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkPermission( new SecurityPermission("setPolicy")); if (p != null) { initPolicy(p); } synchronized (Policy.class) { policy.set(new PolicyInfo(p, p != null)); } } /** * Initialize superclass state such that a legacy provider can * handle queries for itself. * * @since 1.4 */ private static void initPolicy (final Policy p) { /* * A policy provider not on the bootclasspath could trigger * security checks fulfilling a call to either Policy.implies * or Policy.getPermissions. If this does occur the provider * must be able to answer for it's own ProtectionDomain * without triggering additional security checks, otherwise * the policy implementation will end up in an infinite * recursion. * * To mitigate this, the provider can collect it's own * ProtectionDomain and associate a PermissionCollection while * it is being installed. The currently installed policy * provider (if there is one) will handle calls to * Policy.implies or Policy.getPermissions during this * process. * * This Policy superclass caches away the ProtectionDomain and * statically binds permissions so that legacy Policy * implementations will continue to function. */ ProtectionDomain policyDomain = AccessController.doPrivileged(new PrivilegedAction() { public ProtectionDomain run() { return p.getClass().getProtectionDomain(); } }); /* * Collect the permissions granted to this protection domain * so that the provider can be security checked while processing * calls to Policy.implies or Policy.getPermissions. */ PermissionCollection policyPerms = null; synchronized (p) { if (p.pdMapping == null) { p.pdMapping = new WeakHashMap<>(); } } if (policyDomain.getCodeSource() != null) { Policy pol = policy.get().policy; if (pol != null) { policyPerms = pol.getPermissions(policyDomain); } if (policyPerms == null) { // assume it has all policyPerms = new Permissions(); policyPerms.add(SecurityConstants.ALL_PERMISSION); } synchronized (p.pdMapping) { // cache of pd to permissions p.pdMapping.put(policyDomain.key, policyPerms); } } return; } /** * Returns a Policy object of the specified type. * *

This method traverses the list of registered security providers, * starting with the most preferred Provider. * A new Policy object encapsulating the * PolicySpi implementation from the first * Provider that supports the specified type is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param type the specified Policy type. See the Policy section in the * * Java Cryptography Architecture Standard Algorithm Name Documentation * for a list of standard Policy types. * * @param params parameters for the Policy, which may be null. * * @return the new Policy object. * * @exception SecurityException if the caller does not have permission * to get a Policy instance for the specified type. * * @exception NullPointerException if the specified type is null. * * @exception IllegalArgumentException if the specified parameters * are not understood by the PolicySpi implementation * from the selected Provider. * * @exception NoSuchAlgorithmException if no Provider supports a PolicySpi * implementation for the specified type. * * @see Provider * @since 1.6 */ public static Policy getInstance(String type, Policy.Parameters params) throws NoSuchAlgorithmException { checkPermission(type); try { GetInstance.Instance instance = GetInstance.getInstance("Policy", PolicySpi.class, type, params); return new PolicyDelegate((PolicySpi)instance.impl, instance.provider, type, params); } catch (NoSuchAlgorithmException nsae) { return handleException(nsae); } } /** * Returns a Policy object of the specified type. * *

A new Policy object encapsulating the * PolicySpi implementation from the specified provider * is returned. The specified provider must be registered * in the provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param type the specified Policy type. See the Policy section in the * * Java Cryptography Architecture Standard Algorithm Name Documentation * for a list of standard Policy types. * * @param params parameters for the Policy, which may be null. * * @param provider the provider. * * @return the new Policy object. * * @exception SecurityException if the caller does not have permission * to get a Policy instance for the specified type. * * @exception NullPointerException if the specified type is null. * * @exception IllegalArgumentException if the specified provider * is null or empty, * or if the specified parameters are not understood by * the PolicySpi implementation from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception NoSuchAlgorithmException if the specified provider does not * support a PolicySpi implementation for the specified type. * * @see Provider * @since 1.6 */ public static Policy getInstance(String type, Policy.Parameters params, String provider) throws NoSuchProviderException, NoSuchAlgorithmException { if (provider == null || provider.length() == 0) { throw new IllegalArgumentException("missing provider"); } checkPermission(type); try { GetInstance.Instance instance = GetInstance.getInstance("Policy", PolicySpi.class, type, params, provider); return new PolicyDelegate((PolicySpi)instance.impl, instance.provider, type, params); } catch (NoSuchAlgorithmException nsae) { return handleException(nsae); } } /** * Returns a Policy object of the specified type. * *

A new Policy object encapsulating the * PolicySpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param type the specified Policy type. See the Policy section in the * * Java Cryptography Architecture Standard Algorithm Name Documentation * for a list of standard Policy types. * * @param params parameters for the Policy, which may be null. * * @param provider the Provider. * * @return the new Policy object. * * @exception SecurityException if the caller does not have permission * to get a Policy instance for the specified type. * * @exception NullPointerException if the specified type is null. * * @exception IllegalArgumentException if the specified Provider is null, * or if the specified parameters are not understood by * the PolicySpi implementation from the specified Provider. * * @exception NoSuchAlgorithmException if the specified Provider does not * support a PolicySpi implementation for the specified type. * * @see Provider * @since 1.6 */ public static Policy getInstance(String type, Policy.Parameters params, Provider provider) throws NoSuchAlgorithmException { if (provider == null) { throw new IllegalArgumentException("missing provider"); } checkPermission(type); try { GetInstance.Instance instance = GetInstance.getInstance("Policy", PolicySpi.class, type, params, provider); return new PolicyDelegate((PolicySpi)instance.impl, instance.provider, type, params); } catch (NoSuchAlgorithmException nsae) { return handleException(nsae); } } private static Policy handleException(NoSuchAlgorithmException nsae) throws NoSuchAlgorithmException { Throwable cause = nsae.getCause(); if (cause instanceof IllegalArgumentException) { throw (IllegalArgumentException)cause; } throw nsae; } /** * Return the Provider of this Policy. * *

This Policy instance will only have a Provider if it * was obtained via a call to {@code Policy.getInstance}. * Otherwise this method returns null. * * @return the Provider of this Policy, or null. * * @since 1.6 */ public Provider getProvider() { return null; } /** * Return the type of this Policy. * *

This Policy instance will only have a type if it * was obtained via a call to {@code Policy.getInstance}. * Otherwise this method returns null. * * @return the type of this Policy, or null. * * @since 1.6 */ public String getType() { return null; } /** * Return Policy parameters. * *

This Policy instance will only have parameters if it * was obtained via a call to {@code Policy.getInstance}. * Otherwise this method returns null. * * @return Policy parameters, or null. * * @since 1.6 */ public Policy.Parameters getParameters() { return null; } /** * Return a PermissionCollection object containing the set of * permissions granted to the specified CodeSource. * *

Applications are discouraged from calling this method * since this operation may not be supported by all policy implementations. * Applications should solely rely on the {@code implies} method * to perform policy checks. If an application absolutely must call * a getPermissions method, it should call * {@code getPermissions(ProtectionDomain)}. * *

The default implementation of this method returns * Policy.UNSUPPORTED_EMPTY_COLLECTION. This method can be * overridden if the policy implementation can return a set of * permissions granted to a CodeSource. * * @param codesource the CodeSource to which the returned * PermissionCollection has been granted. * * @return a set of permissions granted to the specified CodeSource. * If this operation is supported, the returned * set of permissions must be a new mutable instance * and it must support heterogeneous Permission types. * If this operation is not supported, * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned. */ public PermissionCollection getPermissions(CodeSource codesource) { return Policy.UNSUPPORTED_EMPTY_COLLECTION; } /** * Return a PermissionCollection object containing the set of * permissions granted to the specified ProtectionDomain. * *

Applications are discouraged from calling this method * since this operation may not be supported by all policy implementations. * Applications should rely on the {@code implies} method * to perform policy checks. * *

The default implementation of this method first retrieves * the permissions returned via {@code getPermissions(CodeSource)} * (the CodeSource is taken from the specified ProtectionDomain), * as well as the permissions located inside the specified ProtectionDomain. * All of these permissions are then combined and returned in a new * PermissionCollection object. If {@code getPermissions(CodeSource)} * returns Policy.UNSUPPORTED_EMPTY_COLLECTION, then this method * returns the permissions contained inside the specified ProtectionDomain * in a new PermissionCollection object. * *

This method can be overridden if the policy implementation * supports returning a set of permissions granted to a ProtectionDomain. * * @param domain the ProtectionDomain to which the returned * PermissionCollection has been granted. * * @return a set of permissions granted to the specified ProtectionDomain. * If this operation is supported, the returned * set of permissions must be a new mutable instance * and it must support heterogeneous Permission types. * If this operation is not supported, * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned. * * @since 1.4 */ public PermissionCollection getPermissions(ProtectionDomain domain) { PermissionCollection pc = null; if (domain == null) return new Permissions(); if (pdMapping == null) { initPolicy(this); } synchronized (pdMapping) { pc = pdMapping.get(domain.key); } if (pc != null) { Permissions perms = new Permissions(); synchronized (pc) { for (Enumeration e = pc.elements() ; e.hasMoreElements() ;) { perms.add(e.nextElement()); } } return perms; } pc = getPermissions(domain.getCodeSource()); if (pc == null || pc == UNSUPPORTED_EMPTY_COLLECTION) { pc = new Permissions(); } addStaticPerms(pc, domain.getPermissions()); return pc; } /** * add static permissions to provided permission collection */ private void addStaticPerms(PermissionCollection perms, PermissionCollection statics) { if (statics != null) { synchronized (statics) { Enumeration e = statics.elements(); while (e.hasMoreElements()) { perms.add(e.nextElement()); } } } } /** * Evaluates the global policy for the permissions granted to * the ProtectionDomain and tests whether the permission is * granted. * * @param domain the ProtectionDomain to test * @param permission the Permission object to be tested for implication. * * @return true if "permission" is a proper subset of a permission * granted to this ProtectionDomain. * * @see java.security.ProtectionDomain * @since 1.4 */ public boolean implies(ProtectionDomain domain, Permission permission) { PermissionCollection pc; if (pdMapping == null) { initPolicy(this); } synchronized (pdMapping) { pc = pdMapping.get(domain.key); } if (pc != null) { return pc.implies(permission); } pc = getPermissions(domain); if (pc == null) { return false; } synchronized (pdMapping) { // cache it pdMapping.put(domain.key, pc); } return pc.implies(permission); } /** * Refreshes/reloads the policy configuration. The behavior of this method * depends on the implementation. For example, calling {@code refresh} * on a file-based policy will cause the file to be re-read. * *

The default implementation of this method does nothing. * This method should be overridden if a refresh operation is supported * by the policy implementation. */ public void refresh() { } /** * This subclass is returned by the getInstance calls. All Policy calls * are delegated to the underlying PolicySpi. */ private static class PolicyDelegate extends Policy { private PolicySpi spi; private Provider p; private String type; private Policy.Parameters params; private PolicyDelegate(PolicySpi spi, Provider p, String type, Policy.Parameters params) { this.spi = spi; this.p = p; this.type = type; this.params = params; } @Override public String getType() { return type; } @Override public Policy.Parameters getParameters() { return params; } @Override public Provider getProvider() { return p; } @Override public PermissionCollection getPermissions(CodeSource codesource) { return spi.engineGetPermissions(codesource); } @Override public PermissionCollection getPermissions(ProtectionDomain domain) { return spi.engineGetPermissions(domain); } @Override public boolean implies(ProtectionDomain domain, Permission perm) { return spi.engineImplies(domain, perm); } @Override public void refresh() { spi.engineRefresh(); } } /** * This represents a marker interface for Policy parameters. * * @since 1.6 */ public static interface Parameters { } /** * This class represents a read-only empty PermissionCollection object that * is returned from the {@code getPermissions(CodeSource)} and * {@code getPermissions(ProtectionDomain)} * methods in the Policy class when those operations are not * supported by the Policy implementation. */ private static class UnsupportedEmptyCollection extends PermissionCollection { private static final long serialVersionUID = -8492269157353014774L; private Permissions perms; /** * Create a read-only empty PermissionCollection object. */ public UnsupportedEmptyCollection() { this.perms = new Permissions(); perms.setReadOnly(); } /** * Adds a permission object to the current collection of permission * objects. * * @param permission the Permission object to add. * * @exception SecurityException - if this PermissionCollection object * has been marked readonly */ @Override public void add(Permission permission) { perms.add(permission); } /** * Checks to see if the specified permission is implied by the * collection of Permission objects held in this PermissionCollection. * * @param permission the Permission object to compare. * * @return true if "permission" is implied by the permissions in * the collection, false if not. */ @Override public boolean implies(Permission permission) { return perms.implies(permission); } /** * Returns an enumeration of all the Permission objects in the * collection. * * @return an enumeration of all the Permissions. */ @Override public Enumeration elements() { return perms.elements(); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 4950 Content-Disposition: inline; filename="PolicySpi.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "608ce1fa777990982feed0672762c0f3acbd1e96" /* * Copyright (c) 2005, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This class defines the Service Provider Interface (SPI) * for the {@code Policy} class. * All the abstract methods in this class must be implemented by each * service provider who wishes to supply a Policy implementation. * *

Subclass implementations of this abstract class must provide * a public constructor that takes a {@code Policy.Parameters} * object as an input parameter. This constructor also must throw * an IllegalArgumentException if it does not understand the * {@code Policy.Parameters} input. * * * @since 1.6 */ public abstract class PolicySpi { /** * Check whether the policy has granted a Permission to a ProtectionDomain. * * @param domain the ProtectionDomain to check. * * @param permission check whether this permission is granted to the * specified domain. * * @return boolean true if the permission is granted to the domain. */ protected abstract boolean engineImplies (ProtectionDomain domain, Permission permission); /** * Refreshes/reloads the policy configuration. The behavior of this method * depends on the implementation. For example, calling {@code refresh} * on a file-based policy will cause the file to be re-read. * *

The default implementation of this method does nothing. * This method should be overridden if a refresh operation is supported * by the policy implementation. */ protected void engineRefresh() { } /** * Return a PermissionCollection object containing the set of * permissions granted to the specified CodeSource. * *

The default implementation of this method returns * Policy.UNSUPPORTED_EMPTY_COLLECTION object. This method can be * overridden if the policy implementation can return a set of * permissions granted to a CodeSource. * * @param codesource the CodeSource to which the returned * PermissionCollection has been granted. * * @return a set of permissions granted to the specified CodeSource. * If this operation is supported, the returned * set of permissions must be a new mutable instance * and it must support heterogeneous Permission types. * If this operation is not supported, * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned. */ protected PermissionCollection engineGetPermissions (CodeSource codesource) { return Policy.UNSUPPORTED_EMPTY_COLLECTION; } /** * Return a PermissionCollection object containing the set of * permissions granted to the specified ProtectionDomain. * *

The default implementation of this method returns * Policy.UNSUPPORTED_EMPTY_COLLECTION object. This method can be * overridden if the policy implementation can return a set of * permissions granted to a ProtectionDomain. * * @param domain the ProtectionDomain to which the returned * PermissionCollection has been granted. * * @return a set of permissions granted to the specified ProtectionDomain. * If this operation is supported, the returned * set of permissions must be a new mutable instance * and it must support heterogeneous Permission types. * If this operation is not supported, * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned. */ protected PermissionCollection engineGetPermissions (ProtectionDomain domain) { return Policy.UNSUPPORTED_EMPTY_COLLECTION; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3175 Content-Disposition: inline; filename="Principal.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "a538e707ee761179d0223d1131f8b9c2fca15183" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import javax.security.auth.Subject; /** * This interface represents the abstract notion of a principal, which * can be used to represent any entity, such as an individual, a * corporation, and a login id. * * @see java.security.cert.X509Certificate * * @author Li Gong */ public interface Principal { /** * Compares this principal to the specified object. Returns true * if the object passed in matches the principal represented by * the implementation of this interface. * * @param another principal to compare with. * * @return true if the principal passed in is the same as that * encapsulated by this principal, and false otherwise. */ public boolean equals(Object another); /** * Returns a string representation of this principal. * * @return a string representation of this principal. */ public String toString(); /** * Returns a hashcode for this principal. * * @return a hashcode for this principal. */ public int hashCode(); /** * Returns the name of this principal. * * @return the name of this principal. */ public String getName(); /** * Returns true if the specified subject is implied by this principal. * *

The default implementation of this method returns true if * {@code subject} is non-null and contains at least one principal that * is equal to this principal. * *

Subclasses may override this with a different implementation, if * necessary. * * @param subject the {@code Subject} * @return true if {@code subject} is non-null and is * implied by this principal, or false otherwise. * @since 1.8 */ public default boolean implies(Subject subject) { if (subject == null) return false; return subject.getPrincipals().contains(this); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2706 Content-Disposition: inline; filename="PrivateKey.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "7d8a7ea704184ab14905080b3898ea5d21c9dda4" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * A private key. * The purpose of this interface is to group (and provide type safety * for) all private key interfaces. *

* Note: The specialized private key interfaces extend this interface. * See, for example, the {@code DSAPrivateKey} interface in * {@link java.security.interfaces}. *

* Implementations should override the default {@code destroy} and * {@code isDestroyed} methods from the * {@link javax.security.auth.Destroyable} interface to enable * sensitive key information to be destroyed, cleared, or in the case * where such information is immutable, unreferenced. * Finally, since {@code PrivateKey} is {@code Serializable}, implementations * should also override * {@link java.io.ObjectOutputStream#writeObject(java.lang.Object)} * to prevent keys that have been destroyed from being serialized. * * @see Key * @see PublicKey * @see Certificate * @see Signature#initVerify * @see java.security.interfaces.DSAPrivateKey * @see java.security.interfaces.RSAPrivateKey * @see java.security.interfaces.RSAPrivateCrtKey * * @author Benjamin Renaud * @author Josh Bloch */ public interface PrivateKey extends Key, javax.security.auth.Destroyable { // Declare serialVersionUID to be compatible with JDK1.1 /** * The class fingerprint that is set to indicate serialization * compatibility with a previous version of the class. */ static final long serialVersionUID = 6034044314589513430L; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2381 Content-Disposition: inline; filename="PrivilegedAction.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "b993cea4d2f8d64c3d5fbd853480df8e69ee821d" /* * Copyright (c) 1998, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * A computation to be performed with privileges enabled. The computation is * performed by invoking {@code AccessController.doPrivileged} on the * {@code PrivilegedAction} object. This interface is used only for * computations that do not throw checked exceptions; computations that * throw checked exceptions must use {@code PrivilegedExceptionAction} * instead. * * @see AccessController * @see AccessController#doPrivileged(PrivilegedAction) * @see PrivilegedExceptionAction */ public interface PrivilegedAction { /** * Performs the computation. This method will be called by * {@code AccessController.doPrivileged} after enabling privileges. * * @return a class-dependent value that may represent the results of the * computation. Each class that implements * {@code PrivilegedAction} * should document what (if anything) this value represents. * @see AccessController#doPrivileged(PrivilegedAction) * @see AccessController#doPrivileged(PrivilegedAction, * AccessControlContext) */ T run(); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 4206 Content-Disposition: inline; filename="PrivilegedActionException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "2de696985990015860c5ae8eed25d1bb9de0e759" /* * Copyright (c) 1998, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This exception is thrown by * {@code doPrivileged(PrivilegedExceptionAction)} and * {@code doPrivileged(PrivilegedExceptionAction, * AccessControlContext context)} to indicate * that the action being performed threw a checked exception. The exception * thrown by the action can be obtained by calling the * {@code getException} method. In effect, an * {@code PrivilegedActionException} is a "wrapper" * for an exception thrown by a privileged action. * *

As of release 1.4, this exception has been retrofitted to conform to * the general purpose exception-chaining mechanism. The "exception thrown * by the privileged computation" that is provided at construction time and * accessed via the {@link #getException()} method is now known as the * cause, and may be accessed via the {@link Throwable#getCause()} * method, as well as the aforementioned "legacy method." * * @see PrivilegedExceptionAction * @see AccessController#doPrivileged(PrivilegedExceptionAction) * @see AccessController#doPrivileged(PrivilegedExceptionAction,AccessControlContext) */ public class PrivilegedActionException extends Exception { // use serialVersionUID from JDK 1.2.2 for interoperability private static final long serialVersionUID = 4724086851538908602L; /** * @serial */ private Exception exception; /** * Constructs a new PrivilegedActionException "wrapping" * the specific Exception. * * @param exception The exception thrown */ public PrivilegedActionException(Exception exception) { super((Throwable)null); // Disallow initCause this.exception = exception; } /** * Returns the exception thrown by the privileged computation that * resulted in this {@code PrivilegedActionException}. * *

This method predates the general-purpose exception chaining facility. * The {@link Throwable#getCause()} method is now the preferred means of * obtaining this information. * * @return the exception thrown by the privileged computation that * resulted in this {@code PrivilegedActionException}. * @see PrivilegedExceptionAction * @see AccessController#doPrivileged(PrivilegedExceptionAction) * @see AccessController#doPrivileged(PrivilegedExceptionAction, * AccessControlContext) */ public Exception getException() { return exception; } /** * Returns the cause of this exception (the exception thrown by * the privileged computation that resulted in this * {@code PrivilegedActionException}). * * @return the cause of this exception. * @since 1.4 */ public Throwable getCause() { return exception; } public String toString() { String s = getClass().getName(); return (exception != null) ? (s + ": " + exception.toString()) : s; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2794 Content-Disposition: inline; filename="PrivilegedExceptionAction.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "59a9ba7dc18d43073b597ea225c127cf46712a08" /* * Copyright (c) 1998, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * A computation to be performed with privileges enabled, that throws one or * more checked exceptions. The computation is performed by invoking * {@code AccessController.doPrivileged} on the * {@code PrivilegedExceptionAction} object. This interface is * used only for computations that throw checked exceptions; * computations that do not throw * checked exceptions should use {@code PrivilegedAction} instead. * * @see AccessController * @see AccessController#doPrivileged(PrivilegedExceptionAction) * @see AccessController#doPrivileged(PrivilegedExceptionAction, * AccessControlContext) * @see PrivilegedAction */ public interface PrivilegedExceptionAction { /** * Performs the computation. This method will be called by * {@code AccessController.doPrivileged} after enabling privileges. * * @return a class-dependent value that may represent the results of the * computation. Each class that implements * {@code PrivilegedExceptionAction} should document what * (if anything) this value represents. * @throws Exception an exceptional condition has occurred. Each class * that implements {@code PrivilegedExceptionAction} should * document the exceptions that its run method can throw. * @see AccessController#doPrivileged(PrivilegedExceptionAction) * @see AccessController#doPrivileged(PrivilegedExceptionAction,AccessControlContext) */ T run() throws Exception; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 17760 Content-Disposition: inline; filename="ProtectionDomain.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "7a86115e20db7f748f9229f3ad71ad76d26d2089" /* * Copyright (c) 1997, 2017, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.WeakHashMap; import sun.misc.JavaSecurityAccess; import sun.misc.JavaSecurityProtectionDomainAccess; import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache; import sun.misc.SharedSecrets; import sun.security.util.Debug; import sun.security.util.SecurityConstants; /** * The ProtectionDomain class encapsulates the characteristics of a domain, * which encloses a set of classes whose instances are granted a set * of permissions when being executed on behalf of a given set of Principals. *

* A static set of permissions can be bound to a ProtectionDomain when it is * constructed; such permissions are granted to the domain regardless of the * Policy in force. However, to support dynamic security policies, a * ProtectionDomain can also be constructed such that it is dynamically * mapped to a set of permissions by the current Policy whenever a permission * is checked. *

* * @author Li Gong * @author Roland Schemers * @author Gary Ellison */ public class ProtectionDomain { private static class JavaSecurityAccessImpl implements JavaSecurityAccess { private JavaSecurityAccessImpl() { } @Override public T doIntersectionPrivilege( PrivilegedAction action, final AccessControlContext stack, final AccessControlContext context) { if (action == null) { throw new NullPointerException(); } return AccessController.doPrivileged( action, getCombinedACC(context, stack) ); } @Override public T doIntersectionPrivilege( PrivilegedAction action, AccessControlContext context) { return doIntersectionPrivilege(action, AccessController.getContext(), context); } private static AccessControlContext getCombinedACC(AccessControlContext context, AccessControlContext stack) { AccessControlContext acc = new AccessControlContext(context, stack.getCombiner(), true); return new AccessControlContext(stack.getContext(), acc).optimize(); } } static { // Set up JavaSecurityAccess in SharedSecrets SharedSecrets.setJavaSecurityAccess(new JavaSecurityAccessImpl()); } /* CodeSource */ private CodeSource codesource ; /* ClassLoader the protection domain was consed from */ private ClassLoader classloader; /* Principals running-as within this protection domain */ private Principal[] principals; /* the rights this protection domain is granted */ private PermissionCollection permissions; /* if the permissions object has AllPermission */ private boolean hasAllPerm = false; /* the PermissionCollection is static (pre 1.4 constructor) or dynamic (via a policy refresh) */ private boolean staticPermissions; /* * An object used as a key when the ProtectionDomain is stored in a Map. */ final Key key = new Key(); private static final Debug debug = Debug.getInstance("domain"); /** * Creates a new ProtectionDomain with the given CodeSource and * Permissions. If the permissions object is not null, then * {@code setReadOnly())} will be called on the passed in * Permissions object. The only permissions granted to this domain * are the ones specified; the current Policy will not be consulted. * * @param codesource the codesource associated with this domain * @param permissions the permissions granted to this domain */ public ProtectionDomain(CodeSource codesource, PermissionCollection permissions) { this.codesource = codesource; if (permissions != null) { this.permissions = permissions; this.permissions.setReadOnly(); if (permissions instanceof Permissions && ((Permissions)permissions).allPermission != null) { hasAllPerm = true; } } this.classloader = null; this.principals = new Principal[0]; staticPermissions = true; } /** * Creates a new ProtectionDomain qualified by the given CodeSource, * Permissions, ClassLoader and array of Principals. If the * permissions object is not null, then {@code setReadOnly()} * will be called on the passed in Permissions object. * The permissions granted to this domain are dynamic; they include * both the static permissions passed to this constructor, and any * permissions granted to this domain by the current Policy at the * time a permission is checked. *

* This constructor is typically used by * {@link SecureClassLoader ClassLoaders} * and {@link DomainCombiner DomainCombiners} which delegate to * {@code Policy} to actively associate the permissions granted to * this domain. This constructor affords the * Policy provider the opportunity to augment the supplied * PermissionCollection to reflect policy changes. *

* * @param codesource the CodeSource associated with this domain * @param permissions the permissions granted to this domain * @param classloader the ClassLoader associated with this domain * @param principals the array of Principals associated with this * domain. The contents of the array are copied to protect against * subsequent modification. * @see Policy#refresh * @see Policy#getPermissions(ProtectionDomain) * @since 1.4 */ public ProtectionDomain(CodeSource codesource, PermissionCollection permissions, ClassLoader classloader, Principal[] principals) { this.codesource = codesource; if (permissions != null) { this.permissions = permissions; this.permissions.setReadOnly(); if (permissions instanceof Permissions && ((Permissions)permissions).allPermission != null) { hasAllPerm = true; } } this.classloader = classloader; this.principals = (principals != null ? principals.clone(): new Principal[0]); staticPermissions = false; } /** * Returns the CodeSource of this domain. * @return the CodeSource of this domain which may be null. * @since 1.2 */ public final CodeSource getCodeSource() { return this.codesource; } /** * Returns the ClassLoader of this domain. * @return the ClassLoader of this domain which may be null. * * @since 1.4 */ public final ClassLoader getClassLoader() { return this.classloader; } /** * Returns an array of principals for this domain. * @return a non-null array of principals for this domain. * Returns a new array each time this method is called. * * @since 1.4 */ public final Principal[] getPrincipals() { return this.principals.clone(); } /** * Returns the static permissions granted to this domain. * * @return the static set of permissions for this domain which may be null. * @see Policy#refresh * @see Policy#getPermissions(ProtectionDomain) */ public final PermissionCollection getPermissions() { return permissions; } /** * Check and see if this ProtectionDomain implies the permissions * expressed in the Permission object. *

* The set of permissions evaluated is a function of whether the * ProtectionDomain was constructed with a static set of permissions * or it was bound to a dynamically mapped set of permissions. *

* If the ProtectionDomain was constructed to a * {@link #ProtectionDomain(CodeSource, PermissionCollection) * statically bound} PermissionCollection then the permission will * only be checked against the PermissionCollection supplied at * construction. *

* However, if the ProtectionDomain was constructed with * the constructor variant which supports * {@link #ProtectionDomain(CodeSource, PermissionCollection, * ClassLoader, java.security.Principal[]) dynamically binding} * permissions, then the permission will be checked against the * combination of the PermissionCollection supplied at construction and * the current Policy binding. *

* * @param permission the Permission object to check. * * @return true if "permission" is implicit to this ProtectionDomain. */ public boolean implies(Permission permission) { if (hasAllPerm) { // internal permission collection already has AllPermission - // no need to go to policy return true; } if (!staticPermissions && Policy.getPolicyNoCheck().implies(this, permission)) return true; if (permissions != null) return permissions.implies(permission); return false; } // called by the VM -- do not remove boolean impliesCreateAccessControlContext() { return implies(SecurityConstants.CREATE_ACC_PERMISSION); } /** * Convert a ProtectionDomain to a String. */ @Override public String toString() { String pals = ""; if (principals != null && principals.length > 0) { StringBuilder palBuf = new StringBuilder("(principals "); for (int i = 0; i < principals.length; i++) { palBuf.append(principals[i].getClass().getName() + " \"" + principals[i].getName() + "\""); if (i < principals.length-1) palBuf.append(",\n"); else palBuf.append(")\n"); } pals = palBuf.toString(); } // Check if policy is set; we don't want to load // the policy prematurely here PermissionCollection pc = Policy.isSet() && seeAllp() ? mergePermissions(): getPermissions(); return "ProtectionDomain "+ " "+codesource+"\n"+ " "+classloader+"\n"+ " "+pals+"\n"+ " "+pc+"\n"; } /** * Return true (merge policy permissions) in the following cases: * * . SecurityManager is null * * . SecurityManager is not null, * debug is not null, * SecurityManager impelmentation is in bootclasspath, * Policy implementation is in bootclasspath * (the bootclasspath restrictions avoid recursion) * * . SecurityManager is not null, * debug is null, * caller has Policy.getPolicy permission */ private static boolean seeAllp() { SecurityManager sm = System.getSecurityManager(); if (sm == null) { return true; } else { if (debug != null) { if (sm.getClass().getClassLoader() == null && Policy.getPolicyNoCheck().getClass().getClassLoader() == null) { return true; } } else { try { sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION); return true; } catch (SecurityException se) { // fall thru and return false } } } return false; } private PermissionCollection mergePermissions() { if (staticPermissions) return permissions; PermissionCollection perms = java.security.AccessController.doPrivileged (new java.security.PrivilegedAction() { public PermissionCollection run() { Policy p = Policy.getPolicyNoCheck(); return p.getPermissions(ProtectionDomain.this); } }); Permissions mergedPerms = new Permissions(); int swag = 32; int vcap = 8; Enumeration e; List pdVector = new ArrayList<>(vcap); List plVector = new ArrayList<>(swag); // // Build a vector of domain permissions for subsequent merge if (permissions != null) { synchronized (permissions) { e = permissions.elements(); while (e.hasMoreElements()) { pdVector.add(e.nextElement()); } } } // // Build a vector of Policy permissions for subsequent merge if (perms != null) { synchronized (perms) { e = perms.elements(); while (e.hasMoreElements()) { plVector.add(e.nextElement()); vcap++; } } } if (perms != null && permissions != null) { // // Weed out the duplicates from the policy. Unless a refresh // has occurred since the pd was consed this should result in // an empty vector. synchronized (permissions) { e = permissions.elements(); // domain vs policy while (e.hasMoreElements()) { Permission pdp = e.nextElement(); Class pdpClass = pdp.getClass(); String pdpActions = pdp.getActions(); String pdpName = pdp.getName(); for (int i = 0; i < plVector.size(); i++) { Permission pp = plVector.get(i); if (pdpClass.isInstance(pp)) { // The equals() method on some permissions // have some side effects so this manual // comparison is sufficient. if (pdpName.equals(pp.getName()) && pdpActions.equals(pp.getActions())) { plVector.remove(i); break; } } } } } } if (perms !=null) { // the order of adding to merged perms and permissions // needs to preserve the bugfix 4301064 for (int i = plVector.size()-1; i >= 0; i--) { mergedPerms.add(plVector.get(i)); } } if (permissions != null) { for (int i = pdVector.size()-1; i >= 0; i--) { mergedPerms.add(pdVector.get(i)); } } return mergedPerms; } /** * Used for storing ProtectionDomains as keys in a Map. */ final class Key {} static { SharedSecrets.setJavaSecurityProtectionDomainAccess( new JavaSecurityProtectionDomainAccess() { @Override public ProtectionDomainCache getProtectionDomainCache() { return new ProtectionDomainCache() { private final Map map = Collections.synchronizedMap (new WeakHashMap()); public void put(ProtectionDomain pd, PermissionCollection pc) { map.put((pd == null ? null : pd.key), pc); } public PermissionCollection get(ProtectionDomain pd) { return pd == null ? map.get(null) : map.get(pd.key); } }; } @Override public boolean getStaticPermissionsField(ProtectionDomain pd) { return pd.staticPermissions; } }); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 69978 Content-Disposition: inline; filename="Provider.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "1eadb0e626423ba152f749724ddeaa07324c08e2" /* * Copyright (c) 1996, 2014, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.*; import java.util.*; import static java.util.Locale.ENGLISH; import java.lang.ref.*; import java.lang.reflect.*; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; /** * This class represents a "provider" for the * Java Security API, where a provider implements some or all parts of * Java Security. Services that a provider may implement include: * *

    * *
  • Algorithms (such as DSA, RSA, MD5 or SHA-1). * *
  • Key generation, conversion, and management facilities (such as for * algorithm-specific keys). * *
* *

Each provider has a name and a version number, and is configured * in each runtime it is installed in. * *

See The Provider Class * in the "Java Cryptography Architecture API Specification & Reference" * for information about how a particular type of provider, the * cryptographic service provider, works and is installed. However, * please note that a provider can be used to implement any security * service in Java that uses a pluggable architecture with a choice * of implementations that fit underneath. * *

Some provider implementations may encounter unrecoverable internal * errors during their operation, for example a failure to communicate with a * security token. A {@link ProviderException} should be used to indicate * such errors. * *

The service type {@code Provider} is reserved for use by the * security framework. Services of this type cannot be added, removed, * or modified by applications. * The following attributes are automatically placed in each Provider object: * * * * * * * * * * *
Attributes Automatically Placed in a Provider Object
NameValue
{@code Provider.id name}{@code String.valueOf(provider.getName())}
{@code Provider.id version}{@code String.valueOf(provider.getVersion())}
{@code Provider.id info} {@code String.valueOf(provider.getInfo())}
{@code Provider.id className}{@code provider.getClass().getName()}
* * @author Benjamin Renaud * @author Andreas Sterbenz */ public abstract class Provider extends Properties { // Declare serialVersionUID to be compatible with JDK1.1 static final long serialVersionUID = -4298000515446427739L; private static final sun.security.util.Debug debug = sun.security.util.Debug.getInstance ("provider", "Provider"); /** * The provider name. * * @serial */ private String name; /** * A description of the provider and its services. * * @serial */ private String info; /** * The provider version number. * * @serial */ private double version; private transient Set> entrySet = null; private transient int entrySetCallCount = 0; private transient boolean initialized; /** * Constructs a provider with the specified name, version number, * and information. * * @param name the provider name. * * @param version the provider version number. * * @param info a description of the provider and its services. */ protected Provider(String name, double version, String info) { this.name = name; this.version = version; this.info = info; putId(); initialized = true; } /** * Returns the name of this provider. * * @return the name of this provider. */ public String getName() { return name; } /** * Returns the version number for this provider. * * @return the version number for this provider. */ public double getVersion() { return version; } /** * Returns a human-readable description of the provider and its * services. This may return an HTML page, with relevant links. * * @return a description of the provider and its services. */ public String getInfo() { return info; } /** * Returns a string with the name and the version number * of this provider. * * @return the string with the name and the version number * for this provider. */ public String toString() { return name + " version " + version; } /* * override the following methods to ensure that provider * information can only be changed if the caller has the appropriate * permissions. */ /** * Clears this provider so that it no longer contains the properties * used to look up facilities implemented by the provider. * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the string {@code "clearProviderProperties."+name} * (where {@code name} is the provider name) to see if it's ok to clear * this provider. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to clear this provider * * @since 1.2 */ @Override public synchronized void clear() { check("clearProviderProperties."+name); if (debug != null) { debug.println("Remove " + name + " provider properties"); } implClear(); } /** * Reads a property list (key and element pairs) from the input stream. * * @param inStream the input stream. * @exception IOException if an error occurred when reading from the * input stream. * @see java.util.Properties#load */ @Override public synchronized void load(InputStream inStream) throws IOException { check("putProviderProperty."+name); if (debug != null) { debug.println("Load " + name + " provider properties"); } Properties tempProperties = new Properties(); tempProperties.load(inStream); implPutAll(tempProperties); } /** * Copies all of the mappings from the specified Map to this provider. * These mappings will replace any properties that this provider had * for any of the keys currently in the specified Map. * * @since 1.2 */ @Override public synchronized void putAll(Map t) { check("putProviderProperty."+name); if (debug != null) { debug.println("Put all " + name + " provider properties"); } implPutAll(t); } /** * Returns an unmodifiable Set view of the property entries contained * in this Provider. * * @see java.util.Map.Entry * @since 1.2 */ @Override public synchronized Set> entrySet() { checkInitialized(); if (entrySet == null) { if (entrySetCallCount++ == 0) // Initial call entrySet = Collections.unmodifiableMap(this).entrySet(); else return super.entrySet(); // Recursive call } // This exception will be thrown if the implementation of // Collections.unmodifiableMap.entrySet() is changed such that it // no longer calls entrySet() on the backing Map. (Provider's // entrySet implementation depends on this "implementation detail", // which is unlikely to change. if (entrySetCallCount != 2) throw new RuntimeException("Internal error."); return entrySet; } /** * Returns an unmodifiable Set view of the property keys contained in * this provider. * * @since 1.2 */ @Override public Set keySet() { checkInitialized(); return Collections.unmodifiableSet(super.keySet()); } /** * Returns an unmodifiable Collection view of the property values * contained in this provider. * * @since 1.2 */ @Override public Collection values() { checkInitialized(); return Collections.unmodifiableCollection(super.values()); } /** * Sets the {@code key} property to have the specified * {@code value}. * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the string {@code "putProviderProperty."+name}, * where {@code name} is the provider name, to see if it's ok to set this * provider's property values. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to set property values. * * @since 1.2 */ @Override public synchronized Object put(Object key, Object value) { check("putProviderProperty."+name); if (debug != null) { debug.println("Set " + name + " provider property [" + key + "/" + value +"]"); } return implPut(key, value); } /** * If the specified key is not already associated with a value (or is mapped * to {@code null}) associates it with the given value and returns * {@code null}, else returns the current value. * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the string {@code "putProviderProperty."+name}, * where {@code name} is the provider name, to see if it's ok to set this * provider's property values. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to set property values. * * @since 1.8 */ @Override public synchronized Object putIfAbsent(Object key, Object value) { check("putProviderProperty."+name); if (debug != null) { debug.println("Set " + name + " provider property [" + key + "/" + value +"]"); } return implPutIfAbsent(key, value); } /** * Removes the {@code key} property (and its corresponding * {@code value}). * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the string {@code "removeProviderProperty."+name}, * where {@code name} is the provider name, to see if it's ok to remove this * provider's properties. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to remove this provider's properties. * * @since 1.2 */ @Override public synchronized Object remove(Object key) { check("removeProviderProperty."+name); if (debug != null) { debug.println("Remove " + name + " provider property " + key); } return implRemove(key); } /** * Removes the entry for the specified key only if it is currently * mapped to the specified value. * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the string {@code "removeProviderProperty."+name}, * where {@code name} is the provider name, to see if it's ok to remove this * provider's properties. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to remove this provider's properties. * * @since 1.8 */ @Override public synchronized boolean remove(Object key, Object value) { check("removeProviderProperty."+name); if (debug != null) { debug.println("Remove " + name + " provider property " + key); } return implRemove(key, value); } /** * Replaces the entry for the specified key only if currently * mapped to the specified value. * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the string {@code "putProviderProperty."+name}, * where {@code name} is the provider name, to see if it's ok to set this * provider's property values. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to set property values. * * @since 1.8 */ @Override public synchronized boolean replace(Object key, Object oldValue, Object newValue) { check("putProviderProperty." + name); if (debug != null) { debug.println("Replace " + name + " provider property " + key); } return implReplace(key, oldValue, newValue); } /** * Replaces the entry for the specified key only if it is * currently mapped to some value. * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the string {@code "putProviderProperty."+name}, * where {@code name} is the provider name, to see if it's ok to set this * provider's property values. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to set property values. * * @since 1.8 */ @Override public synchronized Object replace(Object key, Object value) { check("putProviderProperty." + name); if (debug != null) { debug.println("Replace " + name + " provider property " + key); } return implReplace(key, value); } /** * Replaces each entry's value with the result of invoking the given * function on that entry, in the order entries are returned by an entry * set iterator, until all entries have been processed or the function * throws an exception. * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the string {@code "putProviderProperty."+name}, * where {@code name} is the provider name, to see if it's ok to set this * provider's property values. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to set property values. * * @since 1.8 */ @Override public synchronized void replaceAll(BiFunction function) { check("putProviderProperty." + name); if (debug != null) { debug.println("ReplaceAll " + name + " provider property "); } implReplaceAll(function); } /** * Attempts to compute a mapping for the specified key and its * current mapped value (or {@code null} if there is no current * mapping). * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the strings {@code "putProviderProperty."+name} * and {@code "removeProviderProperty."+name}, where {@code name} is the * provider name, to see if it's ok to set this provider's property values * and remove this provider's properties. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to set property values or remove properties. * * @since 1.8 */ @Override public synchronized Object compute(Object key, BiFunction remappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty" + name); if (debug != null) { debug.println("Compute " + name + " provider property " + key); } return implCompute(key, remappingFunction); } /** * If the specified key is not already associated with a value (or * is mapped to {@code null}), attempts to compute its value using * the given mapping function and enters it into this map unless * {@code null}. * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the strings {@code "putProviderProperty."+name} * and {@code "removeProviderProperty."+name}, where {@code name} is the * provider name, to see if it's ok to set this provider's property values * and remove this provider's properties. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to set property values and remove properties. * * @since 1.8 */ @Override public synchronized Object computeIfAbsent(Object key, Function mappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty" + name); if (debug != null) { debug.println("ComputeIfAbsent " + name + " provider property " + key); } return implComputeIfAbsent(key, mappingFunction); } /** * If the value for the specified key is present and non-null, attempts to * compute a new mapping given the key and its current mapped value. * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the strings {@code "putProviderProperty."+name} * and {@code "removeProviderProperty."+name}, where {@code name} is the * provider name, to see if it's ok to set this provider's property values * and remove this provider's properties. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to set property values or remove properties. * * @since 1.8 */ @Override public synchronized Object computeIfPresent(Object key, BiFunction remappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty" + name); if (debug != null) { debug.println("ComputeIfPresent " + name + " provider property " + key); } return implComputeIfPresent(key, remappingFunction); } /** * If the specified key is not already associated with a value or is * associated with null, associates it with the given value. Otherwise, * replaces the value with the results of the given remapping function, * or removes if the result is null. This method may be of use when * combining multiple mapped values for a key. * *

If a security manager is enabled, its {@code checkSecurityAccess} * method is called with the strings {@code "putProviderProperty."+name} * and {@code "removeProviderProperty."+name}, where {@code name} is the * provider name, to see if it's ok to set this provider's property values * and remove this provider's properties. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to set property values or remove properties. * * @since 1.8 */ @Override public synchronized Object merge(Object key, Object value, BiFunction remappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty" + name); if (debug != null) { debug.println("Merge " + name + " provider property " + key); } return implMerge(key, value, remappingFunction); } // let javadoc show doc from superclass @Override public Object get(Object key) { checkInitialized(); return super.get(key); } /** * @since 1.8 */ @Override public synchronized Object getOrDefault(Object key, Object defaultValue) { checkInitialized(); return super.getOrDefault(key, defaultValue); } /** * @since 1.8 */ @Override public synchronized void forEach(BiConsumer action) { checkInitialized(); super.forEach(action); } // let javadoc show doc from superclass @Override public Enumeration keys() { checkInitialized(); return super.keys(); } // let javadoc show doc from superclass @Override public Enumeration elements() { checkInitialized(); return super.elements(); } // let javadoc show doc from superclass public String getProperty(String key) { checkInitialized(); return super.getProperty(key); } private void checkInitialized() { if (!initialized) { throw new IllegalStateException(); } } private void check(String directive) { checkInitialized(); SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkSecurityAccess(directive); } } // legacy properties changed since last call to any services method? private transient boolean legacyChanged; // serviceMap changed since last call to getServices() private transient boolean servicesChanged; // Map private transient Map legacyStrings; // Map // used for services added via putService(), initialized on demand private transient Map serviceMap; // Map // used for services added via legacy methods, init on demand private transient Map legacyMap; // Set // Unmodifiable set of all services. Initialized on demand. private transient Set serviceSet; // register the id attributes for this provider // this is to ensure that equals() and hashCode() do not incorrectly // report to different provider objects as the same private void putId() { // note: name and info may be null super.put("Provider.id name", String.valueOf(name)); super.put("Provider.id version", String.valueOf(version)); super.put("Provider.id info", String.valueOf(info)); super.put("Provider.id className", this.getClass().getName()); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { Map copy = new HashMap<>(); for (Map.Entry entry : super.entrySet()) { copy.put(entry.getKey(), entry.getValue()); } defaults = null; in.defaultReadObject(); implClear(); initialized = true; putAll(copy); } private boolean checkLegacy(Object key) { String keyString = (String)key; if (keyString.startsWith("Provider.")) { return false; } legacyChanged = true; if (legacyStrings == null) { legacyStrings = new LinkedHashMap(); } return true; } /** * Copies all of the mappings from the specified Map to this provider. * Internal method to be called AFTER the security check has been * performed. */ private void implPutAll(Map t) { for (Map.Entry e : t.entrySet()) { implPut(e.getKey(), e.getValue()); } } private Object implRemove(Object key) { if (key instanceof String) { if (!checkLegacy(key)) { return null; } legacyStrings.remove((String)key); } return super.remove(key); } private boolean implRemove(Object key, Object value) { if (key instanceof String && value instanceof String) { if (!checkLegacy(key)) { return false; } legacyStrings.remove((String)key, value); } return super.remove(key, value); } private boolean implReplace(Object key, Object oldValue, Object newValue) { if ((key instanceof String) && (oldValue instanceof String) && (newValue instanceof String)) { if (!checkLegacy(key)) { return false; } legacyStrings.replace((String)key, (String)oldValue, (String)newValue); } return super.replace(key, oldValue, newValue); } private Object implReplace(Object key, Object value) { if ((key instanceof String) && (value instanceof String)) { if (!checkLegacy(key)) { return null; } legacyStrings.replace((String)key, (String)value); } return super.replace(key, value); } private void implReplaceAll(BiFunction function) { legacyChanged = true; if (legacyStrings == null) { legacyStrings = new LinkedHashMap(); } else { legacyStrings.replaceAll((BiFunction) function); } super.replaceAll(function); } private Object implMerge(Object key, Object value, BiFunction remappingFunction) { if ((key instanceof String) && (value instanceof String)) { if (!checkLegacy(key)) { return null; } legacyStrings.merge((String)key, (String)value, (BiFunction) remappingFunction); } return super.merge(key, value, remappingFunction); } private Object implCompute(Object key, BiFunction remappingFunction) { if (key instanceof String) { if (!checkLegacy(key)) { return null; } legacyStrings.computeIfAbsent((String) key, (Function) remappingFunction); } return super.compute(key, remappingFunction); } private Object implComputeIfAbsent(Object key, Function mappingFunction) { if (key instanceof String) { if (!checkLegacy(key)) { return null; } legacyStrings.computeIfAbsent((String) key, (Function) mappingFunction); } return super.computeIfAbsent(key, mappingFunction); } private Object implComputeIfPresent(Object key, BiFunction remappingFunction) { if (key instanceof String) { if (!checkLegacy(key)) { return null; } legacyStrings.computeIfPresent((String) key, (BiFunction) remappingFunction); } return super.computeIfPresent(key, remappingFunction); } private Object implPut(Object key, Object value) { if ((key instanceof String) && (value instanceof String)) { if (!checkLegacy(key)) { return null; } legacyStrings.put((String)key, (String)value); } return super.put(key, value); } private Object implPutIfAbsent(Object key, Object value) { if ((key instanceof String) && (value instanceof String)) { if (!checkLegacy(key)) { return null; } legacyStrings.putIfAbsent((String)key, (String)value); } return super.putIfAbsent(key, value); } private void implClear() { if (legacyStrings != null) { legacyStrings.clear(); } if (legacyMap != null) { legacyMap.clear(); } if (serviceMap != null) { serviceMap.clear(); } legacyChanged = false; servicesChanged = false; serviceSet = null; super.clear(); putId(); } // used as key in the serviceMap and legacyMap HashMaps private static class ServiceKey { private final String type; private final String algorithm; private final String originalAlgorithm; private ServiceKey(String type, String algorithm, boolean intern) { this.type = type; this.originalAlgorithm = algorithm; algorithm = algorithm.toUpperCase(ENGLISH); this.algorithm = intern ? algorithm.intern() : algorithm; } public int hashCode() { return type.hashCode() + algorithm.hashCode(); } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof ServiceKey == false) { return false; } ServiceKey other = (ServiceKey)obj; return this.type.equals(other.type) && this.algorithm.equals(other.algorithm); } boolean matches(String type, String algorithm) { return (this.type == type) && (this.originalAlgorithm == algorithm); } } /** * Ensure all the legacy String properties are fully parsed into * service objects. */ private void ensureLegacyParsed() { if ((legacyChanged == false) || (legacyStrings == null)) { return; } serviceSet = null; if (legacyMap == null) { legacyMap = new LinkedHashMap(); } else { legacyMap.clear(); } for (Map.Entry entry : legacyStrings.entrySet()) { parseLegacyPut(entry.getKey(), entry.getValue()); } removeInvalidServices(legacyMap); legacyChanged = false; } /** * Remove all invalid services from the Map. Invalid services can only * occur if the legacy properties are inconsistent or incomplete. */ private void removeInvalidServices(Map map) { for (Iterator> t = map.entrySet().iterator(); t.hasNext(); ) { Service s = t.next().getValue(); if (s.isValid() == false) { t.remove(); } } } private String[] getTypeAndAlgorithm(String key) { int i = key.indexOf("."); if (i < 1) { if (debug != null) { debug.println("Ignoring invalid entry in provider " + name + ":" + key); } return null; } String type = key.substring(0, i); String alg = key.substring(i + 1); return new String[] {type, alg}; } private final static String ALIAS_PREFIX = "Alg.Alias."; private final static String ALIAS_PREFIX_LOWER = "alg.alias."; private final static int ALIAS_LENGTH = ALIAS_PREFIX.length(); private void parseLegacyPut(String name, String value) { if (name.toLowerCase(ENGLISH).startsWith(ALIAS_PREFIX_LOWER)) { // e.g. put("Alg.Alias.MessageDigest.SHA", "SHA-1"); // aliasKey ~ MessageDigest.SHA String stdAlg = value; String aliasKey = name.substring(ALIAS_LENGTH); String[] typeAndAlg = getTypeAndAlgorithm(aliasKey); if (typeAndAlg == null) { return; } String type = getEngineName(typeAndAlg[0]); String aliasAlg = typeAndAlg[1].intern(); ServiceKey key = new ServiceKey(type, stdAlg, true); Service s = legacyMap.get(key); if (s == null) { s = new Service(this); s.type = type; s.algorithm = stdAlg; legacyMap.put(key, s); } legacyMap.put(new ServiceKey(type, aliasAlg, true), s); s.addAlias(aliasAlg); } else { String[] typeAndAlg = getTypeAndAlgorithm(name); if (typeAndAlg == null) { return; } int i = typeAndAlg[1].indexOf(' '); if (i == -1) { // e.g. put("MessageDigest.SHA-1", "sun.security.provider.SHA"); String type = getEngineName(typeAndAlg[0]); String stdAlg = typeAndAlg[1].intern(); String className = value; ServiceKey key = new ServiceKey(type, stdAlg, true); Service s = legacyMap.get(key); if (s == null) { s = new Service(this); s.type = type; s.algorithm = stdAlg; legacyMap.put(key, s); } s.className = className; } else { // attribute // e.g. put("MessageDigest.SHA-1 ImplementedIn", "Software"); String attributeValue = value; String type = getEngineName(typeAndAlg[0]); String attributeString = typeAndAlg[1]; String stdAlg = attributeString.substring(0, i).intern(); String attributeName = attributeString.substring(i + 1); // kill additional spaces while (attributeName.startsWith(" ")) { attributeName = attributeName.substring(1); } attributeName = attributeName.intern(); ServiceKey key = new ServiceKey(type, stdAlg, true); Service s = legacyMap.get(key); if (s == null) { s = new Service(this); s.type = type; s.algorithm = stdAlg; legacyMap.put(key, s); } s.addAttribute(attributeName, attributeValue); } } } /** * Get the service describing this Provider's implementation of the * specified type of this algorithm or alias. If no such * implementation exists, this method returns null. If there are two * matching services, one added to this provider using * {@link #putService putService()} and one added via {@link #put put()}, * the service added via {@link #putService putService()} is returned. * * @param type the type of {@link Service service} requested * (for example, {@code MessageDigest}) * @param algorithm the case insensitive algorithm name (or alternate * alias) of the service requested (for example, {@code SHA-1}) * * @return the service describing this Provider's matching service * or null if no such service exists * * @throws NullPointerException if type or algorithm is null * * @since 1.5 */ public synchronized Service getService(String type, String algorithm) { checkInitialized(); // avoid allocating a new key object if possible ServiceKey key = previousKey; if (key.matches(type, algorithm) == false) { key = new ServiceKey(type, algorithm, false); previousKey = key; } if (serviceMap != null) { Service service = serviceMap.get(key); if (service != null) { return service; } } ensureLegacyParsed(); return (legacyMap != null) ? legacyMap.get(key) : null; } // ServiceKey from previous getService() call // by re-using it if possible we avoid allocating a new object // and the toUpperCase() call. // re-use will occur e.g. as the framework traverses the provider // list and queries each provider with the same values until it finds // a matching service private static volatile ServiceKey previousKey = new ServiceKey("", "", false); /** * Get an unmodifiable Set of all services supported by * this Provider. * * @return an unmodifiable Set of all services supported by * this Provider * * @since 1.5 */ public synchronized Set getServices() { checkInitialized(); if (legacyChanged || servicesChanged) { serviceSet = null; } if (serviceSet == null) { ensureLegacyParsed(); Set set = new LinkedHashSet<>(); if (serviceMap != null) { set.addAll(serviceMap.values()); } if (legacyMap != null) { set.addAll(legacyMap.values()); } serviceSet = Collections.unmodifiableSet(set); servicesChanged = false; } return serviceSet; } /** * Add a service. If a service of the same type with the same algorithm * name exists and it was added using {@link #putService putService()}, * it is replaced by the new service. * This method also places information about this service * in the provider's Hashtable values in the format described in the * * Java Cryptography Architecture API Specification & Reference . * *

Also, if there is a security manager, its * {@code checkSecurityAccess} method is called with the string * {@code "putProviderProperty."+name}, where {@code name} is * the provider name, to see if it's ok to set this provider's property * values. If the default implementation of {@code checkSecurityAccess} * is used (that is, that method is not overriden), then this results in * a call to the security manager's {@code checkPermission} method with * a {@code SecurityPermission("putProviderProperty."+name)} * permission. * * @param s the Service to add * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method denies * access to set property values. * @throws NullPointerException if s is null * * @since 1.5 */ protected synchronized void putService(Service s) { check("putProviderProperty." + name); if (debug != null) { debug.println(name + ".putService(): " + s); } if (s == null) { throw new NullPointerException(); } if (s.getProvider() != this) { throw new IllegalArgumentException ("service.getProvider() must match this Provider object"); } if (serviceMap == null) { serviceMap = new LinkedHashMap(); } servicesChanged = true; String type = s.getType(); String algorithm = s.getAlgorithm(); ServiceKey key = new ServiceKey(type, algorithm, true); // remove existing service implRemoveService(serviceMap.get(key)); serviceMap.put(key, s); for (String alias : s.getAliases()) { serviceMap.put(new ServiceKey(type, alias, true), s); } putPropertyStrings(s); } /** * Put the string properties for this Service in this Provider's * Hashtable. */ private void putPropertyStrings(Service s) { String type = s.getType(); String algorithm = s.getAlgorithm(); // use super() to avoid permission check and other processing super.put(type + "." + algorithm, s.getClassName()); for (String alias : s.getAliases()) { super.put(ALIAS_PREFIX + type + "." + alias, algorithm); } for (Map.Entry entry : s.attributes.entrySet()) { String key = type + "." + algorithm + " " + entry.getKey(); super.put(key, entry.getValue()); } } /** * Remove the string properties for this Service from this Provider's * Hashtable. */ private void removePropertyStrings(Service s) { String type = s.getType(); String algorithm = s.getAlgorithm(); // use super() to avoid permission check and other processing super.remove(type + "." + algorithm); for (String alias : s.getAliases()) { super.remove(ALIAS_PREFIX + type + "." + alias); } for (Map.Entry entry : s.attributes.entrySet()) { String key = type + "." + algorithm + " " + entry.getKey(); super.remove(key); } } /** * Remove a service previously added using * {@link #putService putService()}. The specified service is removed from * this provider. It will no longer be returned by * {@link #getService getService()} and its information will be removed * from this provider's Hashtable. * *

Also, if there is a security manager, its * {@code checkSecurityAccess} method is called with the string * {@code "removeProviderProperty."+name}, where {@code name} is * the provider name, to see if it's ok to remove this provider's * properties. If the default implementation of * {@code checkSecurityAccess} is used (that is, that method is not * overriden), then this results in a call to the security manager's * {@code checkPermission} method with a * {@code SecurityPermission("removeProviderProperty."+name)} * permission. * * @param s the Service to be removed * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method denies * access to remove this provider's properties. * @throws NullPointerException if s is null * * @since 1.5 */ protected synchronized void removeService(Service s) { check("removeProviderProperty." + name); if (debug != null) { debug.println(name + ".removeService(): " + s); } if (s == null) { throw new NullPointerException(); } implRemoveService(s); } private void implRemoveService(Service s) { if ((s == null) || (serviceMap == null)) { return; } String type = s.getType(); String algorithm = s.getAlgorithm(); ServiceKey key = new ServiceKey(type, algorithm, false); Service oldService = serviceMap.get(key); if (s != oldService) { return; } servicesChanged = true; serviceMap.remove(key); for (String alias : s.getAliases()) { serviceMap.remove(new ServiceKey(type, alias, false)); } removePropertyStrings(s); } // Wrapped String that behaves in a case insensitive way for equals/hashCode private static class UString { final String string; final String lowerString; UString(String s) { this.string = s; this.lowerString = s.toLowerCase(ENGLISH); } public int hashCode() { return lowerString.hashCode(); } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof UString == false) { return false; } UString other = (UString)obj; return lowerString.equals(other.lowerString); } public String toString() { return string; } } // describe relevant properties of a type of engine private static class EngineDescription { final String name; final boolean supportsParameter; final String constructorParameterClassName; private volatile Class constructorParameterClass; EngineDescription(String name, boolean sp, String paramName) { this.name = name; this.supportsParameter = sp; this.constructorParameterClassName = paramName; } Class getConstructorParameterClass() throws ClassNotFoundException { Class clazz = constructorParameterClass; if (clazz == null) { clazz = Class.forName(constructorParameterClassName); constructorParameterClass = clazz; } return clazz; } } // built in knowledge of the engine types shipped as part of the JDK private static final Map knownEngines; private static void addEngine(String name, boolean sp, String paramName) { EngineDescription ed = new EngineDescription(name, sp, paramName); // also index by canonical name to avoid toLowerCase() for some lookups knownEngines.put(name.toLowerCase(ENGLISH), ed); knownEngines.put(name, ed); } static { knownEngines = new HashMap(); // JCA addEngine("AlgorithmParameterGenerator", false, null); addEngine("AlgorithmParameters", false, null); addEngine("KeyFactory", false, null); addEngine("KeyPairGenerator", false, null); addEngine("KeyStore", false, null); addEngine("MessageDigest", false, null); addEngine("SecureRandom", false, null); addEngine("Signature", true, null); addEngine("CertificateFactory", false, null); addEngine("CertPathBuilder", false, null); addEngine("CertPathValidator", false, null); addEngine("CertStore", false, "java.security.cert.CertStoreParameters"); // JCE addEngine("Cipher", true, null); addEngine("ExemptionMechanism", false, null); addEngine("Mac", true, null); addEngine("KeyAgreement", true, null); addEngine("KeyGenerator", false, null); addEngine("SecretKeyFactory", false, null); // JSSE addEngine("KeyManagerFactory", false, null); addEngine("SSLContext", false, null); addEngine("TrustManagerFactory", false, null); // JGSS addEngine("GssApiMechanism", false, null); // SASL addEngine("SaslClientFactory", false, null); addEngine("SaslServerFactory", false, null); // POLICY addEngine("Policy", false, "java.security.Policy$Parameters"); // CONFIGURATION addEngine("Configuration", false, "javax.security.auth.login.Configuration$Parameters"); // XML DSig addEngine("XMLSignatureFactory", false, null); addEngine("KeyInfoFactory", false, null); addEngine("TransformService", false, null); // Smart Card I/O addEngine("TerminalFactory", false, "java.lang.Object"); } // get the "standard" (mixed-case) engine name for arbitary case engine name // if there is no known engine by that name, return s private static String getEngineName(String s) { // try original case first, usually correct EngineDescription e = knownEngines.get(s); if (e == null) { e = knownEngines.get(s.toLowerCase(ENGLISH)); } return (e == null) ? s : e.name; } /** * The description of a security service. It encapsulates the properties * of a service and contains a factory method to obtain new implementation * instances of this service. * *

Each service has a provider that offers the service, a type, * an algorithm name, and the name of the class that implements the * service. Optionally, it also includes a list of alternate algorithm * names for this service (aliases) and attributes, which are a map of * (name, value) String pairs. * *

This class defines the methods {@link #supportsParameter * supportsParameter()} and {@link #newInstance newInstance()} * which are used by the Java security framework when it searches for * suitable services and instantiates them. The valid arguments to those * methods depend on the type of service. For the service types defined * within Java SE, see the * * Java Cryptography Architecture API Specification & Reference * for the valid values. * Note that components outside of Java SE can define additional types of * services and their behavior. * *

Instances of this class are immutable. * * @since 1.5 */ public static class Service { private String type, algorithm, className; private final Provider provider; private List aliases; private Map attributes; // Reference to the cached implementation Class object private volatile Reference> classRef; // flag indicating whether this service has its attributes for // supportedKeyFormats or supportedKeyClasses set // if null, the values have not been initialized // if TRUE, at least one of supportedFormats/Classes is non null private volatile Boolean hasKeyAttributes; // supported encoding formats private String[] supportedFormats; // names of the supported key (super) classes private Class[] supportedClasses; // whether this service has been registered with the Provider private boolean registered; private static final Class[] CLASS0 = new Class[0]; // this constructor and these methods are used for parsing // the legacy string properties. private Service(Provider provider) { this.provider = provider; aliases = Collections.emptyList(); attributes = Collections.emptyMap(); } private boolean isValid() { return (type != null) && (algorithm != null) && (className != null); } private void addAlias(String alias) { if (aliases.isEmpty()) { aliases = new ArrayList(2); } aliases.add(alias); } void addAttribute(String type, String value) { if (attributes.isEmpty()) { attributes = new HashMap(8); } attributes.put(new UString(type), value); } /** * Construct a new service. * * @param provider the provider that offers this service * @param type the type of this service * @param algorithm the algorithm name * @param className the name of the class implementing this service * @param aliases List of aliases or null if algorithm has no aliases * @param attributes Map of attributes or null if this implementation * has no attributes * * @throws NullPointerException if provider, type, algorithm, or * className is null */ public Service(Provider provider, String type, String algorithm, String className, List aliases, Map attributes) { if ((provider == null) || (type == null) || (algorithm == null) || (className == null)) { throw new NullPointerException(); } this.provider = provider; this.type = getEngineName(type); this.algorithm = algorithm; this.className = className; if (aliases == null) { this.aliases = Collections.emptyList(); } else { this.aliases = new ArrayList(aliases); } if (attributes == null) { this.attributes = Collections.emptyMap(); } else { this.attributes = new HashMap(); for (Map.Entry entry : attributes.entrySet()) { this.attributes.put(new UString(entry.getKey()), entry.getValue()); } } } /** * Get the type of this service. For example, {@code MessageDigest}. * * @return the type of this service */ public final String getType() { return type; } /** * Return the name of the algorithm of this service. For example, * {@code SHA-1}. * * @return the algorithm of this service */ public final String getAlgorithm() { return algorithm; } /** * Return the Provider of this service. * * @return the Provider of this service */ public final Provider getProvider() { return provider; } /** * Return the name of the class implementing this service. * * @return the name of the class implementing this service */ public final String getClassName() { return className; } // internal only private final List getAliases() { return aliases; } /** * Return the value of the specified attribute or null if this * attribute is not set for this Service. * * @param name the name of the requested attribute * * @return the value of the specified attribute or null if the * attribute is not present * * @throws NullPointerException if name is null */ public final String getAttribute(String name) { if (name == null) { throw new NullPointerException(); } return attributes.get(new UString(name)); } /** * Return a new instance of the implementation described by this * service. The security provider framework uses this method to * construct implementations. Applications will typically not need * to call it. * *

The default implementation uses reflection to invoke the * standard constructor for this type of service. * Security providers can override this method to implement * instantiation in a different way. * For details and the values of constructorParameter that are * valid for the various types of services see the * * Java Cryptography Architecture API Specification & * Reference. * * @param constructorParameter the value to pass to the constructor, * or null if this type of service does not use a constructorParameter. * * @return a new implementation of this service * * @throws InvalidParameterException if the value of * constructorParameter is invalid for this type of service. * @throws NoSuchAlgorithmException if instantiation failed for * any other reason. */ public Object newInstance(Object constructorParameter) throws NoSuchAlgorithmException { if (registered == false) { if (provider.getService(type, algorithm) != this) { throw new NoSuchAlgorithmException ("Service not registered with Provider " + provider.getName() + ": " + this); } registered = true; } try { EngineDescription cap = knownEngines.get(type); if (cap == null) { // unknown engine type, use generic code // this is the code path future for non-core // optional packages return newInstanceGeneric(constructorParameter); } if (cap.constructorParameterClassName == null) { if (constructorParameter != null) { throw new InvalidParameterException ("constructorParameter not used with " + type + " engines"); } Class clazz = getImplClass(); Class[] empty = {}; Constructor con = clazz.getConstructor(empty); return con.newInstance(); } else { Class paramClass = cap.getConstructorParameterClass(); if (constructorParameter != null) { Class argClass = constructorParameter.getClass(); if (paramClass.isAssignableFrom(argClass) == false) { throw new InvalidParameterException ("constructorParameter must be instanceof " + cap.constructorParameterClassName.replace('$', '.') + " for engine type " + type); } } Class clazz = getImplClass(); Constructor cons = clazz.getConstructor(paramClass); return cons.newInstance(constructorParameter); } } catch (NoSuchAlgorithmException e) { throw e; } catch (InvocationTargetException e) { throw new NoSuchAlgorithmException ("Error constructing implementation (algorithm: " + algorithm + ", provider: " + provider.getName() + ", class: " + className + ")", e.getCause()); } catch (Exception e) { throw new NoSuchAlgorithmException ("Error constructing implementation (algorithm: " + algorithm + ", provider: " + provider.getName() + ", class: " + className + ")", e); } } // return the implementation Class object for this service private Class getImplClass() throws NoSuchAlgorithmException { try { Reference> ref = classRef; Class clazz = (ref == null) ? null : ref.get(); if (clazz == null) { ClassLoader cl = provider.getClass().getClassLoader(); if (cl == null) { clazz = Class.forName(className); } else { clazz = cl.loadClass(className); } if (!Modifier.isPublic(clazz.getModifiers())) { throw new NoSuchAlgorithmException ("class configured for " + type + " (provider: " + provider.getName() + ") is not public."); } classRef = new WeakReference>(clazz); } return clazz; } catch (ClassNotFoundException e) { throw new NoSuchAlgorithmException ("class configured for " + type + " (provider: " + provider.getName() + ") cannot be found.", e); } } /** * Generic code path for unknown engine types. Call the * no-args constructor if constructorParameter is null, otherwise * use the first matching constructor. */ private Object newInstanceGeneric(Object constructorParameter) throws Exception { Class clazz = getImplClass(); if (constructorParameter == null) { // create instance with public no-arg constructor if it exists try { Class[] empty = {}; Constructor con = clazz.getConstructor(empty); return con.newInstance(); } catch (NoSuchMethodException e) { throw new NoSuchAlgorithmException("No public no-arg " + "constructor found in class " + className); } } Class argClass = constructorParameter.getClass(); Constructor[] cons = clazz.getConstructors(); // find first public constructor that can take the // argument as parameter for (Constructor con : cons) { Class[] paramTypes = con.getParameterTypes(); if (paramTypes.length != 1) { continue; } if (paramTypes[0].isAssignableFrom(argClass) == false) { continue; } return con.newInstance(constructorParameter); } throw new NoSuchAlgorithmException("No public constructor matching " + argClass.getName() + " found in class " + className); } /** * Test whether this Service can use the specified parameter. * Returns false if this service cannot use the parameter. Returns * true if this service can use the parameter, if a fast test is * infeasible, or if the status is unknown. * *

The security provider framework uses this method with * some types of services to quickly exclude non-matching * implementations for consideration. * Applications will typically not need to call it. * *

For details and the values of parameter that are valid for the * various types of services see the top of this class and the * * Java Cryptography Architecture API Specification & * Reference. * Security providers can override it to implement their own test. * * @param parameter the parameter to test * * @return false if this this service cannot use the specified * parameter; true if it can possibly use the parameter * * @throws InvalidParameterException if the value of parameter is * invalid for this type of service or if this method cannot be * used with this type of service */ public boolean supportsParameter(Object parameter) { EngineDescription cap = knownEngines.get(type); if (cap == null) { // unknown engine type, return true by default return true; } if (cap.supportsParameter == false) { throw new InvalidParameterException("supportsParameter() not " + "used with " + type + " engines"); } // allow null for keys without attributes for compatibility if ((parameter != null) && (parameter instanceof Key == false)) { throw new InvalidParameterException ("Parameter must be instanceof Key for engine " + type); } if (hasKeyAttributes() == false) { return true; } if (parameter == null) { return false; } Key key = (Key)parameter; if (supportsKeyFormat(key)) { return true; } if (supportsKeyClass(key)) { return true; } return false; } /** * Return whether this service has its Supported* properties for * keys defined. Parses the attributes if not yet initialized. */ private boolean hasKeyAttributes() { Boolean b = hasKeyAttributes; if (b == null) { synchronized (this) { String s; s = getAttribute("SupportedKeyFormats"); if (s != null) { supportedFormats = s.split("\\|"); } s = getAttribute("SupportedKeyClasses"); if (s != null) { String[] classNames = s.split("\\|"); List> classList = new ArrayList<>(classNames.length); for (String className : classNames) { Class clazz = getKeyClass(className); if (clazz != null) { classList.add(clazz); } } supportedClasses = classList.toArray(CLASS0); } boolean bool = (supportedFormats != null) || (supportedClasses != null); b = Boolean.valueOf(bool); hasKeyAttributes = b; } } return b.booleanValue(); } // get the key class object of the specified name private Class getKeyClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { // ignore } try { ClassLoader cl = provider.getClass().getClassLoader(); if (cl != null) { return cl.loadClass(name); } } catch (ClassNotFoundException e) { // ignore } return null; } private boolean supportsKeyFormat(Key key) { if (supportedFormats == null) { return false; } String format = key.getFormat(); if (format == null) { return false; } for (String supportedFormat : supportedFormats) { if (supportedFormat.equals(format)) { return true; } } return false; } private boolean supportsKeyClass(Key key) { if (supportedClasses == null) { return false; } Class keyClass = key.getClass(); for (Class clazz : supportedClasses) { if (clazz.isAssignableFrom(keyClass)) { return true; } } return false; } /** * Return a String representation of this service. * * @return a String representation of this service. */ public String toString() { String aString = aliases.isEmpty() ? "" : "\r\n aliases: " + aliases.toString(); String attrs = attributes.isEmpty() ? "" : "\r\n attributes: " + attributes.toString(); return provider.getName() + ": " + type + "." + algorithm + " -> " + className + aString + attrs + "\r\n"; } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3296 Content-Disposition: inline; filename="ProviderException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "b372ee7575272a3ab0285c1ed0acc72c366c0727" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * A runtime exception for Provider exceptions (such as * misconfiguration errors or unrecoverable internal errors), * which may be subclassed by Providers to * throw specialized, provider-specific runtime errors. * * @author Benjamin Renaud */ public class ProviderException extends RuntimeException { private static final long serialVersionUID = 5256023526693665674L; /** * Constructs a ProviderException with no detail message. A * detail message is a String that describes this particular * exception. */ public ProviderException() { super(); } /** * Constructs a ProviderException with the specified detail * message. A detail message is a String that describes this * particular exception. * * @param s the detail message. */ public ProviderException(String s) { super(s); } /** * Creates a {@code ProviderException} with the specified * detail message and cause. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public ProviderException(String message, Throwable cause) { super(message, cause); } /** * Creates a {@code ProviderException} with the specified cause * and a detail message of {@code (cause==null ? null : cause.toString())} * (which typically contains the class and detail message of * {@code cause}). * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public ProviderException(Throwable cause) { super(cause); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2053 Content-Disposition: inline; filename="PublicKey.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "df49807eea4beb0986cf0bee73349931f2c03bc9" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** *

A public key. This interface contains no methods or constants. * It merely serves to group (and provide type safety for) all public key * interfaces. * * Note: The specialized public key interfaces extend this interface. * See, for example, the DSAPublicKey interface in * {@code java.security.interfaces}. * * @see Key * @see PrivateKey * @see Certificate * @see Signature#initVerify * @see java.security.interfaces.DSAPublicKey * @see java.security.interfaces.RSAPublicKey * */ public interface PublicKey extends Key { // Declare serialVersionUID to be compatible with JDK1.1 /** * The class fingerprint that is set to indicate serialization * compatibility with a previous version of the class. */ static final long serialVersionUID = 7187392471159151072L; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 9171 Content-Disposition: inline; filename="SecureClassLoader.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "145f4fc482b5d9884369e67f5a4a6e419141a7b4" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.HashMap; import java.util.ArrayList; import java.net.URL; import sun.security.util.Debug; /** * This class extends ClassLoader with additional support for defining * classes with an associated code source and permissions which are * retrieved by the system policy by default. * * @author Li Gong * @author Roland Schemers */ public class SecureClassLoader extends ClassLoader { /* * If initialization succeed this is set to true and security checks will * succeed. Otherwise the object is not initialized and the object is * useless. */ private final boolean initialized; // HashMap that maps CodeSource to ProtectionDomain // @GuardedBy("pdcache") private final HashMap pdcache = new HashMap<>(11); private static final Debug debug = Debug.getInstance("scl"); static { ClassLoader.registerAsParallelCapable(); } /** * Creates a new SecureClassLoader using the specified parent * class loader for delegation. * *

If there is a security manager, this method first * calls the security manager's {@code checkCreateClassLoader} * method to ensure creation of a class loader is allowed. *

* @param parent the parent ClassLoader * @exception SecurityException if a security manager exists and its * {@code checkCreateClassLoader} method doesn't allow * creation of a class loader. * @see SecurityManager#checkCreateClassLoader */ protected SecureClassLoader(ClassLoader parent) { super(parent); // this is to make the stack depth consistent with 1.1 SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkCreateClassLoader(); } initialized = true; } /** * Creates a new SecureClassLoader using the default parent class * loader for delegation. * *

If there is a security manager, this method first * calls the security manager's {@code checkCreateClassLoader} * method to ensure creation of a class loader is allowed. * * @exception SecurityException if a security manager exists and its * {@code checkCreateClassLoader} method doesn't allow * creation of a class loader. * @see SecurityManager#checkCreateClassLoader */ protected SecureClassLoader() { super(); // this is to make the stack depth consistent with 1.1 SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkCreateClassLoader(); } initialized = true; } /** * Converts an array of bytes into an instance of class Class, * with an optional CodeSource. Before the * class can be used it must be resolved. *

* If a non-null CodeSource is supplied a ProtectionDomain is * constructed and associated with the class being defined. *

* @param name the expected name of the class, or {@code null} * if not known, using '.' and not '/' as the separator * and without a trailing ".class" suffix. * @param b the bytes that make up the class data. The bytes in * positions {@code off} through {@code off+len-1} * should have the format of a valid class file as defined by * The Java™ Virtual Machine Specification. * @param off the start offset in {@code b} of the class data * @param len the length of the class data * @param cs the associated CodeSource, or {@code null} if none * @return the {@code Class} object created from the data, * and optional CodeSource. * @exception ClassFormatError if the data did not contain a valid class * @exception IndexOutOfBoundsException if either {@code off} or * {@code len} is negative, or if * {@code off+len} is greater than {@code b.length}. * * @exception SecurityException if an attempt is made to add this class * to a package that contains classes that were signed by * a different set of certificates than this class, or if * the class name begins with "java.". */ protected final Class defineClass(String name, byte[] b, int off, int len, CodeSource cs) { return defineClass(name, b, off, len, getProtectionDomain(cs)); } /** * Converts a {@link java.nio.ByteBuffer ByteBuffer} * into an instance of class {@code Class}, with an optional CodeSource. * Before the class can be used it must be resolved. *

* If a non-null CodeSource is supplied a ProtectionDomain is * constructed and associated with the class being defined. *

* @param name the expected name of the class, or {@code null} * if not known, using '.' and not '/' as the separator * and without a trailing ".class" suffix. * @param b the bytes that make up the class data. The bytes from positions * {@code b.position()} through {@code b.position() + b.limit() -1} * should have the format of a valid class file as defined by * The Java™ Virtual Machine Specification. * @param cs the associated CodeSource, or {@code null} if none * @return the {@code Class} object created from the data, * and optional CodeSource. * @exception ClassFormatError if the data did not contain a valid class * @exception SecurityException if an attempt is made to add this class * to a package that contains classes that were signed by * a different set of certificates than this class, or if * the class name begins with "java.". * * @since 1.5 */ protected final Class defineClass(String name, java.nio.ByteBuffer b, CodeSource cs) { return defineClass(name, b, getProtectionDomain(cs)); } /** * Returns the permissions for the given CodeSource object. *

* This method is invoked by the defineClass method which takes * a CodeSource as an argument when it is constructing the * ProtectionDomain for the class being defined. *

* @param codesource the codesource. * * @return the permissions granted to the codesource. * */ protected PermissionCollection getPermissions(CodeSource codesource) { check(); return new Permissions(); // ProtectionDomain defers the binding } /* * Returned cached ProtectionDomain for the specified CodeSource. */ private ProtectionDomain getProtectionDomain(CodeSource cs) { if (cs == null) return null; ProtectionDomain pd = null; synchronized (pdcache) { pd = pdcache.get(cs); if (pd == null) { PermissionCollection perms = getPermissions(cs); pd = new ProtectionDomain(cs, perms, this, null); pdcache.put(cs, pd); if (debug != null) { debug.println(" getPermissions "+ pd); debug.println(""); } } } return pd; } /* * Check to make sure the class loader has been initialized. */ private void check() { if (!initialized) { throw new SecurityException("ClassLoader object not initialized"); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 25118 Content-Disposition: inline; filename="SecureRandom.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "6848be5a2d215b1bbaae1659029b10a85db31d48" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.util.*; import java.util.regex.*; import java.security.Provider.Service; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; import sun.security.util.Debug; /** * This class provides a cryptographically strong random number * generator (RNG). * *

A cryptographically strong random number * minimally complies with the statistical random number generator tests * specified in * FIPS 140-2, Security Requirements for Cryptographic Modules, * section 4.9.1. * Additionally, SecureRandom must produce non-deterministic output. * Therefore any seed material passed to a SecureRandom object must be * unpredictable, and all SecureRandom output sequences must be * cryptographically strong, as described in * * RFC 1750: Randomness Recommendations for Security. * *

A caller obtains a SecureRandom instance via the * no-argument constructor or one of the {@code getInstance} methods: * *

 *      SecureRandom random = new SecureRandom();
 * 
* *

Many SecureRandom implementations are in the form of a pseudo-random * number generator (PRNG), which means they use a deterministic algorithm * to produce a pseudo-random sequence from a true random seed. * Other implementations may produce true random numbers, * and yet others may use a combination of both techniques. * *

Typical callers of SecureRandom invoke the following methods * to retrieve random bytes: * *

 *      SecureRandom random = new SecureRandom();
 *      byte bytes[] = new byte[20];
 *      random.nextBytes(bytes);
 * 
* *

Callers may also invoke the {@code generateSeed} method * to generate a given number of seed bytes (to seed other random number * generators, for example): *

 *      byte seed[] = random.generateSeed(20);
 * 
* * Note: Depending on the implementation, the {@code generateSeed} and * {@code nextBytes} methods may block as entropy is being gathered, * for example, if they need to read from /dev/random on various Unix-like * operating systems. * * @see java.security.SecureRandomSpi * @see java.util.Random * * @author Benjamin Renaud * @author Josh Bloch */ public class SecureRandom extends java.util.Random { private static final Debug pdebug = Debug.getInstance("provider", "Provider"); private static final boolean skipDebug = Debug.isOn("engine=") && !Debug.isOn("securerandom"); /** * The provider. * * @serial * @since 1.2 */ private Provider provider = null; /** * The provider implementation. * * @serial * @since 1.2 */ private SecureRandomSpi secureRandomSpi = null; /* * The algorithm name of null if unknown. * * @serial * @since 1.5 */ private String algorithm; // Seed Generator private static volatile SecureRandom seedGenerator = null; /** * Constructs a secure random number generator (RNG) implementing the * default random number algorithm. * *

This constructor traverses the list of registered security Providers, * starting with the most preferred Provider. * A new SecureRandom object encapsulating the * SecureRandomSpi implementation from the first * Provider that supports a SecureRandom (RNG) algorithm is returned. * If none of the Providers support a RNG algorithm, * then an implementation-specific default is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * *

See the SecureRandom section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard RNG algorithm names. * *

The returned SecureRandom object has not been seeded. To seed the * returned object, call the {@code setSeed} method. * If {@code setSeed} is not called, the first call to * {@code nextBytes} will force the SecureRandom object to seed itself. * This self-seeding will not occur if {@code setSeed} was * previously called. */ public SecureRandom() { /* * This call to our superclass constructor will result in a call * to our own {@code setSeed} method, which will return * immediately when it is passed zero. */ super(0); getDefaultPRNG(false, null); } /** * Constructs a secure random number generator (RNG) implementing the * default random number algorithm. * The SecureRandom instance is seeded with the specified seed bytes. * *

This constructor traverses the list of registered security Providers, * starting with the most preferred Provider. * A new SecureRandom object encapsulating the * SecureRandomSpi implementation from the first * Provider that supports a SecureRandom (RNG) algorithm is returned. * If none of the Providers support a RNG algorithm, * then an implementation-specific default is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * *

See the SecureRandom section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard RNG algorithm names. * * @param seed the seed. */ public SecureRandom(byte seed[]) { super(0); getDefaultPRNG(true, seed); } private void getDefaultPRNG(boolean setSeed, byte[] seed) { String prng = getPrngAlgorithm(); if (prng == null) { // bummer, get the SUN implementation prng = "SHA1PRNG"; this.secureRandomSpi = new sun.security.provider.SecureRandom(); this.provider = Providers.getSunProvider(); if (setSeed) { this.secureRandomSpi.engineSetSeed(seed); } } else { try { SecureRandom random = SecureRandom.getInstance(prng); this.secureRandomSpi = random.getSecureRandomSpi(); this.provider = random.getProvider(); if (setSeed) { this.secureRandomSpi.engineSetSeed(seed); } } catch (NoSuchAlgorithmException nsae) { // never happens, because we made sure the algorithm exists throw new RuntimeException(nsae); } } // JDK 1.1 based implementations subclass SecureRandom instead of // SecureRandomSpi. They will also go through this code path because // they must call a SecureRandom constructor as it is their superclass. // If we are dealing with such an implementation, do not set the // algorithm value as it would be inaccurate. if (getClass() == SecureRandom.class) { this.algorithm = prng; } } /** * Creates a SecureRandom object. * * @param secureRandomSpi the SecureRandom implementation. * @param provider the provider. */ protected SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider) { this(secureRandomSpi, provider, null); } private SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider, String algorithm) { super(0); this.secureRandomSpi = secureRandomSpi; this.provider = provider; this.algorithm = algorithm; if (!skipDebug && pdebug != null) { pdebug.println("SecureRandom." + algorithm + " algorithm from: " + this.provider.getName()); } } /** * Returns a SecureRandom object that implements the specified * Random Number Generator (RNG) algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new SecureRandom object encapsulating the * SecureRandomSpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * *

The returned SecureRandom object has not been seeded. To seed the * returned object, call the {@code setSeed} method. * If {@code setSeed} is not called, the first call to * {@code nextBytes} will force the SecureRandom object to seed itself. * This self-seeding will not occur if {@code setSeed} was * previously called. * * @param algorithm the name of the RNG algorithm. * See the SecureRandom section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard RNG algorithm names. * * @return the new SecureRandom object. * * @exception NoSuchAlgorithmException if no Provider supports a * SecureRandomSpi implementation for the * specified algorithm. * * @see Provider * * @since 1.2 */ public static SecureRandom getInstance(String algorithm) throws NoSuchAlgorithmException { Instance instance = GetInstance.getInstance("SecureRandom", SecureRandomSpi.class, algorithm); return new SecureRandom((SecureRandomSpi)instance.impl, instance.provider, algorithm); } /** * Returns a SecureRandom object that implements the specified * Random Number Generator (RNG) algorithm. * *

A new SecureRandom object encapsulating the * SecureRandomSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * *

The returned SecureRandom object has not been seeded. To seed the * returned object, call the {@code setSeed} method. * If {@code setSeed} is not called, the first call to * {@code nextBytes} will force the SecureRandom object to seed itself. * This self-seeding will not occur if {@code setSeed} was * previously called. * * @param algorithm the name of the RNG algorithm. * See the SecureRandom section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard RNG algorithm names. * * @param provider the name of the provider. * * @return the new SecureRandom object. * * @exception NoSuchAlgorithmException if a SecureRandomSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider name is null * or empty. * * @see Provider * * @since 1.2 */ public static SecureRandom getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Instance instance = GetInstance.getInstance("SecureRandom", SecureRandomSpi.class, algorithm, provider); return new SecureRandom((SecureRandomSpi)instance.impl, instance.provider, algorithm); } /** * Returns a SecureRandom object that implements the specified * Random Number Generator (RNG) algorithm. * *

A new SecureRandom object encapsulating the * SecureRandomSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * *

The returned SecureRandom object has not been seeded. To seed the * returned object, call the {@code setSeed} method. * If {@code setSeed} is not called, the first call to * {@code nextBytes} will force the SecureRandom object to seed itself. * This self-seeding will not occur if {@code setSeed} was * previously called. * * @param algorithm the name of the RNG algorithm. * See the SecureRandom section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard RNG algorithm names. * * @param provider the provider. * * @return the new SecureRandom object. * * @exception NoSuchAlgorithmException if a SecureRandomSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the specified provider is null. * * @see Provider * * @since 1.4 */ public static SecureRandom getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { Instance instance = GetInstance.getInstance("SecureRandom", SecureRandomSpi.class, algorithm, provider); return new SecureRandom((SecureRandomSpi)instance.impl, instance.provider, algorithm); } /** * Returns the SecureRandomSpi of this SecureRandom object. */ SecureRandomSpi getSecureRandomSpi() { return secureRandomSpi; } /** * Returns the provider of this SecureRandom object. * * @return the provider of this SecureRandom object. */ public final Provider getProvider() { return provider; } /** * Returns the name of the algorithm implemented by this SecureRandom * object. * * @return the name of the algorithm or {@code unknown} * if the algorithm name cannot be determined. * @since 1.5 */ public String getAlgorithm() { return (algorithm != null) ? algorithm : "unknown"; } /** * Reseeds this random object. The given seed supplements, rather than * replaces, the existing seed. Thus, repeated calls are guaranteed * never to reduce randomness. * * @param seed the seed. * * @see #getSeed */ synchronized public void setSeed(byte[] seed) { secureRandomSpi.engineSetSeed(seed); } /** * Reseeds this random object, using the eight bytes contained * in the given {@code long seed}. The given seed supplements, * rather than replaces, the existing seed. Thus, repeated calls * are guaranteed never to reduce randomness. * *

This method is defined for compatibility with * {@code java.util.Random}. * * @param seed the seed. * * @see #getSeed */ @Override public void setSeed(long seed) { /* * Ignore call from super constructor (as well as any other calls * unfortunate enough to be passing 0). It's critical that we * ignore call from superclass constructor, as digest has not * yet been initialized at that point. */ if (seed != 0) { secureRandomSpi.engineSetSeed(longToByteArray(seed)); } } /** * Generates a user-specified number of random bytes. * *

If a call to {@code setSeed} had not occurred previously, * the first call to this method forces this SecureRandom object * to seed itself. This self-seeding will not occur if * {@code setSeed} was previously called. * * @param bytes the array to be filled in with random bytes. */ @Override public void nextBytes(byte[] bytes) { secureRandomSpi.engineNextBytes(bytes); } /** * Generates an integer containing the user-specified number of * pseudo-random bits (right justified, with leading zeros). This * method overrides a {@code java.util.Random} method, and serves * to provide a source of random bits to all of the methods inherited * from that class (for example, {@code nextInt}, * {@code nextLong}, and {@code nextFloat}). * * @param numBits number of pseudo-random bits to be generated, where * {@code 0 <= numBits <= 32}. * * @return an {@code int} containing the user-specified number * of pseudo-random bits (right justified, with leading zeros). */ @Override final protected int next(int numBits) { int numBytes = (numBits+7)/8; byte b[] = new byte[numBytes]; int next = 0; nextBytes(b); for (int i = 0; i < numBytes; i++) { next = (next << 8) + (b[i] & 0xFF); } return next >>> (numBytes*8 - numBits); } /** * Returns the given number of seed bytes, computed using the seed * generation algorithm that this class uses to seed itself. This * call may be used to seed other random number generators. * *

This method is only included for backwards compatibility. * The caller is encouraged to use one of the alternative * {@code getInstance} methods to obtain a SecureRandom object, and * then call the {@code generateSeed} method to obtain seed bytes * from that object. * * @param numBytes the number of seed bytes to generate. * * @return the seed bytes. * * @see #setSeed */ public static byte[] getSeed(int numBytes) { if (seedGenerator == null) { seedGenerator = new SecureRandom(); } return seedGenerator.generateSeed(numBytes); } /** * Returns the given number of seed bytes, computed using the seed * generation algorithm that this class uses to seed itself. This * call may be used to seed other random number generators. * * @param numBytes the number of seed bytes to generate. * * @return the seed bytes. */ public byte[] generateSeed(int numBytes) { return secureRandomSpi.engineGenerateSeed(numBytes); } /** * Helper function to convert a long into a byte array (least significant * byte first). */ private static byte[] longToByteArray(long l) { byte[] retVal = new byte[8]; for (int i = 0; i < 8; i++) { retVal[i] = (byte) l; l >>= 8; } return retVal; } /** * Gets a default PRNG algorithm by looking through all registered * providers. Returns the first PRNG algorithm of the first provider that * has registered a SecureRandom implementation, or null if none of the * registered providers supplies a SecureRandom implementation. */ private static String getPrngAlgorithm() { for (Provider p : Providers.getProviderList().providers()) { for (Service s : p.getServices()) { if (s.getType().equals("SecureRandom")) { return s.getAlgorithm(); } } } return null; } /* * Lazily initialize since Pattern.compile() is heavy. * Effective Java (2nd Edition), Item 71. */ private static final class StrongPatternHolder { /* * Entries are alg:prov separated by , * Allow for prepended/appended whitespace between entries. * * Capture groups: * 1 - alg * 2 - :prov (optional) * 3 - prov (optional) * 4 - ,nextEntry (optional) * 5 - nextEntry (optional) */ private static Pattern pattern = Pattern.compile( "\\s*([\\S&&[^:,]]*)(\\:([\\S&&[^,]]*))?\\s*(\\,(.*))?"); } /** * Returns a {@code SecureRandom} object that was selected by using * the algorithms/providers specified in the {@code * securerandom.strongAlgorithms} {@link Security} property. *

* Some situations require strong random values, such as when * creating high-value/long-lived secrets like RSA public/private * keys. To help guide applications in selecting a suitable strong * {@code SecureRandom} implementation, Java distributions * include a list of known strong {@code SecureRandom} * implementations in the {@code securerandom.strongAlgorithms} * Security property. *

* Every implementation of the Java platform is required to * support at least one strong {@code SecureRandom} implementation. * * @return a strong {@code SecureRandom} implementation as indicated * by the {@code securerandom.strongAlgorithms} Security property * * @throws NoSuchAlgorithmException if no algorithm is available * * @see Security#getProperty(String) * * @since 1.8 */ public static SecureRandom getInstanceStrong() throws NoSuchAlgorithmException { String property = AccessController.doPrivileged( new PrivilegedAction() { @Override public String run() { return Security.getProperty( "securerandom.strongAlgorithms"); } }); if ((property == null) || (property.length() == 0)) { throw new NoSuchAlgorithmException( "Null/empty securerandom.strongAlgorithms Security Property"); } String remainder = property; while (remainder != null) { Matcher m; if ((m = StrongPatternHolder.pattern.matcher( remainder)).matches()) { String alg = m.group(1); String prov = m.group(3); try { if (prov == null) { return SecureRandom.getInstance(alg); } else { return SecureRandom.getInstance(alg, prov); } } catch (NoSuchAlgorithmException | NoSuchProviderException e) { } remainder = m.group(5); } else { remainder = null; } } throw new NoSuchAlgorithmException( "No strong SecureRandom impls available: " + property); } // Declare serialVersionUID to be compatible with JDK1.1 static final long serialVersionUID = 4940670005562187L; // Retain unused values serialized from JDK1.1 /** * @serial */ private byte[] state; /** * @serial */ private MessageDigest digest = null; /** * @serial * * We know that the MessageDigest class does not implement * java.io.Serializable. However, since this field is no longer * used, it will always be NULL and won't affect the serialization * of the SecureRandom class itself. */ private byte[] randomBytes; /** * @serial */ private int randomBytesUsed; /** * @serial */ private long counter; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2815 Content-Disposition: inline; filename="SecureRandomSpi.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "ef6c243363087f9c4713a567a6f48fc3e9341f41" /* * Copyright (c) 1998, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This class defines the Service Provider Interface (SPI) * for the {@code SecureRandom} class. * All the abstract methods in this class must be implemented by each * service provider who wishes to supply the implementation * of a cryptographically strong pseudo-random number generator. * * * @see SecureRandom * @since 1.2 */ public abstract class SecureRandomSpi implements java.io.Serializable { private static final long serialVersionUID = -2991854161009191830L; /** * Reseeds this random object. The given seed supplements, rather than * replaces, the existing seed. Thus, repeated calls are guaranteed * never to reduce randomness. * * @param seed the seed. */ protected abstract void engineSetSeed(byte[] seed); /** * Generates a user-specified number of random bytes. * *

If a call to {@code engineSetSeed} had not occurred previously, * the first call to this method forces this SecureRandom implementation * to seed itself. This self-seeding will not occur if * {@code engineSetSeed} was previously called. * * @param bytes the array to be filled in with random bytes. */ protected abstract void engineNextBytes(byte[] bytes); /** * Returns the given number of seed bytes. This call may be used to * seed other random number generators. * * @param numBytes the number of seed bytes to generate. * * @return the seed bytes. */ protected abstract byte[] engineGenerateSeed(int numBytes); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 44724 Content-Disposition: inline; filename="Security.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "0db09da7061a28e80691a863ad12987167986afe" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.lang.reflect.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.io.*; import java.net.URL; import sun.security.util.Debug; import sun.security.util.PropertyExpander; import sun.security.jca.*; /** *

This class centralizes all security properties and common security * methods. One of its primary uses is to manage providers. * *

The default values of security properties are read from an * implementation-specific location, which is typically the properties file * {@code lib/security/java.security} in the Java installation directory. * * @author Benjamin Renaud */ public final class Security { /* Are we debugging? -- for developers */ private static final Debug sdebug = Debug.getInstance("properties"); /* The java.security properties */ private static Properties props; // An element in the cache private static class ProviderProperty { String className; Provider provider; } static { // doPrivileged here because there are multiple // things in initialize that might require privs. // (the FileInputStream call and the File.exists call, // the securityPropFile call, etc) AccessController.doPrivileged(new PrivilegedAction() { public Void run() { initialize(); return null; } }); } private static void initialize() { props = new Properties(); boolean loadedProps = false; boolean overrideAll = false; // first load the system properties file // to determine the value of security.overridePropertiesFile File propFile = securityPropFile("java.security"); if (propFile.exists()) { InputStream is = null; try { FileInputStream fis = new FileInputStream(propFile); is = new BufferedInputStream(fis); props.load(is); loadedProps = true; if (sdebug != null) { sdebug.println("reading security properties file: " + propFile); } } catch (IOException e) { if (sdebug != null) { sdebug.println("unable to load security properties from " + propFile); e.printStackTrace(); } } finally { if (is != null) { try { is.close(); } catch (IOException ioe) { if (sdebug != null) { sdebug.println("unable to close input stream"); } } } } } if ("true".equalsIgnoreCase(props.getProperty ("security.overridePropertiesFile"))) { String extraPropFile = System.getProperty ("java.security.properties"); if (extraPropFile != null && extraPropFile.startsWith("=")) { overrideAll = true; extraPropFile = extraPropFile.substring(1); } if (overrideAll) { props = new Properties(); if (sdebug != null) { sdebug.println ("overriding other security properties files!"); } } // now load the user-specified file so its values // will win if they conflict with the earlier values if (extraPropFile != null) { BufferedInputStream bis = null; try { URL propURL; extraPropFile = PropertyExpander.expand(extraPropFile); propFile = new File(extraPropFile); if (propFile.exists()) { propURL = new URL ("file:" + propFile.getCanonicalPath()); } else { propURL = new URL(extraPropFile); } bis = new BufferedInputStream(propURL.openStream()); props.load(bis); loadedProps = true; if (sdebug != null) { sdebug.println("reading security properties file: " + propURL); if (overrideAll) { sdebug.println ("overriding other security properties files!"); } } } catch (Exception e) { if (sdebug != null) { sdebug.println ("unable to load security properties from " + extraPropFile); e.printStackTrace(); } } finally { if (bis != null) { try { bis.close(); } catch (IOException ioe) { if (sdebug != null) { sdebug.println("unable to close input stream"); } } } } } } if (!loadedProps) { initializeStatic(); if (sdebug != null) { sdebug.println("unable to load security properties " + "-- using defaults"); } } } /* * Initialize to default values, if /lib/java.security * is not found. */ private static void initializeStatic() { props.put("security.provider.1", "sun.security.provider.Sun"); props.put("security.provider.2", "sun.security.rsa.SunRsaSign"); props.put("security.provider.3", "com.sun.net.ssl.internal.ssl.Provider"); props.put("security.provider.4", "com.sun.crypto.provider.SunJCE"); props.put("security.provider.5", "sun.security.jgss.SunProvider"); props.put("security.provider.6", "com.sun.security.sasl.Provider"); } /** * Don't let anyone instantiate this. */ private Security() { } private static File securityPropFile(String filename) { // maybe check for a system property which will specify where to // look. Someday. String sep = File.separator; return new File(System.getProperty("java.home") + sep + "lib" + sep + "security" + sep + filename); } /** * Looks up providers, and returns the property (and its associated * provider) mapping the key, if any. * The order in which the providers are looked up is the * provider-preference order, as specificed in the security * properties file. */ private static ProviderProperty getProviderProperty(String key) { ProviderProperty entry = null; List providers = Providers.getProviderList().providers(); for (int i = 0; i < providers.size(); i++) { String matchKey = null; Provider prov = providers.get(i); String prop = prov.getProperty(key); if (prop == null) { // Is there a match if we do a case-insensitive property name // comparison? Let's try ... for (Enumeration e = prov.keys(); e.hasMoreElements() && prop == null; ) { matchKey = (String)e.nextElement(); if (key.equalsIgnoreCase(matchKey)) { prop = prov.getProperty(matchKey); break; } } } if (prop != null) { ProviderProperty newEntry = new ProviderProperty(); newEntry.className = prop; newEntry.provider = prov; return newEntry; } } return entry; } /** * Returns the property (if any) mapping the key for the given provider. */ private static String getProviderProperty(String key, Provider provider) { String prop = provider.getProperty(key); if (prop == null) { // Is there a match if we do a case-insensitive property name // comparison? Let's try ... for (Enumeration e = provider.keys(); e.hasMoreElements() && prop == null; ) { String matchKey = (String)e.nextElement(); if (key.equalsIgnoreCase(matchKey)) { prop = provider.getProperty(matchKey); break; } } } return prop; } /** * Gets a specified property for an algorithm. The algorithm name * should be a standard name. See the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * One possible use is by specialized algorithm parsers, which may map * classes to algorithms which they understand (much like Key parsers * do). * * @param algName the algorithm name. * * @param propName the name of the property to get. * * @return the value of the specified property. * * @deprecated This method used to return the value of a proprietary * property in the master file of the "SUN" Cryptographic Service * Provider in order to determine how to parse algorithm-specific * parameters. Use the new provider-based and algorithm-independent * {@code AlgorithmParameters} and {@code KeyFactory} engine * classes (introduced in the J2SE version 1.2 platform) instead. */ @Deprecated public static String getAlgorithmProperty(String algName, String propName) { ProviderProperty entry = getProviderProperty("Alg." + propName + "." + algName); if (entry != null) { return entry.className; } else { return null; } } /** * Adds a new provider, at a specified position. The position is * the preference order in which providers are searched for * requested algorithms. The position is 1-based, that is, * 1 is most preferred, followed by 2, and so on. * *

If the given provider is installed at the requested position, * the provider that used to be at that position, and all providers * with a position greater than {@code position}, are shifted up * one position (towards the end of the list of installed providers). * *

A provider cannot be added if it is already installed. * *

If there is a security manager, the * {@link java.lang.SecurityManager#checkSecurityAccess} method is called * with the {@code "insertProvider"} permission target name to see if * it's ok to add a new provider. If this permission check is denied, * {@code checkSecurityAccess} is called again with the * {@code "insertProvider."+provider.getName()} permission target name. If * both checks are denied, a {@code SecurityException} is thrown. * * @param provider the provider to be added. * * @param position the preference position that the caller would * like for this provider. * * @return the actual preference position in which the provider was * added, or -1 if the provider was not added because it is * already installed. * * @throws NullPointerException if provider is null * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to add a new provider * * @see #getProvider * @see #removeProvider * @see java.security.SecurityPermission */ public static synchronized int insertProviderAt(Provider provider, int position) { String providerName = provider.getName(); checkInsertProvider(providerName); ProviderList list = Providers.getFullProviderList(); ProviderList newList = ProviderList.insertAt(list, provider, position - 1); if (list == newList) { return -1; } Providers.setProviderList(newList); return newList.getIndex(providerName) + 1; } /** * Adds a provider to the next position available. * *

If there is a security manager, the * {@link java.lang.SecurityManager#checkSecurityAccess} method is called * with the {@code "insertProvider"} permission target name to see if * it's ok to add a new provider. If this permission check is denied, * {@code checkSecurityAccess} is called again with the * {@code "insertProvider."+provider.getName()} permission target name. If * both checks are denied, a {@code SecurityException} is thrown. * * @param provider the provider to be added. * * @return the preference position in which the provider was * added, or -1 if the provider was not added because it is * already installed. * * @throws NullPointerException if provider is null * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies access to add a new provider * * @see #getProvider * @see #removeProvider * @see java.security.SecurityPermission */ public static int addProvider(Provider provider) { /* * We can't assign a position here because the statically * registered providers may not have been installed yet. * insertProviderAt() will fix that value after it has * loaded the static providers. */ return insertProviderAt(provider, 0); } /** * Removes the provider with the specified name. * *

When the specified provider is removed, all providers located * at a position greater than where the specified provider was are shifted * down one position (towards the head of the list of installed * providers). * *

This method returns silently if the provider is not installed or * if name is null. * *

First, if there is a security manager, its * {@code checkSecurityAccess} * method is called with the string {@code "removeProvider."+name} * to see if it's ok to remove the provider. * If the default implementation of {@code checkSecurityAccess} * is used (i.e., that method is not overriden), then this will result in * a call to the security manager's {@code checkPermission} method * with a {@code SecurityPermission("removeProvider."+name)} * permission. * * @param name the name of the provider to remove. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkSecurityAccess} method * denies * access to remove the provider * * @see #getProvider * @see #addProvider */ public static synchronized void removeProvider(String name) { check("removeProvider." + name); ProviderList list = Providers.getFullProviderList(); ProviderList newList = ProviderList.remove(list, name); Providers.setProviderList(newList); } /** * Returns an array containing all the installed providers. The order of * the providers in the array is their preference order. * * @return an array of all the installed providers. */ public static Provider[] getProviders() { return Providers.getFullProviderList().toArray(); } /** * Returns the provider installed with the specified name, if * any. Returns null if no provider with the specified name is * installed or if name is null. * * @param name the name of the provider to get. * * @return the provider of the specified name. * * @see #removeProvider * @see #addProvider */ public static Provider getProvider(String name) { return Providers.getProviderList().getProvider(name); } /** * Returns an array containing all installed providers that satisfy the * specified selection criterion, or null if no such providers have been * installed. The returned providers are ordered * according to their * {@linkplain #insertProviderAt(java.security.Provider, int) preference order}. * *

A cryptographic service is always associated with a particular * algorithm or type. For example, a digital signature service is * always associated with a particular algorithm (e.g., DSA), * and a CertificateFactory service is always associated with * a particular certificate type (e.g., X.509). * *

The selection criterion must be specified in one of the following two * formats: *

    *
  • {@literal .} *

    The cryptographic service name must not contain any dots. *

    A * provider satisfies the specified selection criterion iff the provider * implements the * specified algorithm or type for the specified cryptographic service. *

    For example, "CertificateFactory.X.509" * would be satisfied by any provider that supplied * a CertificateFactory implementation for X.509 certificates. *

  • {@literal . * :} *

    The cryptographic service name must not contain any dots. There * must be one or more space characters between the * {@literal } and the * {@literal }. *

    A provider satisfies this selection criterion iff the * provider implements the specified algorithm or type for the specified * cryptographic service and its implementation meets the * constraint expressed by the specified attribute name/value pair. *

    For example, "Signature.SHA1withDSA KeySize:1024" would be * satisfied by any provider that implemented * the SHA1withDSA signature algorithm with a keysize of 1024 (or larger). * *

* *

See the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard cryptographic service names, standard * algorithm names and standard attribute names. * * @param filter the criterion for selecting * providers. The filter is case-insensitive. * * @return all the installed providers that satisfy the selection * criterion, or null if no such providers have been installed. * * @throws InvalidParameterException * if the filter is not in the required format * @throws NullPointerException if filter is null * * @see #getProviders(java.util.Map) * @since 1.3 */ public static Provider[] getProviders(String filter) { String key = null; String value = null; int index = filter.indexOf(':'); if (index == -1) { key = filter; value = ""; } else { key = filter.substring(0, index); value = filter.substring(index + 1); } Hashtable hashtableFilter = new Hashtable<>(1); hashtableFilter.put(key, value); return (getProviders(hashtableFilter)); } /** * Returns an array containing all installed providers that satisfy the * specified* selection criteria, or null if no such providers have been * installed. The returned providers are ordered * according to their * {@linkplain #insertProviderAt(java.security.Provider, int) * preference order}. * *

The selection criteria are represented by a map. * Each map entry represents a selection criterion. * A provider is selected iff it satisfies all selection * criteria. The key for any entry in such a map must be in one of the * following two formats: *

    *
  • {@literal .} *

    The cryptographic service name must not contain any dots. *

    The value associated with the key must be an empty string. *

    A provider * satisfies this selection criterion iff the provider implements the * specified algorithm or type for the specified cryptographic service. *

  • {@literal }. * {@literal } *

    The cryptographic service name must not contain any dots. There * must be one or more space characters between the * {@literal } * and the {@literal }. *

    The value associated with the key must be a non-empty string. * A provider satisfies this selection criterion iff the * provider implements the specified algorithm or type for the specified * cryptographic service and its implementation meets the * constraint expressed by the specified attribute name/value pair. *

* *

See the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard cryptographic service names, standard * algorithm names and standard attribute names. * * @param filter the criteria for selecting * providers. The filter is case-insensitive. * * @return all the installed providers that satisfy the selection * criteria, or null if no such providers have been installed. * * @throws InvalidParameterException * if the filter is not in the required format * @throws NullPointerException if filter is null * * @see #getProviders(java.lang.String) * @since 1.3 */ public static Provider[] getProviders(Map filter) { // Get all installed providers first. // Then only return those providers who satisfy the selection criteria. Provider[] allProviders = Security.getProviders(); Set keySet = filter.keySet(); LinkedHashSet candidates = new LinkedHashSet<>(5); // Returns all installed providers // if the selection criteria is null. if ((keySet == null) || (allProviders == null)) { return allProviders; } boolean firstSearch = true; // For each selection criterion, remove providers // which don't satisfy the criterion from the candidate set. for (Iterator ite = keySet.iterator(); ite.hasNext(); ) { String key = ite.next(); String value = filter.get(key); LinkedHashSet newCandidates = getAllQualifyingCandidates(key, value, allProviders); if (firstSearch) { candidates = newCandidates; firstSearch = false; } if ((newCandidates != null) && !newCandidates.isEmpty()) { // For each provider in the candidates set, if it // isn't in the newCandidate set, we should remove // it from the candidate set. for (Iterator cansIte = candidates.iterator(); cansIte.hasNext(); ) { Provider prov = cansIte.next(); if (!newCandidates.contains(prov)) { cansIte.remove(); } } } else { candidates = null; break; } } if ((candidates == null) || (candidates.isEmpty())) return null; Object[] candidatesArray = candidates.toArray(); Provider[] result = new Provider[candidatesArray.length]; for (int i = 0; i < result.length; i++) { result[i] = (Provider)candidatesArray[i]; } return result; } // Map containing cached Spi Class objects of the specified type private static final Map> spiMap = new ConcurrentHashMap<>(); /** * Return the Class object for the given engine type * (e.g. "MessageDigest"). Works for Spis in the java.security package * only. */ private static Class getSpiClass(String type) { Class clazz = spiMap.get(type); if (clazz != null) { return clazz; } try { clazz = Class.forName("java.security." + type + "Spi"); spiMap.put(type, clazz); return clazz; } catch (ClassNotFoundException e) { throw new AssertionError("Spi class not found", e); } } /* * Returns an array of objects: the first object in the array is * an instance of an implementation of the requested algorithm * and type, and the second object in the array identifies the provider * of that implementation. * The {@code provider} argument can be null, in which case all * configured providers will be searched in order of preference. */ static Object[] getImpl(String algorithm, String type, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { if (provider == null) { return GetInstance.getInstance (type, getSpiClass(type), algorithm).toArray(); } else { return GetInstance.getInstance (type, getSpiClass(type), algorithm, provider).toArray(); } } static Object[] getImpl(String algorithm, String type, String provider, Object params) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { if (provider == null) { return GetInstance.getInstance (type, getSpiClass(type), algorithm, params).toArray(); } else { return GetInstance.getInstance (type, getSpiClass(type), algorithm, params, provider).toArray(); } } /* * Returns an array of objects: the first object in the array is * an instance of an implementation of the requested algorithm * and type, and the second object in the array identifies the provider * of that implementation. * The {@code provider} argument cannot be null. */ static Object[] getImpl(String algorithm, String type, Provider provider) throws NoSuchAlgorithmException { return GetInstance.getInstance (type, getSpiClass(type), algorithm, provider).toArray(); } static Object[] getImpl(String algorithm, String type, Provider provider, Object params) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { return GetInstance.getInstance (type, getSpiClass(type), algorithm, params, provider).toArray(); } /** * Gets a security property value. * *

First, if there is a security manager, its * {@code checkPermission} method is called with a * {@code java.security.SecurityPermission("getProperty."+key)} * permission to see if it's ok to retrieve the specified * security property value.. * * @param key the key of the property being retrieved. * * @return the value of the security property corresponding to key. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkPermission} method * denies * access to retrieve the specified security property value * @throws NullPointerException is key is null * * @see #setProperty * @see java.security.SecurityPermission */ public static String getProperty(String key) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new SecurityPermission("getProperty."+ key)); } String name = props.getProperty(key); if (name != null) name = name.trim(); // could be a class name with trailing ws return name; } /** * Sets a security property value. * *

First, if there is a security manager, its * {@code checkPermission} method is called with a * {@code java.security.SecurityPermission("setProperty."+key)} * permission to see if it's ok to set the specified * security property value. * * @param key the name of the property to be set. * * @param datum the value of the property to be set. * * @throws SecurityException * if a security manager exists and its {@link * java.lang.SecurityManager#checkPermission} method * denies access to set the specified security property value * @throws NullPointerException if key or datum is null * * @see #getProperty * @see java.security.SecurityPermission */ public static void setProperty(String key, String datum) { check("setProperty."+key); props.put(key, datum); invalidateSMCache(key); /* See below. */ } /* * Implementation detail: If the property we just set in * setProperty() was either "package.access" or * "package.definition", we need to signal to the SecurityManager * class that the value has just changed, and that it should * invalidate it's local cache values. * * Rather than create a new API entry for this function, * we use reflection to set a private variable. */ private static void invalidateSMCache(String key) { final boolean pa = key.equals("package.access"); final boolean pd = key.equals("package.definition"); if (pa || pd) { AccessController.doPrivileged(new PrivilegedAction() { public Void run() { try { /* Get the class via the bootstrap class loader. */ Class cl = Class.forName( "java.lang.SecurityManager", false, null); Field f = null; boolean accessible = false; if (pa) { f = cl.getDeclaredField("packageAccessValid"); accessible = f.isAccessible(); f.setAccessible(true); } else { f = cl.getDeclaredField("packageDefinitionValid"); accessible = f.isAccessible(); f.setAccessible(true); } f.setBoolean(f, false); f.setAccessible(accessible); } catch (Exception e1) { /* If we couldn't get the class, it hasn't * been loaded yet. If there is no such * field, we shouldn't try to set it. There * shouldn't be a security execption, as we * are loaded by boot class loader, and we * are inside a doPrivileged() here. * * NOOP: don't do anything... */ } return null; } /* run */ }); /* PrivilegedAction */ } /* if */ } private static void check(String directive) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkSecurityAccess(directive); } } private static void checkInsertProvider(String name) { SecurityManager security = System.getSecurityManager(); if (security != null) { try { security.checkSecurityAccess("insertProvider"); } catch (SecurityException se1) { try { security.checkSecurityAccess("insertProvider." + name); } catch (SecurityException se2) { // throw first exception, but add second to suppressed se1.addSuppressed(se2); throw se1; } } } } /* * Returns all providers who satisfy the specified * criterion. */ private static LinkedHashSet getAllQualifyingCandidates( String filterKey, String filterValue, Provider[] allProviders) { String[] filterComponents = getFilterComponents(filterKey, filterValue); // The first component is the service name. // The second is the algorithm name. // If the third isn't null, that is the attrinute name. String serviceName = filterComponents[0]; String algName = filterComponents[1]; String attrName = filterComponents[2]; return getProvidersNotUsingCache(serviceName, algName, attrName, filterValue, allProviders); } private static LinkedHashSet getProvidersNotUsingCache( String serviceName, String algName, String attrName, String filterValue, Provider[] allProviders) { LinkedHashSet candidates = new LinkedHashSet<>(5); for (int i = 0; i < allProviders.length; i++) { if (isCriterionSatisfied(allProviders[i], serviceName, algName, attrName, filterValue)) { candidates.add(allProviders[i]); } } return candidates; } /* * Returns true if the given provider satisfies * the selection criterion key:value. */ private static boolean isCriterionSatisfied(Provider prov, String serviceName, String algName, String attrName, String filterValue) { String key = serviceName + '.' + algName; if (attrName != null) { key += ' ' + attrName; } // Check whether the provider has a property // whose key is the same as the given key. String propValue = getProviderProperty(key, prov); if (propValue == null) { // Check whether we have an alias instead // of a standard name in the key. String standardName = getProviderProperty("Alg.Alias." + serviceName + "." + algName, prov); if (standardName != null) { key = serviceName + "." + standardName; if (attrName != null) { key += ' ' + attrName; } propValue = getProviderProperty(key, prov); } if (propValue == null) { // The provider doesn't have the given // key in its property list. return false; } } // If the key is in the format of: // ., // there is no need to check the value. if (attrName == null) { return true; } // If we get here, the key must be in the // format of . . if (isStandardAttr(attrName)) { return isConstraintSatisfied(attrName, filterValue, propValue); } else { return filterValue.equalsIgnoreCase(propValue); } } /* * Returns true if the attribute is a standard attribute; * otherwise, returns false. */ private static boolean isStandardAttr(String attribute) { // For now, we just have two standard attributes: // KeySize and ImplementedIn. if (attribute.equalsIgnoreCase("KeySize")) return true; if (attribute.equalsIgnoreCase("ImplementedIn")) return true; return false; } /* * Returns true if the requested attribute value is supported; * otherwise, returns false. */ private static boolean isConstraintSatisfied(String attribute, String value, String prop) { // For KeySize, prop is the max key size the // provider supports for a specific .. if (attribute.equalsIgnoreCase("KeySize")) { int requestedSize = Integer.parseInt(value); int maxSize = Integer.parseInt(prop); if (requestedSize <= maxSize) { return true; } else { return false; } } // For Type, prop is the type of the implementation // for a specific .. if (attribute.equalsIgnoreCase("ImplementedIn")) { return value.equalsIgnoreCase(prop); } return false; } static String[] getFilterComponents(String filterKey, String filterValue) { int algIndex = filterKey.indexOf('.'); if (algIndex < 0) { // There must be a dot in the filter, and the dot // shouldn't be at the beginning of this string. throw new InvalidParameterException("Invalid filter"); } String serviceName = filterKey.substring(0, algIndex); String algName = null; String attrName = null; if (filterValue.length() == 0) { // The filterValue is an empty string. So the filterKey // should be in the format of .. algName = filterKey.substring(algIndex + 1).trim(); if (algName.length() == 0) { // There must be a algorithm or type name. throw new InvalidParameterException("Invalid filter"); } } else { // The filterValue is a non-empty string. So the filterKey must be // in the format of // . int attrIndex = filterKey.indexOf(' '); if (attrIndex == -1) { // There is no attribute name in the filter. throw new InvalidParameterException("Invalid filter"); } else { attrName = filterKey.substring(attrIndex + 1).trim(); if (attrName.length() == 0) { // There is no attribute name in the filter. throw new InvalidParameterException("Invalid filter"); } } // There must be an algorithm name in the filter. if ((attrIndex < algIndex) || (algIndex == attrIndex - 1)) { throw new InvalidParameterException("Invalid filter"); } else { algName = filterKey.substring(algIndex + 1, attrIndex); } } String[] result = new String[3]; result[0] = serviceName; result[1] = algName; result[2] = attrName; return result; } /** * Returns a Set of Strings containing the names of all available * algorithms or types for the specified Java cryptographic service * (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore). Returns * an empty Set if there is no provider that supports the * specified service or if serviceName is null. For a complete list * of Java cryptographic services, please see the * Java * Cryptography Architecture API Specification & Reference. * Note: the returned set is immutable. * * @param serviceName the name of the Java cryptographic * service (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore). * Note: this parameter is case-insensitive. * * @return a Set of Strings containing the names of all available * algorithms or types for the specified Java cryptographic service * or an empty set if no provider supports the specified service. * * @since 1.4 **/ public static Set getAlgorithms(String serviceName) { if ((serviceName == null) || (serviceName.length() == 0) || (serviceName.endsWith("."))) { return Collections.emptySet(); } HashSet result = new HashSet<>(); Provider[] providers = Security.getProviders(); for (int i = 0; i < providers.length; i++) { // Check the keys for each provider. for (Enumeration e = providers[i].keys(); e.hasMoreElements(); ) { String currentKey = ((String)e.nextElement()).toUpperCase(Locale.ENGLISH); if (currentKey.startsWith( serviceName.toUpperCase(Locale.ENGLISH))) { // We should skip the currentKey if it contains a // whitespace. The reason is: such an entry in the // provider property contains attributes for the // implementation of an algorithm. We are only interested // in entries which lead to the implementation // classes. if (currentKey.indexOf(" ") < 0) { result.add(currentKey.substring( serviceName.length() + 1)); } } } } return Collections.unmodifiableSet(result); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 14634 Content-Disposition: inline; filename="SecurityPermission.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "5bb74569d3fe88b962ac5f1a7e0a112bc99726c9" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.security.*; import java.util.Enumeration; import java.util.Hashtable; import java.util.StringTokenizer; /** * This class is for security permissions. * A SecurityPermission contains a name (also referred to as a "target name") * but no actions list; you either have the named permission * or you don't. *

* The target name is the name of a security configuration parameter (see below). * Currently the SecurityPermission object is used to guard access * to the Policy, Security, Provider, Signer, and Identity * objects. *

* The following table lists all the possible SecurityPermission target names, * and for each provides a description of what the permission allows * and a discussion of the risks of granting code the permission. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Permission Target NameWhat the Permission AllowsRisks of Allowing this Permission
createAccessControlContextCreation of an AccessControlContextThis allows someone to instantiate an AccessControlContext * with a {@code DomainCombiner}. Extreme care must be taken when * granting this permission. Malicious code could create a DomainCombiner * that augments the set of permissions granted to code, and even grant the * code {@link java.security.AllPermission}.
getDomainCombinerRetrieval of an AccessControlContext's DomainCombinerThis allows someone to retrieve an AccessControlContext's * {@code DomainCombiner}. Since DomainCombiners may contain * sensitive information, this could potentially lead to a privacy leak.
getPolicyRetrieval of the system-wide security policy (specifically, of the * currently-installed Policy object)This allows someone to query the policy via the * {@code getPermissions} call, * which discloses which permissions would be granted to a given CodeSource. * While revealing the policy does not compromise the security of * the system, it does provide malicious code with additional information * which it may use to better aim an attack. It is wise * not to divulge more information than necessary.
setPolicySetting of the system-wide security policy (specifically, * the Policy object)Granting this permission is extremely dangerous, as malicious * code may grant itself all the necessary permissions it needs * to successfully mount an attack on the system.
createPolicy.{policy type}Getting an instance of a Policy implementation from a providerGranting this permission enables code to obtain a Policy object. * Malicious code may query the Policy object to determine what permissions * have been granted to code other than itself.
getProperty.{key}Retrieval of the security property with the specified keyDepending on the particular key for which access has * been granted, the code may have access to the list of security * providers, as well as the location of the system-wide and user * security policies. while revealing this information does not * compromise the security of the system, it does provide malicious * code with additional information which it may use to better aim * an attack.
setProperty.{key}Setting of the security property with the specified keyThis could include setting a security provider or defining * the location of the system-wide security policy. Malicious * code that has permission to set a new security provider may * set a rogue provider that steals confidential information such * as cryptographic private keys. In addition, malicious code with * permission to set the location of the system-wide security policy * may point it to a security policy that grants the attacker * all the necessary permissions it requires to successfully mount * an attack on the system.
insertProviderAddition of a new providerThis would allow somebody to introduce a possibly * malicious provider (e.g., one that discloses the private keys passed * to it) as the highest-priority provider. This would be possible * because the Security object (which manages the installed providers) * currently does not check the integrity or authenticity of a provider * before attaching it. The "insertProvider" permission subsumes the * "insertProvider.{provider name}" permission (see the section below for * more information). *
removeProvider.{provider name}Removal of the specified providerThis may change the behavior or disable execution of other * parts of the program. If a provider subsequently requested by the * program has been removed, execution may fail. Also, if the removed * provider is not explicitly requested by the rest of the program, but * it would normally be the provider chosen when a cryptography service * is requested (due to its previous order in the list of providers), * a different provider will be chosen instead, or no suitable provider * will be found, thereby resulting in program failure.
clearProviderProperties.{provider name}"Clearing" of a Provider so that it no longer contains the properties * used to look up services implemented by the providerThis disables the lookup of services implemented by the provider. * This may thus change the behavior or disable execution of other * parts of the program that would normally utilize the Provider, as * described under the "removeProvider.{provider name}" permission.
putProviderProperty.{provider name}Setting of properties for the specified ProviderThe provider properties each specify the name and location * of a particular service implemented by the provider. By granting * this permission, you let code replace the service specification * with another one, thereby specifying a different implementation.
removeProviderProperty.{provider name}Removal of properties from the specified ProviderThis disables the lookup of services implemented by the * provider. They are no longer accessible due to removal of the properties * specifying their names and locations. This * may change the behavior or disable execution of other * parts of the program that would normally utilize the Provider, as * described under the "removeProvider.{provider name}" permission.
* *

* The following permissions have been superseded by newer permissions or are * associated with classes that have been deprecated: {@link Identity}, * {@link IdentityScope}, {@link Signer}. Use of them is discouraged. See the * applicable classes for more information. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Permission Target NameWhat the Permission AllowsRisks of Allowing this Permission
insertProvider.{provider name}Addition of a new provider, with the specified nameUse of this permission is discouraged from further use because it is * possible to circumvent the name restrictions by overriding the * {@link java.security.Provider#getName} method. Also, there is an equivalent * level of risk associated with granting code permission to insert a provider * with a specific name, or any name it chooses. Users should use the * "insertProvider" permission instead. *

This would allow somebody to introduce a possibly * malicious provider (e.g., one that discloses the private keys passed * to it) as the highest-priority provider. This would be possible * because the Security object (which manages the installed providers) * currently does not check the integrity or authenticity of a provider * before attaching it.

setSystemScopeSetting of the system identity scopeThis would allow an attacker to configure the system identity scope with * certificates that should not be trusted, thereby granting applet or * application code signed with those certificates privileges that * would have been denied by the system's original identity scope.
setIdentityPublicKeySetting of the public key for an IdentityIf the identity is marked as "trusted", this allows an attacker to * introduce a different public key (e.g., its own) that is not trusted * by the system's identity scope, thereby granting applet or * application code signed with that public key privileges that * would have been denied otherwise.
setIdentityInfoSetting of a general information string for an IdentityThis allows attackers to set the general description for * an identity. This may trick applications into using a different * identity than intended or may prevent applications from finding a * particular identity.
addIdentityCertificateAddition of a certificate for an IdentityThis allows attackers to set a certificate for * an identity's public key. This is dangerous because it affects * the trust relationship across the system. This public key suddenly * becomes trusted to a wider audience than it otherwise would be.
removeIdentityCertificateRemoval of a certificate for an IdentityThis allows attackers to remove a certificate for * an identity's public key. This is dangerous because it affects * the trust relationship across the system. This public key suddenly * becomes considered less trustworthy than it otherwise would be.
printIdentityViewing the name of a principal * and optionally the scope in which it is used, and whether * or not it is considered "trusted" in that scopeThe scope that is printed out may be a filename, in which case * it may convey local system information. For example, here's a sample * printout of an identity named "carol", who is * marked not trusted in the user's identity database:
* carol[/home/luehe/identitydb.obj][not trusted]
getSignerPrivateKeyRetrieval of a Signer's private keyIt is very dangerous to allow access to a private key; private * keys are supposed to be kept secret. Otherwise, code can use the * private key to sign various files and claim the signature came from * the Signer.
setSignerKeyPairSetting of the key pair (public key and private key) for a SignerThis would allow an attacker to replace somebody else's (the "target's") * keypair with a possibly weaker keypair (e.g., a keypair of a smaller * keysize). This also would allow the attacker to listen in on encrypted * communication between the target and its peers. The target's peers * might wrap an encryption session key under the target's "new" public * key, which would allow the attacker (who possesses the corresponding * private key) to unwrap the session key and decipher the communication * data encrypted under that session key.
* * @see java.security.BasicPermission * @see java.security.Permission * @see java.security.Permissions * @see java.security.PermissionCollection * @see java.lang.SecurityManager * * * @author Marianne Mueller * @author Roland Schemers */ public final class SecurityPermission extends BasicPermission { private static final long serialVersionUID = 5236109936224050470L; /** * Creates a new SecurityPermission with the specified name. * The name is the symbolic name of the SecurityPermission. An asterisk * may appear at the end of the name, following a ".", or by itself, to * signify a wildcard match. * * @param name the name of the SecurityPermission * * @throws NullPointerException if {@code name} is {@code null}. * @throws IllegalArgumentException if {@code name} is empty. */ public SecurityPermission(String name) { super(name); } /** * Creates a new SecurityPermission object with the specified name. * The name is the symbolic name of the SecurityPermission, and the * actions String is currently unused and should be null. * * @param name the name of the SecurityPermission * @param actions should be null. * * @throws NullPointerException if {@code name} is {@code null}. * @throws IllegalArgumentException if {@code name} is empty. */ public SecurityPermission(String name, String actions) { super(name, actions); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 51343 Content-Disposition: inline; filename="Signature.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "5232b9c469869344567ae6b5c8b52c8c8c0ccfa2" /* * Copyright (c) 1996, 2017, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.security.spec.AlgorithmParameterSpec; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.io.*; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.nio.ByteBuffer; import java.security.Provider.Service; import javax.crypto.Cipher; import javax.crypto.CipherSpi; import javax.crypto.IllegalBlockSizeException; import javax.crypto.BadPaddingException; import javax.crypto.NoSuchPaddingException; import sun.security.util.Debug; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; /** * The Signature class is used to provide applications the functionality * of a digital signature algorithm. Digital signatures are used for * authentication and integrity assurance of digital data. * *

The signature algorithm can be, among others, the NIST standard * DSA, using DSA and SHA-256. The DSA algorithm using the * SHA-256 message digest algorithm can be specified as {@code SHA256withDSA}. * In the case of RSA the signing algorithm could be specified as, for example, * {@code SHA256withRSA}. * The algorithm name must be specified, as there is no default. * *

A Signature object can be used to generate and verify digital * signatures. * *

There are three phases to the use of a Signature object for * either signing data or verifying a signature:

    * *
  1. Initialization, with either * *
      * *
    • a public key, which initializes the signature for * verification (see {@link #initVerify(PublicKey) initVerify}), or * *
    • a private key (and optionally a Secure Random Number Generator), * which initializes the signature for signing * (see {@link #initSign(PrivateKey)} * and {@link #initSign(PrivateKey, SecureRandom)}). * *
    * *
  2. Updating * *

    Depending on the type of initialization, this will update the * bytes to be signed or verified. See the * {@link #update(byte) update} methods. * *

  3. Signing or Verifying a signature on all updated bytes. See the * {@link #sign() sign} methods and the {@link #verify(byte[]) verify} * method. * *
* *

Note that this class is abstract and extends from * {@code SignatureSpi} for historical reasons. * Application developers should only take notice of the methods defined in * this {@code Signature} class; all the methods in * the superclass are intended for cryptographic service providers who wish to * supply their own implementations of digital signature algorithms. * *

Every implementation of the Java platform is required to support the * following standard {@code Signature} algorithms: *

    *
  • {@code SHA1withDSA}
  • *
  • {@code SHA1withRSA}
  • *
  • {@code SHA256withRSA}
  • *
* These algorithms are described in the * Signature section of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * Consult the release documentation for your implementation to see if any * other algorithms are supported. * * @author Benjamin Renaud * */ public abstract class Signature extends SignatureSpi { private static final Debug debug = Debug.getInstance("jca", "Signature"); private static final Debug pdebug = Debug.getInstance("provider", "Provider"); private static final boolean skipDebug = Debug.isOn("engine=") && !Debug.isOn("signature"); /* * The algorithm for this signature object. * This value is used to map an OID to the particular algorithm. * The mapping is done in AlgorithmObject.algOID(String algorithm) */ private String algorithm; // The provider Provider provider; /** * Possible {@link #state} value, signifying that * this signature object has not yet been initialized. */ protected final static int UNINITIALIZED = 0; /** * Possible {@link #state} value, signifying that * this signature object has been initialized for signing. */ protected final static int SIGN = 2; /** * Possible {@link #state} value, signifying that * this signature object has been initialized for verification. */ protected final static int VERIFY = 3; /** * Current state of this signature object. */ protected int state = UNINITIALIZED; /** * Creates a Signature object for the specified algorithm. * * @param algorithm the standard string name of the algorithm. * See the Signature section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. */ protected Signature(String algorithm) { this.algorithm = algorithm; } // name of the special signature alg private final static String RSA_SIGNATURE = "NONEwithRSA"; // name of the equivalent cipher alg private final static String RSA_CIPHER = "RSA/ECB/PKCS1Padding"; // all the services we need to lookup for compatibility with Cipher private final static List rsaIds = Arrays.asList( new ServiceId[] { new ServiceId("Signature", "NONEwithRSA"), new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"), new ServiceId("Cipher", "RSA/ECB"), new ServiceId("Cipher", "RSA//PKCS1Padding"), new ServiceId("Cipher", "RSA"), } ); /** * Returns a Signature object that implements the specified signature * algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new Signature object encapsulating the * SignatureSpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the algorithm requested. * See the Signature section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the new Signature object. * * @exception NoSuchAlgorithmException if no Provider supports a * Signature implementation for the * specified algorithm. * * @see Provider */ public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException { List list; if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { list = GetInstance.getServices(rsaIds); } else { list = GetInstance.getServices("Signature", algorithm); } Iterator t = list.iterator(); if (t.hasNext() == false) { throw new NoSuchAlgorithmException (algorithm + " Signature not available"); } // try services until we find an Spi or a working Signature subclass NoSuchAlgorithmException failure; do { Service s = t.next(); if (isSpi(s)) { return new Delegate(s, t, algorithm); } else { // must be a subclass of Signature, disable dynamic selection try { Instance instance = GetInstance.getInstance(s, SignatureSpi.class); return getInstance(instance, algorithm); } catch (NoSuchAlgorithmException e) { failure = e; } } } while (t.hasNext()); throw failure; } private static Signature getInstance(Instance instance, String algorithm) { Signature sig; if (instance.impl instanceof Signature) { sig = (Signature)instance.impl; sig.algorithm = algorithm; } else { SignatureSpi spi = (SignatureSpi)instance.impl; sig = new Delegate(spi, algorithm); } sig.provider = instance.provider; return sig; } private final static Map signatureInfo; static { signatureInfo = new ConcurrentHashMap(); Boolean TRUE = Boolean.TRUE; // pre-initialize with values for our SignatureSpi implementations signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE); signatureInfo.put("sun.security.provider.DSA$SHA1withDSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA256withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA384withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA512withRSA", TRUE); signatureInfo.put("com.sun.net.ssl.internal.ssl.RSASignature", TRUE); signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE); } private static boolean isSpi(Service s) { if (s.getType().equals("Cipher")) { // must be a CipherSpi, which we can wrap with the CipherAdapter return true; } String className = s.getClassName(); Boolean result = signatureInfo.get(className); if (result == null) { try { Object instance = s.newInstance(null); // Signature extends SignatureSpi // so it is a "real" Spi if it is an // instance of SignatureSpi but not Signature boolean r = (instance instanceof SignatureSpi) && (instance instanceof Signature == false); if ((debug != null) && (r == false)) { debug.println("Not a SignatureSpi " + className); debug.println("Delayed provider selection may not be " + "available for algorithm " + s.getAlgorithm()); } result = Boolean.valueOf(r); signatureInfo.put(className, result); } catch (Exception e) { // something is wrong, assume not an SPI return false; } } return result.booleanValue(); } /** * Returns a Signature object that implements the specified signature * algorithm. * *

A new Signature object encapsulating the * SignatureSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm requested. * See the Signature section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the name of the provider. * * @return the new Signature object. * * @exception NoSuchAlgorithmException if a SignatureSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider name is null * or empty. * * @see Provider */ public static Signature getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { // exception compatibility with existing code if ((provider == null) || (provider.length() == 0)) { throw new IllegalArgumentException("missing provider"); } Provider p = Security.getProvider(provider); if (p == null) { throw new NoSuchProviderException ("no such provider: " + provider); } return getInstanceRSA(p); } Instance instance = GetInstance.getInstance ("Signature", SignatureSpi.class, algorithm, provider); return getInstance(instance, algorithm); } /** * Returns a Signature object that implements the specified * signature algorithm. * *

A new Signature object encapsulating the * SignatureSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the name of the algorithm requested. * See the Signature section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the provider. * * @return the new Signature object. * * @exception NoSuchAlgorithmException if a SignatureSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the provider is null. * * @see Provider * * @since 1.4 */ public static Signature getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { // exception compatibility with existing code if (provider == null) { throw new IllegalArgumentException("missing provider"); } return getInstanceRSA(provider); } Instance instance = GetInstance.getInstance ("Signature", SignatureSpi.class, algorithm, provider); return getInstance(instance, algorithm); } // return an implementation for NONEwithRSA, which is a special case // because of the Cipher.RSA/ECB/PKCS1Padding compatibility wrapper private static Signature getInstanceRSA(Provider p) throws NoSuchAlgorithmException { // try Signature first Service s = p.getService("Signature", RSA_SIGNATURE); if (s != null) { Instance instance = GetInstance.getInstance(s, SignatureSpi.class); return getInstance(instance, RSA_SIGNATURE); } // check Cipher try { Cipher c = Cipher.getInstance(RSA_CIPHER, p); return new Delegate(new CipherAdapter(c), RSA_SIGNATURE); } catch (GeneralSecurityException e) { // throw Signature style exception message to avoid confusion, // but append Cipher exception as cause throw new NoSuchAlgorithmException("no such algorithm: " + RSA_SIGNATURE + " for provider " + p.getName(), e); } } /** * Returns the provider of this signature object. * * @return the provider of this signature object */ public final Provider getProvider() { chooseFirstProvider(); return this.provider; } private String getProviderName() { return (provider == null) ? "(no provider)" : provider.getName(); } void chooseFirstProvider() { // empty, overridden in Delegate } /** * Initializes this object for verification. If this method is called * again with a different argument, it negates the effect * of this call. * * @param publicKey the public key of the identity whose signature is * going to be verified. * * @exception InvalidKeyException if the key is invalid. */ public final void initVerify(PublicKey publicKey) throws InvalidKeyException { engineInitVerify(publicKey); state = VERIFY; if (!skipDebug && pdebug != null) { pdebug.println("Signature." + algorithm + " verification algorithm from: " + getProviderName()); } } /** * Initializes this object for verification, using the public key from * the given certificate. *

If the certificate is of type X.509 and has a key usage * extension field marked as critical, and the value of the key usage * extension field implies that the public key in * the certificate and its corresponding private key are not * supposed to be used for digital signatures, an * {@code InvalidKeyException} is thrown. * * @param certificate the certificate of the identity whose signature is * going to be verified. * * @exception InvalidKeyException if the public key in the certificate * is not encoded properly or does not include required parameter * information or cannot be used for digital signature purposes. * @since 1.3 */ public final void initVerify(Certificate certificate) throws InvalidKeyException { // If the certificate is of type X509Certificate, // we should check whether it has a Key Usage // extension marked as critical. if (certificate instanceof java.security.cert.X509Certificate) { // Check whether the cert has a key usage extension // marked as a critical extension. // The OID for KeyUsage extension is 2.5.29.15. X509Certificate cert = (X509Certificate)certificate; Set critSet = cert.getCriticalExtensionOIDs(); if (critSet != null && !critSet.isEmpty() && critSet.contains("2.5.29.15")) { boolean[] keyUsageInfo = cert.getKeyUsage(); // keyUsageInfo[0] is for digitalSignature. if ((keyUsageInfo != null) && (keyUsageInfo[0] == false)) throw new InvalidKeyException("Wrong key usage"); } } PublicKey publicKey = certificate.getPublicKey(); engineInitVerify(publicKey); state = VERIFY; if (!skipDebug && pdebug != null) { pdebug.println("Signature." + algorithm + " verification algorithm from: " + getProviderName()); } } /** * Initialize this object for signing. If this method is called * again with a different argument, it negates the effect * of this call. * * @param privateKey the private key of the identity whose signature * is going to be generated. * * @exception InvalidKeyException if the key is invalid. */ public final void initSign(PrivateKey privateKey) throws InvalidKeyException { engineInitSign(privateKey); state = SIGN; if (!skipDebug && pdebug != null) { pdebug.println("Signature." + algorithm + " signing algorithm from: " + getProviderName()); } } /** * Initialize this object for signing. If this method is called * again with a different argument, it negates the effect * of this call. * * @param privateKey the private key of the identity whose signature * is going to be generated. * * @param random the source of randomness for this signature. * * @exception InvalidKeyException if the key is invalid. */ public final void initSign(PrivateKey privateKey, SecureRandom random) throws InvalidKeyException { engineInitSign(privateKey, random); state = SIGN; if (!skipDebug && pdebug != null) { pdebug.println("Signature." + algorithm + " signing algorithm from: " + getProviderName()); } } /** * Returns the signature bytes of all the data updated. * The format of the signature depends on the underlying * signature scheme. * *

A call to this method resets this signature object to the state * it was in when previously initialized for signing via a * call to {@code initSign(PrivateKey)}. That is, the object is * reset and available to generate another signature from the same * signer, if desired, via new calls to {@code update} and * {@code sign}. * * @return the signature bytes of the signing operation's result. * * @exception SignatureException if this signature object is not * initialized properly or if this signature algorithm is unable to * process the input data provided. */ public final byte[] sign() throws SignatureException { if (state == SIGN) { return engineSign(); } throw new SignatureException("object not initialized for " + "signing"); } /** * Finishes the signature operation and stores the resulting signature * bytes in the provided buffer {@code outbuf}, starting at * {@code offset}. * The format of the signature depends on the underlying * signature scheme. * *

This signature object is reset to its initial state (the state it * was in after a call to one of the {@code initSign} methods) and * can be reused to generate further signatures with the same private key. * * @param outbuf buffer for the signature result. * * @param offset offset into {@code outbuf} where the signature is * stored. * * @param len number of bytes within {@code outbuf} allotted for the * signature. * * @return the number of bytes placed into {@code outbuf}. * * @exception SignatureException if this signature object is not * initialized properly, if this signature algorithm is unable to * process the input data provided, or if {@code len} is less * than the actual signature length. * * @since 1.2 */ public final int sign(byte[] outbuf, int offset, int len) throws SignatureException { if (outbuf == null) { throw new IllegalArgumentException("No output buffer given"); } if (offset < 0 || len < 0) { throw new IllegalArgumentException("offset or len is less than 0"); } if (outbuf.length - offset < len) { throw new IllegalArgumentException ("Output buffer too small for specified offset and length"); } if (state != SIGN) { throw new SignatureException("object not initialized for " + "signing"); } return engineSign(outbuf, offset, len); } /** * Verifies the passed-in signature. * *

A call to this method resets this signature object to the state * it was in when previously initialized for verification via a * call to {@code initVerify(PublicKey)}. That is, the object is * reset and available to verify another signature from the identity * whose public key was specified in the call to {@code initVerify}. * * @param signature the signature bytes to be verified. * * @return true if the signature was verified, false if not. * * @exception SignatureException if this signature object is not * initialized properly, the passed-in signature is improperly * encoded or of the wrong type, if this signature algorithm is unable to * process the input data provided, etc. */ public final boolean verify(byte[] signature) throws SignatureException { if (state == VERIFY) { return engineVerify(signature); } throw new SignatureException("object not initialized for " + "verification"); } /** * Verifies the passed-in signature in the specified array * of bytes, starting at the specified offset. * *

A call to this method resets this signature object to the state * it was in when previously initialized for verification via a * call to {@code initVerify(PublicKey)}. That is, the object is * reset and available to verify another signature from the identity * whose public key was specified in the call to {@code initVerify}. * * * @param signature the signature bytes to be verified. * @param offset the offset to start from in the array of bytes. * @param length the number of bytes to use, starting at offset. * * @return true if the signature was verified, false if not. * * @exception SignatureException if this signature object is not * initialized properly, the passed-in signature is improperly * encoded or of the wrong type, if this signature algorithm is unable to * process the input data provided, etc. * @exception IllegalArgumentException if the {@code signature} * byte array is null, or the {@code offset} or {@code length} * is less than 0, or the sum of the {@code offset} and * {@code length} is greater than the length of the * {@code signature} byte array. * @since 1.4 */ public final boolean verify(byte[] signature, int offset, int length) throws SignatureException { if (state == VERIFY) { if (signature == null) { throw new IllegalArgumentException("signature is null"); } if (offset < 0 || length < 0) { throw new IllegalArgumentException ("offset or length is less than 0"); } if (signature.length - offset < length) { throw new IllegalArgumentException ("signature too small for specified offset and length"); } return engineVerify(signature, offset, length); } throw new SignatureException("object not initialized for " + "verification"); } /** * Updates the data to be signed or verified by a byte. * * @param b the byte to use for the update. * * @exception SignatureException if this signature object is not * initialized properly. */ public final void update(byte b) throws SignatureException { if (state == VERIFY || state == SIGN) { engineUpdate(b); } else { throw new SignatureException("object not initialized for " + "signature or verification"); } } /** * Updates the data to be signed or verified, using the specified * array of bytes. * * @param data the byte array to use for the update. * * @exception SignatureException if this signature object is not * initialized properly. */ public final void update(byte[] data) throws SignatureException { update(data, 0, data.length); } /** * Updates the data to be signed or verified, using the specified * array of bytes, starting at the specified offset. * * @param data the array of bytes. * @param off the offset to start from in the array of bytes. * @param len the number of bytes to use, starting at offset. * * @exception SignatureException if this signature object is not * initialized properly. */ public final void update(byte[] data, int off, int len) throws SignatureException { if (state == SIGN || state == VERIFY) { if (data == null) { throw new IllegalArgumentException("data is null"); } if (off < 0 || len < 0) { throw new IllegalArgumentException("off or len is less than 0"); } if (data.length - off < len) { throw new IllegalArgumentException ("data too small for specified offset and length"); } engineUpdate(data, off, len); } else { throw new SignatureException("object not initialized for " + "signature or verification"); } } /** * Updates the data to be signed or verified using the specified * ByteBuffer. Processes the {@code data.remaining()} bytes * starting at at {@code data.position()}. * Upon return, the buffer's position will be equal to its limit; * its limit will not have changed. * * @param data the ByteBuffer * * @exception SignatureException if this signature object is not * initialized properly. * @since 1.5 */ public final void update(ByteBuffer data) throws SignatureException { if ((state != SIGN) && (state != VERIFY)) { throw new SignatureException("object not initialized for " + "signature or verification"); } if (data == null) { throw new NullPointerException(); } engineUpdate(data); } /** * Returns the name of the algorithm for this signature object. * * @return the name of the algorithm for this signature object. */ public final String getAlgorithm() { return this.algorithm; } /** * Returns a string representation of this signature object, * providing information that includes the state of the object * and the name of the algorithm used. * * @return a string representation of this signature object. */ public String toString() { String initState = ""; switch (state) { case UNINITIALIZED: initState = ""; break; case VERIFY: initState = ""; break; case SIGN: initState = ""; break; } return "Signature object: " + getAlgorithm() + initState; } /** * Sets the specified algorithm parameter to the specified value. * This method supplies a general-purpose mechanism through * which it is possible to set the various parameters of this object. * A parameter may be any settable parameter for the algorithm, such as * a parameter size, or a source of random bits for signature generation * (if appropriate), or an indication of whether or not to perform * a specific but optional computation. A uniform algorithm-specific * naming scheme for each parameter is desirable but left unspecified * at this time. * * @param param the string identifier of the parameter. * @param value the parameter value. * * @exception InvalidParameterException if {@code param} is an * invalid parameter for this signature algorithm engine, * the parameter is already set * and cannot be set again, a security exception occurs, and so on. * * @see #getParameter * * @deprecated Use * {@link #setParameter(java.security.spec.AlgorithmParameterSpec) * setParameter}. */ @Deprecated public final void setParameter(String param, Object value) throws InvalidParameterException { engineSetParameter(param, value); } /** * Initializes this signature engine with the specified parameter set. * * @param params the parameters * * @exception InvalidAlgorithmParameterException if the given parameters * are inappropriate for this signature engine * * @see #getParameters */ public final void setParameter(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { engineSetParameter(params); } /** * Returns the parameters used with this signature object. * *

The returned parameters may be the same that were used to initialize * this signature, or may contain a combination of default and randomly * generated parameter values used by the underlying signature * implementation if this signature requires algorithm parameters but * was not initialized with any. * * @return the parameters used with this signature, or null if this * signature does not use any parameters. * * @see #setParameter(AlgorithmParameterSpec) * @since 1.4 */ public final AlgorithmParameters getParameters() { return engineGetParameters(); } /** * Gets the value of the specified algorithm parameter. This method * supplies a general-purpose mechanism through which it is possible to * get the various parameters of this object. A parameter may be any * settable parameter for the algorithm, such as a parameter size, or * a source of random bits for signature generation (if appropriate), * or an indication of whether or not to perform a specific but optional * computation. A uniform algorithm-specific naming scheme for each * parameter is desirable but left unspecified at this time. * * @param param the string name of the parameter. * * @return the object that represents the parameter value, or null if * there is none. * * @exception InvalidParameterException if {@code param} is an invalid * parameter for this engine, or another exception occurs while * trying to get this parameter. * * @see #setParameter(String, Object) * * @deprecated */ @Deprecated public final Object getParameter(String param) throws InvalidParameterException { return engineGetParameter(param); } /** * Returns a clone if the implementation is cloneable. * * @return a clone if the implementation is cloneable. * * @exception CloneNotSupportedException if this is called * on an implementation that does not support {@code Cloneable}. */ public Object clone() throws CloneNotSupportedException { if (this instanceof Cloneable) { return super.clone(); } else { throw new CloneNotSupportedException(); } } /* * The following class allows providers to extend from SignatureSpi * rather than from Signature. It represents a Signature with an * encapsulated, provider-supplied SPI object (of type SignatureSpi). * If the provider implementation is an instance of SignatureSpi, the * getInstance() methods above return an instance of this class, with * the SPI object encapsulated. * * Note: All SPI methods from the original Signature class have been * moved up the hierarchy into a new class (SignatureSpi), which has * been interposed in the hierarchy between the API (Signature) * and its original parent (Object). */ @SuppressWarnings("deprecation") private static class Delegate extends Signature { // The provider implementation (delegate) // filled in once the provider is selected private SignatureSpi sigSpi; // lock for mutex during provider selection private final Object lock; // next service to try in provider selection // null once provider is selected private Service firstService; // remaining services to try in provider selection // null once provider is selected private Iterator serviceIterator; // constructor Delegate(SignatureSpi sigSpi, String algorithm) { super(algorithm); this.sigSpi = sigSpi; this.lock = null; // no lock needed } // used with delayed provider selection Delegate(Service service, Iterator iterator, String algorithm) { super(algorithm); this.firstService = service; this.serviceIterator = iterator; this.lock = new Object(); } /** * Returns a clone if the delegate is cloneable. * * @return a clone if the delegate is cloneable. * * @exception CloneNotSupportedException if this is called on a * delegate that does not support {@code Cloneable}. */ public Object clone() throws CloneNotSupportedException { chooseFirstProvider(); if (sigSpi instanceof Cloneable) { SignatureSpi sigSpiClone = (SignatureSpi)sigSpi.clone(); // Because 'algorithm' and 'provider' are private // members of our supertype, we must perform a cast to // access them. Signature that = new Delegate(sigSpiClone, ((Signature)this).algorithm); that.provider = ((Signature)this).provider; return that; } else { throw new CloneNotSupportedException(); } } private static SignatureSpi newInstance(Service s) throws NoSuchAlgorithmException { if (s.getType().equals("Cipher")) { // must be NONEwithRSA try { Cipher c = Cipher.getInstance(RSA_CIPHER, s.getProvider()); return new CipherAdapter(c); } catch (NoSuchPaddingException e) { throw new NoSuchAlgorithmException(e); } } else { Object o = s.newInstance(null); if (o instanceof SignatureSpi == false) { throw new NoSuchAlgorithmException ("Not a SignatureSpi: " + o.getClass().getName()); } return (SignatureSpi)o; } } // max number of debug warnings to print from chooseFirstProvider() private static int warnCount = 10; /** * Choose the Spi from the first provider available. Used if * delayed provider selection is not possible because initSign()/ * initVerify() is not the first method called. */ void chooseFirstProvider() { if (sigSpi != null) { return; } synchronized (lock) { if (sigSpi != null) { return; } if (debug != null) { int w = --warnCount; if (w >= 0) { debug.println("Signature.init() not first method " + "called, disabling delayed provider selection"); if (w == 0) { debug.println("Further warnings of this type will " + "be suppressed"); } new Exception("Debug call trace").printStackTrace(); } } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; if (firstService != null) { s = firstService; firstService = null; } else { s = serviceIterator.next(); } if (isSpi(s) == false) { continue; } try { sigSpi = newInstance(s); provider = s.getProvider(); // not needed any more firstService = null; serviceIterator = null; return; } catch (NoSuchAlgorithmException e) { lastException = e; } } ProviderException e = new ProviderException ("Could not construct SignatureSpi instance"); if (lastException != null) { e.initCause(lastException); } throw e; } } private void chooseProvider(int type, Key key, SecureRandom random) throws InvalidKeyException { synchronized (lock) { if (sigSpi != null) { init(sigSpi, type, key, random); return; } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; if (firstService != null) { s = firstService; firstService = null; } else { s = serviceIterator.next(); } // if provider says it does not support this key, ignore it if (s.supportsParameter(key) == false) { continue; } // if instance is not a SignatureSpi, ignore it if (isSpi(s) == false) { continue; } try { SignatureSpi spi = newInstance(s); init(spi, type, key, random); provider = s.getProvider(); sigSpi = spi; firstService = null; serviceIterator = null; return; } catch (Exception e) { // NoSuchAlgorithmException from newInstance() // InvalidKeyException from init() // RuntimeException (ProviderException) from init() if (lastException == null) { lastException = e; } } } // no working provider found, fail if (lastException instanceof InvalidKeyException) { throw (InvalidKeyException)lastException; } if (lastException instanceof RuntimeException) { throw (RuntimeException)lastException; } String k = (key != null) ? key.getClass().getName() : "(null)"; throw new InvalidKeyException ("No installed provider supports this key: " + k, lastException); } } private final static int I_PUB = 1; private final static int I_PRIV = 2; private final static int I_PRIV_SR = 3; private void init(SignatureSpi spi, int type, Key key, SecureRandom random) throws InvalidKeyException { switch (type) { case I_PUB: spi.engineInitVerify((PublicKey)key); break; case I_PRIV: spi.engineInitSign((PrivateKey)key); break; case I_PRIV_SR: spi.engineInitSign((PrivateKey)key, random); break; default: throw new AssertionError("Internal error: " + type); } } protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { if (sigSpi != null) { sigSpi.engineInitVerify(publicKey); } else { chooseProvider(I_PUB, publicKey, null); } } protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException { if (sigSpi != null) { sigSpi.engineInitSign(privateKey); } else { chooseProvider(I_PRIV, privateKey, null); } } protected void engineInitSign(PrivateKey privateKey, SecureRandom sr) throws InvalidKeyException { if (sigSpi != null) { sigSpi.engineInitSign(privateKey, sr); } else { chooseProvider(I_PRIV_SR, privateKey, sr); } } protected void engineUpdate(byte b) throws SignatureException { chooseFirstProvider(); sigSpi.engineUpdate(b); } protected void engineUpdate(byte[] b, int off, int len) throws SignatureException { chooseFirstProvider(); sigSpi.engineUpdate(b, off, len); } protected void engineUpdate(ByteBuffer data) { chooseFirstProvider(); sigSpi.engineUpdate(data); } protected byte[] engineSign() throws SignatureException { chooseFirstProvider(); return sigSpi.engineSign(); } protected int engineSign(byte[] outbuf, int offset, int len) throws SignatureException { chooseFirstProvider(); return sigSpi.engineSign(outbuf, offset, len); } protected boolean engineVerify(byte[] sigBytes) throws SignatureException { chooseFirstProvider(); return sigSpi.engineVerify(sigBytes); } protected boolean engineVerify(byte[] sigBytes, int offset, int length) throws SignatureException { chooseFirstProvider(); return sigSpi.engineVerify(sigBytes, offset, length); } protected void engineSetParameter(String param, Object value) throws InvalidParameterException { chooseFirstProvider(); sigSpi.engineSetParameter(param, value); } protected void engineSetParameter(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { chooseFirstProvider(); sigSpi.engineSetParameter(params); } protected Object engineGetParameter(String param) throws InvalidParameterException { chooseFirstProvider(); return sigSpi.engineGetParameter(param); } protected AlgorithmParameters engineGetParameters() { chooseFirstProvider(); return sigSpi.engineGetParameters(); } } // adapter for RSA/ECB/PKCS1Padding ciphers @SuppressWarnings("deprecation") private static class CipherAdapter extends SignatureSpi { private final Cipher cipher; private ByteArrayOutputStream data; CipherAdapter(Cipher cipher) { this.cipher = cipher; } protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { cipher.init(Cipher.DECRYPT_MODE, publicKey); if (data == null) { data = new ByteArrayOutputStream(128); } else { data.reset(); } } protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException { cipher.init(Cipher.ENCRYPT_MODE, privateKey); data = null; } protected void engineInitSign(PrivateKey privateKey, SecureRandom random) throws InvalidKeyException { cipher.init(Cipher.ENCRYPT_MODE, privateKey, random); data = null; } protected void engineUpdate(byte b) throws SignatureException { engineUpdate(new byte[] {b}, 0, 1); } protected void engineUpdate(byte[] b, int off, int len) throws SignatureException { if (data != null) { data.write(b, off, len); return; } byte[] out = cipher.update(b, off, len); if ((out != null) && (out.length != 0)) { throw new SignatureException ("Cipher unexpectedly returned data"); } } protected byte[] engineSign() throws SignatureException { try { return cipher.doFinal(); } catch (IllegalBlockSizeException e) { throw new SignatureException("doFinal() failed", e); } catch (BadPaddingException e) { throw new SignatureException("doFinal() failed", e); } } protected boolean engineVerify(byte[] sigBytes) throws SignatureException { try { byte[] out = cipher.doFinal(sigBytes); byte[] dataBytes = data.toByteArray(); data.reset(); return MessageDigest.isEqual(out, dataBytes); } catch (BadPaddingException e) { // e.g. wrong public key used // return false rather than throwing exception return false; } catch (IllegalBlockSizeException e) { throw new SignatureException("doFinal() failed", e); } } protected void engineSetParameter(String param, Object value) throws InvalidParameterException { throw new InvalidParameterException("Parameters not supported"); } protected Object engineGetParameter(String param) throws InvalidParameterException { throw new InvalidParameterException("Parameters not supported"); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3148 Content-Disposition: inline; filename="SignatureException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "2e1fa592f609cf8875175add96f39deee7c1df25" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This is the generic Signature exception. * * @author Benjamin Renaud */ public class SignatureException extends GeneralSecurityException { private static final long serialVersionUID = 7509989324975124438L; /** * Constructs a SignatureException with no detail message. A * detail message is a String that describes this particular * exception. */ public SignatureException() { super(); } /** * Constructs a SignatureException with the specified detail * message. A detail message is a String that describes this * particular exception. * * @param msg the detail message. */ public SignatureException(String msg) { super(msg); } /** * Creates a {@code SignatureException} with the specified * detail message and cause. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public SignatureException(String message, Throwable cause) { super(message, cause); } /** * Creates a {@code SignatureException} with the specified cause * and a detail message of {@code (cause==null ? null : cause.toString())} * (which typically contains the class and detail message of * {@code cause}). * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @since 1.5 */ public SignatureException(Throwable cause) { super(cause); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 14876 Content-Disposition: inline; filename="SignatureSpi.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "d6d2bc39b5e7b9b5d415bbaa0080d10636d222bb" /* * Copyright (c) 1997, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.security.spec.AlgorithmParameterSpec; import java.util.*; import java.io.*; import java.nio.ByteBuffer; import sun.security.jca.JCAUtil; /** * This class defines the Service Provider Interface (SPI) * for the {@code Signature} class, which is used to provide the * functionality of a digital signature algorithm. Digital signatures are used * for authentication and integrity assurance of digital data. *. *

All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a particular signature algorithm. * * @author Benjamin Renaud * * * @see Signature */ public abstract class SignatureSpi { /** * Application-specified source of randomness. */ protected SecureRandom appRandom = null; /** * Initializes this signature object with the specified * public key for verification operations. * * @param publicKey the public key of the identity whose signature is * going to be verified. * * @exception InvalidKeyException if the key is improperly * encoded, parameters are missing, and so on. */ protected abstract void engineInitVerify(PublicKey publicKey) throws InvalidKeyException; /** * Initializes this signature object with the specified * private key for signing operations. * * @param privateKey the private key of the identity whose signature * will be generated. * * @exception InvalidKeyException if the key is improperly * encoded, parameters are missing, and so on. */ protected abstract void engineInitSign(PrivateKey privateKey) throws InvalidKeyException; /** * Initializes this signature object with the specified * private key and source of randomness for signing operations. * *

This concrete method has been added to this previously-defined * abstract class. (For backwards compatibility, it cannot be abstract.) * * @param privateKey the private key of the identity whose signature * will be generated. * @param random the source of randomness * * @exception InvalidKeyException if the key is improperly * encoded, parameters are missing, and so on. */ protected void engineInitSign(PrivateKey privateKey, SecureRandom random) throws InvalidKeyException { this.appRandom = random; engineInitSign(privateKey); } /** * Updates the data to be signed or verified * using the specified byte. * * @param b the byte to use for the update. * * @exception SignatureException if the engine is not initialized * properly. */ protected abstract void engineUpdate(byte b) throws SignatureException; /** * Updates the data to be signed or verified, using the * specified array of bytes, starting at the specified offset. * * @param b the array of bytes * @param off the offset to start from in the array of bytes * @param len the number of bytes to use, starting at offset * * @exception SignatureException if the engine is not initialized * properly */ protected abstract void engineUpdate(byte[] b, int off, int len) throws SignatureException; /** * Updates the data to be signed or verified using the specified * ByteBuffer. Processes the {@code data.remaining()} bytes * starting at at {@code data.position()}. * Upon return, the buffer's position will be equal to its limit; * its limit will not have changed. * * @param input the ByteBuffer * @since 1.5 */ protected void engineUpdate(ByteBuffer input) { if (input.hasRemaining() == false) { return; } try { if (input.hasArray()) { byte[] b = input.array(); int ofs = input.arrayOffset(); int pos = input.position(); int lim = input.limit(); engineUpdate(b, ofs + pos, lim - pos); input.position(lim); } else { int len = input.remaining(); byte[] b = new byte[JCAUtil.getTempArraySize(len)]; while (len > 0) { int chunk = Math.min(len, b.length); input.get(b, 0, chunk); engineUpdate(b, 0, chunk); len -= chunk; } } } catch (SignatureException e) { // is specified to only occur when the engine is not initialized // this case should never occur as it is caught in Signature.java throw new ProviderException("update() failed", e); } } /** * Returns the signature bytes of all the data * updated so far. * The format of the signature depends on the underlying * signature scheme. * * @return the signature bytes of the signing operation's result. * * @exception SignatureException if the engine is not * initialized properly or if this signature algorithm is unable to * process the input data provided. */ protected abstract byte[] engineSign() throws SignatureException; /** * Finishes this signature operation and stores the resulting signature * bytes in the provided buffer {@code outbuf}, starting at * {@code offset}. * The format of the signature depends on the underlying * signature scheme. * *

The signature implementation is reset to its initial state * (the state it was in after a call to one of the * {@code engineInitSign} methods) * and can be reused to generate further signatures with the same private * key. * * This method should be abstract, but we leave it concrete for * binary compatibility. Knowledgeable providers should override this * method. * * @param outbuf buffer for the signature result. * * @param offset offset into {@code outbuf} where the signature is * stored. * * @param len number of bytes within {@code outbuf} allotted for the * signature. * Both this default implementation and the SUN provider do not * return partial digests. If the value of this parameter is less * than the actual signature length, this method will throw a * SignatureException. * This parameter is ignored if its value is greater than or equal to * the actual signature length. * * @return the number of bytes placed into {@code outbuf} * * @exception SignatureException if the engine is not * initialized properly, if this signature algorithm is unable to * process the input data provided, or if {@code len} is less * than the actual signature length. * * @since 1.2 */ protected int engineSign(byte[] outbuf, int offset, int len) throws SignatureException { byte[] sig = engineSign(); if (len < sig.length) { throw new SignatureException ("partial signatures not returned"); } if (outbuf.length - offset < sig.length) { throw new SignatureException ("insufficient space in the output buffer to store the " + "signature"); } System.arraycopy(sig, 0, outbuf, offset, sig.length); return sig.length; } /** * Verifies the passed-in signature. * * @param sigBytes the signature bytes to be verified. * * @return true if the signature was verified, false if not. * * @exception SignatureException if the engine is not * initialized properly, the passed-in signature is improperly * encoded or of the wrong type, if this signature algorithm is unable to * process the input data provided, etc. */ protected abstract boolean engineVerify(byte[] sigBytes) throws SignatureException; /** * Verifies the passed-in signature in the specified array * of bytes, starting at the specified offset. * *

Note: Subclasses should overwrite the default implementation. * * * @param sigBytes the signature bytes to be verified. * @param offset the offset to start from in the array of bytes. * @param length the number of bytes to use, starting at offset. * * @return true if the signature was verified, false if not. * * @exception SignatureException if the engine is not * initialized properly, the passed-in signature is improperly * encoded or of the wrong type, if this signature algorithm is unable to * process the input data provided, etc. * @since 1.4 */ protected boolean engineVerify(byte[] sigBytes, int offset, int length) throws SignatureException { byte[] sigBytesCopy = new byte[length]; System.arraycopy(sigBytes, offset, sigBytesCopy, 0, length); return engineVerify(sigBytesCopy); } /** * Sets the specified algorithm parameter to the specified * value. This method supplies a general-purpose mechanism through * which it is possible to set the various parameters of this object. * A parameter may be any settable parameter for the algorithm, such as * a parameter size, or a source of random bits for signature generation * (if appropriate), or an indication of whether or not to perform * a specific but optional computation. A uniform algorithm-specific * naming scheme for each parameter is desirable but left unspecified * at this time. * * @param param the string identifier of the parameter. * * @param value the parameter value. * * @exception InvalidParameterException if {@code param} is an * invalid parameter for this signature algorithm engine, * the parameter is already set * and cannot be set again, a security exception occurs, and so on. * * @deprecated Replaced by {@link * #engineSetParameter(java.security.spec.AlgorithmParameterSpec) * engineSetParameter}. */ @Deprecated protected abstract void engineSetParameter(String param, Object value) throws InvalidParameterException; /** *

This method is overridden by providers to initialize * this signature engine with the specified parameter set. * * @param params the parameters * * @exception UnsupportedOperationException if this method is not * overridden by a provider * * @exception InvalidAlgorithmParameterException if this method is * overridden by a provider and the given parameters * are inappropriate for this signature engine */ protected void engineSetParameter(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { throw new UnsupportedOperationException(); } /** *

This method is overridden by providers to return the * parameters used with this signature engine, or null * if this signature engine does not use any parameters. * *

The returned parameters may be the same that were used to initialize * this signature engine, or may contain a combination of default and * randomly generated parameter values used by the underlying signature * implementation if this signature engine requires algorithm parameters * but was not initialized with any. * * @return the parameters used with this signature engine, or null if this * signature engine does not use any parameters * * @exception UnsupportedOperationException if this method is * not overridden by a provider * @since 1.4 */ protected AlgorithmParameters engineGetParameters() { throw new UnsupportedOperationException(); } /** * Gets the value of the specified algorithm parameter. * This method supplies a general-purpose mechanism through which it * is possible to get the various parameters of this object. A parameter * may be any settable parameter for the algorithm, such as a parameter * size, or a source of random bits for signature generation (if * appropriate), or an indication of whether or not to perform a * specific but optional computation. A uniform algorithm-specific * naming scheme for each parameter is desirable but left unspecified * at this time. * * @param param the string name of the parameter. * * @return the object that represents the parameter value, or null if * there is none. * * @exception InvalidParameterException if {@code param} is an * invalid parameter for this engine, or another exception occurs while * trying to get this parameter. * * @deprecated */ @Deprecated protected abstract Object engineGetParameter(String param) throws InvalidParameterException; /** * Returns a clone if the implementation is cloneable. * * @return a clone if the implementation is cloneable. * * @exception CloneNotSupportedException if this is called * on an implementation that does not support {@code Cloneable}. */ public Object clone() throws CloneNotSupportedException { if (this instanceof Cloneable) { return super.clone(); } else { throw new CloneNotSupportedException(); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 10066 Content-Disposition: inline; filename="SignedObject.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "beb88c0e31075428bc9bdf271cfb80eafff7f0ca" /* * Copyright (c) 1997, 2017, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.*; /** *

SignedObject is a class for the purpose of creating authentic * runtime objects whose integrity cannot be compromised without being * detected. * *

More specifically, a SignedObject contains another Serializable * object, the (to-be-)signed object and its signature. * *

The signed object is a "deep copy" (in serialized form) of an * original object. Once the copy is made, further manipulation of * the original object has no side effect on the copy. * *

The underlying signing algorithm is designated by the Signature * object passed to the constructor and the {@code verify} method. * A typical usage for signing is the following: * *

{@code
 * Signature signingEngine = Signature.getInstance(algorithm,
 *                                                 provider);
 * SignedObject so = new SignedObject(myobject, signingKey,
 *                                    signingEngine);
 * }
* *

A typical usage for verification is the following (having * received SignedObject {@code so}): * *

{@code
 * Signature verificationEngine =
 *     Signature.getInstance(algorithm, provider);
 * if (so.verify(publickey, verificationEngine))
 *     try {
 *         Object myobj = so.getObject();
 *     } catch (java.lang.ClassNotFoundException e) {};
 * }
* *

Several points are worth noting. First, there is no need to * initialize the signing or verification engine, as it will be * re-initialized inside the constructor and the {@code verify} * method. Secondly, for verification to succeed, the specified * public key must be the public key corresponding to the private key * used to generate the SignedObject. * *

More importantly, for flexibility reasons, the * constructor and {@code verify} method allow for * customized signature engines, which can implement signature * algorithms that are not installed formally as part of a crypto * provider. However, it is crucial that the programmer writing the * verifier code be aware what {@code Signature} engine is being * used, as its own implementation of the {@code verify} method * is invoked to verify a signature. In other words, a malicious * {@code Signature} may choose to always return true on * verification in an attempt to bypass a security check. * *

The signature algorithm can be, among others, the NIST standard * DSA, using DSA and SHA-256. The algorithm is specified using the * same convention as that for signatures. The DSA algorithm using the * SHA-256 message digest algorithm can be specified, for example, as * "SHA256withDSA". In the case of * RSA the signing algorithm could be specified as, for example, * "SHA256withRSA". The algorithm name must be * specified, as there is no default. * *

The name of the Cryptography Package Provider is designated * also by the Signature parameter to the constructor and the * {@code verify} method. If the provider is not * specified, the default provider is used. Each installation can * be configured to use a particular provider as default. * *

Potential applications of SignedObject include: *

    *
  • It can be used * internally to any Java runtime as an unforgeable authorization * token -- one that can be passed around without the fear that the * token can be maliciously modified without being detected. *
  • It * can be used to sign and serialize data/object for storage outside * the Java runtime (e.g., storing critical access control data on * disk). *
  • Nested SignedObjects can be used to construct a logical * sequence of signatures, resembling a chain of authorization and * delegation. *
* * @see Signature * * @author Li Gong */ public final class SignedObject implements Serializable { private static final long serialVersionUID = 720502720485447167L; /* * The original content is "deep copied" in its serialized format * and stored in a byte array. The signature field is also in the * form of byte array. */ private byte[] content; private byte[] signature; private String thealgorithm; /** * Constructs a SignedObject from any Serializable object. * The given object is signed with the given signing key, using the * designated signature engine. * * @param object the object to be signed. * @param signingKey the private key for signing. * @param signingEngine the signature signing engine. * * @exception IOException if an error occurs during serialization * @exception InvalidKeyException if the key is invalid. * @exception SignatureException if signing fails. */ public SignedObject(Serializable object, PrivateKey signingKey, Signature signingEngine) throws IOException, InvalidKeyException, SignatureException { // creating a stream pipe-line, from a to b ByteArrayOutputStream b = new ByteArrayOutputStream(); ObjectOutput a = new ObjectOutputStream(b); // write and flush the object content to byte array a.writeObject(object); a.flush(); a.close(); this.content = b.toByteArray(); b.close(); // now sign the encapsulated object this.sign(signingKey, signingEngine); } /** * Retrieves the encapsulated object. * The encapsulated object is de-serialized before it is returned. * * @return the encapsulated object. * * @exception IOException if an error occurs during de-serialization * @exception ClassNotFoundException if an error occurs during * de-serialization */ public Object getObject() throws IOException, ClassNotFoundException { // creating a stream pipe-line, from b to a ByteArrayInputStream b = new ByteArrayInputStream(this.content); ObjectInput a = new ObjectInputStream(b); Object obj = a.readObject(); b.close(); a.close(); return obj; } /** * Retrieves the signature on the signed object, in the form of a * byte array. * * @return the signature. Returns a new array each time this * method is called. */ public byte[] getSignature() { return this.signature.clone(); } /** * Retrieves the name of the signature algorithm. * * @return the signature algorithm name. */ public String getAlgorithm() { return this.thealgorithm; } /** * Verifies that the signature in this SignedObject is the valid * signature for the object stored inside, with the given * verification key, using the designated verification engine. * * @param verificationKey the public key for verification. * @param verificationEngine the signature verification engine. * * @exception SignatureException if signature verification failed. * @exception InvalidKeyException if the verification key is invalid. * * @return {@code true} if the signature * is valid, {@code false} otherwise */ public boolean verify(PublicKey verificationKey, Signature verificationEngine) throws InvalidKeyException, SignatureException { verificationEngine.initVerify(verificationKey); verificationEngine.update(this.content.clone()); return verificationEngine.verify(this.signature.clone()); } /* * Signs the encapsulated object with the given signing key, using the * designated signature engine. * * @param signingKey the private key for signing. * @param signingEngine the signature signing engine. * * @exception InvalidKeyException if the key is invalid. * @exception SignatureException if signing fails. */ private void sign(PrivateKey signingKey, Signature signingEngine) throws InvalidKeyException, SignatureException { // initialize the signing engine signingEngine.initSign(signingKey); signingEngine.update(this.content.clone()); this.signature = signingEngine.sign().clone(); this.thealgorithm = signingEngine.getAlgorithm(); } /** * readObject is called to restore the state of the SignedObject from * a stream. */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { java.io.ObjectInputStream.GetField fields = s.readFields(); content = ((byte[])fields.get("content", null)).clone(); signature = ((byte[])fields.get("signature", null)).clone(); thealgorithm = (String)fields.get("thealgorithm", null); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5756 Content-Disposition: inline; filename="Signer.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "077538da9798e75be70b4e808f92be6f92831b87" /* * Copyright (c) 1996, 2013, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.*; /** * This class is used to represent an Identity that can also digitally * sign data. * *

The management of a signer's private keys is an important and * sensitive issue that should be handled by subclasses as appropriate * to their intended use. * * @see Identity * * @author Benjamin Renaud * * @deprecated This class is no longer used. Its functionality has been * replaced by {@code java.security.KeyStore}, the * {@code java.security.cert} package, and * {@code java.security.Principal}. */ @Deprecated public abstract class Signer extends Identity { private static final long serialVersionUID = -1763464102261361480L; /** * The signer's private key. * * @serial */ private PrivateKey privateKey; /** * Creates a signer. This constructor should only be used for * serialization. */ protected Signer() { super(); } /** * Creates a signer with the specified identity name. * * @param name the identity name. */ public Signer(String name) { super(name); } /** * Creates a signer with the specified identity name and scope. * * @param name the identity name. * * @param scope the scope of the identity. * * @exception KeyManagementException if there is already an identity * with the same name in the scope. */ public Signer(String name, IdentityScope scope) throws KeyManagementException { super(name, scope); } /** * Returns this signer's private key. * *

First, if there is a security manager, its {@code checkSecurityAccess} * method is called with {@code "getSignerPrivateKey"} * as its argument to see if it's ok to return the private key. * * @return this signer's private key, or null if the private key has * not yet been set. * * @exception SecurityException if a security manager exists and its * {@code checkSecurityAccess} method doesn't allow * returning the private key. * * @see SecurityManager#checkSecurityAccess */ public PrivateKey getPrivateKey() { check("getSignerPrivateKey"); return privateKey; } /** * Sets the key pair (public key and private key) for this signer. * *

First, if there is a security manager, its {@code checkSecurityAccess} * method is called with {@code "setSignerKeyPair"} * as its argument to see if it's ok to set the key pair. * * @param pair an initialized key pair. * * @exception InvalidParameterException if the key pair is not * properly initialized. * @exception KeyException if the key pair cannot be set for any * other reason. * @exception SecurityException if a security manager exists and its * {@code checkSecurityAccess} method doesn't allow * setting the key pair. * * @see SecurityManager#checkSecurityAccess */ public final void setKeyPair(KeyPair pair) throws InvalidParameterException, KeyException { check("setSignerKeyPair"); final PublicKey pub = pair.getPublic(); PrivateKey priv = pair.getPrivate(); if (pub == null || priv == null) { throw new InvalidParameterException(); } try { AccessController.doPrivileged( new PrivilegedExceptionAction() { public Void run() throws KeyManagementException { setPublicKey(pub); return null; } }); } catch (PrivilegedActionException pae) { throw (KeyManagementException) pae.getException(); } privateKey = priv; } String printKeys() { String keys = ""; PublicKey publicKey = getPublicKey(); if (publicKey != null && privateKey != null) { keys = "\tpublic and private keys initialized"; } else { keys = "\tno keys"; } return keys; } /** * Returns a string of information about the signer. * * @return a string of information about the signer. */ public String toString() { return "[Signer]" + super.toString(); } private static void check(String directive) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkSecurityAccess(directive); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5228 Content-Disposition: inline; filename="Timestamp.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "f66d2883e62294bb7178f62c647c86cf44100baf" /* * Copyright (c) 2003, 2011, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import java.io.*; import java.security.cert.Certificate; import java.security.cert.CertPath; import java.security.cert.X509Extension; import java.util.Date; import java.util.List; /** * This class encapsulates information about a signed timestamp. * It is immutable. * It includes the timestamp's date and time as well as information about the * Timestamping Authority (TSA) which generated and signed the timestamp. * * @since 1.5 * @author Vincent Ryan */ public final class Timestamp implements Serializable { private static final long serialVersionUID = -5502683707821851294L; /** * The timestamp's date and time * * @serial */ private Date timestamp; /** * The TSA's certificate path. * * @serial */ private CertPath signerCertPath; /* * Hash code for this timestamp. */ private transient int myhash = -1; /** * Constructs a Timestamp. * * @param timestamp is the timestamp's date and time. It must not be null. * @param signerCertPath is the TSA's certificate path. It must not be null. * @throws NullPointerException if timestamp or signerCertPath is null. */ public Timestamp(Date timestamp, CertPath signerCertPath) { if (timestamp == null || signerCertPath == null) { throw new NullPointerException(); } this.timestamp = new Date(timestamp.getTime()); // clone this.signerCertPath = signerCertPath; } /** * Returns the date and time when the timestamp was generated. * * @return The timestamp's date and time. */ public Date getTimestamp() { return new Date(timestamp.getTime()); // clone } /** * Returns the certificate path for the Timestamping Authority. * * @return The TSA's certificate path. */ public CertPath getSignerCertPath() { return signerCertPath; } /** * Returns the hash code value for this timestamp. * The hash code is generated using the date and time of the timestamp * and the TSA's certificate path. * * @return a hash code value for this timestamp. */ public int hashCode() { if (myhash == -1) { myhash = timestamp.hashCode() + signerCertPath.hashCode(); } return myhash; } /** * Tests for equality between the specified object and this * timestamp. Two timestamps are considered equal if the date and time of * their timestamp's and their signer's certificate paths are equal. * * @param obj the object to test for equality with this timestamp. * * @return true if the timestamp are considered equal, false otherwise. */ public boolean equals(Object obj) { if (obj == null || (!(obj instanceof Timestamp))) { return false; } Timestamp that = (Timestamp)obj; if (this == that) { return true; } return (timestamp.equals(that.getTimestamp()) && signerCertPath.equals(that.getSignerCertPath())); } /** * Returns a string describing this timestamp. * * @return A string comprising the date and time of the timestamp and * its signer's certificate. */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append("("); sb.append("timestamp: " + timestamp); List certs = signerCertPath.getCertificates(); if (!certs.isEmpty()) { sb.append("TSA: " + certs.get(0)); } else { sb.append("TSA: "); } sb.append(")"); return sb.toString(); } // Explicitly reset hash code value to -1 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); myhash = -1; timestamp = new Date(timestamp.getTime()); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2090 Content-Disposition: inline; filename="URIParameter.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "5cce54424b581307b6a6c58f83e3005d2fe6f4da" /* * Copyright (c) 2005, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * A parameter that contains a URI pointing to data intended for a * PolicySpi or ConfigurationSpi implementation. * * @since 1.6 */ public class URIParameter implements Policy.Parameters, javax.security.auth.login.Configuration.Parameters { private java.net.URI uri; /** * Constructs a URIParameter with the URI pointing to * data intended for an SPI implementation. * * @param uri the URI pointing to the data. * * @exception NullPointerException if the specified URI is null. */ public URIParameter(java.net.URI uri) { if (uri == null) { throw new NullPointerException("invalid null URI"); } this.uri = uri; } /** * Returns the URI. * * @return uri the URI. */ public java.net.URI getURI() { return uri; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 1956 Content-Disposition: inline; filename="UnrecoverableEntryException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "0314e3d9c904d0956cd64d834011c08eaae6e58a" /* * Copyright (c) 2003, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This exception is thrown if an entry in the keystore cannot be recovered. * * * @since 1.5 */ public class UnrecoverableEntryException extends GeneralSecurityException { private static final long serialVersionUID = -4527142945246286535L; /** * Constructs an UnrecoverableEntryException with no detail message. */ public UnrecoverableEntryException() { super(); } /** * Constructs an UnrecoverableEntryException with the specified detail * message, which provides more information about why this exception * has been thrown. * * @param msg the detail message. */ public UnrecoverableEntryException(String msg) { super(msg); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 1951 Content-Disposition: inline; filename="UnrecoverableKeyException.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "09fcc6ed532af6fb5d55c19a38a73b8431eea4b2" /* * Copyright (c) 1997, 2005, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; /** * This exception is thrown if a key in the keystore cannot be recovered. * * * @since 1.2 */ public class UnrecoverableKeyException extends UnrecoverableEntryException { private static final long serialVersionUID = 7275063078190151277L; /** * Constructs an UnrecoverableKeyException with no detail message. */ public UnrecoverableKeyException() { super(); } /** * Constructs an UnrecoverableKeyException with the specified detail * message, which provides more information about why this exception * has been thrown. * * @param msg the detail message. */ public UnrecoverableKeyException(String msg) { super(msg); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 21939 Content-Disposition: inline; filename="UnresolvedPermission.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "c7eee55af7c4cdbc40afef50d487d205477fa3ab" /* * Copyright (c) 1997, 2017, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ package java.security; import sun.misc.IOUtils; import java.io.IOException; import java.io.ByteArrayInputStream; import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Hashtable; import java.lang.reflect.*; import java.security.cert.*; import java.util.List; /** * The UnresolvedPermission class is used to hold Permissions that * were "unresolved" when the Policy was initialized. * An unresolved permission is one whose actual Permission class * does not yet exist at the time the Policy is initialized (see below). * *

The policy for a Java runtime (specifying * which permissions are available for code from various principals) * is represented by a Policy object. * Whenever a Policy is initialized or refreshed, Permission objects of * appropriate classes are created for all permissions * allowed by the Policy. * *

Many permission class types * referenced by the policy configuration are ones that exist * locally (i.e., ones that can be found on CLASSPATH). * Objects for such permissions can be instantiated during * Policy initialization. For example, it is always possible * to instantiate a java.io.FilePermission, since the * FilePermission class is found on the CLASSPATH. * *

Other permission classes may not yet exist during Policy * initialization. For example, a referenced permission class may * be in a JAR file that will later be loaded. * For each such class, an UnresolvedPermission is instantiated. * Thus, an UnresolvedPermission is essentially a "placeholder" * containing information about the permission. * *

Later, when code calls AccessController.checkPermission * on a permission of a type that was previously unresolved, * but whose class has since been loaded, previously-unresolved * permissions of that type are "resolved". That is, * for each such UnresolvedPermission, a new object of * the appropriate class type is instantiated, based on the * information in the UnresolvedPermission. * *

To instantiate the new class, UnresolvedPermission assumes * the class provides a zero, one, and/or two-argument constructor. * The zero-argument constructor would be used to instantiate * a permission without a name and without actions. * A one-arg constructor is assumed to take a {@code String} * name as input, and a two-arg constructor is assumed to take a * {@code String} name and {@code String} actions * as input. UnresolvedPermission may invoke a * constructor with a {@code null} name and/or actions. * If an appropriate permission constructor is not available, * the UnresolvedPermission is ignored and the relevant permission * will not be granted to executing code. * *

The newly created permission object replaces the * UnresolvedPermission, which is removed. * *

Note that the {@code getName} method for an * {@code UnresolvedPermission} returns the * {@code type} (class name) for the underlying permission * that has not been resolved. * * @see java.security.Permission * @see java.security.Permissions * @see java.security.PermissionCollection * @see java.security.Policy * * * @author Roland Schemers */ public final class UnresolvedPermission extends Permission implements java.io.Serializable { private static final long serialVersionUID = -4821973115467008846L; private static final sun.security.util.Debug debug = sun.security.util.Debug.getInstance ("policy,access", "UnresolvedPermission"); /** * The class name of the Permission class that will be * created when this unresolved permission is resolved. * * @serial */ private String type; /** * The permission name. * * @serial */ private String name; /** * The actions of the permission. * * @serial */ private String actions; private transient java.security.cert.Certificate certs[]; /** * Creates a new UnresolvedPermission containing the permission * information needed later to actually create a Permission of the * specified class, when the permission is resolved. * * @param type the class name of the Permission class that will be * created when this unresolved permission is resolved. * @param name the name of the permission. * @param actions the actions of the permission. * @param certs the certificates the permission's class was signed with. * This is a list of certificate chains, where each chain is composed of a * signer certificate and optionally its supporting certificate chain. * Each chain is ordered bottom-to-top (i.e., with the signer certificate * first and the (root) certificate authority last). The signer * certificates are copied from the array. Subsequent changes to * the array will not affect this UnsolvedPermission. */ public UnresolvedPermission(String type, String name, String actions, java.security.cert.Certificate certs[]) { super(type); if (type == null) throw new NullPointerException("type can't be null"); this.type = type; this.name = name; this.actions = actions; if (certs != null) { // Extract the signer certs from the list of certificates. for (int i=0; i signerCerts = new ArrayList<>(); i = 0; while (i < certs.length) { signerCerts.add(certs[i]); while (((i+1) < certs.length) && ((X509Certificate)certs[i]).getIssuerDN().equals( ((X509Certificate)certs[i+1]).getSubjectDN())) { i++; } i++; } this.certs = new java.security.cert.Certificate[signerCerts.size()]; signerCerts.toArray(this.certs); } } } } private static final Class[] PARAMS0 = { }; private static final Class[] PARAMS1 = { String.class }; private static final Class[] PARAMS2 = { String.class, String.class }; /** * try and resolve this permission using the class loader of the permission * that was passed in. */ Permission resolve(Permission p, java.security.cert.Certificate certs[]) { if (this.certs != null) { // if p wasn't signed, we don't have a match if (certs == null) { return null; } // all certs in this.certs must be present in certs boolean match; for (int i = 0; i < this.certs.length; i++) { match = false; for (int j = 0; j < certs.length; j++) { if (this.certs[i].equals(certs[j])) { match = true; break; } } if (!match) return null; } } try { Class pc = p.getClass(); if (name == null && actions == null) { try { Constructor c = pc.getConstructor(PARAMS0); return (Permission)c.newInstance(new Object[] {}); } catch (NoSuchMethodException ne) { try { Constructor c = pc.getConstructor(PARAMS1); return (Permission) c.newInstance( new Object[] { name}); } catch (NoSuchMethodException ne1) { Constructor c = pc.getConstructor(PARAMS2); return (Permission) c.newInstance( new Object[] { name, actions }); } } } else { if (name != null && actions == null) { try { Constructor c = pc.getConstructor(PARAMS1); return (Permission) c.newInstance( new Object[] { name}); } catch (NoSuchMethodException ne) { Constructor c = pc.getConstructor(PARAMS2); return (Permission) c.newInstance( new Object[] { name, actions }); } } else { Constructor c = pc.getConstructor(PARAMS2); return (Permission) c.newInstance( new Object[] { name, actions }); } } } catch (NoSuchMethodException nsme) { if (debug != null ) { debug.println("NoSuchMethodException:\n could not find " + "proper constructor for " + type); nsme.printStackTrace(); } return null; } catch (Exception e) { if (debug != null ) { debug.println("unable to instantiate " + name); e.printStackTrace(); } return null; } } /** * This method always returns false for unresolved permissions. * That is, an UnresolvedPermission is never considered to * imply another permission. * * @param p the permission to check against. * * @return false. */ public boolean implies(Permission p) { return false; } /** * Checks two UnresolvedPermission objects for equality. * Checks that obj is an UnresolvedPermission, and has * the same type (class) name, permission name, actions, and * certificates as this object. * *

To determine certificate equality, this method only compares * actual signer certificates. Supporting certificate chains * are not taken into consideration by this method. * * @param obj the object we are testing for equality with this object. * * @return true if obj is an UnresolvedPermission, and has the same * type (class) name, permission name, actions, and * certificates as this object. */ public boolean equals(Object obj) { if (obj == this) return true; if (! (obj instanceof UnresolvedPermission)) return false; UnresolvedPermission that = (UnresolvedPermission) obj; // check type if (!this.type.equals(that.type)) { return false; } // check name if (this.name == null) { if (that.name != null) { return false; } } else if (!this.name.equals(that.name)) { return false; } // check actions if (this.actions == null) { if (that.actions != null) { return false; } } else { if (!this.actions.equals(that.actions)) { return false; } } // check certs if ((this.certs == null && that.certs != null) || (this.certs != null && that.certs == null) || (this.certs != null && that.certs != null && this.certs.length != that.certs.length)) { return false; } int i,j; boolean match; for (i = 0; this.certs != null && i < this.certs.length; i++) { match = false; for (j = 0; j < that.certs.length; j++) { if (this.certs[i].equals(that.certs[j])) { match = true; break; } } if (!match) return false; } for (i = 0; that.certs != null && i < that.certs.length; i++) { match = false; for (j = 0; j < this.certs.length; j++) { if (that.certs[i].equals(this.certs[j])) { match = true; break; } } if (!match) return false; } return true; } /** * Returns the hash code value for this object. * * @return a hash code value for this object. */ public int hashCode() { int hash = type.hashCode(); if (name != null) hash ^= name.hashCode(); if (actions != null) hash ^= actions.hashCode(); return hash; } /** * Returns the canonical string representation of the actions, * which currently is the empty string "", since there are no actions for * an UnresolvedPermission. That is, the actions for the * permission that will be created when this UnresolvedPermission * is resolved may be non-null, but an UnresolvedPermission * itself is never considered to have any actions. * * @return the empty string "". */ public String getActions() { return ""; } /** * Get the type (class name) of the underlying permission that * has not been resolved. * * @return the type (class name) of the underlying permission that * has not been resolved * * @since 1.5 */ public String getUnresolvedType() { return type; } /** * Get the target name of the underlying permission that * has not been resolved. * * @return the target name of the underlying permission that * has not been resolved, or {@code null}, * if there is no target name * * @since 1.5 */ public String getUnresolvedName() { return name; } /** * Get the actions for the underlying permission that * has not been resolved. * * @return the actions for the underlying permission that * has not been resolved, or {@code null} * if there are no actions * * @since 1.5 */ public String getUnresolvedActions() { return actions; } /** * Get the signer certificates (without any supporting chain) * for the underlying permission that has not been resolved. * * @return the signer certificates for the underlying permission that * has not been resolved, or null, if there are no signer certificates. * Returns a new array each time this method is called. * * @since 1.5 */ public java.security.cert.Certificate[] getUnresolvedCerts() { return (certs == null) ? null : certs.clone(); } /** * Returns a string describing this UnresolvedPermission. The convention * is to specify the class name, the permission name, and the actions, in * the following format: '(unresolved "ClassName" "name" "actions")'. * * @return information about this UnresolvedPermission. */ public String toString() { return "(unresolved " + type + " " + name + " " + actions + ")"; } /** * Returns a new PermissionCollection object for storing * UnresolvedPermission objects. *

* @return a new PermissionCollection object suitable for * storing UnresolvedPermissions. */ public PermissionCollection newPermissionCollection() { return new UnresolvedPermissionCollection(); } /** * Writes this object out to a stream (i.e., serializes it). * * @serialData An initial {@code String} denoting the * {@code type} is followed by a {@code String} denoting the * {@code name} is followed by a {@code String} denoting the * {@code actions} is followed by an {@code int} indicating the * number of certificates to follow * (a value of "zero" denotes that there are no certificates associated * with this object). * Each certificate is written out starting with a {@code String} * denoting the certificate type, followed by an * {@code int} specifying the length of the certificate encoding, * followed by the certificate encoding itself which is written out as an * array of bytes. */ private void writeObject(java.io.ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); if (certs==null || certs.length==0) { oos.writeInt(0); } else { // write out the total number of certs oos.writeInt(certs.length); // write out each cert, including its type for (int i=0; i < certs.length; i++) { java.security.cert.Certificate cert = certs[i]; try { oos.writeUTF(cert.getType()); byte[] encoded = cert.getEncoded(); oos.writeInt(encoded.length); oos.write(encoded); } catch (CertificateEncodingException cee) { throw new IOException(cee.getMessage()); } } } } /** * Restores this object from a stream (i.e., deserializes it). */ private void readObject(java.io.ObjectInputStream ois) throws IOException, ClassNotFoundException { CertificateFactory cf; Hashtable cfs = null; List certList = null; ois.defaultReadObject(); if (type == null) throw new NullPointerException("type can't be null"); // process any new-style certs in the stream (if present) int size = ois.readInt(); if (size > 0) { // we know of 3 different cert types: X.509, PGP, SDSI, which // could all be present in the stream at the same time cfs = new Hashtable<>(3); certList = new ArrayList<>(size > 20 ? 20 : size); } else if (size < 0) { throw new IOException("size cannot be negative"); } for (int i=0; i> perms; /** * Create an empty UnresolvedPermissionCollection object. * */ public UnresolvedPermissionCollection() { perms = new HashMap>(11); } /** * Adds a permission to this UnresolvedPermissionCollection. * The key for the hash is the unresolved permission's type (class) name. * * @param permission the Permission object to add. */ public void add(Permission permission) { if (! (permission instanceof UnresolvedPermission)) throw new IllegalArgumentException("invalid permission: "+ permission); UnresolvedPermission up = (UnresolvedPermission) permission; List v; synchronized (this) { v = perms.get(up.getName()); if (v == null) { v = new ArrayList(); perms.put(up.getName(), v); } } synchronized (v) { v.add(up); } } /** * get any unresolved permissions of the same type as p, * and return the List containing them. */ List getUnresolvedPermissions(Permission p) { synchronized (this) { return perms.get(p.getClass().getName()); } } /** * always returns false for unresolved permissions * */ public boolean implies(Permission permission) { return false; } /** * Returns an enumeration of all the UnresolvedPermission lists in the * container. * * @return an enumeration of all the UnresolvedPermission objects. */ public Enumeration elements() { List results = new ArrayList<>(); // where results are stored // Get iterator of Map values (which are lists of permissions) synchronized (this) { for (List l : perms.values()) { synchronized (l) { results.addAll(l); } } } return Collections.enumeration(results); } private static final long serialVersionUID = -7176153071733132400L; // Need to maintain serialization interoperability with earlier releases, // which had the serializable field: // private Hashtable permissions; // keyed on type /** * @serialField permissions java.util.Hashtable * A table of the UnresolvedPermissions keyed on type, value is Vector * of permissions */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("permissions", Hashtable.class), }; /** * @serialData Default field. */ /* * Writes the contents of the perms field out as a Hashtable * in which the values are Vectors for * serialization compatibility with earlier releases. */ private void writeObject(ObjectOutputStream out) throws IOException { // Don't call out.defaultWriteObject() // Copy perms into a Hashtable Hashtable> permissions = new Hashtable<>(perms.size()*2); // Convert each entry (List) into a Vector synchronized (this) { Set>> set = perms.entrySet(); for (Map.Entry> e : set) { // Convert list into Vector List list = e.getValue(); Vector vec = new Vector<>(list.size()); synchronized (list) { vec.addAll(list); } // Add to Hashtable being serialized permissions.put(e.getKey(), vec); } } // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); pfields.put("permissions", permissions); out.writeFields(); } /* * Reads in a Hashtable in which the values are Vectors of * UnresolvedPermissions and saves them in the perms field. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // Don't call defaultReadObject() // Read in serialized fields ObjectInputStream.GetField gfields = in.readFields(); // Get permissions @SuppressWarnings("unchecked") // writeObject writes a Hashtable> // for the permissions key, so this cast is safe, unless the data is corrupt. Hashtable> permissions = (Hashtable>) gfields.get("permissions", null); perms = new HashMap>(permissions.size()*2); // Convert each entry (Vector) into a List Set>> set = permissions.entrySet(); for (Map.Entry> e : set) { // Convert Vector into ArrayList Vector vec = e.getValue(); List list = new ArrayList<>(vec.size()); list.addAll(vec); // Add to Hashtable being serialized perms.put(e.getKey(), list); } } } Content-Type: text/plain; charset=UTF-8 Content-Length: 7555 Content-Disposition: inline; filename="UnresolvedPermissionCollection.java" Last-Modified: Wed, 10 Jul 2024 15:45:47 GMT Expires: Wed, 10 Jul 2024 15:50:47 GMT ETag: "9e09a9c0754c35b3e5591ef7eac8f369eb060b9f" /src/share/classes/java/security/acl/

/src/share/classes/java/security/acl/