Showing the changes to java/pkg/java/security (402 of 18352 files). Show all
Unified · Split
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,598 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.util.ArrayList; | |
| 29 | +import java.util.List; | |
| 30 | +import sun.security.util.Debug; | |
| 31 | +import sun.security.util.SecurityConstants; | |
| 32 | +import sun.misc.JavaSecurityAccess; | |
| 33 | +import sun.misc.SharedSecrets; | |
| 34 | + | |
| 35 | + | |
| 36 | +/** | |
| 37 | + * An AccessControlContext is used to make system resource access decisions | |
| 38 | + * based on the context it encapsulates. | |
| 39 | + * | |
| 40 | + * <p>More specifically, it encapsulates a context and | |
| 41 | + * has a single method, <code>checkPermission</code>, | |
| 42 | + * that is equivalent to the <code>checkPermission</code> method | |
| 43 | + * in the AccessController class, with one difference: The AccessControlContext | |
| 44 | + * <code>checkPermission</code> method makes access decisions based on the | |
| 45 | + * context it encapsulates, | |
| 46 | + * rather than that of the current execution thread. | |
| 47 | + * | |
| 48 | + * <p>Thus, the purpose of AccessControlContext is for those situations where | |
| 49 | + * a security check that should be made within a given context | |
| 50 | + * actually needs to be done from within a | |
| 51 | + * <i>different</i> context (for example, from within a worker thread). | |
| 52 | + * | |
| 53 | + * <p> An AccessControlContext is created by calling the | |
| 54 | + * <code>AccessController.getContext</code> method. | |
| 55 | + * The <code>getContext</code> method takes a "snapshot" | |
| 56 | + * of the current calling context, and places | |
| 57 | + * it in an AccessControlContext object, which it returns. A sample call is | |
| 58 | + * the following: | |
| 59 | + * | |
| 60 | + * <pre> | |
| 61 | + * AccessControlContext acc = AccessController.getContext() | |
| 62 | + * </pre> | |
| 63 | + * | |
| 64 | + * <p> | |
| 65 | + * Code within a different context can subsequently call the | |
| 66 | + * <code>checkPermission</code> method on the | |
| 67 | + * previously-saved AccessControlContext object. A sample call is the | |
| 68 | + * following: | |
| 69 | + * | |
| 70 | + * <pre> | |
| 71 | + * acc.checkPermission(permission) | |
| 72 | + * </pre> | |
| 73 | + * | |
| 74 | + * @see AccessController | |
| 75 | + * | |
| 76 | + * @author Roland Schemers | |
| 77 | + */ | |
| 78 | + | |
| 79 | +public final class AccessControlContext { | |
| 80 | + | |
| 81 | + private ProtectionDomain context[]; | |
| 82 | + private boolean isPrivileged; | |
| 83 | + | |
| 84 | + // Note: This field is directly used by the virtual machine | |
| 85 | + // native codes. Don't touch it. | |
| 86 | + private AccessControlContext privilegedContext; | |
| 87 | + | |
| 88 | + private DomainCombiner combiner = null; | |
| 89 | + | |
| 90 | + private static boolean debugInit = false; | |
| 91 | + private static Debug debug = null; | |
| 92 | + | |
| 93 | + static Debug getDebug() | |
| 94 | + { | |
| 95 | + if (debugInit) | |
| 96 | + return debug; | |
| 97 | + else { | |
| 98 | + if (Policy.isSet()) { | |
| 99 | + debug = Debug.getInstance("access"); | |
| 100 | + debugInit = true; | |
| 101 | + } | |
| 102 | + return debug; | |
| 103 | + } | |
| 104 | + } | |
| 105 | + | |
| 106 | + /** | |
| 107 | + * Create an AccessControlContext with the given array of ProtectionDomains. | |
| 108 | + * Context must not be null. Duplicate domains will be removed from the | |
| 109 | + * context. | |
| 110 | + * | |
| 111 | + * @param context the ProtectionDomains associated with this context. | |
| 112 | + * The non-duplicate domains are copied from the array. Subsequent | |
| 113 | + * changes to the array will not affect this AccessControlContext. | |
| 114 | + * @throws NullPointerException if <code>context</code> is <code>null</code> | |
| 115 | + */ | |
| 116 | + public AccessControlContext(ProtectionDomain context[]) | |
| 117 | + { | |
| 118 | + if (context.length == 0) { | |
| 119 | + this.context = null; | |
| 120 | + } else if (context.length == 1) { | |
| 121 | + if (context[0] != null) { | |
| 122 | + this.context = context.clone(); | |
| 123 | + } else { | |
| 124 | + this.context = null; | |
| 125 | + } | |
| 126 | + } else { | |
| 127 | + List<ProtectionDomain> v = new ArrayList<>(context.length); | |
| 128 | + for (int i =0; i< context.length; i++) { | |
| 129 | + if ((context[i] != null) && (!v.contains(context[i]))) | |
| 130 | + v.add(context[i]); | |
| 131 | + } | |
| 132 | + if (!v.isEmpty()) { | |
| 133 | + this.context = new ProtectionDomain[v.size()]; | |
| 134 | + this.context = v.toArray(this.context); | |
| 135 | + } | |
| 136 | + } | |
| 137 | + } | |
| 138 | + | |
| 139 | + /** | |
| 140 | + * Create a new <code>AccessControlContext</code> with the given | |
| 141 | + * <code>AccessControlContext</code> and <code>DomainCombiner</code>. | |
| 142 | + * This constructor associates the provided | |
| 143 | + * <code>DomainCombiner</code> with the provided | |
| 144 | + * <code>AccessControlContext</code>. | |
| 145 | + * | |
| 146 | + * <p> | |
| 147 | + * | |
| 148 | + * @param acc the <code>AccessControlContext</code> associated | |
| 149 | + * with the provided <code>DomainCombiner</code>. | |
| 150 | + * | |
| 151 | + * @param combiner the <code>DomainCombiner</code> to be associated | |
| 152 | + * with the provided <code>AccessControlContext</code>. | |
| 153 | + * | |
| 154 | + * @exception NullPointerException if the provided | |
| 155 | + * <code>context</code> is <code>null</code>. | |
| 156 | + * | |
| 157 | + * @exception SecurityException if a security manager is installed and the | |
| 158 | + * caller does not have the "createAccessControlContext" | |
| 159 | + * {@link SecurityPermission} | |
| 160 | + * @since 1.3 | |
| 161 | + */ | |
| 162 | + public AccessControlContext(AccessControlContext acc, | |
| 163 | + DomainCombiner combiner) { | |
| 164 | + | |
| 165 | + SecurityManager sm = System.getSecurityManager(); | |
| 166 | + if (sm != null) { | |
| 167 | + sm.checkPermission(SecurityConstants.CREATE_ACC_PERMISSION); | |
| 168 | + } | |
| 169 | + | |
| 170 | + this.context = acc.context; | |
| 171 | + | |
| 172 | + // we do not need to run the combine method on the | |
| 173 | + // provided ACC. it was already "combined" when the | |
| 174 | + // context was originally retrieved. | |
| 175 | + // | |
| 176 | + // at this point in time, we simply throw away the old | |
| 177 | + // combiner and use the newly provided one. | |
| 178 | + this.combiner = combiner; | |
| 179 | + } | |
| 180 | + | |
| 181 | + /** | |
| 182 | + * package private for AccessController | |
| 183 | + */ | |
| 184 | + AccessControlContext(ProtectionDomain context[], DomainCombiner combiner) { | |
| 185 | + if (context != null) { | |
| 186 | + this.context = context.clone(); | |
| 187 | + } | |
| 188 | + this.combiner = combiner; | |
| 189 | + } | |
| 190 | + | |
| 191 | + /** | |
| 192 | + * package private constructor for AccessController.getContext() | |
| 193 | + */ | |
| 194 | + | |
| 195 | + AccessControlContext(ProtectionDomain context[], | |
| 196 | + boolean isPrivileged) | |
| 197 | + { | |
| 198 | + this.context = context; | |
| 199 | + this.isPrivileged = isPrivileged; | |
| 200 | + } | |
| 201 | + | |
| 202 | + /** | |
| 203 | + * Constructor for JavaSecurityAccess.doIntersectionPrivilege() | |
| 204 | + */ | |
| 205 | + AccessControlContext(ProtectionDomain[] context, | |
| 206 | + AccessControlContext privilegedContext) | |
| 207 | + { | |
| 208 | + this.context = context; | |
| 209 | + this.privilegedContext = privilegedContext; | |
| 210 | + this.isPrivileged = true; | |
| 211 | + } | |
| 212 | + | |
| 213 | + /** | |
| 214 | + * Returns this context's context. | |
| 215 | + */ | |
| 216 | + ProtectionDomain[] getContext() { | |
| 217 | + return context; | |
| 218 | + } | |
| 219 | + | |
| 220 | + /** | |
| 221 | + * Returns true if this context is privileged. | |
| 222 | + */ | |
| 223 | + boolean isPrivileged() | |
| 224 | + { | |
| 225 | + return isPrivileged; | |
| 226 | + } | |
| 227 | + | |
| 228 | + /** | |
| 229 | + * get the assigned combiner from the privileged or inherited context | |
| 230 | + */ | |
| 231 | + DomainCombiner getAssignedCombiner() { | |
| 232 | + AccessControlContext acc; | |
| 233 | + if (isPrivileged) { | |
| 234 | + acc = privilegedContext; | |
| 235 | + } else { | |
| 236 | + acc = AccessController.getInheritedAccessControlContext(); | |
| 237 | + } | |
| 238 | + if (acc != null) { | |
| 239 | + return acc.combiner; | |
| 240 | + } | |
| 241 | + return null; | |
| 242 | + } | |
| 243 | + | |
| 244 | + /** | |
| 245 | + * Get the <code>DomainCombiner</code> associated with this | |
| 246 | + * <code>AccessControlContext</code>. | |
| 247 | + * | |
| 248 | + * <p> | |
| 249 | + * | |
| 250 | + * @return the <code>DomainCombiner</code> associated with this | |
| 251 | + * <code>AccessControlContext</code>, or <code>null</code> | |
| 252 | + * if there is none. | |
| 253 | + * | |
| 254 | + * @exception SecurityException if a security manager is installed and | |
| 255 | + * the caller does not have the "getDomainCombiner" | |
| 256 | + * {@link SecurityPermission} | |
| 257 | + * @since 1.3 | |
| 258 | + */ | |
| 259 | + public DomainCombiner getDomainCombiner() { | |
| 260 | + | |
| 261 | + SecurityManager sm = System.getSecurityManager(); | |
| 262 | + if (sm != null) { | |
| 263 | + sm.checkPermission(SecurityConstants.GET_COMBINER_PERMISSION); | |
| 264 | + } | |
| 265 | + return combiner; | |
| 266 | + } | |
| 267 | + | |
| 268 | + /** | |
| 269 | + * Determines whether the access request indicated by the | |
| 270 | + * specified permission should be allowed or denied, based on | |
| 271 | + * the security policy currently in effect, and the context in | |
| 272 | + * this object. The request is allowed only if every ProtectionDomain | |
| 273 | + * in the context implies the permission. Otherwise the request is | |
| 274 | + * denied. | |
| 275 | + * | |
| 276 | + * <p> | |
| 277 | + * This method quietly returns if the access request | |
| 278 | + * is permitted, or throws a suitable AccessControlException otherwise. | |
| 279 | + * | |
| 280 | + * @param perm the requested permission. | |
| 281 | + * | |
| 282 | + * @exception AccessControlException if the specified permission | |
| 283 | + * is not permitted, based on the current security policy and the | |
| 284 | + * context encapsulated by this object. | |
| 285 | + * @exception NullPointerException if the permission to check for is null. | |
| 286 | + */ | |
| 287 | + public void checkPermission(Permission perm) | |
| 288 | + throws AccessControlException | |
| 289 | + { | |
| 290 | + boolean dumpDebug = false; | |
| 291 | + | |
| 292 | + if (perm == null) { | |
| 293 | + throw new NullPointerException("permission can't be null"); | |
| 294 | + } | |
| 295 | + if (getDebug() != null) { | |
| 296 | + // If "codebase" is not specified, we dump the info by default. | |
| 297 | + dumpDebug = !Debug.isOn("codebase="); | |
| 298 | + if (!dumpDebug) { | |
| 299 | + // If "codebase" is specified, only dump if the specified code | |
| 300 | + // value is in the stack. | |
| 301 | + for (int i = 0; context != null && i < context.length; i++) { | |
| 302 | + if (context[i].getCodeSource() != null && | |
| 303 | + context[i].getCodeSource().getLocation() != null && | |
| 304 | + Debug.isOn("codebase=" + context[i].getCodeSource().getLocation().toString())) { | |
| 305 | + dumpDebug = true; | |
| 306 | + break; | |
| 307 | + } | |
| 308 | + } | |
| 309 | + } | |
| 310 | + | |
| 311 | + dumpDebug &= !Debug.isOn("permission=") || | |
| 312 | + Debug.isOn("permission=" + perm.getClass().getCanonicalName()); | |
| 313 | + | |
| 314 | + if (dumpDebug && Debug.isOn("stack")) { | |
| 315 | + Thread.currentThread().dumpStack(); | |
| 316 | + } | |
| 317 | + | |
| 318 | + if (dumpDebug && Debug.isOn("domain")) { | |
| 319 | + if (context == null) { | |
| 320 | + debug.println("domain (context is null)"); | |
| 321 | + } else { | |
| 322 | + for (int i=0; i< context.length; i++) { | |
| 323 | + debug.println("domain "+i+" "+context[i]); | |
| 324 | + } | |
| 325 | + } | |
| 326 | + } | |
| 327 | + } | |
| 328 | + | |
| 329 | + /* | |
| 330 | + * iterate through the ProtectionDomains in the context. | |
| 331 | + * Stop at the first one that doesn't allow the | |
| 332 | + * requested permission (throwing an exception). | |
| 333 | + * | |
| 334 | + */ | |
| 335 | + | |
| 336 | + /* if ctxt is null, all we had on the stack were system domains, | |
| 337 | + or the first domain was a Privileged system domain. This | |
| 338 | + is to make the common case for system code very fast */ | |
| 339 | + | |
| 340 | + if (context == null) | |
| 341 | + return; | |
| 342 | + | |
| 343 | + for (int i=0; i< context.length; i++) { | |
| 344 | + if (context[i] != null && !context[i].implies(perm)) { | |
| 345 | + if (dumpDebug) { | |
| 346 | + debug.println("access denied " + perm); | |
| 347 | + } | |
| 348 | + | |
| 349 | + if (Debug.isOn("failure") && debug != null) { | |
| 350 | + // Want to make sure this is always displayed for failure, | |
| 351 | + // but do not want to display again if already displayed | |
| 352 | + // above. | |
| 353 | + if (!dumpDebug) { | |
| 354 | + debug.println("access denied " + perm); | |
| 355 | + } | |
| 356 | + Thread.currentThread().dumpStack(); | |
| 357 | + final ProtectionDomain pd = context[i]; | |
| 358 | + final Debug db = debug; | |
| 359 | + AccessController.doPrivileged (new PrivilegedAction<Void>() { | |
| 360 | + public Void run() { | |
| 361 | + db.println("domain that failed "+pd); | |
| 362 | + return null; | |
| 363 | + } | |
| 364 | + }); | |
| 365 | + } | |
| 366 | + throw new AccessControlException("access denied "+perm, perm); | |
| 367 | + } | |
| 368 | + } | |
| 369 | + | |
| 370 | + // allow if all of them allowed access | |
| 371 | + if (dumpDebug) { | |
| 372 | + debug.println("access allowed "+perm); | |
| 373 | + } | |
| 374 | + | |
| 375 | + return; | |
| 376 | + } | |
| 377 | + | |
| 378 | + /** | |
| 379 | + * Take the stack-based context (this) and combine it with the | |
| 380 | + * privileged or inherited context, if need be. | |
| 381 | + */ | |
| 382 | + AccessControlContext optimize() { | |
| 383 | + // the assigned (privileged or inherited) context | |
| 384 | + AccessControlContext acc; | |
| 385 | + if (isPrivileged) { | |
| 386 | + acc = privilegedContext; | |
| 387 | + } else { | |
| 388 | + acc = AccessController.getInheritedAccessControlContext(); | |
| 389 | + } | |
| 390 | + | |
| 391 | + // this.context could be null if only system code is on the stack; | |
| 392 | + // in that case, ignore the stack context | |
| 393 | + boolean skipStack = (context == null); | |
| 394 | + | |
| 395 | + // acc.context could be null if only system code was involved; | |
| 396 | + // in that case, ignore the assigned context | |
| 397 | + boolean skipAssigned = (acc == null || acc.context == null); | |
| 398 | + | |
| 399 | + if (acc != null && acc.combiner != null) { | |
| 400 | + // let the assigned acc's combiner do its thing | |
| 401 | + return goCombiner(context, acc); | |
| 402 | + } | |
| 403 | + | |
| 404 | + // optimization: if neither have contexts; return acc if possible | |
| 405 | + // rather than this, because acc might have a combiner | |
| 406 | + if (skipAssigned && skipStack) { | |
| 407 | + return this; | |
| 408 | + } | |
| 409 | + | |
| 410 | + // optimization: if there is no stack context; there is no reason | |
| 411 | + // to compress the assigned context, it already is compressed | |
| 412 | + if (skipStack) { | |
| 413 | + return acc; | |
| 414 | + } | |
| 415 | + | |
| 416 | + int slen = context.length; | |
| 417 | + | |
| 418 | + // optimization: if there is no assigned context and the stack length | |
| 419 | + // is less then or equal to two; there is no reason to compress the | |
| 420 | + // stack context, it already is | |
| 421 | + if (skipAssigned && slen <= 2) { | |
| 422 | + return this; | |
| 423 | + } | |
| 424 | + | |
| 425 | + // optimization: if there is a single stack domain and that domain | |
| 426 | + // is already in the assigned context; no need to combine | |
| 427 | + if ((slen == 1) && (context[0] == acc.context[0])) { | |
| 428 | + return acc; | |
| 429 | + } | |
| 430 | + | |
| 431 | + int n = (skipAssigned) ? 0 : acc.context.length; | |
| 432 | + | |
| 433 | + // now we combine both of them, and create a new context | |
| 434 | + ProtectionDomain pd[] = new ProtectionDomain[slen + n]; | |
| 435 | + | |
| 436 | + // first copy in the assigned context domains, no need to compress | |
| 437 | + if (!skipAssigned) { | |
| 438 | + System.arraycopy(acc.context, 0, pd, 0, n); | |
| 439 | + } | |
| 440 | + | |
| 441 | + // now add the stack context domains, discarding nulls and duplicates | |
| 442 | + outer: | |
| 443 | + for (int i = 0; i < context.length; i++) { | |
| 444 | + ProtectionDomain sd = context[i]; | |
| 445 | + if (sd != null) { | |
| 446 | + for (int j = 0; j < n; j++) { | |
| 447 | + if (sd == pd[j]) { | |
| 448 | + continue outer; | |
| 449 | + } | |
| 450 | + } | |
| 451 | + pd[n++] = sd; | |
| 452 | + } | |
| 453 | + } | |
| 454 | + | |
| 455 | + // if length isn't equal, we need to shorten the array | |
| 456 | + if (n != pd.length) { | |
| 457 | + // optimization: if we didn't really combine anything | |
| 458 | + if (!skipAssigned && n == acc.context.length) { | |
| 459 | + return acc; | |
| 460 | + } else if (skipAssigned && n == slen) { | |
| 461 | + return this; | |
| 462 | + } | |
| 463 | + ProtectionDomain tmp[] = new ProtectionDomain[n]; | |
| 464 | + System.arraycopy(pd, 0, tmp, 0, n); | |
| 465 | + pd = tmp; | |
| 466 | + } | |
| 467 | + | |
| 468 | + // return new AccessControlContext(pd, false); | |
| 469 | + | |
| 470 | + // Reuse existing ACC | |
| 471 | + | |
| 472 | + this.context = pd; | |
| 473 | + this.combiner = null; | |
| 474 | + this.isPrivileged = false; | |
| 475 | + | |
| 476 | + return this; | |
| 477 | + } | |
| 478 | + | |
| 479 | + private AccessControlContext goCombiner(ProtectionDomain[] current, | |
| 480 | + AccessControlContext assigned) { | |
| 481 | + | |
| 482 | + // the assigned ACC's combiner is not null -- | |
| 483 | + // let the combiner do its thing | |
| 484 | + | |
| 485 | + // XXX we could add optimizations to 'current' here ... | |
| 486 | + | |
| 487 | + if (getDebug() != null) { | |
| 488 | + debug.println("AccessControlContext invoking the Combiner"); | |
| 489 | + } | |
| 490 | + | |
| 491 | + // No need to clone current and assigned.context | |
| 492 | + // combine() will not update them | |
| 493 | + ProtectionDomain[] combinedPds = assigned.combiner.combine( | |
| 494 | + current, assigned.context); | |
| 495 | + | |
| 496 | + // return new AccessControlContext(combinedPds, assigned.combiner); | |
| 497 | + | |
| 498 | + // Reuse existing ACC | |
| 499 | + this.context = combinedPds; | |
| 500 | + this.combiner = assigned.combiner; | |
| 501 | + this.isPrivileged = false; | |
| 502 | + | |
| 503 | + return this; | |
| 504 | + } | |
| 505 | + | |
| 506 | + /** | |
| 507 | + * Checks two AccessControlContext objects for equality. | |
| 508 | + * Checks that <i>obj</i> is | |
| 509 | + * an AccessControlContext and has the same set of ProtectionDomains | |
| 510 | + * as this context. | |
| 511 | + * <P> | |
| 512 | + * @param obj the object we are testing for equality with this object. | |
| 513 | + * @return true if <i>obj</i> is an AccessControlContext, and has the | |
| 514 | + * same set of ProtectionDomains as this context, false otherwise. | |
| 515 | + */ | |
| 516 | + public boolean equals(Object obj) { | |
| 517 | + if (obj == this) | |
| 518 | + return true; | |
| 519 | + | |
| 520 | + if (! (obj instanceof AccessControlContext)) | |
| 521 | + return false; | |
| 522 | + | |
| 523 | + AccessControlContext that = (AccessControlContext) obj; | |
| 524 | + | |
| 525 | + | |
| 526 | + if (context == null) { | |
| 527 | + return (that.context == null); | |
| 528 | + } | |
| 529 | + | |
| 530 | + if (that.context == null) | |
| 531 | + return false; | |
| 532 | + | |
| 533 | + if (!(this.containsAllPDs(that) && that.containsAllPDs(this))) | |
| 534 | + return false; | |
| 535 | + | |
| 536 | + if (this.combiner == null) | |
| 537 | + return (that.combiner == null); | |
| 538 | + | |
| 539 | + if (that.combiner == null) | |
| 540 | + return false; | |
| 541 | + | |
| 542 | + if (!this.combiner.equals(that.combiner)) | |
| 543 | + return false; | |
| 544 | + | |
| 545 | + return true; | |
| 546 | + } | |
| 547 | + | |
| 548 | + private boolean containsAllPDs(AccessControlContext that) { | |
| 549 | + boolean match = false; | |
| 550 | + // | |
| 551 | + // ProtectionDomains within an ACC currently cannot be null | |
| 552 | + // and this is enforced by the constructor and the various | |
| 553 | + // optimize methods. However, historically this logic made attempts | |
| 554 | + // to support the notion of a null PD and therefore this logic continues | |
| 555 | + // to support that notion. | |
| 556 | + ProtectionDomain thisPd; | |
| 557 | + for (int i = 0; i < context.length; i++) { | |
| 558 | + match = false; | |
| 559 | + if ((thisPd = context[i]) == null) { | |
| 560 | + for (int j = 0; (j < that.context.length) && !match; j++) { | |
| 561 | + match = (that.context[j] == null); | |
| 562 | + } | |
| 563 | + } else { | |
| 564 | + Class thisPdClass = thisPd.getClass(); | |
| 565 | + ProtectionDomain thatPd; | |
| 566 | + for (int j = 0; (j < that.context.length) && !match; j++) { | |
| 567 | + thatPd = that.context[j]; | |
| 568 | + | |
| 569 | + // Class check required to avoid PD exposure (4285406) | |
| 570 | + match = (thatPd != null && | |
| 571 | + thisPdClass == thatPd.getClass() && thisPd.equals(thatPd)); | |
| 572 | + } | |
| 573 | + } | |
| 574 | + if (!match) return false; | |
| 575 | + } | |
| 576 | + return match; | |
| 577 | + } | |
| 578 | + /** | |
| 579 | + * Returns the hash code value for this context. The hash code | |
| 580 | + * is computed by exclusive or-ing the hash code of all the protection | |
| 581 | + * domains in the context together. | |
| 582 | + * | |
| 583 | + * @return a hash code value for this context. | |
| 584 | + */ | |
| 585 | + | |
| 586 | + public int hashCode() { | |
| 587 | + int hashCode = 0; | |
| 588 | + | |
| 589 | + if (context == null) | |
| 590 | + return hashCode; | |
| 591 | + | |
| 592 | + for (int i =0; i < context.length; i++) { | |
| 593 | + if (context[i] != null) | |
| 594 | + hashCode ^= context[i].hashCode(); | |
| 595 | + } | |
| 596 | + return hashCode; | |
| 597 | + } | |
| 598 | +} | |
Binary file not shown.
| @@ -0,0 +1,82 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * <p> This exception is thrown by the AccessController to indicate | |
| 30 | + * that a requested access (to a critical system resource such as the | |
| 31 | + * file system or the network) is denied. | |
| 32 | + * | |
| 33 | + * <p> The reason to deny access can vary. For example, the requested | |
| 34 | + * permission might be of an incorrect type, contain an invalid | |
| 35 | + * value, or request access that is not allowed according to the | |
| 36 | + * security policy. Such information should be given whenever | |
| 37 | + * possible at the time the exception is thrown. | |
| 38 | + * | |
| 39 | + * @author Li Gong | |
| 40 | + * @author Roland Schemers | |
| 41 | + */ | |
| 42 | + | |
| 43 | +public class AccessControlException extends SecurityException { | |
| 44 | + | |
| 45 | + private static final long serialVersionUID = 5138225684096988535L; | |
| 46 | + | |
| 47 | + // the permission that caused the exeception to be thrown. | |
| 48 | + private Permission perm; | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * Constructs an <code>AccessControlException</code> with the | |
| 52 | + * specified, detailed message. | |
| 53 | + * | |
| 54 | + * @param s the detail message. | |
| 55 | + */ | |
| 56 | + public AccessControlException(String s) { | |
| 57 | + super(s); | |
| 58 | + } | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * Constructs an <code>AccessControlException</code> with the | |
| 62 | + * specified, detailed message, and the requested permission that caused | |
| 63 | + * the exception. | |
| 64 | + * | |
| 65 | + * @param s the detail message. | |
| 66 | + * @param p the permission that caused the exception. | |
| 67 | + */ | |
| 68 | + public AccessControlException(String s, Permission p) { | |
| 69 | + super(s); | |
| 70 | + perm = p; | |
| 71 | + } | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * Gets the Permission object associated with this exeception, or | |
| 75 | + * null if there was no corresponding Permission object. | |
| 76 | + * | |
| 77 | + * @return the Permission object. | |
| 78 | + */ | |
| 79 | + public Permission getPermission() { | |
| 80 | + return perm; | |
| 81 | + } | |
| 82 | +} | |
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,557 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import sun.security.util.Debug; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * <p> The AccessController class is used for access control operations | |
| 32 | + * and decisions. | |
| 33 | + * | |
| 34 | + * <p> More specifically, the AccessController class is used for | |
| 35 | + * three purposes: | |
| 36 | + * | |
| 37 | + * <ul> | |
| 38 | + * <li> to decide whether an access to a critical system | |
| 39 | + * resource is to be allowed or denied, based on the security policy | |
| 40 | + * currently in effect,<p> | |
| 41 | + * <li>to mark code as being "privileged", thus affecting subsequent | |
| 42 | + * access determinations, and<p> | |
| 43 | + * <li>to obtain a "snapshot" of the current calling context so | |
| 44 | + * access-control decisions from a different context can be made with | |
| 45 | + * respect to the saved context. </ul> | |
| 46 | + * | |
| 47 | + * <p> The {@link #checkPermission(Permission) checkPermission} method | |
| 48 | + * determines whether the access request indicated by a specified | |
| 49 | + * permission should be granted or denied. A sample call appears | |
| 50 | + * below. In this example, <code>checkPermission</code> will determine | |
| 51 | + * whether or not to grant "read" access to the file named "testFile" in | |
| 52 | + * the "/temp" directory. | |
| 53 | + * | |
| 54 | + * <pre> | |
| 55 | + * | |
| 56 | + * FilePermission perm = new FilePermission("/temp/testFile", "read"); | |
| 57 | + * AccessController.checkPermission(perm); | |
| 58 | + * | |
| 59 | + * </pre> | |
| 60 | + * | |
| 61 | + * <p> If a requested access is allowed, | |
| 62 | + * <code>checkPermission</code> returns quietly. If denied, an | |
| 63 | + * AccessControlException is | |
| 64 | + * thrown. AccessControlException can also be thrown if the requested | |
| 65 | + * permission is of an incorrect type or contains an invalid value. | |
| 66 | + * Such information is given whenever possible. | |
| 67 | + * | |
| 68 | + * Suppose the current thread traversed m callers, in the order of caller 1 | |
| 69 | + * to caller 2 to caller m. Then caller m invoked the | |
| 70 | + * <code>checkPermission</code> method. | |
| 71 | + * The <code>checkPermission </code>method determines whether access | |
| 72 | + * is granted or denied based on the following algorithm: | |
| 73 | + * | |
| 74 | + * <pre> {@code | |
| 75 | + * for (int i = m; i > 0; i--) { | |
| 76 | + * | |
| 77 | + * if (caller i's domain does not have the permission) | |
| 78 | + * throw AccessControlException | |
| 79 | + * | |
| 80 | + * else if (caller i is marked as privileged) { | |
| 81 | + * if (a context was specified in the call to doPrivileged) | |
| 82 | + * context.checkPermission(permission) | |
| 83 | + * return; | |
| 84 | + * } | |
| 85 | + * }; | |
| 86 | + * | |
| 87 | + * // Next, check the context inherited when the thread was created. | |
| 88 | + * // Whenever a new thread is created, the AccessControlContext at | |
| 89 | + * // that time is stored and associated with the new thread, as the | |
| 90 | + * // "inherited" context. | |
| 91 | + * | |
| 92 | + * inheritedContext.checkPermission(permission); | |
| 93 | + * }</pre> | |
| 94 | + * | |
| 95 | + * <p> A caller can be marked as being "privileged" | |
| 96 | + * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below). | |
| 97 | + * When making access control decisions, the <code>checkPermission</code> | |
| 98 | + * method stops checking if it reaches a caller that | |
| 99 | + * was marked as "privileged" via a <code>doPrivileged</code> | |
| 100 | + * call without a context argument (see below for information about a | |
| 101 | + * context argument). If that caller's domain has the | |
| 102 | + * specified permission, no further checking is done and | |
| 103 | + * <code>checkPermission</code> | |
| 104 | + * returns quietly, indicating that the requested access is allowed. | |
| 105 | + * If that domain does not have the specified permission, an exception | |
| 106 | + * is thrown, as usual. | |
| 107 | + * | |
| 108 | + * <p> The normal use of the "privileged" feature is as follows. If you | |
| 109 | + * don't need to return a value from within the "privileged" block, do | |
| 110 | + * the following: | |
| 111 | + * | |
| 112 | + * <pre> {@code | |
| 113 | + * somemethod() { | |
| 114 | + * ...normal code here... | |
| 115 | + * AccessController.doPrivileged(new PrivilegedAction<Void>() { | |
| 116 | + * public Void run() { | |
| 117 | + * // privileged code goes here, for example: | |
| 118 | + * System.loadLibrary("awt"); | |
| 119 | + * return null; // nothing to return | |
| 120 | + * } | |
| 121 | + * }); | |
| 122 | + * ...normal code here... | |
| 123 | + * }}</pre> | |
| 124 | + * | |
| 125 | + * <p> | |
| 126 | + * PrivilegedAction is an interface with a single method, named | |
| 127 | + * <code>run</code>. | |
| 128 | + * The above example shows creation of an implementation | |
| 129 | + * of that interface; a concrete implementation of the | |
| 130 | + * <code>run</code> method is supplied. | |
| 131 | + * When the call to <code>doPrivileged</code> is made, an | |
| 132 | + * instance of the PrivilegedAction implementation is passed | |
| 133 | + * to it. The <code>doPrivileged</code> method calls the | |
| 134 | + * <code>run</code> method from the PrivilegedAction | |
| 135 | + * implementation after enabling privileges, and returns the | |
| 136 | + * <code>run</code> method's return value as the | |
| 137 | + * <code>doPrivileged</code> return value (which is | |
| 138 | + * ignored in this example). | |
| 139 | + * | |
| 140 | + * <p> If you need to return a value, you can do something like the following: | |
| 141 | + * | |
| 142 | + * <pre> {@code | |
| 143 | + * somemethod() { | |
| 144 | + * ...normal code here... | |
| 145 | + * String user = AccessController.doPrivileged( | |
| 146 | + * new PrivilegedAction<String>() { | |
| 147 | + * public String run() { | |
| 148 | + * return System.getProperty("user.name"); | |
| 149 | + * } | |
| 150 | + * }); | |
| 151 | + * ...normal code here... | |
| 152 | + * }}</pre> | |
| 153 | + * | |
| 154 | + * <p>If the action performed in your <code>run</code> method could | |
| 155 | + * throw a "checked" exception (those listed in the <code>throws</code> clause | |
| 156 | + * of a method), then you need to use the | |
| 157 | + * <code>PrivilegedExceptionAction</code> interface instead of the | |
| 158 | + * <code>PrivilegedAction</code> interface: | |
| 159 | + * | |
| 160 | + * <pre> {@code | |
| 161 | + * somemethod() throws FileNotFoundException { | |
| 162 | + * ...normal code here... | |
| 163 | + * try { | |
| 164 | + * FileInputStream fis = AccessController.doPrivileged( | |
| 165 | + * new PrivilegedExceptionAction<FileInputStream>() { | |
| 166 | + * public FileInputStream run() throws FileNotFoundException { | |
| 167 | + * return new FileInputStream("someFile"); | |
| 168 | + * } | |
| 169 | + * }); | |
| 170 | + * } catch (PrivilegedActionException e) { | |
| 171 | + * // e.getException() should be an instance of FileNotFoundException, | |
| 172 | + * // as only "checked" exceptions will be "wrapped" in a | |
| 173 | + * // PrivilegedActionException. | |
| 174 | + * throw (FileNotFoundException) e.getException(); | |
| 175 | + * } | |
| 176 | + * ...normal code here... | |
| 177 | + * }}</pre> | |
| 178 | + * | |
| 179 | + * <p> Be *very* careful in your use of the "privileged" construct, and | |
| 180 | + * always remember to make the privileged code section as small as possible. | |
| 181 | + * | |
| 182 | + * <p> Note that <code>checkPermission</code> always performs security checks | |
| 183 | + * within the context of the currently executing thread. | |
| 184 | + * Sometimes a security check that should be made within a given context | |
| 185 | + * will actually need to be done from within a | |
| 186 | + * <i>different</i> context (for example, from within a worker thread). | |
| 187 | + * The {@link #getContext() getContext} method and | |
| 188 | + * AccessControlContext class are provided | |
| 189 | + * for this situation. The <code>getContext</code> method takes a "snapshot" | |
| 190 | + * of the current calling context, and places | |
| 191 | + * it in an AccessControlContext object, which it returns. A sample call is | |
| 192 | + * the following: | |
| 193 | + * | |
| 194 | + * <pre> | |
| 195 | + * | |
| 196 | + * AccessControlContext acc = AccessController.getContext() | |
| 197 | + * | |
| 198 | + * </pre> | |
| 199 | + * | |
| 200 | + * <p> | |
| 201 | + * AccessControlContext itself has a <code>checkPermission</code> method | |
| 202 | + * that makes access decisions based on the context <i>it</i> encapsulates, | |
| 203 | + * rather than that of the current execution thread. | |
| 204 | + * Code within a different context can thus call that method on the | |
| 205 | + * previously-saved AccessControlContext object. A sample call is the | |
| 206 | + * following: | |
| 207 | + * | |
| 208 | + * <pre> | |
| 209 | + * | |
| 210 | + * acc.checkPermission(permission) | |
| 211 | + * | |
| 212 | + * </pre> | |
| 213 | + * | |
| 214 | + * <p> There are also times where you don't know a priori which permissions | |
| 215 | + * to check the context against. In these cases you can use the | |
| 216 | + * doPrivileged method that takes a context: | |
| 217 | + * | |
| 218 | + * <pre> {@code | |
| 219 | + * somemethod() { | |
| 220 | + * AccessController.doPrivileged(new PrivilegedAction<Object>() { | |
| 221 | + * public Object run() { | |
| 222 | + * // Code goes here. Any permission checks within this | |
| 223 | + * // run method will require that the intersection of the | |
| 224 | + * // callers protection domain and the snapshot's | |
| 225 | + * // context have the desired permission. | |
| 226 | + * } | |
| 227 | + * }, acc); | |
| 228 | + * ...normal code here... | |
| 229 | + * }}</pre> | |
| 230 | + * | |
| 231 | + * @see AccessControlContext | |
| 232 | + * | |
| 233 | + * @author Li Gong | |
| 234 | + * @author Roland Schemers | |
| 235 | + */ | |
| 236 | + | |
| 237 | +public final class AccessController { | |
| 238 | + | |
| 239 | + /** | |
| 240 | + * Don't allow anyone to instantiate an AccessController | |
| 241 | + */ | |
| 242 | + private AccessController() { } | |
| 243 | + | |
| 244 | + /** | |
| 245 | + * Performs the specified <code>PrivilegedAction</code> with privileges | |
| 246 | + * enabled. The action is performed with <i>all</i> of the permissions | |
| 247 | + * possessed by the caller's protection domain. | |
| 248 | + * | |
| 249 | + * <p> If the action's <code>run</code> method throws an (unchecked) | |
| 250 | + * exception, it will propagate through this method. | |
| 251 | + * | |
| 252 | + * <p> Note that any DomainCombiner associated with the current | |
| 253 | + * AccessControlContext will be ignored while the action is performed. | |
| 254 | + * | |
| 255 | + * @param action the action to be performed. | |
| 256 | + * | |
| 257 | + * @return the value returned by the action's <code>run</code> method. | |
| 258 | + * | |
| 259 | + * @exception NullPointerException if the action is <code>null</code> | |
| 260 | + * | |
| 261 | + * @see #doPrivileged(PrivilegedAction,AccessControlContext) | |
| 262 | + * @see #doPrivileged(PrivilegedExceptionAction) | |
| 263 | + * @see #doPrivilegedWithCombiner(PrivilegedAction) | |
| 264 | + * @see java.security.DomainCombiner | |
| 265 | + */ | |
| 266 | + | |
| 267 | + public static native <T> T doPrivileged(PrivilegedAction<T> action); | |
| 268 | + | |
| 269 | + /** | |
| 270 | + * Performs the specified <code>PrivilegedAction</code> with privileges | |
| 271 | + * enabled. The action is performed with <i>all</i> of the permissions | |
| 272 | + * possessed by the caller's protection domain. | |
| 273 | + * | |
| 274 | + * <p> If the action's <code>run</code> method throws an (unchecked) | |
| 275 | + * exception, it will propagate through this method. | |
| 276 | + * | |
| 277 | + * <p> This method preserves the current AccessControlContext's | |
| 278 | + * DomainCombiner (which may be null) while the action is performed. | |
| 279 | + * | |
| 280 | + * @param action the action to be performed. | |
| 281 | + * | |
| 282 | + * @return the value returned by the action's <code>run</code> method. | |
| 283 | + * | |
| 284 | + * @exception NullPointerException if the action is <code>null</code> | |
| 285 | + * | |
| 286 | + * @see #doPrivileged(PrivilegedAction) | |
| 287 | + * @see java.security.DomainCombiner | |
| 288 | + * | |
| 289 | + * @since 1.6 | |
| 290 | + */ | |
| 291 | + public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) { | |
| 292 | + | |
| 293 | + DomainCombiner dc = null; | |
| 294 | + AccessControlContext acc = getStackAccessControlContext(); | |
| 295 | + if (acc == null || (dc = acc.getAssignedCombiner()) == null) { | |
| 296 | + return AccessController.doPrivileged(action); | |
| 297 | + } | |
| 298 | + return AccessController.doPrivileged(action, preserveCombiner(dc)); | |
| 299 | + } | |
| 300 | + | |
| 301 | + | |
| 302 | + /** | |
| 303 | + * Performs the specified <code>PrivilegedAction</code> with privileges | |
| 304 | + * enabled and restricted by the specified | |
| 305 | + * <code>AccessControlContext</code>. | |
| 306 | + * The action is performed with the intersection of the permissions | |
| 307 | + * possessed by the caller's protection domain, and those possessed | |
| 308 | + * by the domains represented by the specified | |
| 309 | + * <code>AccessControlContext</code>. | |
| 310 | + * <p> | |
| 311 | + * If the action's <code>run</code> method throws an (unchecked) exception, | |
| 312 | + * it will propagate through this method. | |
| 313 | + * | |
| 314 | + * @param action the action to be performed. | |
| 315 | + * @param context an <i>access control context</i> | |
| 316 | + * representing the restriction to be applied to the | |
| 317 | + * caller's domain's privileges before performing | |
| 318 | + * the specified action. If the context is | |
| 319 | + * <code>null</code>, | |
| 320 | + * then no additional restriction is applied. | |
| 321 | + * | |
| 322 | + * @return the value returned by the action's <code>run</code> method. | |
| 323 | + * | |
| 324 | + * @exception NullPointerException if the action is <code>null</code> | |
| 325 | + * | |
| 326 | + * @see #doPrivileged(PrivilegedAction) | |
| 327 | + * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) | |
| 328 | + */ | |
| 329 | + public static native <T> T doPrivileged(PrivilegedAction<T> action, | |
| 330 | + AccessControlContext context); | |
| 331 | + | |
| 332 | + /** | |
| 333 | + * Performs the specified <code>PrivilegedExceptionAction</code> with | |
| 334 | + * privileges enabled. The action is performed with <i>all</i> of the | |
| 335 | + * permissions possessed by the caller's protection domain. | |
| 336 | + * | |
| 337 | + * <p> If the action's <code>run</code> method throws an <i>unchecked</i> | |
| 338 | + * exception, it will propagate through this method. | |
| 339 | + * | |
| 340 | + * <p> Note that any DomainCombiner associated with the current | |
| 341 | + * AccessControlContext will be ignored while the action is performed. | |
| 342 | + * | |
| 343 | + * @param action the action to be performed | |
| 344 | + * | |
| 345 | + * @return the value returned by the action's <code>run</code> method | |
| 346 | + * | |
| 347 | + * @exception PrivilegedActionException if the specified action's | |
| 348 | + * <code>run</code> method threw a <i>checked</i> exception | |
| 349 | + * @exception NullPointerException if the action is <code>null</code> | |
| 350 | + * | |
| 351 | + * @see #doPrivileged(PrivilegedAction) | |
| 352 | + * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) | |
| 353 | + * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction) | |
| 354 | + * @see java.security.DomainCombiner | |
| 355 | + */ | |
| 356 | + public static native <T> T | |
| 357 | + doPrivileged(PrivilegedExceptionAction<T> action) | |
| 358 | + throws PrivilegedActionException; | |
| 359 | + | |
| 360 | + | |
| 361 | + /** | |
| 362 | + * Performs the specified <code>PrivilegedExceptionAction</code> with | |
| 363 | + * privileges enabled. The action is performed with <i>all</i> of the | |
| 364 | + * permissions possessed by the caller's protection domain. | |
| 365 | + * | |
| 366 | + * <p> If the action's <code>run</code> method throws an <i>unchecked</i> | |
| 367 | + * exception, it will propagate through this method. | |
| 368 | + * | |
| 369 | + * <p> This method preserves the current AccessControlContext's | |
| 370 | + * DomainCombiner (which may be null) while the action is performed. | |
| 371 | + * | |
| 372 | + * @param action the action to be performed. | |
| 373 | + * | |
| 374 | + * @return the value returned by the action's <code>run</code> method | |
| 375 | + * | |
| 376 | + * @exception PrivilegedActionException if the specified action's | |
| 377 | + * <code>run</code> method threw a <i>checked</i> exception | |
| 378 | + * @exception NullPointerException if the action is <code>null</code> | |
| 379 | + * | |
| 380 | + * @see #doPrivileged(PrivilegedAction) | |
| 381 | + * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) | |
| 382 | + * @see java.security.DomainCombiner | |
| 383 | + * | |
| 384 | + * @since 1.6 | |
| 385 | + */ | |
| 386 | + public static <T> T doPrivilegedWithCombiner | |
| 387 | + (PrivilegedExceptionAction<T> action) throws PrivilegedActionException { | |
| 388 | + | |
| 389 | + DomainCombiner dc = null; | |
| 390 | + AccessControlContext acc = getStackAccessControlContext(); | |
| 391 | + if (acc == null || (dc = acc.getAssignedCombiner()) == null) { | |
| 392 | + return AccessController.doPrivileged(action); | |
| 393 | + } | |
| 394 | + return AccessController.doPrivileged(action, preserveCombiner(dc)); | |
| 395 | + } | |
| 396 | + | |
| 397 | + /** | |
| 398 | + * preserve the combiner across the doPrivileged call | |
| 399 | + */ | |
| 400 | + private static AccessControlContext preserveCombiner | |
| 401 | + (DomainCombiner combiner) { | |
| 402 | + | |
| 403 | + /** | |
| 404 | + * callerClass[0] = Reflection.getCallerClass | |
| 405 | + * callerClass[1] = AccessController.preserveCombiner | |
| 406 | + * callerClass[2] = AccessController.doPrivileged | |
| 407 | + * callerClass[3] = caller | |
| 408 | + */ | |
| 409 | + final Class callerClass = sun.reflect.Reflection.getCallerClass(3); | |
| 410 | + ProtectionDomain callerPd = doPrivileged | |
| 411 | + (new PrivilegedAction<ProtectionDomain>() { | |
| 412 | + public ProtectionDomain run() { | |
| 413 | + return callerClass.getProtectionDomain(); | |
| 414 | + } | |
| 415 | + }); | |
| 416 | + | |
| 417 | + // perform 'combine' on the caller of doPrivileged, | |
| 418 | + // even if the caller is from the bootclasspath | |
| 419 | + ProtectionDomain[] pds = new ProtectionDomain[] {callerPd}; | |
| 420 | + return new AccessControlContext(combiner.combine(pds, null), combiner); | |
| 421 | + } | |
| 422 | + | |
| 423 | + | |
| 424 | + /** | |
| 425 | + * Performs the specified <code>PrivilegedExceptionAction</code> with | |
| 426 | + * privileges enabled and restricted by the specified | |
| 427 | + * <code>AccessControlContext</code>. The action is performed with the | |
| 428 | + * intersection of the permissions possessed by the caller's | |
| 429 | + * protection domain, and those possessed by the domains represented by the | |
| 430 | + * specified <code>AccessControlContext</code>. | |
| 431 | + * <p> | |
| 432 | + * If the action's <code>run</code> method throws an <i>unchecked</i> | |
| 433 | + * exception, it will propagate through this method. | |
| 434 | + * | |
| 435 | + * @param action the action to be performed | |
| 436 | + * @param context an <i>access control context</i> | |
| 437 | + * representing the restriction to be applied to the | |
| 438 | + * caller's domain's privileges before performing | |
| 439 | + * the specified action. If the context is | |
| 440 | + * <code>null</code>, | |
| 441 | + * then no additional restriction is applied. | |
| 442 | + * | |
| 443 | + * @return the value returned by the action's <code>run</code> method | |
| 444 | + * | |
| 445 | + * @exception PrivilegedActionException if the specified action's | |
| 446 | + * <code>run</code> method | |
| 447 | + * threw a <i>checked</i> exception | |
| 448 | + * @exception NullPointerException if the action is <code>null</code> | |
| 449 | + * | |
| 450 | + * @see #doPrivileged(PrivilegedAction) | |
| 451 | + * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) | |
| 452 | + */ | |
| 453 | + public static native <T> T | |
| 454 | + doPrivileged(PrivilegedExceptionAction<T> action, | |
| 455 | + AccessControlContext context) | |
| 456 | + throws PrivilegedActionException; | |
| 457 | + | |
| 458 | + /** | |
| 459 | + * Returns the AccessControl context. i.e., it gets | |
| 460 | + * the protection domains of all the callers on the stack, | |
| 461 | + * starting at the first class with a non-null | |
| 462 | + * ProtectionDomain. | |
| 463 | + * | |
| 464 | + * @return the access control context based on the current stack or | |
| 465 | + * null if there was only privileged system code. | |
| 466 | + */ | |
| 467 | + | |
| 468 | + private static native AccessControlContext getStackAccessControlContext(); | |
| 469 | + | |
| 470 | + /** | |
| 471 | + * Returns the "inherited" AccessControl context. This is the context | |
| 472 | + * that existed when the thread was created. Package private so | |
| 473 | + * AccessControlContext can use it. | |
| 474 | + */ | |
| 475 | + | |
| 476 | + static native AccessControlContext getInheritedAccessControlContext(); | |
| 477 | + | |
| 478 | + /** | |
| 479 | + * This method takes a "snapshot" of the current calling context, which | |
| 480 | + * includes the current Thread's inherited AccessControlContext, | |
| 481 | + * and places it in an AccessControlContext object. This context may then | |
| 482 | + * be checked at a later point, possibly in another thread. | |
| 483 | + * | |
| 484 | + * @see AccessControlContext | |
| 485 | + * | |
| 486 | + * @return the AccessControlContext based on the current context. | |
| 487 | + */ | |
| 488 | + | |
| 489 | + public static AccessControlContext getContext() | |
| 490 | + { | |
| 491 | + AccessControlContext acc = getStackAccessControlContext(); | |
| 492 | + if (acc == null) { | |
| 493 | + // all we had was privileged system code. We don't want | |
| 494 | + // to return null though, so we construct a real ACC. | |
| 495 | + return new AccessControlContext(null, true); | |
| 496 | + } else { | |
| 497 | + return acc.optimize(); | |
| 498 | + } | |
| 499 | + } | |
| 500 | + | |
| 501 | + /** | |
| 502 | + * Determines whether the access request indicated by the | |
| 503 | + * specified permission should be allowed or denied, based on | |
| 504 | + * the current AccessControlContext and security policy. | |
| 505 | + * This method quietly returns if the access request | |
| 506 | + * is permitted, or throws an AccessControlException otherwise. The | |
| 507 | + * getPermission method of the AccessControlException returns the | |
| 508 | + * <code>perm</code> Permission object instance. | |
| 509 | + * | |
| 510 | + * @param perm the requested permission. | |
| 511 | + * | |
| 512 | + * @exception AccessControlException if the specified permission | |
| 513 | + * is not permitted, based on the current security policy. | |
| 514 | + * @exception NullPointerException if the specified permission | |
| 515 | + * is <code>null</code> and is checked based on the | |
| 516 | + * security policy currently in effect. | |
| 517 | + */ | |
| 518 | + | |
| 519 | + public static void checkPermission(Permission perm) | |
| 520 | + throws AccessControlException | |
| 521 | + { | |
| 522 | + //System.err.println("checkPermission "+perm); | |
| 523 | + //Thread.currentThread().dumpStack(); | |
| 524 | + | |
| 525 | + if (perm == null) { | |
| 526 | + throw new NullPointerException("permission can't be null"); | |
| 527 | + } | |
| 528 | + | |
| 529 | + AccessControlContext stack = getStackAccessControlContext(); | |
| 530 | + // if context is null, we had privileged system code on the stack. | |
| 531 | + if (stack == null) { | |
| 532 | + Debug debug = AccessControlContext.getDebug(); | |
| 533 | + boolean dumpDebug = false; | |
| 534 | + if (debug != null) { | |
| 535 | + dumpDebug = !Debug.isOn("codebase="); | |
| 536 | + dumpDebug &= !Debug.isOn("permission=") || | |
| 537 | + Debug.isOn("permission=" + perm.getClass().getCanonicalName()); | |
| 538 | + } | |
| 539 | + | |
| 540 | + if (dumpDebug && Debug.isOn("stack")) { | |
| 541 | + Thread.currentThread().dumpStack(); | |
| 542 | + } | |
| 543 | + | |
| 544 | + if (dumpDebug && Debug.isOn("domain")) { | |
| 545 | + debug.println("domain (context is null)"); | |
| 546 | + } | |
| 547 | + | |
| 548 | + if (dumpDebug) { | |
| 549 | + debug.println("access allowed "+perm); | |
| 550 | + } | |
| 551 | + return; | |
| 552 | + } | |
| 553 | + | |
| 554 | + AccessControlContext acc = stack.optimize(); | |
| 555 | + acc.checkPermission(perm); | |
| 556 | + } | |
| 557 | +} | |
Binary file not shown.
| @@ -0,0 +1,108 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.util.Set; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * This interface specifies constraints for cryptographic algorithms, | |
| 32 | + * keys (key sizes), and other algorithm parameters. | |
| 33 | + * <p> | |
| 34 | + * {@code AlgorithmConstraints} objects are immutable. An implementation | |
| 35 | + * of this interface should not provide methods that can change the state | |
| 36 | + * of an instance once it has been created. | |
| 37 | + * <p> | |
| 38 | + * Note that {@code AlgorithmConstraints} can be used to represent the | |
| 39 | + * restrictions described by the security properties | |
| 40 | + * {@code jdk.certpath.disabledAlgorithms} and | |
| 41 | + * {@code jdk.tls.disabledAlgorithms}, or could be used by a | |
| 42 | + * concrete {@code PKIXCertPathChecker} to check whether a specified | |
| 43 | + * certificate in the certification path contains the required algorithm | |
| 44 | + * constraints. | |
| 45 | + * | |
| 46 | + * @see javax.net.ssl.SSLParameters#getAlgorithmConstraints | |
| 47 | + * @see javax.net.ssl.SSLParameters#setAlgorithmConstraints(AlgorithmConstraints) | |
| 48 | + * | |
| 49 | + * @since 1.7 | |
| 50 | + */ | |
| 51 | + | |
| 52 | +public interface AlgorithmConstraints { | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * Determines whether an algorithm is granted permission for the | |
| 56 | + * specified cryptographic primitives. | |
| 57 | + * | |
| 58 | + * @param primitives a set of cryptographic primitives | |
| 59 | + * @param algorithm the algorithm name | |
| 60 | + * @param parameters the algorithm parameters, or null if no additional | |
| 61 | + * parameters | |
| 62 | + * | |
| 63 | + * @return true if the algorithm is permitted and can be used for all | |
| 64 | + * of the specified cryptographic primitives | |
| 65 | + * | |
| 66 | + * @throws IllegalArgumentException if primitives or algorithm is null | |
| 67 | + * or empty | |
| 68 | + */ | |
| 69 | + public boolean permits(Set<CryptoPrimitive> primitives, | |
| 70 | + String algorithm, AlgorithmParameters parameters); | |
| 71 | + | |
| 72 | + /** | |
| 73 | + * Determines whether a key is granted permission for the specified | |
| 74 | + * cryptographic primitives. | |
| 75 | + * <p> | |
| 76 | + * This method is usually used to check key size and key usage. | |
| 77 | + * | |
| 78 | + * @param primitives a set of cryptographic primitives | |
| 79 | + * @param key the key | |
| 80 | + * | |
| 81 | + * @return true if the key can be used for all of the specified | |
| 82 | + * cryptographic primitives | |
| 83 | + * | |
| 84 | + * @throws IllegalArgumentException if primitives is null or empty, | |
| 85 | + * or the key is null | |
| 86 | + */ | |
| 87 | + public boolean permits(Set<CryptoPrimitive> primitives, Key key); | |
| 88 | + | |
| 89 | + /** | |
| 90 | + * Determines whether an algorithm and the corresponding key are granted | |
| 91 | + * permission for the specified cryptographic primitives. | |
| 92 | + * | |
| 93 | + * @param primitives a set of cryptographic primitives | |
| 94 | + * @param algorithm the algorithm name | |
| 95 | + * @param key the key | |
| 96 | + * @param parameters the algorithm parameters, or null if no additional | |
| 97 | + * parameters | |
| 98 | + * | |
| 99 | + * @return true if the key and the algorithm can be used for all of the | |
| 100 | + * specified cryptographic primitives | |
| 101 | + * | |
| 102 | + * @throws IllegalArgumentException if primitives or algorithm is null | |
| 103 | + * or empty, or the key is null | |
| 104 | + */ | |
| 105 | + public boolean permits(Set<CryptoPrimitive> primitives, | |
| 106 | + String algorithm, Key key, AlgorithmParameters parameters); | |
| 107 | + | |
| 108 | +} | |
Binary file not shown.
| @@ -0,0 +1,343 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.security.spec.AlgorithmParameterSpec; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * The <code>AlgorithmParameterGenerator</code> class is used to generate a | |
| 32 | + * set of | |
| 33 | + * parameters to be used with a certain algorithm. Parameter generators | |
| 34 | + * are constructed using the <code>getInstance</code> factory methods | |
| 35 | + * (static methods that return instances of a given class). | |
| 36 | + * | |
| 37 | + * <P>The object that will generate the parameters can be initialized | |
| 38 | + * in two different ways: in an algorithm-independent manner, or in an | |
| 39 | + * algorithm-specific manner: | |
| 40 | + * | |
| 41 | + * <ul> | |
| 42 | + * <li>The algorithm-independent approach uses the fact that all parameter | |
| 43 | + * generators share the concept of a "size" and a | |
| 44 | + * source of randomness. The measure of size is universally shared | |
| 45 | + * by all algorithm parameters, though it is interpreted differently | |
| 46 | + * for different algorithms. For example, in the case of parameters for | |
| 47 | + * the <i>DSA</i> algorithm, "size" corresponds to the size | |
| 48 | + * of the prime modulus (in bits). | |
| 49 | + * When using this approach, algorithm-specific parameter generation | |
| 50 | + * values - if any - default to some standard values, unless they can be | |
| 51 | + * derived from the specified size.<P> | |
| 52 | + * | |
| 53 | + * <li>The other approach initializes a parameter generator object | |
| 54 | + * using algorithm-specific semantics, which are represented by a set of | |
| 55 | + * algorithm-specific parameter generation values. To generate | |
| 56 | + * Diffie-Hellman system parameters, for example, the parameter generation | |
| 57 | + * values usually | |
| 58 | + * consist of the size of the prime modulus and the size of the | |
| 59 | + * random exponent, both specified in number of bits. | |
| 60 | + * </ul> | |
| 61 | + * | |
| 62 | + * <P>In case the client does not explicitly initialize the | |
| 63 | + * AlgorithmParameterGenerator | |
| 64 | + * (via a call to an <code>init</code> method), each provider must supply (and | |
| 65 | + * document) a default initialization. For example, the Sun provider uses a | |
| 66 | + * default modulus prime size of 1024 bits for the generation of DSA | |
| 67 | + * parameters. | |
| 68 | + * | |
| 69 | + * <p> Every implementation of the Java platform is required to support the | |
| 70 | + * following standard <code>AlgorithmParameterGenerator</code> algorithms and | |
| 71 | + * keysizes in parentheses: | |
| 72 | + * <ul> | |
| 73 | + * <li><tt>DiffieHellman</tt> (1024)</li> | |
| 74 | + * <li><tt>DSA</tt> (1024)</li> | |
| 75 | + * </ul> | |
| 76 | + * These algorithms are described in the <a href= | |
| 77 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> | |
| 78 | + * AlgorithmParameterGenerator section</a> of the | |
| 79 | + * Java Cryptography Architecture Standard Algorithm Name Documentation. | |
| 80 | + * Consult the release documentation for your implementation to see if any | |
| 81 | + * other algorithms are supported. | |
| 82 | + * | |
| 83 | + * @author Jan Luehe | |
| 84 | + * | |
| 85 | + * | |
| 86 | + * @see AlgorithmParameters | |
| 87 | + * @see java.security.spec.AlgorithmParameterSpec | |
| 88 | + * | |
| 89 | + * @since 1.2 | |
| 90 | + */ | |
| 91 | + | |
| 92 | +public class AlgorithmParameterGenerator { | |
| 93 | + | |
| 94 | + // The provider | |
| 95 | + private Provider provider; | |
| 96 | + | |
| 97 | + // The provider implementation (delegate) | |
| 98 | + private AlgorithmParameterGeneratorSpi paramGenSpi; | |
| 99 | + | |
| 100 | + // The algorithm | |
| 101 | + private String algorithm; | |
| 102 | + | |
| 103 | + /** | |
| 104 | + * Creates an AlgorithmParameterGenerator object. | |
| 105 | + * | |
| 106 | + * @param paramGenSpi the delegate | |
| 107 | + * @param provider the provider | |
| 108 | + * @param algorithm the algorithm | |
| 109 | + */ | |
| 110 | + protected AlgorithmParameterGenerator | |
| 111 | + (AlgorithmParameterGeneratorSpi paramGenSpi, Provider provider, | |
| 112 | + String algorithm) { | |
| 113 | + this.paramGenSpi = paramGenSpi; | |
| 114 | + this.provider = provider; | |
| 115 | + this.algorithm = algorithm; | |
| 116 | + } | |
| 117 | + | |
| 118 | + /** | |
| 119 | + * Returns the standard name of the algorithm this parameter | |
| 120 | + * generator is associated with. | |
| 121 | + * | |
| 122 | + * @return the string name of the algorithm. | |
| 123 | + */ | |
| 124 | + public final String getAlgorithm() { | |
| 125 | + return this.algorithm; | |
| 126 | + } | |
| 127 | + | |
| 128 | + /** | |
| 129 | + * Returns an AlgorithmParameterGenerator object for generating | |
| 130 | + * a set of parameters to be used with the specified algorithm. | |
| 131 | + * | |
| 132 | + * <p> This method traverses the list of registered security Providers, | |
| 133 | + * starting with the most preferred Provider. | |
| 134 | + * A new AlgorithmParameterGenerator object encapsulating the | |
| 135 | + * AlgorithmParameterGeneratorSpi implementation from the first | |
| 136 | + * Provider that supports the specified algorithm is returned. | |
| 137 | + * | |
| 138 | + * <p> Note that the list of registered providers may be retrieved via | |
| 139 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 140 | + * | |
| 141 | + * @param algorithm the name of the algorithm this | |
| 142 | + * parameter generator is associated with. | |
| 143 | + * See the AlgorithmParameterGenerator section in the <a href= | |
| 144 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> | |
| 145 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 146 | + * for information about standard algorithm names. | |
| 147 | + * | |
| 148 | + * @return the new AlgorithmParameterGenerator object. | |
| 149 | + * | |
| 150 | + * @exception NoSuchAlgorithmException if no Provider supports an | |
| 151 | + * AlgorithmParameterGeneratorSpi implementation for the | |
| 152 | + * specified algorithm. | |
| 153 | + * | |
| 154 | + * @see Provider | |
| 155 | + */ | |
| 156 | + public static AlgorithmParameterGenerator getInstance(String algorithm) | |
| 157 | + throws NoSuchAlgorithmException { | |
| 158 | + try { | |
| 159 | + Object[] objs = Security.getImpl(algorithm, | |
| 160 | + "AlgorithmParameterGenerator", | |
| 161 | + (String)null); | |
| 162 | + return new AlgorithmParameterGenerator | |
| 163 | + ((AlgorithmParameterGeneratorSpi)objs[0], | |
| 164 | + (Provider)objs[1], | |
| 165 | + algorithm); | |
| 166 | + } catch(NoSuchProviderException e) { | |
| 167 | + throw new NoSuchAlgorithmException(algorithm + " not found"); | |
| 168 | + } | |
| 169 | + } | |
| 170 | + | |
| 171 | + /** | |
| 172 | + * Returns an AlgorithmParameterGenerator object for generating | |
| 173 | + * a set of parameters to be used with the specified algorithm. | |
| 174 | + * | |
| 175 | + * <p> A new AlgorithmParameterGenerator object encapsulating the | |
| 176 | + * AlgorithmParameterGeneratorSpi implementation from the specified provider | |
| 177 | + * is returned. The specified provider must be registered | |
| 178 | + * in the security provider list. | |
| 179 | + * | |
| 180 | + * <p> Note that the list of registered providers may be retrieved via | |
| 181 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 182 | + * | |
| 183 | + * @param algorithm the name of the algorithm this | |
| 184 | + * parameter generator is associated with. | |
| 185 | + * See the AlgorithmParameterGenerator section in the <a href= | |
| 186 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> | |
| 187 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 188 | + * for information about standard algorithm names. | |
| 189 | + * | |
| 190 | + * @param provider the string name of the Provider. | |
| 191 | + * | |
| 192 | + * @return the new AlgorithmParameterGenerator object. | |
| 193 | + * | |
| 194 | + * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi | |
| 195 | + * implementation for the specified algorithm is not | |
| 196 | + * available from the specified provider. | |
| 197 | + * | |
| 198 | + * @exception NoSuchProviderException if the specified provider is not | |
| 199 | + * registered in the security provider list. | |
| 200 | + * | |
| 201 | + * @exception IllegalArgumentException if the provider name is null | |
| 202 | + * or empty. | |
| 203 | + * | |
| 204 | + * @see Provider | |
| 205 | + */ | |
| 206 | + public static AlgorithmParameterGenerator getInstance(String algorithm, | |
| 207 | + String provider) | |
| 208 | + throws NoSuchAlgorithmException, NoSuchProviderException | |
| 209 | + { | |
| 210 | + if (provider == null || provider.length() == 0) | |
| 211 | + throw new IllegalArgumentException("missing provider"); | |
| 212 | + Object[] objs = Security.getImpl(algorithm, | |
| 213 | + "AlgorithmParameterGenerator", | |
| 214 | + provider); | |
| 215 | + return new AlgorithmParameterGenerator | |
| 216 | + ((AlgorithmParameterGeneratorSpi)objs[0], (Provider)objs[1], | |
| 217 | + algorithm); | |
| 218 | + } | |
| 219 | + | |
| 220 | + /** | |
| 221 | + * Returns an AlgorithmParameterGenerator object for generating | |
| 222 | + * a set of parameters to be used with the specified algorithm. | |
| 223 | + * | |
| 224 | + * <p> A new AlgorithmParameterGenerator object encapsulating the | |
| 225 | + * AlgorithmParameterGeneratorSpi implementation from the specified Provider | |
| 226 | + * object is returned. Note that the specified Provider object | |
| 227 | + * does not have to be registered in the provider list. | |
| 228 | + * | |
| 229 | + * @param algorithm the string name of the algorithm this | |
| 230 | + * parameter generator is associated with. | |
| 231 | + * See the AlgorithmParameterGenerator section in the <a href= | |
| 232 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator"> | |
| 233 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 234 | + * for information about standard algorithm names. | |
| 235 | + * | |
| 236 | + * @param provider the Provider object. | |
| 237 | + * | |
| 238 | + * @return the new AlgorithmParameterGenerator object. | |
| 239 | + * | |
| 240 | + * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi | |
| 241 | + * implementation for the specified algorithm is not available | |
| 242 | + * from the specified Provider object. | |
| 243 | + * | |
| 244 | + * @exception IllegalArgumentException if the specified provider is null. | |
| 245 | + * | |
| 246 | + * @see Provider | |
| 247 | + * | |
| 248 | + * @since 1.4 | |
| 249 | + */ | |
| 250 | + public static AlgorithmParameterGenerator getInstance(String algorithm, | |
| 251 | + Provider provider) | |
| 252 | + throws NoSuchAlgorithmException | |
| 253 | + { | |
| 254 | + if (provider == null) | |
| 255 | + throw new IllegalArgumentException("missing provider"); | |
| 256 | + Object[] objs = Security.getImpl(algorithm, | |
| 257 | + "AlgorithmParameterGenerator", | |
| 258 | + provider); | |
| 259 | + return new AlgorithmParameterGenerator | |
| 260 | + ((AlgorithmParameterGeneratorSpi)objs[0], (Provider)objs[1], | |
| 261 | + algorithm); | |
| 262 | + } | |
| 263 | + | |
| 264 | + /** | |
| 265 | + * Returns the provider of this algorithm parameter generator object. | |
| 266 | + * | |
| 267 | + * @return the provider of this algorithm parameter generator object | |
| 268 | + */ | |
| 269 | + public final Provider getProvider() { | |
| 270 | + return this.provider; | |
| 271 | + } | |
| 272 | + | |
| 273 | + /** | |
| 274 | + * Initializes this parameter generator for a certain size. | |
| 275 | + * To create the parameters, the <code>SecureRandom</code> | |
| 276 | + * implementation of the highest-priority installed provider is used as | |
| 277 | + * the source of randomness. | |
| 278 | + * (If none of the installed providers supply an implementation of | |
| 279 | + * <code>SecureRandom</code>, a system-provided source of randomness is | |
| 280 | + * used.) | |
| 281 | + * | |
| 282 | + * @param size the size (number of bits). | |
| 283 | + */ | |
| 284 | + public final void init(int size) { | |
| 285 | + paramGenSpi.engineInit(size, new SecureRandom()); | |
| 286 | + } | |
| 287 | + | |
| 288 | + /** | |
| 289 | + * Initializes this parameter generator for a certain size and source | |
| 290 | + * of randomness. | |
| 291 | + * | |
| 292 | + * @param size the size (number of bits). | |
| 293 | + * @param random the source of randomness. | |
| 294 | + */ | |
| 295 | + public final void init(int size, SecureRandom random) { | |
| 296 | + paramGenSpi.engineInit(size, random); | |
| 297 | + } | |
| 298 | + | |
| 299 | + /** | |
| 300 | + * Initializes this parameter generator with a set of algorithm-specific | |
| 301 | + * parameter generation values. | |
| 302 | + * To generate the parameters, the <code>SecureRandom</code> | |
| 303 | + * implementation of the highest-priority installed provider is used as | |
| 304 | + * the source of randomness. | |
| 305 | + * (If none of the installed providers supply an implementation of | |
| 306 | + * <code>SecureRandom</code>, a system-provided source of randomness is | |
| 307 | + * used.) | |
| 308 | + * | |
| 309 | + * @param genParamSpec the set of algorithm-specific parameter generation values. | |
| 310 | + * | |
| 311 | + * @exception InvalidAlgorithmParameterException if the given parameter | |
| 312 | + * generation values are inappropriate for this parameter generator. | |
| 313 | + */ | |
| 314 | + public final void init(AlgorithmParameterSpec genParamSpec) | |
| 315 | + throws InvalidAlgorithmParameterException { | |
| 316 | + paramGenSpi.engineInit(genParamSpec, new SecureRandom()); | |
| 317 | + } | |
| 318 | + | |
| 319 | + /** | |
| 320 | + * Initializes this parameter generator with a set of algorithm-specific | |
| 321 | + * parameter generation values. | |
| 322 | + * | |
| 323 | + * @param genParamSpec the set of algorithm-specific parameter generation values. | |
| 324 | + * @param random the source of randomness. | |
| 325 | + * | |
| 326 | + * @exception InvalidAlgorithmParameterException if the given parameter | |
| 327 | + * generation values are inappropriate for this parameter generator. | |
| 328 | + */ | |
| 329 | + public final void init(AlgorithmParameterSpec genParamSpec, | |
| 330 | + SecureRandom random) | |
| 331 | + throws InvalidAlgorithmParameterException { | |
| 332 | + paramGenSpi.engineInit(genParamSpec, random); | |
| 333 | + } | |
| 334 | + | |
| 335 | + /** | |
| 336 | + * Generates the parameters. | |
| 337 | + * | |
| 338 | + * @return the new AlgorithmParameters object. | |
| 339 | + */ | |
| 340 | + public final AlgorithmParameters generateParameters() { | |
| 341 | + return paramGenSpi.engineGenerateParameters(); | |
| 342 | + } | |
| 343 | +} | |
Binary file not shown.
| @@ -0,0 +1,86 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.security.spec.AlgorithmParameterSpec; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) | |
| 32 | + * for the <code>AlgorithmParameterGenerator</code> class, which | |
| 33 | + * is used to generate a set of parameters to be used with a certain algorithm. | |
| 34 | + * | |
| 35 | + * <p> All the abstract methods in this class must be implemented by each | |
| 36 | + * cryptographic service provider who wishes to supply the implementation | |
| 37 | + * of a parameter generator for a particular algorithm. | |
| 38 | + * | |
| 39 | + * <p> In case the client does not explicitly initialize the | |
| 40 | + * AlgorithmParameterGenerator (via a call to an <code>engineInit</code> | |
| 41 | + * method), each provider must supply (and document) a default initialization. | |
| 42 | + * For example, the Sun provider uses a default modulus prime size of 1024 | |
| 43 | + * bits for the generation of DSA parameters. | |
| 44 | + * | |
| 45 | + * @author Jan Luehe | |
| 46 | + * | |
| 47 | + * | |
| 48 | + * @see AlgorithmParameterGenerator | |
| 49 | + * @see AlgorithmParameters | |
| 50 | + * @see java.security.spec.AlgorithmParameterSpec | |
| 51 | + * | |
| 52 | + * @since 1.2 | |
| 53 | + */ | |
| 54 | + | |
| 55 | +public abstract class AlgorithmParameterGeneratorSpi { | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * Initializes this parameter generator for a certain size | |
| 59 | + * and source of randomness. | |
| 60 | + * | |
| 61 | + * @param size the size (number of bits). | |
| 62 | + * @param random the source of randomness. | |
| 63 | + */ | |
| 64 | + protected abstract void engineInit(int size, SecureRandom random); | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * Initializes this parameter generator with a set of | |
| 68 | + * algorithm-specific parameter generation values. | |
| 69 | + * | |
| 70 | + * @param genParamSpec the set of algorithm-specific parameter generation values. | |
| 71 | + * @param random the source of randomness. | |
| 72 | + * | |
| 73 | + * @exception InvalidAlgorithmParameterException if the given parameter | |
| 74 | + * generation values are inappropriate for this parameter generator. | |
| 75 | + */ | |
| 76 | + protected abstract void engineInit(AlgorithmParameterSpec genParamSpec, | |
| 77 | + SecureRandom random) | |
| 78 | + throws InvalidAlgorithmParameterException; | |
| 79 | + | |
| 80 | + /** | |
| 81 | + * Generates the parameters. | |
| 82 | + * | |
| 83 | + * @return the new AlgorithmParameters object. | |
| 84 | + */ | |
| 85 | + protected abstract AlgorithmParameters engineGenerateParameters(); | |
| 86 | +} | |
Binary file not shown.
| @@ -0,0 +1,398 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.*; | |
| 29 | +import java.security.spec.AlgorithmParameterSpec; | |
| 30 | +import java.security.spec.InvalidParameterSpecException; | |
| 31 | + | |
| 32 | +/** | |
| 33 | + * This class is used as an opaque representation of cryptographic parameters. | |
| 34 | + * | |
| 35 | + * <p>An <code>AlgorithmParameters</code> object for managing the parameters | |
| 36 | + * for a particular algorithm can be obtained by | |
| 37 | + * calling one of the <code>getInstance</code> factory methods | |
| 38 | + * (static methods that return instances of a given class). | |
| 39 | + * | |
| 40 | + * <p>Once an <code>AlgorithmParameters</code> object is obtained, it must be | |
| 41 | + * initialized via a call to <code>init</code>, using an appropriate parameter | |
| 42 | + * specification or parameter encoding. | |
| 43 | + * | |
| 44 | + * <p>A transparent parameter specification is obtained from an | |
| 45 | + * <code>AlgorithmParameters</code> object via a call to | |
| 46 | + * <code>getParameterSpec</code>, and a byte encoding of the parameters is | |
| 47 | + * obtained via a call to <code>getEncoded</code>. | |
| 48 | + * | |
| 49 | + * <p> Every implementation of the Java platform is required to support the | |
| 50 | + * following standard <code>AlgorithmParameters</code> algorithms: | |
| 51 | + * <ul> | |
| 52 | + * <li><tt>AES</tt></li> | |
| 53 | + * <li><tt>DES</tt></li> | |
| 54 | + * <li><tt>DESede</tt></li> | |
| 55 | + * <li><tt>DiffieHellman</tt></li> | |
| 56 | + * <li><tt>DSA</tt></li> | |
| 57 | + * </ul> | |
| 58 | + * These algorithms are described in the <a href= | |
| 59 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters"> | |
| 60 | + * AlgorithmParameters section</a> of the | |
| 61 | + * Java Cryptography Architecture Standard Algorithm Name Documentation. | |
| 62 | + * Consult the release documentation for your implementation to see if any | |
| 63 | + * other algorithms are supported. | |
| 64 | + * | |
| 65 | + * @author Jan Luehe | |
| 66 | + * | |
| 67 | + * | |
| 68 | + * @see java.security.spec.AlgorithmParameterSpec | |
| 69 | + * @see java.security.spec.DSAParameterSpec | |
| 70 | + * @see KeyPairGenerator | |
| 71 | + * | |
| 72 | + * @since 1.2 | |
| 73 | + */ | |
| 74 | + | |
| 75 | +public class AlgorithmParameters { | |
| 76 | + | |
| 77 | + // The provider | |
| 78 | + private Provider provider; | |
| 79 | + | |
| 80 | + // The provider implementation (delegate) | |
| 81 | + private AlgorithmParametersSpi paramSpi; | |
| 82 | + | |
| 83 | + // The algorithm | |
| 84 | + private String algorithm; | |
| 85 | + | |
| 86 | + // Has this object been initialized? | |
| 87 | + private boolean initialized = false; | |
| 88 | + | |
| 89 | + /** | |
| 90 | + * Creates an AlgorithmParameters object. | |
| 91 | + * | |
| 92 | + * @param paramSpi the delegate | |
| 93 | + * @param provider the provider | |
| 94 | + * @param algorithm the algorithm | |
| 95 | + */ | |
| 96 | + protected AlgorithmParameters(AlgorithmParametersSpi paramSpi, | |
| 97 | + Provider provider, String algorithm) | |
| 98 | + { | |
| 99 | + this.paramSpi = paramSpi; | |
| 100 | + this.provider = provider; | |
| 101 | + this.algorithm = algorithm; | |
| 102 | + } | |
| 103 | + | |
| 104 | + /** | |
| 105 | + * Returns the name of the algorithm associated with this parameter object. | |
| 106 | + * | |
| 107 | + * @return the algorithm name. | |
| 108 | + */ | |
| 109 | + public final String getAlgorithm() { | |
| 110 | + return this.algorithm; | |
| 111 | + } | |
| 112 | + | |
| 113 | + /** | |
| 114 | + * Returns a parameter object for the specified algorithm. | |
| 115 | + * | |
| 116 | + * <p> This method traverses the list of registered security Providers, | |
| 117 | + * starting with the most preferred Provider. | |
| 118 | + * A new AlgorithmParameters object encapsulating the | |
| 119 | + * AlgorithmParametersSpi implementation from the first | |
| 120 | + * Provider that supports the specified algorithm is returned. | |
| 121 | + * | |
| 122 | + * <p> Note that the list of registered providers may be retrieved via | |
| 123 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 124 | + * | |
| 125 | + * <p> The returned parameter object must be initialized via a call to | |
| 126 | + * <code>init</code>, using an appropriate parameter specification or | |
| 127 | + * parameter encoding. | |
| 128 | + * | |
| 129 | + * @param algorithm the name of the algorithm requested. | |
| 130 | + * See the AlgorithmParameters section in the <a href= | |
| 131 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters"> | |
| 132 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 133 | + * for information about standard algorithm names. | |
| 134 | + * | |
| 135 | + * @return the new parameter object. | |
| 136 | + * | |
| 137 | + * @exception NoSuchAlgorithmException if no Provider supports an | |
| 138 | + * AlgorithmParametersSpi implementation for the | |
| 139 | + * specified algorithm. | |
| 140 | + * | |
| 141 | + * @see Provider | |
| 142 | + */ | |
| 143 | + public static AlgorithmParameters getInstance(String algorithm) | |
| 144 | + throws NoSuchAlgorithmException { | |
| 145 | + try { | |
| 146 | + Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters", | |
| 147 | + (String)null); | |
| 148 | + return new AlgorithmParameters((AlgorithmParametersSpi)objs[0], | |
| 149 | + (Provider)objs[1], | |
| 150 | + algorithm); | |
| 151 | + } catch(NoSuchProviderException e) { | |
| 152 | + throw new NoSuchAlgorithmException(algorithm + " not found"); | |
| 153 | + } | |
| 154 | + } | |
| 155 | + | |
| 156 | + /** | |
| 157 | + * Returns a parameter object for the specified algorithm. | |
| 158 | + * | |
| 159 | + * <p> A new AlgorithmParameters object encapsulating the | |
| 160 | + * AlgorithmParametersSpi implementation from the specified provider | |
| 161 | + * is returned. The specified provider must be registered | |
| 162 | + * in the security provider list. | |
| 163 | + * | |
| 164 | + * <p> Note that the list of registered providers may be retrieved via | |
| 165 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 166 | + * | |
| 167 | + * <p>The returned parameter object must be initialized via a call to | |
| 168 | + * <code>init</code>, using an appropriate parameter specification or | |
| 169 | + * parameter encoding. | |
| 170 | + * | |
| 171 | + * @param algorithm the name of the algorithm requested. | |
| 172 | + * See the AlgorithmParameters section in the <a href= | |
| 173 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters"> | |
| 174 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 175 | + * for information about standard algorithm names. | |
| 176 | + * | |
| 177 | + * @param provider the name of the provider. | |
| 178 | + * | |
| 179 | + * @return the new parameter object. | |
| 180 | + * | |
| 181 | + * @exception NoSuchAlgorithmException if an AlgorithmParametersSpi | |
| 182 | + * implementation for the specified algorithm is not | |
| 183 | + * available from the specified provider. | |
| 184 | + * | |
| 185 | + * @exception NoSuchProviderException if the specified provider is not | |
| 186 | + * registered in the security provider list. | |
| 187 | + * | |
| 188 | + * @exception IllegalArgumentException if the provider name is null | |
| 189 | + * or empty. | |
| 190 | + * | |
| 191 | + * @see Provider | |
| 192 | + */ | |
| 193 | + public static AlgorithmParameters getInstance(String algorithm, | |
| 194 | + String provider) | |
| 195 | + throws NoSuchAlgorithmException, NoSuchProviderException | |
| 196 | + { | |
| 197 | + if (provider == null || provider.length() == 0) | |
| 198 | + throw new IllegalArgumentException("missing provider"); | |
| 199 | + Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters", | |
| 200 | + provider); | |
| 201 | + return new AlgorithmParameters((AlgorithmParametersSpi)objs[0], | |
| 202 | + (Provider)objs[1], | |
| 203 | + algorithm); | |
| 204 | + } | |
| 205 | + | |
| 206 | + /** | |
| 207 | + * Returns a parameter object for the specified algorithm. | |
| 208 | + * | |
| 209 | + * <p> A new AlgorithmParameters object encapsulating the | |
| 210 | + * AlgorithmParametersSpi implementation from the specified Provider | |
| 211 | + * object is returned. Note that the specified Provider object | |
| 212 | + * does not have to be registered in the provider list. | |
| 213 | + * | |
| 214 | + * <p>The returned parameter object must be initialized via a call to | |
| 215 | + * <code>init</code>, using an appropriate parameter specification or | |
| 216 | + * parameter encoding. | |
| 217 | + * | |
| 218 | + * @param algorithm the name of the algorithm requested. | |
| 219 | + * See the AlgorithmParameters section in the <a href= | |
| 220 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters"> | |
| 221 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 222 | + * for information about standard algorithm names. | |
| 223 | + * | |
| 224 | + * @param provider the name of the provider. | |
| 225 | + * | |
| 226 | + * @return the new parameter object. | |
| 227 | + * | |
| 228 | + * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi | |
| 229 | + * implementation for the specified algorithm is not available | |
| 230 | + * from the specified Provider object. | |
| 231 | + * | |
| 232 | + * @exception IllegalArgumentException if the provider is null. | |
| 233 | + * | |
| 234 | + * @see Provider | |
| 235 | + * | |
| 236 | + * @since 1.4 | |
| 237 | + */ | |
| 238 | + public static AlgorithmParameters getInstance(String algorithm, | |
| 239 | + Provider provider) | |
| 240 | + throws NoSuchAlgorithmException | |
| 241 | + { | |
| 242 | + if (provider == null) | |
| 243 | + throw new IllegalArgumentException("missing provider"); | |
| 244 | + Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters", | |
| 245 | + provider); | |
| 246 | + return new AlgorithmParameters((AlgorithmParametersSpi)objs[0], | |
| 247 | + (Provider)objs[1], | |
| 248 | + algorithm); | |
| 249 | + } | |
| 250 | + | |
| 251 | + /** | |
| 252 | + * Returns the provider of this parameter object. | |
| 253 | + * | |
| 254 | + * @return the provider of this parameter object | |
| 255 | + */ | |
| 256 | + public final Provider getProvider() { | |
| 257 | + return this.provider; | |
| 258 | + } | |
| 259 | + | |
| 260 | + /** | |
| 261 | + * Initializes this parameter object using the parameters | |
| 262 | + * specified in <code>paramSpec</code>. | |
| 263 | + * | |
| 264 | + * @param paramSpec the parameter specification. | |
| 265 | + * | |
| 266 | + * @exception InvalidParameterSpecException if the given parameter | |
| 267 | + * specification is inappropriate for the initialization of this parameter | |
| 268 | + * object, or if this parameter object has already been initialized. | |
| 269 | + */ | |
| 270 | + public final void init(AlgorithmParameterSpec paramSpec) | |
| 271 | + throws InvalidParameterSpecException | |
| 272 | + { | |
| 273 | + if (this.initialized) | |
| 274 | + throw new InvalidParameterSpecException("already initialized"); | |
| 275 | + paramSpi.engineInit(paramSpec); | |
| 276 | + this.initialized = true; | |
| 277 | + } | |
| 278 | + | |
| 279 | + /** | |
| 280 | + * Imports the specified parameters and decodes them according to the | |
| 281 | + * primary decoding format for parameters. The primary decoding | |
| 282 | + * format for parameters is ASN.1, if an ASN.1 specification for this type | |
| 283 | + * of parameters exists. | |
| 284 | + * | |
| 285 | + * @param params the encoded parameters. | |
| 286 | + * | |
| 287 | + * @exception IOException on decoding errors, or if this parameter object | |
| 288 | + * has already been initialized. | |
| 289 | + */ | |
| 290 | + public final void init(byte[] params) throws IOException { | |
| 291 | + if (this.initialized) | |
| 292 | + throw new IOException("already initialized"); | |
| 293 | + paramSpi.engineInit(params); | |
| 294 | + this.initialized = true; | |
| 295 | + } | |
| 296 | + | |
| 297 | + /** | |
| 298 | + * Imports the parameters from <code>params</code> and decodes them | |
| 299 | + * according to the specified decoding scheme. | |
| 300 | + * If <code>format</code> is null, the | |
| 301 | + * primary decoding format for parameters is used. The primary decoding | |
| 302 | + * format is ASN.1, if an ASN.1 specification for these parameters | |
| 303 | + * exists. | |
| 304 | + * | |
| 305 | + * @param params the encoded parameters. | |
| 306 | + * | |
| 307 | + * @param format the name of the decoding scheme. | |
| 308 | + * | |
| 309 | + * @exception IOException on decoding errors, or if this parameter object | |
| 310 | + * has already been initialized. | |
| 311 | + */ | |
| 312 | + public final void init(byte[] params, String format) throws IOException { | |
| 313 | + if (this.initialized) | |
| 314 | + throw new IOException("already initialized"); | |
| 315 | + paramSpi.engineInit(params, format); | |
| 316 | + this.initialized = true; | |
| 317 | + } | |
| 318 | + | |
| 319 | + /** | |
| 320 | + * Returns a (transparent) specification of this parameter object. | |
| 321 | + * <code>paramSpec</code> identifies the specification class in which | |
| 322 | + * the parameters should be returned. It could, for example, be | |
| 323 | + * <code>DSAParameterSpec.class</code>, to indicate that the | |
| 324 | + * parameters should be returned in an instance of the | |
| 325 | + * <code>DSAParameterSpec</code> class. | |
| 326 | + * | |
| 327 | + * @param paramSpec the specification class in which | |
| 328 | + * the parameters should be returned. | |
| 329 | + * | |
| 330 | + * @return the parameter specification. | |
| 331 | + * | |
| 332 | + * @exception InvalidParameterSpecException if the requested parameter | |
| 333 | + * specification is inappropriate for this parameter object, or if this | |
| 334 | + * parameter object has not been initialized. | |
| 335 | + */ | |
| 336 | + public final <T extends AlgorithmParameterSpec> | |
| 337 | + T getParameterSpec(Class<T> paramSpec) | |
| 338 | + throws InvalidParameterSpecException | |
| 339 | + { | |
| 340 | + if (this.initialized == false) { | |
| 341 | + throw new InvalidParameterSpecException("not initialized"); | |
| 342 | + } | |
| 343 | + return paramSpi.engineGetParameterSpec(paramSpec); | |
| 344 | + } | |
| 345 | + | |
| 346 | + /** | |
| 347 | + * Returns the parameters in their primary encoding format. | |
| 348 | + * The primary encoding format for parameters is ASN.1, if an ASN.1 | |
| 349 | + * specification for this type of parameters exists. | |
| 350 | + * | |
| 351 | + * @return the parameters encoded using their primary encoding format. | |
| 352 | + * | |
| 353 | + * @exception IOException on encoding errors, or if this parameter object | |
| 354 | + * has not been initialized. | |
| 355 | + */ | |
| 356 | + public final byte[] getEncoded() throws IOException | |
| 357 | + { | |
| 358 | + if (this.initialized == false) { | |
| 359 | + throw new IOException("not initialized"); | |
| 360 | + } | |
| 361 | + return paramSpi.engineGetEncoded(); | |
| 362 | + } | |
| 363 | + | |
| 364 | + /** | |
| 365 | + * Returns the parameters encoded in the specified scheme. | |
| 366 | + * If <code>format</code> is null, the | |
| 367 | + * primary encoding format for parameters is used. The primary encoding | |
| 368 | + * format is ASN.1, if an ASN.1 specification for these parameters | |
| 369 | + * exists. | |
| 370 | + * | |
| 371 | + * @param format the name of the encoding format. | |
| 372 | + * | |
| 373 | + * @return the parameters encoded using the specified encoding scheme. | |
| 374 | + * | |
| 375 | + * @exception IOException on encoding errors, or if this parameter object | |
| 376 | + * has not been initialized. | |
| 377 | + */ | |
| 378 | + public final byte[] getEncoded(String format) throws IOException | |
| 379 | + { | |
| 380 | + if (this.initialized == false) { | |
| 381 | + throw new IOException("not initialized"); | |
| 382 | + } | |
| 383 | + return paramSpi.engineGetEncoded(format); | |
| 384 | + } | |
| 385 | + | |
| 386 | + /** | |
| 387 | + * Returns a formatted string describing the parameters. | |
| 388 | + * | |
| 389 | + * @return a formatted string describing the parameters, or null if this | |
| 390 | + * parameter object has not been initialized. | |
| 391 | + */ | |
| 392 | + public final String toString() { | |
| 393 | + if (this.initialized == false) { | |
| 394 | + return null; | |
| 395 | + } | |
| 396 | + return paramSpi.engineToString(); | |
| 397 | + } | |
| 398 | +} | |
Binary file not shown.
| @@ -0,0 +1,151 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.*; | |
| 29 | +import java.security.spec.AlgorithmParameterSpec; | |
| 30 | +import java.security.spec.InvalidParameterSpecException; | |
| 31 | + | |
| 32 | +/** | |
| 33 | + * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) | |
| 34 | + * for the <code>AlgorithmParameters</code> class, which is used to manage | |
| 35 | + * algorithm parameters. | |
| 36 | + * | |
| 37 | + * <p> All the abstract methods in this class must be implemented by each | |
| 38 | + * cryptographic service provider who wishes to supply parameter management | |
| 39 | + * for a particular algorithm. | |
| 40 | + * | |
| 41 | + * @author Jan Luehe | |
| 42 | + * | |
| 43 | + * | |
| 44 | + * @see AlgorithmParameters | |
| 45 | + * @see java.security.spec.AlgorithmParameterSpec | |
| 46 | + * @see java.security.spec.DSAParameterSpec | |
| 47 | + * | |
| 48 | + * @since 1.2 | |
| 49 | + */ | |
| 50 | + | |
| 51 | +public abstract class AlgorithmParametersSpi { | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * Initializes this parameters object using the parameters | |
| 55 | + * specified in <code>paramSpec</code>. | |
| 56 | + * | |
| 57 | + * @param paramSpec the parameter specification. | |
| 58 | + * | |
| 59 | + * @exception InvalidParameterSpecException if the given parameter | |
| 60 | + * specification is inappropriate for the initialization of this parameter | |
| 61 | + * object. | |
| 62 | + */ | |
| 63 | + protected abstract void engineInit(AlgorithmParameterSpec paramSpec) | |
| 64 | + throws InvalidParameterSpecException; | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * Imports the specified parameters and decodes them | |
| 68 | + * according to the primary decoding format for parameters. | |
| 69 | + * The primary decoding format for parameters is ASN.1, if an ASN.1 | |
| 70 | + * specification for this type of parameters exists. | |
| 71 | + * | |
| 72 | + * @param params the encoded parameters. | |
| 73 | + * | |
| 74 | + * @exception IOException on decoding errors | |
| 75 | + */ | |
| 76 | + protected abstract void engineInit(byte[] params) | |
| 77 | + throws IOException; | |
| 78 | + | |
| 79 | + /** | |
| 80 | + * Imports the parameters from <code>params</code> and | |
| 81 | + * decodes them according to the specified decoding format. | |
| 82 | + * If <code>format</code> is null, the | |
| 83 | + * primary decoding format for parameters is used. The primary decoding | |
| 84 | + * format is ASN.1, if an ASN.1 specification for these parameters | |
| 85 | + * exists. | |
| 86 | + * | |
| 87 | + * @param params the encoded parameters. | |
| 88 | + * | |
| 89 | + * @param format the name of the decoding format. | |
| 90 | + * | |
| 91 | + * @exception IOException on decoding errors | |
| 92 | + */ | |
| 93 | + protected abstract void engineInit(byte[] params, String format) | |
| 94 | + throws IOException; | |
| 95 | + | |
| 96 | + /** | |
| 97 | + * Returns a (transparent) specification of this parameters | |
| 98 | + * object. | |
| 99 | + * <code>paramSpec</code> identifies the specification class in which | |
| 100 | + * the parameters should be returned. It could, for example, be | |
| 101 | + * <code>DSAParameterSpec.class</code>, to indicate that the | |
| 102 | + * parameters should be returned in an instance of the | |
| 103 | + * <code>DSAParameterSpec</code> class. | |
| 104 | + * | |
| 105 | + * @param paramSpec the specification class in which | |
| 106 | + * the parameters should be returned. | |
| 107 | + * | |
| 108 | + * @return the parameter specification. | |
| 109 | + * | |
| 110 | + * @exception InvalidParameterSpecException if the requested parameter | |
| 111 | + * specification is inappropriate for this parameter object. | |
| 112 | + */ | |
| 113 | + protected abstract | |
| 114 | + <T extends AlgorithmParameterSpec> | |
| 115 | + T engineGetParameterSpec(Class<T> paramSpec) | |
| 116 | + throws InvalidParameterSpecException; | |
| 117 | + | |
| 118 | + /** | |
| 119 | + * Returns the parameters in their primary encoding format. | |
| 120 | + * The primary encoding format for parameters is ASN.1, if an ASN.1 | |
| 121 | + * specification for this type of parameters exists. | |
| 122 | + * | |
| 123 | + * @return the parameters encoded using their primary encoding format. | |
| 124 | + * | |
| 125 | + * @exception IOException on encoding errors. | |
| 126 | + */ | |
| 127 | + protected abstract byte[] engineGetEncoded() throws IOException; | |
| 128 | + | |
| 129 | + /** | |
| 130 | + * Returns the parameters encoded in the specified format. | |
| 131 | + * If <code>format</code> is null, the | |
| 132 | + * primary encoding format for parameters is used. The primary encoding | |
| 133 | + * format is ASN.1, if an ASN.1 specification for these parameters | |
| 134 | + * exists. | |
| 135 | + * | |
| 136 | + * @param format the name of the encoding format. | |
| 137 | + * | |
| 138 | + * @return the parameters encoded using the specified encoding scheme. | |
| 139 | + * | |
| 140 | + * @exception IOException on encoding errors. | |
| 141 | + */ | |
| 142 | + protected abstract byte[] engineGetEncoded(String format) | |
| 143 | + throws IOException; | |
| 144 | + | |
| 145 | + /** | |
| 146 | + * Returns a formatted string describing the parameters. | |
| 147 | + * | |
| 148 | + * @return a formatted string describing the parameters. | |
| 149 | + */ | |
| 150 | + protected abstract String engineToString(); | |
| 151 | +} | |
Binary file not shown.
| @@ -0,0 +1,237 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.security.*; | |
| 29 | +import java.util.Enumeration; | |
| 30 | +import java.util.Hashtable; | |
| 31 | +import java.util.StringTokenizer; | |
| 32 | +import sun.security.util.SecurityConstants; | |
| 33 | + | |
| 34 | +/** | |
| 35 | + * The AllPermission is a permission that implies all other permissions. | |
| 36 | + * <p> | |
| 37 | + * <b>Note:</b> Granting AllPermission should be done with extreme care, | |
| 38 | + * as it implies all other permissions. Thus, it grants code the ability | |
| 39 | + * to run with security | |
| 40 | + * disabled. Extreme caution should be taken before granting such | |
| 41 | + * a permission to code. This permission should be used only during testing, | |
| 42 | + * or in extremely rare cases where an application or applet is | |
| 43 | + * completely trusted and adding the necessary permissions to the policy | |
| 44 | + * is prohibitively cumbersome. | |
| 45 | + * | |
| 46 | + * @see java.security.Permission | |
| 47 | + * @see java.security.AccessController | |
| 48 | + * @see java.security.Permissions | |
| 49 | + * @see java.security.PermissionCollection | |
| 50 | + * @see java.lang.SecurityManager | |
| 51 | + * | |
| 52 | + * | |
| 53 | + * @author Roland Schemers | |
| 54 | + * | |
| 55 | + * @serial exclude | |
| 56 | + */ | |
| 57 | + | |
| 58 | +public final class AllPermission extends Permission { | |
| 59 | + | |
| 60 | + private static final long serialVersionUID = -2916474571451318075L; | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * Creates a new AllPermission object. | |
| 64 | + */ | |
| 65 | + | |
| 66 | + public AllPermission() | |
| 67 | + { | |
| 68 | + super("<all permissions>"); | |
| 69 | + } | |
| 70 | + | |
| 71 | + | |
| 72 | + /** | |
| 73 | + * Creates a new AllPermission object. This | |
| 74 | + * constructor exists for use by the <code>Policy</code> object | |
| 75 | + * to instantiate new Permission objects. | |
| 76 | + * | |
| 77 | + * @param name ignored | |
| 78 | + * @param actions ignored. | |
| 79 | + */ | |
| 80 | + public AllPermission(String name, String actions) | |
| 81 | + { | |
| 82 | + this(); | |
| 83 | + } | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * Checks if the specified permission is "implied" by | |
| 87 | + * this object. This method always returns true. | |
| 88 | + * | |
| 89 | + * @param p the permission to check against. | |
| 90 | + * | |
| 91 | + * @return return | |
| 92 | + */ | |
| 93 | + public boolean implies(Permission p) { | |
| 94 | + return true; | |
| 95 | + } | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * Checks two AllPermission objects for equality. Two AllPermission | |
| 99 | + * objects are always equal. | |
| 100 | + * | |
| 101 | + * @param obj the object we are testing for equality with this object. | |
| 102 | + * @return true if <i>obj</i> is an AllPermission, false otherwise. | |
| 103 | + */ | |
| 104 | + public boolean equals(Object obj) { | |
| 105 | + return (obj instanceof AllPermission); | |
| 106 | + } | |
| 107 | + | |
| 108 | + /** | |
| 109 | + * Returns the hash code value for this object. | |
| 110 | + * | |
| 111 | + * @return a hash code value for this object. | |
| 112 | + */ | |
| 113 | + | |
| 114 | + public int hashCode() { | |
| 115 | + return 1; | |
| 116 | + } | |
| 117 | + | |
| 118 | + /** | |
| 119 | + * Returns the canonical string representation of the actions. | |
| 120 | + * | |
| 121 | + * @return the actions. | |
| 122 | + */ | |
| 123 | + public String getActions() | |
| 124 | + { | |
| 125 | + return "<all actions>"; | |
| 126 | + } | |
| 127 | + | |
| 128 | + /** | |
| 129 | + * Returns a new PermissionCollection object for storing AllPermission | |
| 130 | + * objects. | |
| 131 | + * <p> | |
| 132 | + * | |
| 133 | + * @return a new PermissionCollection object suitable for | |
| 134 | + * storing AllPermissions. | |
| 135 | + */ | |
| 136 | + | |
| 137 | + public PermissionCollection newPermissionCollection() { | |
| 138 | + return new AllPermissionCollection(); | |
| 139 | + } | |
| 140 | + | |
| 141 | +} | |
| 142 | + | |
| 143 | +/** | |
| 144 | + * A AllPermissionCollection stores a collection | |
| 145 | + * of AllPermission permissions. AllPermission objects | |
| 146 | + * must be stored in a manner that allows them to be inserted in any | |
| 147 | + * order, but enable the implies function to evaluate the implies | |
| 148 | + * method in an efficient (and consistent) manner. | |
| 149 | + * | |
| 150 | + * @see java.security.Permission | |
| 151 | + * @see java.security.Permissions | |
| 152 | + * | |
| 153 | + * | |
| 154 | + * @author Roland Schemers | |
| 155 | + * | |
| 156 | + * @serial include | |
| 157 | + */ | |
| 158 | + | |
| 159 | +final class AllPermissionCollection | |
| 160 | +extends PermissionCollection | |
| 161 | +implements java.io.Serializable | |
| 162 | +{ | |
| 163 | + | |
| 164 | + // use serialVersionUID from JDK 1.2.2 for interoperability | |
| 165 | + private static final long serialVersionUID = -4023755556366636806L; | |
| 166 | + | |
| 167 | + private boolean all_allowed; // true if any all permissions have been added | |
| 168 | + | |
| 169 | + /** | |
| 170 | + * Create an empty AllPermissions object. | |
| 171 | + * | |
| 172 | + */ | |
| 173 | + | |
| 174 | + public AllPermissionCollection() { | |
| 175 | + all_allowed = false; | |
| 176 | + } | |
| 177 | + | |
| 178 | + /** | |
| 179 | + * Adds a permission to the AllPermissions. The key for the hash is | |
| 180 | + * permission.path. | |
| 181 | + * | |
| 182 | + * @param permission the Permission object to add. | |
| 183 | + * | |
| 184 | + * @exception IllegalArgumentException - if the permission is not a | |
| 185 | + * AllPermission | |
| 186 | + * | |
| 187 | + * @exception SecurityException - if this AllPermissionCollection object | |
| 188 | + * has been marked readonly | |
| 189 | + */ | |
| 190 | + | |
| 191 | + public void add(Permission permission) | |
| 192 | + { | |
| 193 | + if (! (permission instanceof AllPermission)) | |
| 194 | + throw new IllegalArgumentException("invalid permission: "+ | |
| 195 | + permission); | |
| 196 | + if (isReadOnly()) | |
| 197 | + throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection"); | |
| 198 | + | |
| 199 | + all_allowed = true; // No sync; staleness OK | |
| 200 | + } | |
| 201 | + | |
| 202 | + /** | |
| 203 | + * Check and see if this set of permissions implies the permissions | |
| 204 | + * expressed in "permission". | |
| 205 | + * | |
| 206 | + * @param p the Permission object to compare | |
| 207 | + * | |
| 208 | + * @return always returns true. | |
| 209 | + */ | |
| 210 | + | |
| 211 | + public boolean implies(Permission permission) | |
| 212 | + { | |
| 213 | + return all_allowed; // No sync; staleness OK | |
| 214 | + } | |
| 215 | + | |
| 216 | + /** | |
| 217 | + * Returns an enumeration of all the AllPermission objects in the | |
| 218 | + * container. | |
| 219 | + * | |
| 220 | + * @return an enumeration of all the AllPermission objects. | |
| 221 | + */ | |
| 222 | + public Enumeration<Permission> elements() | |
| 223 | + { | |
| 224 | + return new Enumeration<Permission>() { | |
| 225 | + private boolean hasMore = all_allowed; | |
| 226 | + | |
| 227 | + public boolean hasMoreElements() { | |
| 228 | + return hasMore; | |
| 229 | + } | |
| 230 | + | |
| 231 | + public Permission nextElement() { | |
| 232 | + hasMore = false; | |
| 233 | + return SecurityConstants.ALL_PERMISSION; | |
| 234 | + } | |
| 235 | + }; | |
| 236 | + } | |
| 237 | +} | |
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,126 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import javax.security.auth.Subject; | |
| 29 | +import javax.security.auth.login.LoginException; | |
| 30 | +import javax.security.auth.callback.CallbackHandler; | |
| 31 | + | |
| 32 | +/** | |
| 33 | + * This class defines login and logout methods for a provider. | |
| 34 | + * | |
| 35 | + * <p> While callers may invoke <code>login</code> directly, | |
| 36 | + * the provider may also invoke <code>login</code> on behalf of callers | |
| 37 | + * if it determines that a login must be performed | |
| 38 | + * prior to certain operations. | |
| 39 | + * | |
| 40 | + * @since 1.5 | |
| 41 | + */ | |
| 42 | +public abstract class AuthProvider extends Provider { | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * Constructs a provider with the specified name, version number, | |
| 46 | + * and information. | |
| 47 | + * | |
| 48 | + * @param name the provider name. | |
| 49 | + * @param version the provider version number. | |
| 50 | + * @param info a description of the provider and its services. | |
| 51 | + */ | |
| 52 | + protected AuthProvider(String name, double version, String info) { | |
| 53 | + super(name, version, info); | |
| 54 | + } | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * Log in to this provider. | |
| 58 | + * | |
| 59 | + * <p> The provider relies on a <code>CallbackHandler</code> | |
| 60 | + * to obtain authentication information from the caller | |
| 61 | + * (a PIN, for example). If the caller passes a <code>null</code> | |
| 62 | + * handler to this method, the provider uses the handler set in the | |
| 63 | + * <code>setCallbackHandler</code> method. | |
| 64 | + * If no handler was set in that method, the provider queries the | |
| 65 | + * <i>auth.login.defaultCallbackHandler</i> security property | |
| 66 | + * for the fully qualified class name of a default handler implementation. | |
| 67 | + * If the security property is not set, | |
| 68 | + * the provider is assumed to have alternative means | |
| 69 | + * for obtaining authentication information. | |
| 70 | + * | |
| 71 | + * @param subject the <code>Subject</code> which may contain | |
| 72 | + * principals/credentials used for authentication, | |
| 73 | + * or may be populated with additional principals/credentials | |
| 74 | + * after successful authentication has completed. | |
| 75 | + * This parameter may be <code>null</code>. | |
| 76 | + * @param handler the <code>CallbackHandler</code> used by | |
| 77 | + * this provider to obtain authentication information | |
| 78 | + * from the caller, which may be <code>null</code> | |
| 79 | + * | |
| 80 | + * @exception LoginException if the login operation fails | |
| 81 | + * @exception SecurityException if the caller does not pass a | |
| 82 | + * security check for | |
| 83 | + * <code>SecurityPermission("authProvider.<i>name</i>")</code>, | |
| 84 | + * where <i>name</i> is the value returned by | |
| 85 | + * this provider's <code>getName</code> method | |
| 86 | + */ | |
| 87 | + public abstract void login(Subject subject, CallbackHandler handler) | |
| 88 | + throws LoginException; | |
| 89 | + | |
| 90 | + /** | |
| 91 | + * Log out from this provider. | |
| 92 | + * | |
| 93 | + * @exception LoginException if the logout operation fails | |
| 94 | + * @exception SecurityException if the caller does not pass a | |
| 95 | + * security check for | |
| 96 | + * <code>SecurityPermission("authProvider.<i>name</i>")</code>, | |
| 97 | + * where <i>name</i> is the value returned by | |
| 98 | + * this provider's <code>getName</code> method | |
| 99 | + */ | |
| 100 | + public abstract void logout() throws LoginException; | |
| 101 | + | |
| 102 | + /** | |
| 103 | + * Set a <code>CallbackHandler</code>. | |
| 104 | + * | |
| 105 | + * <p> The provider uses this handler if one is not passed to the | |
| 106 | + * <code>login</code> method. The provider also uses this handler | |
| 107 | + * if it invokes <code>login</code> on behalf of callers. | |
| 108 | + * In either case if a handler is not set via this method, | |
| 109 | + * the provider queries the | |
| 110 | + * <i>auth.login.defaultCallbackHandler</i> security property | |
| 111 | + * for the fully qualified class name of a default handler implementation. | |
| 112 | + * If the security property is not set, | |
| 113 | + * the provider is assumed to have alternative means | |
| 114 | + * for obtaining authentication information. | |
| 115 | + * | |
| 116 | + * @param handler a <code>CallbackHandler</code> for obtaining | |
| 117 | + * authentication information, which may be <code>null</code> | |
| 118 | + * | |
| 119 | + * @exception SecurityException if the caller does not pass a | |
| 120 | + * security check for | |
| 121 | + * <code>SecurityPermission("authProvider.<i>name</i>")</code>, | |
| 122 | + * where <i>name</i> is the value returned by | |
| 123 | + * this provider's <code>getName</code> method | |
| 124 | + */ | |
| 125 | + public abstract void setCallbackHandler(CallbackHandler handler); | |
| 126 | +} | |
Binary file not shown.
| @@ -0,0 +1,565 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.security.*; | |
| 29 | +import java.util.Enumeration; | |
| 30 | +import java.util.Map; | |
| 31 | +import java.util.HashMap; | |
| 32 | +import java.util.Hashtable; | |
| 33 | +import java.util.Collections; | |
| 34 | +import java.io.ObjectStreamField; | |
| 35 | +import java.io.ObjectOutputStream; | |
| 36 | +import java.io.ObjectInputStream; | |
| 37 | +import java.io.IOException; | |
| 38 | + | |
| 39 | +/** | |
| 40 | + * The BasicPermission class extends the Permission class, and | |
| 41 | + * can be used as the base class for permissions that want to | |
| 42 | + * follow the same naming convention as BasicPermission. | |
| 43 | + * <P> | |
| 44 | + * The name for a BasicPermission is the name of the given permission | |
| 45 | + * (for example, "exit", | |
| 46 | + * "setFactory", "print.queueJob", etc). The naming | |
| 47 | + * convention follows the hierarchical property naming convention. | |
| 48 | + * An asterisk may appear by itself, or if immediately preceded by a "." | |
| 49 | + * may appear at the end of the name, to signify a wildcard match. | |
| 50 | + * For example, "*" and "java.*" are valid, while "*java", "a*b", | |
| 51 | + * and "java*" are not valid. | |
| 52 | + * <P> | |
| 53 | + * The action string (inherited from Permission) is unused. | |
| 54 | + * Thus, BasicPermission is commonly used as the base class for | |
| 55 | + * "named" permissions | |
| 56 | + * (ones that contain a name but no actions list; you either have the | |
| 57 | + * named permission or you don't.) | |
| 58 | + * Subclasses may implement actions on top of BasicPermission, | |
| 59 | + * if desired. | |
| 60 | + * <p> | |
| 61 | + * <P> | |
| 62 | + * @see java.security.Permission | |
| 63 | + * @see java.security.Permissions | |
| 64 | + * @see java.security.PermissionCollection | |
| 65 | + * @see java.lang.SecurityManager | |
| 66 | + * | |
| 67 | + * @author Marianne Mueller | |
| 68 | + * @author Roland Schemers | |
| 69 | + */ | |
| 70 | + | |
| 71 | +public abstract class BasicPermission extends Permission | |
| 72 | +implements java.io.Serializable | |
| 73 | +{ | |
| 74 | + | |
| 75 | + private static final long serialVersionUID = 6279438298436773498L; | |
| 76 | + | |
| 77 | + // does this permission have a wildcard at the end? | |
| 78 | + private transient boolean wildcard; | |
| 79 | + | |
| 80 | + // the name without the wildcard on the end | |
| 81 | + private transient String path; | |
| 82 | + | |
| 83 | + // is this permission the old-style exitVM permission (pre JDK 1.6)? | |
| 84 | + private transient boolean exitVM; | |
| 85 | + | |
| 86 | + /** | |
| 87 | + * initialize a BasicPermission object. Common to all constructors. | |
| 88 | + * | |
| 89 | + */ | |
| 90 | + private void init(String name) | |
| 91 | + { | |
| 92 | + if (name == null) | |
| 93 | + throw new NullPointerException("name can't be null"); | |
| 94 | + | |
| 95 | + int len = name.length(); | |
| 96 | + | |
| 97 | + if (len == 0) { | |
| 98 | + throw new IllegalArgumentException("name can't be empty"); | |
| 99 | + } | |
| 100 | + | |
| 101 | + char last = name.charAt(len - 1); | |
| 102 | + | |
| 103 | + // Is wildcard or ends with ".*"? | |
| 104 | + if (last == '*' && (len == 1 || name.charAt(len - 2) == '.')) { | |
| 105 | + wildcard = true; | |
| 106 | + if (len == 1) { | |
| 107 | + path = ""; | |
| 108 | + } else { | |
| 109 | + path = name.substring(0, len - 1); | |
| 110 | + } | |
| 111 | + } else { | |
| 112 | + if (name.equals("exitVM")) { | |
| 113 | + wildcard = true; | |
| 114 | + path = "exitVM."; | |
| 115 | + exitVM = true; | |
| 116 | + } else { | |
| 117 | + path = name; | |
| 118 | + } | |
| 119 | + } | |
| 120 | + } | |
| 121 | + | |
| 122 | + /** | |
| 123 | + * Creates a new BasicPermission with the specified name. | |
| 124 | + * Name is the symbolic name of the permission, such as | |
| 125 | + * "setFactory", | |
| 126 | + * "print.queueJob", or "topLevelWindow", etc. | |
| 127 | + * | |
| 128 | + * @param name the name of the BasicPermission. | |
| 129 | + * | |
| 130 | + * @throws NullPointerException if <code>name</code> is <code>null</code>. | |
| 131 | + * @throws IllegalArgumentException if <code>name</code> is empty. | |
| 132 | + */ | |
| 133 | + | |
| 134 | + public BasicPermission(String name) | |
| 135 | + { | |
| 136 | + super(name); | |
| 137 | + init(name); | |
| 138 | + } | |
| 139 | + | |
| 140 | + | |
| 141 | + /** | |
| 142 | + * Creates a new BasicPermission object with the specified name. | |
| 143 | + * The name is the symbolic name of the BasicPermission, and the | |
| 144 | + * actions String is currently unused. | |
| 145 | + * | |
| 146 | + * @param name the name of the BasicPermission. | |
| 147 | + * @param actions ignored. | |
| 148 | + * | |
| 149 | + * @throws NullPointerException if <code>name</code> is <code>null</code>. | |
| 150 | + * @throws IllegalArgumentException if <code>name</code> is empty. | |
| 151 | + */ | |
| 152 | + public BasicPermission(String name, String actions) | |
| 153 | + { | |
| 154 | + super(name); | |
| 155 | + init(name); | |
| 156 | + } | |
| 157 | + | |
| 158 | + /** | |
| 159 | + * Checks if the specified permission is "implied" by | |
| 160 | + * this object. | |
| 161 | + * <P> | |
| 162 | + * More specifically, this method returns true if:<p> | |
| 163 | + * <ul> | |
| 164 | + * <li> <i>p</i>'s class is the same as this object's class, and<p> | |
| 165 | + * <li> <i>p</i>'s name equals or (in the case of wildcards) | |
| 166 | + * is implied by this object's | |
| 167 | + * name. For example, "a.b.*" implies "a.b.c". | |
| 168 | + * </ul> | |
| 169 | + * | |
| 170 | + * @param p the permission to check against. | |
| 171 | + * | |
| 172 | + * @return true if the passed permission is equal to or | |
| 173 | + * implied by this permission, false otherwise. | |
| 174 | + */ | |
| 175 | + public boolean implies(Permission p) { | |
| 176 | + if ((p == null) || (p.getClass() != getClass())) | |
| 177 | + return false; | |
| 178 | + | |
| 179 | + BasicPermission that = (BasicPermission) p; | |
| 180 | + | |
| 181 | + if (this.wildcard) { | |
| 182 | + if (that.wildcard) { | |
| 183 | + // one wildcard can imply another | |
| 184 | + return that.path.startsWith(path); | |
| 185 | + } else { | |
| 186 | + // make sure ap.path is longer so a.b.* doesn't imply a.b | |
| 187 | + return (that.path.length() > this.path.length()) && | |
| 188 | + that.path.startsWith(this.path); | |
| 189 | + } | |
| 190 | + } else { | |
| 191 | + if (that.wildcard) { | |
| 192 | + // a non-wildcard can't imply a wildcard | |
| 193 | + return false; | |
| 194 | + } | |
| 195 | + else { | |
| 196 | + return this.path.equals(that.path); | |
| 197 | + } | |
| 198 | + } | |
| 199 | + } | |
| 200 | + | |
| 201 | + /** | |
| 202 | + * Checks two BasicPermission objects for equality. | |
| 203 | + * Checks that <i>obj</i>'s class is the same as this object's class | |
| 204 | + * and has the same name as this object. | |
| 205 | + * <P> | |
| 206 | + * @param obj the object we are testing for equality with this object. | |
| 207 | + * @return true if <i>obj</i>'s class is the same as this object's class | |
| 208 | + * and has the same name as this BasicPermission object, false otherwise. | |
| 209 | + */ | |
| 210 | + public boolean equals(Object obj) { | |
| 211 | + if (obj == this) | |
| 212 | + return true; | |
| 213 | + | |
| 214 | + if ((obj == null) || (obj.getClass() != getClass())) | |
| 215 | + return false; | |
| 216 | + | |
| 217 | + BasicPermission bp = (BasicPermission) obj; | |
| 218 | + | |
| 219 | + return getName().equals(bp.getName()); | |
| 220 | + } | |
| 221 | + | |
| 222 | + | |
| 223 | + /** | |
| 224 | + * Returns the hash code value for this object. | |
| 225 | + * The hash code used is the hash code of the name, that is, | |
| 226 | + * <code>getName().hashCode()</code>, where <code>getName</code> is | |
| 227 | + * from the Permission superclass. | |
| 228 | + * | |
| 229 | + * @return a hash code value for this object. | |
| 230 | + */ | |
| 231 | + public int hashCode() { | |
| 232 | + return this.getName().hashCode(); | |
| 233 | + } | |
| 234 | + | |
| 235 | + /** | |
| 236 | + * Returns the canonical string representation of the actions, | |
| 237 | + * which currently is the empty string "", since there are no actions for | |
| 238 | + * a BasicPermission. | |
| 239 | + * | |
| 240 | + * @return the empty string "". | |
| 241 | + */ | |
| 242 | + public String getActions() | |
| 243 | + { | |
| 244 | + return ""; | |
| 245 | + } | |
| 246 | + | |
| 247 | + /** | |
| 248 | + * Returns a new PermissionCollection object for storing BasicPermission | |
| 249 | + * objects. | |
| 250 | + * | |
| 251 | + * <p>BasicPermission objects must be stored in a manner that allows them | |
| 252 | + * to be inserted in any order, but that also enables the | |
| 253 | + * PermissionCollection <code>implies</code> method | |
| 254 | + * to be implemented in an efficient (and consistent) manner. | |
| 255 | + * | |
| 256 | + * @return a new PermissionCollection object suitable for | |
| 257 | + * storing BasicPermissions. | |
| 258 | + */ | |
| 259 | + public PermissionCollection newPermissionCollection() { | |
| 260 | + return new BasicPermissionCollection(this.getClass()); | |
| 261 | + } | |
| 262 | + | |
| 263 | + /** | |
| 264 | + * readObject is called to restore the state of the BasicPermission from | |
| 265 | + * a stream. | |
| 266 | + */ | |
| 267 | + private void readObject(ObjectInputStream s) | |
| 268 | + throws IOException, ClassNotFoundException | |
| 269 | + { | |
| 270 | + s.defaultReadObject(); | |
| 271 | + // init is called to initialize the rest of the values. | |
| 272 | + init(getName()); | |
| 273 | + } | |
| 274 | + | |
| 275 | + /** | |
| 276 | + * Returns the canonical name of this BasicPermission. | |
| 277 | + * All internal invocations of getName should invoke this method, so | |
| 278 | + * that the pre-JDK 1.6 "exitVM" and current "exitVM.*" permission are | |
| 279 | + * equivalent in equals/hashCode methods. | |
| 280 | + * | |
| 281 | + * @return the canonical name of this BasicPermission. | |
| 282 | + */ | |
| 283 | + final String getCanonicalName() { | |
| 284 | + return exitVM ? "exitVM.*" : getName(); | |
| 285 | + } | |
| 286 | +} | |
| 287 | + | |
| 288 | +/** | |
| 289 | + * A BasicPermissionCollection stores a collection | |
| 290 | + * of BasicPermission permissions. BasicPermission objects | |
| 291 | + * must be stored in a manner that allows them to be inserted in any | |
| 292 | + * order, but enable the implies function to evaluate the implies | |
| 293 | + * method in an efficient (and consistent) manner. | |
| 294 | + * | |
| 295 | + * A BasicPermissionCollection handles comparing a permission like "a.b.c.d.e" | |
| 296 | + * with a Permission such as "a.b.*", or "*". | |
| 297 | + * | |
| 298 | + * @see java.security.Permission | |
| 299 | + * @see java.security.Permissions | |
| 300 | + * @see java.security.PermissionsImpl | |
| 301 | + * | |
| 302 | + * | |
| 303 | + * @author Roland Schemers | |
| 304 | + * | |
| 305 | + * @serial include | |
| 306 | + */ | |
| 307 | + | |
| 308 | +final class BasicPermissionCollection | |
| 309 | +extends PermissionCollection | |
| 310 | +implements java.io.Serializable | |
| 311 | +{ | |
| 312 | + | |
| 313 | + private static final long serialVersionUID = 739301742472979399L; | |
| 314 | + | |
| 315 | + /** | |
| 316 | + * Key is name, value is permission. All permission objects in | |
| 317 | + * collection must be of the same type. | |
| 318 | + * Not serialized; see serialization section at end of class. | |
| 319 | + */ | |
| 320 | + private transient Map<String, Permission> perms; | |
| 321 | + | |
| 322 | + /** | |
| 323 | + * This is set to <code>true</code> if this BasicPermissionCollection | |
| 324 | + * contains a BasicPermission with '*' as its permission name. | |
| 325 | + * | |
| 326 | + * @see #serialPersistentFields | |
| 327 | + */ | |
| 328 | + private boolean all_allowed; | |
| 329 | + | |
| 330 | + /** | |
| 331 | + * The class to which all BasicPermissions in this | |
| 332 | + * BasicPermissionCollection belongs. | |
| 333 | + * | |
| 334 | + * @see #serialPersistentFields | |
| 335 | + */ | |
| 336 | + private Class permClass; | |
| 337 | + | |
| 338 | + /** | |
| 339 | + * Create an empty BasicPermissionCollection object. | |
| 340 | + * | |
| 341 | + */ | |
| 342 | + | |
| 343 | + public BasicPermissionCollection(Class clazz) { | |
| 344 | + perms = new HashMap<String, Permission>(11); | |
| 345 | + all_allowed = false; | |
| 346 | + permClass = clazz; | |
| 347 | + } | |
| 348 | + | |
| 349 | + /** | |
| 350 | + * Adds a permission to the BasicPermissions. The key for the hash is | |
| 351 | + * permission.path. | |
| 352 | + * | |
| 353 | + * @param permission the Permission object to add. | |
| 354 | + * | |
| 355 | + * @exception IllegalArgumentException - if the permission is not a | |
| 356 | + * BasicPermission, or if | |
| 357 | + * the permission is not of the | |
| 358 | + * same Class as the other | |
| 359 | + * permissions in this collection. | |
| 360 | + * | |
| 361 | + * @exception SecurityException - if this BasicPermissionCollection object | |
| 362 | + * has been marked readonly | |
| 363 | + */ | |
| 364 | + | |
| 365 | + public void add(Permission permission) | |
| 366 | + { | |
| 367 | + if (! (permission instanceof BasicPermission)) | |
| 368 | + throw new IllegalArgumentException("invalid permission: "+ | |
| 369 | + permission); | |
| 370 | + if (isReadOnly()) | |
| 371 | + throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection"); | |
| 372 | + | |
| 373 | + BasicPermission bp = (BasicPermission) permission; | |
| 374 | + | |
| 375 | + // make sure we only add new BasicPermissions of the same class | |
| 376 | + // Also check null for compatibility with deserialized form from | |
| 377 | + // previous versions. | |
| 378 | + if (permClass == null) { | |
| 379 | + // adding first permission | |
| 380 | + permClass = bp.getClass(); | |
| 381 | + } else { | |
| 382 | + if (bp.getClass() != permClass) | |
| 383 | + throw new IllegalArgumentException("invalid permission: " + | |
| 384 | + permission); | |
| 385 | + } | |
| 386 | + | |
| 387 | + synchronized (this) { | |
| 388 | + perms.put(bp.getCanonicalName(), permission); | |
| 389 | + } | |
| 390 | + | |
| 391 | + // No sync on all_allowed; staleness OK | |
| 392 | + if (!all_allowed) { | |
| 393 | + if (bp.getCanonicalName().equals("*")) | |
| 394 | + all_allowed = true; | |
| 395 | + } | |
| 396 | + } | |
| 397 | + | |
| 398 | + /** | |
| 399 | + * Check and see if this set of permissions implies the permissions | |
| 400 | + * expressed in "permission". | |
| 401 | + * | |
| 402 | + * @param p the Permission object to compare | |
| 403 | + * | |
| 404 | + * @return true if "permission" is a proper subset of a permission in | |
| 405 | + * the set, false if not. | |
| 406 | + */ | |
| 407 | + | |
| 408 | + public boolean implies(Permission permission) | |
| 409 | + { | |
| 410 | + if (! (permission instanceof BasicPermission)) | |
| 411 | + return false; | |
| 412 | + | |
| 413 | + BasicPermission bp = (BasicPermission) permission; | |
| 414 | + | |
| 415 | + // random subclasses of BasicPermission do not imply each other | |
| 416 | + if (bp.getClass() != permClass) | |
| 417 | + return false; | |
| 418 | + | |
| 419 | + // short circuit if the "*" Permission was added | |
| 420 | + if (all_allowed) | |
| 421 | + return true; | |
| 422 | + | |
| 423 | + // strategy: | |
| 424 | + // Check for full match first. Then work our way up the | |
| 425 | + // path looking for matches on a.b..* | |
| 426 | + | |
| 427 | + String path = bp.getCanonicalName(); | |
| 428 | + //System.out.println("check "+path); | |
| 429 | + | |
| 430 | + Permission x; | |
| 431 | + | |
| 432 | + synchronized (this) { | |
| 433 | + x = perms.get(path); | |
| 434 | + } | |
| 435 | + | |
| 436 | + if (x != null) { | |
| 437 | + // we have a direct hit! | |
| 438 | + return x.implies(permission); | |
| 439 | + } | |
| 440 | + | |
| 441 | + // work our way up the tree... | |
| 442 | + int last, offset; | |
| 443 | + | |
| 444 | + offset = path.length()-1; | |
| 445 | + | |
| 446 | + while ((last = path.lastIndexOf(".", offset)) != -1) { | |
| 447 | + | |
| 448 | + path = path.substring(0, last+1) + "*"; | |
| 449 | + //System.out.println("check "+path); | |
| 450 | + | |
| 451 | + synchronized (this) { | |
| 452 | + x = perms.get(path); | |
| 453 | + } | |
| 454 | + | |
| 455 | + if (x != null) { | |
| 456 | + return x.implies(permission); | |
| 457 | + } | |
| 458 | + offset = last -1; | |
| 459 | + } | |
| 460 | + | |
| 461 | + // we don't have to check for "*" as it was already checked | |
| 462 | + // at the top (all_allowed), so we just return false | |
| 463 | + return false; | |
| 464 | + } | |
| 465 | + | |
| 466 | + /** | |
| 467 | + * Returns an enumeration of all the BasicPermission objects in the | |
| 468 | + * container. | |
| 469 | + * | |
| 470 | + * @return an enumeration of all the BasicPermission objects. | |
| 471 | + */ | |
| 472 | + | |
| 473 | + public Enumeration<Permission> elements() { | |
| 474 | + // Convert Iterator of Map values into an Enumeration | |
| 475 | + synchronized (this) { | |
| 476 | + return Collections.enumeration(perms.values()); | |
| 477 | + } | |
| 478 | + } | |
| 479 | + | |
| 480 | + // Need to maintain serialization interoperability with earlier releases, | |
| 481 | + // which had the serializable field: | |
| 482 | + // | |
| 483 | + // @serial the Hashtable is indexed by the BasicPermission name | |
| 484 | + // | |
| 485 | + // private Hashtable permissions; | |
| 486 | + /** | |
| 487 | + * @serialField permissions java.util.Hashtable | |
| 488 | + * The BasicPermissions in this BasicPermissionCollection. | |
| 489 | + * All BasicPermissions in the collection must belong to the same class. | |
| 490 | + * The Hashtable is indexed by the BasicPermission name; the value | |
| 491 | + * of the Hashtable entry is the permission. | |
| 492 | + * @serialField all_allowed boolean | |
| 493 | + * This is set to <code>true</code> if this BasicPermissionCollection | |
| 494 | + * contains a BasicPermission with '*' as its permission name. | |
| 495 | + * @serialField permClass java.lang.Class | |
| 496 | + * The class to which all BasicPermissions in this | |
| 497 | + * BasicPermissionCollection belongs. | |
| 498 | + */ | |
| 499 | + private static final ObjectStreamField[] serialPersistentFields = { | |
| 500 | + new ObjectStreamField("permissions", Hashtable.class), | |
| 501 | + new ObjectStreamField("all_allowed", Boolean.TYPE), | |
| 502 | + new ObjectStreamField("permClass", Class.class), | |
| 503 | + }; | |
| 504 | + | |
| 505 | + /** | |
| 506 | + * @serialData Default fields. | |
| 507 | + */ | |
| 508 | + /* | |
| 509 | + * Writes the contents of the perms field out as a Hashtable for | |
| 510 | + * serialization compatibility with earlier releases. all_allowed | |
| 511 | + * and permClass unchanged. | |
| 512 | + */ | |
| 513 | + private void writeObject(ObjectOutputStream out) throws IOException { | |
| 514 | + // Don't call out.defaultWriteObject() | |
| 515 | + | |
| 516 | + // Copy perms into a Hashtable | |
| 517 | + Hashtable<String, Permission> permissions = | |
| 518 | + new Hashtable<>(perms.size()*2); | |
| 519 | + | |
| 520 | + synchronized (this) { | |
| 521 | + permissions.putAll(perms); | |
| 522 | + } | |
| 523 | + | |
| 524 | + // Write out serializable fields | |
| 525 | + ObjectOutputStream.PutField pfields = out.putFields(); | |
| 526 | + pfields.put("all_allowed", all_allowed); | |
| 527 | + pfields.put("permissions", permissions); | |
| 528 | + pfields.put("permClass", permClass); | |
| 529 | + out.writeFields(); | |
| 530 | + } | |
| 531 | + | |
| 532 | + /** | |
| 533 | + * readObject is called to restore the state of the | |
| 534 | + * BasicPermissionCollection from a stream. | |
| 535 | + */ | |
| 536 | + private void readObject(java.io.ObjectInputStream in) | |
| 537 | + throws IOException, ClassNotFoundException | |
| 538 | + { | |
| 539 | + // Don't call defaultReadObject() | |
| 540 | + | |
| 541 | + // Read in serialized fields | |
| 542 | + ObjectInputStream.GetField gfields = in.readFields(); | |
| 543 | + | |
| 544 | + // Get permissions | |
| 545 | + Hashtable<String, Permission> permissions = | |
| 546 | + (Hashtable<String, Permission>)gfields.get("permissions", null); | |
| 547 | + perms = new HashMap<String, Permission>(permissions.size()*2); | |
| 548 | + perms.putAll(permissions); | |
| 549 | + | |
| 550 | + // Get all_allowed | |
| 551 | + all_allowed = gfields.get("all_allowed", false); | |
| 552 | + | |
| 553 | + // Get permClass | |
| 554 | + permClass = (Class) gfields.get("permClass", null); | |
| 555 | + | |
| 556 | + if (permClass == null) { | |
| 557 | + // set permClass | |
| 558 | + Enumeration<Permission> e = permissions.elements(); | |
| 559 | + if (e.hasMoreElements()) { | |
| 560 | + Permission p = e.nextElement(); | |
| 561 | + permClass = p.getClass(); | |
| 562 | + } | |
| 563 | + } | |
| 564 | + } | |
| 565 | +} | |
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,156 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.*; | |
| 29 | +import java.util.Date; | |
| 30 | + | |
| 31 | +/** | |
| 32 | + * <p>This is an interface of abstract methods for managing a | |
| 33 | + * variety of identity certificates. | |
| 34 | + * An identity certificate is a guarantee by a principal that | |
| 35 | + * a public key is that of another principal. (A principal represents | |
| 36 | + * an entity such as an individual user, a group, or a corporation.) | |
| 37 | + * | |
| 38 | + * <p>In particular, this interface is intended to be a common | |
| 39 | + * abstraction for constructs that have different formats but | |
| 40 | + * important common uses. For example, different types of | |
| 41 | + * certificates, such as X.509 certificates and PGP certificates, | |
| 42 | + * share general certificate functionality (the need to encode and | |
| 43 | + * decode certificates) and some types of information, such as a | |
| 44 | + * public key, the principal whose key it is, and the guarantor | |
| 45 | + * guaranteeing that the public key is that of the specified | |
| 46 | + * principal. So an implementation of X.509 certificates and an | |
| 47 | + * implementation of PGP certificates can both utilize the Certificate | |
| 48 | + * interface, even though their formats and additional types and | |
| 49 | + * amounts of information stored are different. | |
| 50 | + * | |
| 51 | + * <p><b>Important</b>: This interface is useful for cataloging and | |
| 52 | + * grouping objects sharing certain common uses. It does not have any | |
| 53 | + * semantics of its own. In particular, a Certificate object does not | |
| 54 | + * make any statement as to the <i>validity</i> of the binding. It is | |
| 55 | + * the duty of the application implementing this interface to verify | |
| 56 | + * the certificate and satisfy itself of its validity. | |
| 57 | + * | |
| 58 | + * @author Benjamin Renaud | |
| 59 | + * @deprecated A new certificate handling package is created in the Java platform. | |
| 60 | + * This Certificate interface is entirely deprecated and | |
| 61 | + * is here to allow for a smooth transition to the new | |
| 62 | + * package. | |
| 63 | + * @see java.security.cert.Certificate | |
| 64 | + */ | |
| 65 | +@Deprecated | |
| 66 | +public interface Certificate { | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * Returns the guarantor of the certificate, that is, the principal | |
| 70 | + * guaranteeing that the public key associated with this certificate | |
| 71 | + * is that of the principal associated with this certificate. For X.509 | |
| 72 | + * certificates, the guarantor will typically be a Certificate Authority | |
| 73 | + * (such as the United States Postal Service or Verisign, Inc.). | |
| 74 | + * | |
| 75 | + * @return the guarantor which guaranteed the principal-key | |
| 76 | + * binding. | |
| 77 | + */ | |
| 78 | + public abstract Principal getGuarantor(); | |
| 79 | + | |
| 80 | + /** | |
| 81 | + * Returns the principal of the principal-key pair being guaranteed by | |
| 82 | + * the guarantor. | |
| 83 | + * | |
| 84 | + * @return the principal to which this certificate is bound. | |
| 85 | + */ | |
| 86 | + public abstract Principal getPrincipal(); | |
| 87 | + | |
| 88 | + /** | |
| 89 | + * Returns the key of the principal-key pair being guaranteed by | |
| 90 | + * the guarantor. | |
| 91 | + * | |
| 92 | + * @return the public key that this certificate certifies belongs | |
| 93 | + * to a particular principal. | |
| 94 | + */ | |
| 95 | + public abstract PublicKey getPublicKey(); | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * Encodes the certificate to an output stream in a format that can | |
| 99 | + * be decoded by the <code>decode</code> method. | |
| 100 | + * | |
| 101 | + * @param stream the output stream to which to encode the | |
| 102 | + * certificate. | |
| 103 | + * | |
| 104 | + * @exception KeyException if the certificate is not | |
| 105 | + * properly initialized, or data is missing, etc. | |
| 106 | + * | |
| 107 | + * @exception IOException if a stream exception occurs while | |
| 108 | + * trying to output the encoded certificate to the output stream. | |
| 109 | + * | |
| 110 | + * @see #decode | |
| 111 | + * @see #getFormat | |
| 112 | + */ | |
| 113 | + public abstract void encode(OutputStream stream) | |
| 114 | + throws KeyException, IOException; | |
| 115 | + | |
| 116 | + /** | |
| 117 | + * Decodes a certificate from an input stream. The format should be | |
| 118 | + * that returned by <code>getFormat</code> and produced by | |
| 119 | + * <code>encode</code>. | |
| 120 | + * | |
| 121 | + * @param stream the input stream from which to fetch the data | |
| 122 | + * being decoded. | |
| 123 | + * | |
| 124 | + * @exception KeyException if the certificate is not properly initialized, | |
| 125 | + * or data is missing, etc. | |
| 126 | + * | |
| 127 | + * @exception IOException if an exception occurs while trying to input | |
| 128 | + * the encoded certificate from the input stream. | |
| 129 | + * | |
| 130 | + * @see #encode | |
| 131 | + * @see #getFormat | |
| 132 | + */ | |
| 133 | + public abstract void decode(InputStream stream) | |
| 134 | + throws KeyException, IOException; | |
| 135 | + | |
| 136 | + | |
| 137 | + /** | |
| 138 | + * Returns the name of the coding format. This is used as a hint to find | |
| 139 | + * an appropriate parser. It could be "X.509", "PGP", etc. This is | |
| 140 | + * the format produced and understood by the <code>encode</code> | |
| 141 | + * and <code>decode</code> methods. | |
| 142 | + * | |
| 143 | + * @return the name of the coding format. | |
| 144 | + */ | |
| 145 | + public abstract String getFormat(); | |
| 146 | + | |
| 147 | + /** | |
| 148 | + * Returns a string that represents the contents of the certificate. | |
| 149 | + * | |
| 150 | + * @param detailed whether or not to give detailed information | |
| 151 | + * about the certificate | |
| 152 | + * | |
| 153 | + * @return a string representing the contents of the certificate | |
| 154 | + */ | |
| 155 | + public String toString(boolean detailed); | |
| 156 | +} | |
Binary file not shown.
| @@ -0,0 +1,173 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.*; | |
| 29 | +import java.security.cert.CertPath; | |
| 30 | + | |
| 31 | +/** | |
| 32 | + * This class encapsulates information about a code signer. | |
| 33 | + * It is immutable. | |
| 34 | + * | |
| 35 | + * @since 1.5 | |
| 36 | + * @author Vincent Ryan | |
| 37 | + */ | |
| 38 | + | |
| 39 | +public final class CodeSigner implements Serializable { | |
| 40 | + | |
| 41 | + private static final long serialVersionUID = 6819288105193937581L; | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * The signer's certificate path. | |
| 45 | + * | |
| 46 | + * @serial | |
| 47 | + */ | |
| 48 | + private CertPath signerCertPath; | |
| 49 | + | |
| 50 | + /* | |
| 51 | + * The signature timestamp. | |
| 52 | + * | |
| 53 | + * @serial | |
| 54 | + */ | |
| 55 | + private Timestamp timestamp; | |
| 56 | + | |
| 57 | + /* | |
| 58 | + * Hash code for this code signer. | |
| 59 | + */ | |
| 60 | + private transient int myhash = -1; | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * Constructs a CodeSigner object. | |
| 64 | + * | |
| 65 | + * @param signerCertPath The signer's certificate path. | |
| 66 | + * It must not be <code>null</code>. | |
| 67 | + * @param timestamp A signature timestamp. | |
| 68 | + * If <code>null</code> then no timestamp was generated | |
| 69 | + * for the signature. | |
| 70 | + * @throws NullPointerException if <code>signerCertPath</code> is | |
| 71 | + * <code>null</code>. | |
| 72 | + */ | |
| 73 | + public CodeSigner(CertPath signerCertPath, Timestamp timestamp) { | |
| 74 | + if (signerCertPath == null) { | |
| 75 | + throw new NullPointerException(); | |
| 76 | + } | |
| 77 | + this.signerCertPath = signerCertPath; | |
| 78 | + this.timestamp = timestamp; | |
| 79 | + } | |
| 80 | + | |
| 81 | + /** | |
| 82 | + * Returns the signer's certificate path. | |
| 83 | + * | |
| 84 | + * @return A certificate path. | |
| 85 | + */ | |
| 86 | + public CertPath getSignerCertPath() { | |
| 87 | + return signerCertPath; | |
| 88 | + } | |
| 89 | + | |
| 90 | + /** | |
| 91 | + * Returns the signature timestamp. | |
| 92 | + * | |
| 93 | + * @return The timestamp or <code>null</code> if none is present. | |
| 94 | + */ | |
| 95 | + public Timestamp getTimestamp() { | |
| 96 | + return timestamp; | |
| 97 | + } | |
| 98 | + | |
| 99 | + /** | |
| 100 | + * Returns the hash code value for this code signer. | |
| 101 | + * The hash code is generated using the signer's certificate path and the | |
| 102 | + * timestamp, if present. | |
| 103 | + * | |
| 104 | + * @return a hash code value for this code signer. | |
| 105 | + */ | |
| 106 | + public int hashCode() { | |
| 107 | + if (myhash == -1) { | |
| 108 | + if (timestamp == null) { | |
| 109 | + myhash = signerCertPath.hashCode(); | |
| 110 | + } else { | |
| 111 | + myhash = signerCertPath.hashCode() + timestamp.hashCode(); | |
| 112 | + } | |
| 113 | + } | |
| 114 | + return myhash; | |
| 115 | + } | |
| 116 | + | |
| 117 | + /** | |
| 118 | + * Tests for equality between the specified object and this | |
| 119 | + * code signer. Two code signers are considered equal if their | |
| 120 | + * signer certificate paths are equal and if their timestamps are equal, | |
| 121 | + * if present in both. | |
| 122 | + * | |
| 123 | + * @param obj the object to test for equality with this object. | |
| 124 | + * | |
| 125 | + * @return true if the objects are considered equal, false otherwise. | |
| 126 | + */ | |
| 127 | + public boolean equals(Object obj) { | |
| 128 | + if (obj == null || (!(obj instanceof CodeSigner))) { | |
| 129 | + return false; | |
| 130 | + } | |
| 131 | + CodeSigner that = (CodeSigner)obj; | |
| 132 | + | |
| 133 | + if (this == that) { | |
| 134 | + return true; | |
| 135 | + } | |
| 136 | + Timestamp thatTimestamp = that.getTimestamp(); | |
| 137 | + if (timestamp == null) { | |
| 138 | + if (thatTimestamp != null) { | |
| 139 | + return false; | |
| 140 | + } | |
| 141 | + } else { | |
| 142 | + if (thatTimestamp == null || | |
| 143 | + (! timestamp.equals(thatTimestamp))) { | |
| 144 | + return false; | |
| 145 | + } | |
| 146 | + } | |
| 147 | + return signerCertPath.equals(that.getSignerCertPath()); | |
| 148 | + } | |
| 149 | + | |
| 150 | + /** | |
| 151 | + * Returns a string describing this code signer. | |
| 152 | + * | |
| 153 | + * @return A string comprising the signer's certificate and a timestamp, | |
| 154 | + * if present. | |
| 155 | + */ | |
| 156 | + public String toString() { | |
| 157 | + StringBuffer sb = new StringBuffer(); | |
| 158 | + sb.append("("); | |
| 159 | + sb.append("Signer: " + signerCertPath.getCertificates().get(0)); | |
| 160 | + if (timestamp != null) { | |
| 161 | + sb.append("timestamp: " + timestamp); | |
| 162 | + } | |
| 163 | + sb.append(")"); | |
| 164 | + return sb.toString(); | |
| 165 | + } | |
| 166 | + | |
| 167 | + // Explicitly reset hash code value to -1 | |
| 168 | + private void readObject(ObjectInputStream ois) | |
| 169 | + throws IOException, ClassNotFoundException { | |
| 170 | + ois.defaultReadObject(); | |
| 171 | + myhash = -1; | |
| 172 | + } | |
| 173 | +} | |
Binary file not shown.
| @@ -0,0 +1,639 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | + | |
| 29 | +import java.net.URL; | |
| 30 | +import java.net.SocketPermission; | |
| 31 | +import java.util.ArrayList; | |
| 32 | +import java.util.List; | |
| 33 | +import java.util.Hashtable; | |
| 34 | +import java.io.ByteArrayInputStream; | |
| 35 | +import java.io.IOException; | |
| 36 | +import java.security.cert.*; | |
| 37 | + | |
| 38 | +/** | |
| 39 | + * | |
| 40 | + * <p>This class extends the concept of a codebase to | |
| 41 | + * encapsulate not only the location (URL) but also the certificate chains | |
| 42 | + * that were used to verify signed code originating from that location. | |
| 43 | + * | |
| 44 | + * @author Li Gong | |
| 45 | + * @author Roland Schemers | |
| 46 | + */ | |
| 47 | + | |
| 48 | +public class CodeSource implements java.io.Serializable { | |
| 49 | + | |
| 50 | + private static final long serialVersionUID = 4977541819976013951L; | |
| 51 | + | |
| 52 | + /** | |
| 53 | + * The code location. | |
| 54 | + * | |
| 55 | + * @serial | |
| 56 | + */ | |
| 57 | + private URL location; | |
| 58 | + | |
| 59 | + /* | |
| 60 | + * The code signers. | |
| 61 | + */ | |
| 62 | + private transient CodeSigner[] signers = null; | |
| 63 | + | |
| 64 | + /* | |
| 65 | + * The code signers. Certificate chains are concatenated. | |
| 66 | + */ | |
| 67 | + private transient java.security.cert.Certificate certs[] = null; | |
| 68 | + | |
| 69 | + // cached SocketPermission used for matchLocation | |
| 70 | + private transient SocketPermission sp; | |
| 71 | + | |
| 72 | + // for generating cert paths | |
| 73 | + private transient CertificateFactory factory = null; | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * Constructs a CodeSource and associates it with the specified | |
| 77 | + * location and set of certificates. | |
| 78 | + * | |
| 79 | + * @param url the location (URL). | |
| 80 | + * | |
| 81 | + * @param certs the certificate(s). It may be null. The contents of the | |
| 82 | + * array are copied to protect against subsequent modification. | |
| 83 | + */ | |
| 84 | + public CodeSource(URL url, java.security.cert.Certificate certs[]) { | |
| 85 | + this.location = url; | |
| 86 | + | |
| 87 | + // Copy the supplied certs | |
| 88 | + if (certs != null) { | |
| 89 | + this.certs = certs.clone(); | |
| 90 | + } | |
| 91 | + } | |
| 92 | + | |
| 93 | + /** | |
| 94 | + * Constructs a CodeSource and associates it with the specified | |
| 95 | + * location and set of code signers. | |
| 96 | + * | |
| 97 | + * @param url the location (URL). | |
| 98 | + * @param signers the code signers. It may be null. The contents of the | |
| 99 | + * array are copied to protect against subsequent modification. | |
| 100 | + * | |
| 101 | + * @since 1.5 | |
| 102 | + */ | |
| 103 | + public CodeSource(URL url, CodeSigner[] signers) { | |
| 104 | + this.location = url; | |
| 105 | + | |
| 106 | + // Copy the supplied signers | |
| 107 | + if (signers != null) { | |
| 108 | + this.signers = signers.clone(); | |
| 109 | + } | |
| 110 | + } | |
| 111 | + | |
| 112 | + /** | |
| 113 | + * Returns the hash code value for this object. | |
| 114 | + * | |
| 115 | + * @return a hash code value for this object. | |
| 116 | + */ | |
| 117 | + | |
| 118 | + public int hashCode() { | |
| 119 | + if (location != null) | |
| 120 | + return location.hashCode(); | |
| 121 | + else | |
| 122 | + return 0; | |
| 123 | + } | |
| 124 | + | |
| 125 | + /** | |
| 126 | + * Tests for equality between the specified object and this | |
| 127 | + * object. Two CodeSource objects are considered equal if their | |
| 128 | + * locations are of identical value and if their signer certificate | |
| 129 | + * chains are of identical value. It is not required that | |
| 130 | + * the certificate chains be in the same order. | |
| 131 | + * | |
| 132 | + * @param obj the object to test for equality with this object. | |
| 133 | + * | |
| 134 | + * @return true if the objects are considered equal, false otherwise. | |
| 135 | + */ | |
| 136 | + public boolean equals(Object obj) { | |
| 137 | + if (obj == this) | |
| 138 | + return true; | |
| 139 | + | |
| 140 | + // objects types must be equal | |
| 141 | + if (!(obj instanceof CodeSource)) | |
| 142 | + return false; | |
| 143 | + | |
| 144 | + CodeSource cs = (CodeSource) obj; | |
| 145 | + | |
| 146 | + // URLs must match | |
| 147 | + if (location == null) { | |
| 148 | + // if location is null, then cs.location must be null as well | |
| 149 | + if (cs.location != null) return false; | |
| 150 | + } else { | |
| 151 | + // if location is not null, then it must equal cs.location | |
| 152 | + if (!location.equals(cs.location)) return false; | |
| 153 | + } | |
| 154 | + | |
| 155 | + // certs must match | |
| 156 | + return matchCerts(cs, true); | |
| 157 | + } | |
| 158 | + | |
| 159 | + /** | |
| 160 | + * Returns the location associated with this CodeSource. | |
| 161 | + * | |
| 162 | + * @return the location (URL). | |
| 163 | + */ | |
| 164 | + public final URL getLocation() { | |
| 165 | + /* since URL is practically immutable, returning itself is not | |
| 166 | + a security problem */ | |
| 167 | + return this.location; | |
| 168 | + } | |
| 169 | + | |
| 170 | + /** | |
| 171 | + * Returns the certificates associated with this CodeSource. | |
| 172 | + * <p> | |
| 173 | + * If this CodeSource object was created using the | |
| 174 | + * {@link #CodeSource(URL url, CodeSigner[] signers)} | |
| 175 | + * constructor then its certificate chains are extracted and used to | |
| 176 | + * create an array of Certificate objects. Each signer certificate is | |
| 177 | + * followed by its supporting certificate chain (which may be empty). | |
| 178 | + * Each signer certificate and its supporting certificate chain is ordered | |
| 179 | + * bottom-to-top (i.e., with the signer certificate first and the (root) | |
| 180 | + * certificate authority last). | |
| 181 | + * | |
| 182 | + * @return A copy of the certificates array, or null if there is none. | |
| 183 | + */ | |
| 184 | + public final java.security.cert.Certificate[] getCertificates() { | |
| 185 | + if (certs != null) { | |
| 186 | + return certs.clone(); | |
| 187 | + | |
| 188 | + } else if (signers != null) { | |
| 189 | + // Convert the code signers to certs | |
| 190 | + ArrayList<java.security.cert.Certificate> certChains = | |
| 191 | + new ArrayList<>(); | |
| 192 | + for (int i = 0; i < signers.length; i++) { | |
| 193 | + certChains.addAll( | |
| 194 | + signers[i].getSignerCertPath().getCertificates()); | |
| 195 | + } | |
| 196 | + certs = certChains.toArray( | |
| 197 | + new java.security.cert.Certificate[certChains.size()]); | |
| 198 | + return certs.clone(); | |
| 199 | + | |
| 200 | + } else { | |
| 201 | + return null; | |
| 202 | + } | |
| 203 | + } | |
| 204 | + | |
| 205 | + /** | |
| 206 | + * Returns the code signers associated with this CodeSource. | |
| 207 | + * <p> | |
| 208 | + * If this CodeSource object was created using the | |
| 209 | + * {@link #CodeSource(URL url, Certificate[] certs)} | |
| 210 | + * constructor then its certificate chains are extracted and used to | |
| 211 | + * create an array of CodeSigner objects. Note that only X.509 certificates | |
| 212 | + * are examined - all other certificate types are ignored. | |
| 213 | + * | |
| 214 | + * @return A copy of the code signer array, or null if there is none. | |
| 215 | + * | |
| 216 | + * @since 1.5 | |
| 217 | + */ | |
| 218 | + public final CodeSigner[] getCodeSigners() { | |
| 219 | + if (signers != null) { | |
| 220 | + return signers.clone(); | |
| 221 | + | |
| 222 | + } else if (certs != null) { | |
| 223 | + // Convert the certs to code signers | |
| 224 | + signers = convertCertArrayToSignerArray(certs); | |
| 225 | + return signers.clone(); | |
| 226 | + | |
| 227 | + } else { | |
| 228 | + return null; | |
| 229 | + } | |
| 230 | + } | |
| 231 | + | |
| 232 | + /** | |
| 233 | + * Returns true if this CodeSource object "implies" the specified CodeSource. | |
| 234 | + * <P> | |
| 235 | + * More specifically, this method makes the following checks, in order. | |
| 236 | + * If any fail, it returns false. If they all succeed, it returns true.<p> | |
| 237 | + * <ol> | |
| 238 | + * <li> <i>codesource</i> must not be null. | |
| 239 | + * <li> If this object's certificates are not null, then all | |
| 240 | + * of this object's certificates must be present in <i>codesource</i>'s | |
| 241 | + * certificates. | |
| 242 | + * <li> If this object's location (getLocation()) is not null, then the | |
| 243 | + * following checks are made against this object's location and | |
| 244 | + * <i>codesource</i>'s:<p> | |
| 245 | + * <ol> | |
| 246 | + * <li> <i>codesource</i>'s location must not be null. | |
| 247 | + * | |
| 248 | + * <li> If this object's location | |
| 249 | + * equals <i>codesource</i>'s location, then return true. | |
| 250 | + * | |
| 251 | + * <li> This object's protocol (getLocation().getProtocol()) must be | |
| 252 | + * equal to <i>codesource</i>'s protocol. | |
| 253 | + * | |
| 254 | + * <li> If this object's host (getLocation().getHost()) is not null, | |
| 255 | + * then the SocketPermission | |
| 256 | + * constructed with this object's host must imply the | |
| 257 | + * SocketPermission constructed with <i>codesource</i>'s host. | |
| 258 | + * | |
| 259 | + * <li> If this object's port (getLocation().getPort()) is not | |
| 260 | + * equal to -1 (that is, if a port is specified), it must equal | |
| 261 | + * <i>codesource</i>'s port. | |
| 262 | + * | |
| 263 | + * <li> If this object's file (getLocation().getFile()) doesn't equal | |
| 264 | + * <i>codesource</i>'s file, then the following checks are made: | |
| 265 | + * If this object's file ends with "/-", | |
| 266 | + * then <i>codesource</i>'s file must start with this object's | |
| 267 | + * file (exclusive the trailing "-"). | |
| 268 | + * If this object's file ends with a "/*", | |
| 269 | + * then <i>codesource</i>'s file must start with this object's | |
| 270 | + * file and must not have any further "/" separators. | |
| 271 | + * If this object's file doesn't end with a "/", | |
| 272 | + * then <i>codesource</i>'s file must match this object's | |
| 273 | + * file with a '/' appended. | |
| 274 | + * | |
| 275 | + * <li> If this object's reference (getLocation().getRef()) is | |
| 276 | + * not null, it must equal <i>codesource</i>'s reference. | |
| 277 | + * | |
| 278 | + * </ol> | |
| 279 | + * </ol> | |
| 280 | + * <p> | |
| 281 | + * For example, the codesource objects with the following locations | |
| 282 | + * and null certificates all imply | |
| 283 | + * the codesource with the location "http://java.sun.com/classes/foo.jar" | |
| 284 | + * and null certificates: | |
| 285 | + * <pre> | |
| 286 | + * http: | |
| 287 | + * http://*.sun.com/classes/* | |
| 288 | + * http://java.sun.com/classes/- | |
| 289 | + * http://java.sun.com/classes/foo.jar | |
| 290 | + * </pre> | |
| 291 | + * | |
| 292 | + * Note that if this CodeSource has a null location and a null | |
| 293 | + * certificate chain, then it implies every other CodeSource. | |
| 294 | + * | |
| 295 | + * @param codesource CodeSource to compare against. | |
| 296 | + * | |
| 297 | + * @return true if the specified codesource is implied by this codesource, | |
| 298 | + * false if not. | |
| 299 | + */ | |
| 300 | + | |
| 301 | + public boolean implies(CodeSource codesource) | |
| 302 | + { | |
| 303 | + if (codesource == null) | |
| 304 | + return false; | |
| 305 | + | |
| 306 | + return matchCerts(codesource, false) && matchLocation(codesource); | |
| 307 | + } | |
| 308 | + | |
| 309 | + /** | |
| 310 | + * Returns true if all the certs in this | |
| 311 | + * CodeSource are also in <i>that</i>. | |
| 312 | + * | |
| 313 | + * @param that the CodeSource to check against. | |
| 314 | + * @param strict If true then a strict equality match is performed. | |
| 315 | + * Otherwise a subset match is performed. | |
| 316 | + */ | |
| 317 | + private boolean matchCerts(CodeSource that, boolean strict) | |
| 318 | + { | |
| 319 | + boolean match; | |
| 320 | + | |
| 321 | + // match any key | |
| 322 | + if (certs == null && signers == null) { | |
| 323 | + if (strict) { | |
| 324 | + return (that.certs == null && that.signers == null); | |
| 325 | + } else { | |
| 326 | + return true; | |
| 327 | + } | |
| 328 | + // both have signers | |
| 329 | + } else if (signers != null && that.signers != null) { | |
| 330 | + if (strict && signers.length != that.signers.length) { | |
| 331 | + return false; | |
| 332 | + } | |
| 333 | + for (int i = 0; i < signers.length; i++) { | |
| 334 | + match = false; | |
| 335 | + for (int j = 0; j < that.signers.length; j++) { | |
| 336 | + if (signers[i].equals(that.signers[j])) { | |
| 337 | + match = true; | |
| 338 | + break; | |
| 339 | + } | |
| 340 | + } | |
| 341 | + if (!match) return false; | |
| 342 | + } | |
| 343 | + return true; | |
| 344 | + | |
| 345 | + // both have certs | |
| 346 | + } else if (certs != null && that.certs != null) { | |
| 347 | + if (strict && certs.length != that.certs.length) { | |
| 348 | + return false; | |
| 349 | + } | |
| 350 | + for (int i = 0; i < certs.length; i++) { | |
| 351 | + match = false; | |
| 352 | + for (int j = 0; j < that.certs.length; j++) { | |
| 353 | + if (certs[i].equals(that.certs[j])) { | |
| 354 | + match = true; | |
| 355 | + break; | |
| 356 | + } | |
| 357 | + } | |
| 358 | + if (!match) return false; | |
| 359 | + } | |
| 360 | + return true; | |
| 361 | + } | |
| 362 | + | |
| 363 | + return false; | |
| 364 | + } | |
| 365 | + | |
| 366 | + | |
| 367 | + /** | |
| 368 | + * Returns true if two CodeSource's have the "same" location. | |
| 369 | + * | |
| 370 | + * @param that CodeSource to compare against | |
| 371 | + */ | |
| 372 | + private boolean matchLocation(CodeSource that) | |
| 373 | + { | |
| 374 | + if (location == null) { | |
| 375 | + return true; | |
| 376 | + } | |
| 377 | + | |
| 378 | + if ((that == null) || (that.location == null)) | |
| 379 | + return false; | |
| 380 | + | |
| 381 | + if (location.equals(that.location)) | |
| 382 | + return true; | |
| 383 | + | |
| 384 | + if (!location.getProtocol().equals(that.location.getProtocol())) | |
| 385 | + return false; | |
| 386 | + | |
| 387 | + String thisHost = location.getHost(); | |
| 388 | + String thatHost = that.location.getHost(); | |
| 389 | + | |
| 390 | + if (thisHost != null) { | |
| 391 | + if (("".equals(thisHost) || "localhost".equals(thisHost)) && | |
| 392 | + ("".equals(thatHost) || "localhost".equals(thatHost))) { | |
| 393 | + // ok | |
| 394 | + } else if (!thisHost.equals(thatHost)) { | |
| 395 | + if (thatHost == null) { | |
| 396 | + return false; | |
| 397 | + } | |
| 398 | + if (this.sp == null) { | |
| 399 | + this.sp = new SocketPermission(thisHost, "resolve"); | |
| 400 | + } | |
| 401 | + if (that.sp == null) { | |
| 402 | + that.sp = new SocketPermission(thatHost, "resolve"); | |
| 403 | + } | |
| 404 | + if (!this.sp.implies(that.sp)) { | |
| 405 | + return false; | |
| 406 | + } | |
| 407 | + } | |
| 408 | + } | |
| 409 | + | |
| 410 | + if (location.getPort() != -1) { | |
| 411 | + if (location.getPort() != that.location.getPort()) | |
| 412 | + return false; | |
| 413 | + } | |
| 414 | + | |
| 415 | + if (location.getFile().endsWith("/-")) { | |
| 416 | + // Matches the directory and (recursively) all files | |
| 417 | + // and subdirectories contained in that directory. | |
| 418 | + // For example, "/a/b/-" implies anything that starts with | |
| 419 | + // "/a/b/" | |
| 420 | + String thisPath = location.getFile().substring(0, | |
| 421 | + location.getFile().length()-1); | |
| 422 | + if (!that.location.getFile().startsWith(thisPath)) | |
| 423 | + return false; | |
| 424 | + } else if (location.getFile().endsWith("/*")) { | |
| 425 | + // Matches the directory and all the files contained in that | |
| 426 | + // directory. | |
| 427 | + // For example, "/a/b/*" implies anything that starts with | |
| 428 | + // "/a/b/" but has no further slashes | |
| 429 | + int last = that.location.getFile().lastIndexOf('/'); | |
| 430 | + if (last == -1) | |
| 431 | + return false; | |
| 432 | + String thisPath = location.getFile().substring(0, | |
| 433 | + location.getFile().length()-1); | |
| 434 | + String thatPath = that.location.getFile().substring(0, last+1); | |
| 435 | + if (!thatPath.equals(thisPath)) | |
| 436 | + return false; | |
| 437 | + } else { | |
| 438 | + // Exact matches only. | |
| 439 | + // For example, "/a/b" and "/a/b/" both imply "/a/b/" | |
| 440 | + if ((!that.location.getFile().equals(location.getFile())) | |
| 441 | + && (!that.location.getFile().equals(location.getFile()+"/"))) { | |
| 442 | + return false; | |
| 443 | + } | |
| 444 | + } | |
| 445 | + | |
| 446 | + if (location.getRef() == null) | |
| 447 | + return true; | |
| 448 | + else | |
| 449 | + return location.getRef().equals(that.location.getRef()); | |
| 450 | + } | |
| 451 | + | |
| 452 | + /** | |
| 453 | + * Returns a string describing this CodeSource, telling its | |
| 454 | + * URL and certificates. | |
| 455 | + * | |
| 456 | + * @return information about this CodeSource. | |
| 457 | + */ | |
| 458 | + public String toString() { | |
| 459 | + StringBuilder sb = new StringBuilder(); | |
| 460 | + sb.append("("); | |
| 461 | + sb.append(this.location); | |
| 462 | + | |
| 463 | + if (this.certs != null && this.certs.length > 0) { | |
| 464 | + for (int i = 0; i < this.certs.length; i++) { | |
| 465 | + sb.append( " " + this.certs[i]); | |
| 466 | + } | |
| 467 | + | |
| 468 | + } else if (this.signers != null && this.signers.length > 0) { | |
| 469 | + for (int i = 0; i < this.signers.length; i++) { | |
| 470 | + sb.append( " " + this.signers[i]); | |
| 471 | + } | |
| 472 | + } else { | |
| 473 | + sb.append(" <no signer certificates>"); | |
| 474 | + } | |
| 475 | + sb.append(")"); | |
| 476 | + return sb.toString(); | |
| 477 | + } | |
| 478 | + | |
| 479 | + /** | |
| 480 | + * Writes this object out to a stream (i.e., serializes it). | |
| 481 | + * | |
| 482 | + * @serialData An initial <code>URL</code> is followed by an | |
| 483 | + * <code>int</code> indicating the number of certificates to follow | |
| 484 | + * (a value of "zero" denotes that there are no certificates associated | |
| 485 | + * with this object). | |
| 486 | + * Each certificate is written out starting with a <code>String</code> | |
| 487 | + * denoting the certificate type, followed by an | |
| 488 | + * <code>int</code> specifying the length of the certificate encoding, | |
| 489 | + * followed by the certificate encoding itself which is written out as an | |
| 490 | + * array of bytes. Finally, if any code signers are present then the array | |
| 491 | + * of code signers is serialized and written out too. | |
| 492 | + */ | |
| 493 | + private void writeObject(java.io.ObjectOutputStream oos) | |
| 494 | + throws IOException | |
| 495 | + { | |
| 496 | + oos.defaultWriteObject(); // location | |
| 497 | + | |
| 498 | + // Serialize the array of certs | |
| 499 | + if (certs == null || certs.length == 0) { | |
| 500 | + oos.writeInt(0); | |
| 501 | + } else { | |
| 502 | + // write out the total number of certs | |
| 503 | + oos.writeInt(certs.length); | |
| 504 | + // write out each cert, including its type | |
| 505 | + for (int i = 0; i < certs.length; i++) { | |
| 506 | + java.security.cert.Certificate cert = certs[i]; | |
| 507 | + try { | |
| 508 | + oos.writeUTF(cert.getType()); | |
| 509 | + byte[] encoded = cert.getEncoded(); | |
| 510 | + oos.writeInt(encoded.length); | |
| 511 | + oos.write(encoded); | |
| 512 | + } catch (CertificateEncodingException cee) { | |
| 513 | + throw new IOException(cee.getMessage()); | |
| 514 | + } | |
| 515 | + } | |
| 516 | + } | |
| 517 | + | |
| 518 | + // Serialize the array of code signers (if any) | |
| 519 | + if (signers != null && signers.length > 0) { | |
| 520 | + oos.writeObject(signers); | |
| 521 | + } | |
| 522 | + } | |
| 523 | + | |
| 524 | + /** | |
| 525 | + * Restores this object from a stream (i.e., deserializes it). | |
| 526 | + */ | |
| 527 | + private void readObject(java.io.ObjectInputStream ois) | |
| 528 | + throws IOException, ClassNotFoundException | |
| 529 | + { | |
| 530 | + CertificateFactory cf; | |
| 531 | + Hashtable<String, CertificateFactory> cfs = null; | |
| 532 | + | |
| 533 | + ois.defaultReadObject(); // location | |
| 534 | + | |
| 535 | + // process any new-style certs in the stream (if present) | |
| 536 | + int size = ois.readInt(); | |
| 537 | + if (size > 0) { | |
| 538 | + // we know of 3 different cert types: X.509, PGP, SDSI, which | |
| 539 | + // could all be present in the stream at the same time | |
| 540 | + cfs = new Hashtable<String, CertificateFactory>(3); | |
| 541 | + this.certs = new java.security.cert.Certificate[size]; | |
| 542 | + } | |
| 543 | + | |
| 544 | + for (int i = 0; i < size; i++) { | |
| 545 | + // read the certificate type, and instantiate a certificate | |
| 546 | + // factory of that type (reuse existing factory if possible) | |
| 547 | + String certType = ois.readUTF(); | |
| 548 | + if (cfs.containsKey(certType)) { | |
| 549 | + // reuse certificate factory | |
| 550 | + cf = cfs.get(certType); | |
| 551 | + } else { | |
| 552 | + // create new certificate factory | |
| 553 | + try { | |
| 554 | + cf = CertificateFactory.getInstance(certType); | |
| 555 | + } catch (CertificateException ce) { | |
| 556 | + throw new ClassNotFoundException | |
| 557 | + ("Certificate factory for " + certType + " not found"); | |
| 558 | + } | |
| 559 | + // store the certificate factory so we can reuse it later | |
| 560 | + cfs.put(certType, cf); | |
| 561 | + } | |
| 562 | + // parse the certificate | |
| 563 | + byte[] encoded = null; | |
| 564 | + try { | |
| 565 | + encoded = new byte[ois.readInt()]; | |
| 566 | + } catch (OutOfMemoryError oome) { | |
| 567 | + throw new IOException("Certificate too big"); | |
| 568 | + } | |
| 569 | + ois.readFully(encoded); | |
| 570 | + ByteArrayInputStream bais = new ByteArrayInputStream(encoded); | |
| 571 | + try { | |
| 572 | + this.certs[i] = cf.generateCertificate(bais); | |
| 573 | + } catch (CertificateException ce) { | |
| 574 | + throw new IOException(ce.getMessage()); | |
| 575 | + } | |
| 576 | + bais.close(); | |
| 577 | + } | |
| 578 | + | |
| 579 | + // Deserialize array of code signers (if any) | |
| 580 | + try { | |
| 581 | + this.signers = ((CodeSigner[])ois.readObject()).clone(); | |
| 582 | + } catch (IOException ioe) { | |
| 583 | + // no signers present | |
| 584 | + } | |
| 585 | + } | |
| 586 | + | |
| 587 | + /* | |
| 588 | + * Convert an array of certificates to an array of code signers. | |
| 589 | + * The array of certificates is a concatenation of certificate chains | |
| 590 | + * where the initial certificate in each chain is the end-entity cert. | |
| 591 | + * | |
| 592 | + * @return An array of code signers or null if none are generated. | |
| 593 | + */ | |
| 594 | + private CodeSigner[] convertCertArrayToSignerArray( | |
| 595 | + java.security.cert.Certificate[] certs) { | |
| 596 | + | |
| 597 | + if (certs == null) { | |
| 598 | + return null; | |
| 599 | + } | |
| 600 | + | |
| 601 | + try { | |
| 602 | + // Initialize certificate factory | |
| 603 | + if (factory == null) { | |
| 604 | + factory = CertificateFactory.getInstance("X.509"); | |
| 605 | + } | |
| 606 | + | |
| 607 | + // Iterate through all the certificates | |
| 608 | + int i = 0; | |
| 609 | + List<CodeSigner> signers = new ArrayList<>(); | |
| 610 | + while (i < certs.length) { | |
| 611 | + List<java.security.cert.Certificate> certChain = | |
| 612 | + new ArrayList<>(); | |
| 613 | + certChain.add(certs[i++]); // first cert is an end-entity cert | |
| 614 | + int j = i; | |
| 615 | + | |
| 616 | + // Extract chain of certificates | |
| 617 | + // (loop while certs are not end-entity certs) | |
| 618 | + while (j < certs.length && | |
| 619 | + certs[j] instanceof X509Certificate && | |
| 620 | + ((X509Certificate)certs[j]).getBasicConstraints() != -1) { | |
| 621 | + certChain.add(certs[j]); | |
| 622 | + j++; | |
| 623 | + } | |
| 624 | + i = j; | |
| 625 | + CertPath certPath = factory.generateCertPath(certChain); | |
| 626 | + signers.add(new CodeSigner(certPath, null)); | |
| 627 | + } | |
| 628 | + | |
| 629 | + if (signers.isEmpty()) { | |
| 630 | + return null; | |
| 631 | + } else { | |
| 632 | + return signers.toArray(new CodeSigner[signers.size()]); | |
| 633 | + } | |
| 634 | + | |
| 635 | + } catch (CertificateException e) { | |
| 636 | + return null; //TODO - may be better to throw an ex. here | |
| 637 | + } | |
| 638 | + } | |
| 639 | +} | |
Binary file not shown.
| @@ -0,0 +1,83 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * An enumeration of cryptographic primitives. | |
| 30 | + * | |
| 31 | + * @since 1.7 | |
| 32 | + */ | |
| 33 | +public enum CryptoPrimitive { | |
| 34 | + /** | |
| 35 | + * Hash function | |
| 36 | + */ | |
| 37 | + MESSAGE_DIGEST, | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * Cryptographic random number generator | |
| 41 | + */ | |
| 42 | + SECURE_RANDOM, | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * Symmetric primitive: block cipher | |
| 46 | + */ | |
| 47 | + BLOCK_CIPHER, | |
| 48 | + | |
| 49 | + /** | |
| 50 | + * Symmetric primitive: stream cipher | |
| 51 | + */ | |
| 52 | + STREAM_CIPHER, | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * Symmetric primitive: message authentication code | |
| 56 | + */ | |
| 57 | + MAC, | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * Symmetric primitive: key wrap | |
| 61 | + */ | |
| 62 | + KEY_WRAP, | |
| 63 | + | |
| 64 | + /** | |
| 65 | + * Asymmetric primitive: public key encryption | |
| 66 | + */ | |
| 67 | + PUBLIC_KEY_ENCRYPTION, | |
| 68 | + | |
| 69 | + /** | |
| 70 | + * Asymmetric primitive: signature scheme | |
| 71 | + */ | |
| 72 | + SIGNATURE, | |
| 73 | + | |
| 74 | + /** | |
| 75 | + * Asymmetric primitive: key encapsulation mechanism | |
| 76 | + */ | |
| 77 | + KEY_ENCAPSULATION, | |
| 78 | + | |
| 79 | + /** | |
| 80 | + * Asymmetric primitive: key agreement and key distribution | |
| 81 | + */ | |
| 82 | + KEY_AGREEMENT | |
| 83 | +} | |
Binary file not shown.
| @@ -0,0 +1,86 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This is the generic Message Digest exception. | |
| 30 | + * | |
| 31 | + * @author Benjamin Renaud | |
| 32 | + */ | |
| 33 | +public class DigestException extends GeneralSecurityException { | |
| 34 | + | |
| 35 | + private static final long serialVersionUID = 5821450303093652515L; | |
| 36 | + | |
| 37 | + /** | |
| 38 | + * Constructs a DigestException with no detail message. (A | |
| 39 | + * detail message is a String that describes this particular | |
| 40 | + * exception.) | |
| 41 | + */ | |
| 42 | + public DigestException() { | |
| 43 | + super(); | |
| 44 | + } | |
| 45 | + | |
| 46 | + /** | |
| 47 | + * Constructs a DigestException with the specified detail | |
| 48 | + * message. (A detail message is a String that describes this | |
| 49 | + * particular exception.) | |
| 50 | + * | |
| 51 | + * @param msg the detail message. | |
| 52 | + */ | |
| 53 | + public DigestException(String msg) { | |
| 54 | + super(msg); | |
| 55 | + } | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * Creates a <code>DigestException</code> with the specified | |
| 59 | + * detail message and cause. | |
| 60 | + * | |
| 61 | + * @param message the detail message (which is saved for later retrieval | |
| 62 | + * by the {@link #getMessage()} method). | |
| 63 | + * @param cause the cause (which is saved for later retrieval by the | |
| 64 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 65 | + * and indicates that the cause is nonexistent or unknown.) | |
| 66 | + * @since 1.5 | |
| 67 | + */ | |
| 68 | + public DigestException(String message, Throwable cause) { | |
| 69 | + super(message, cause); | |
| 70 | + } | |
| 71 | + | |
| 72 | + /** | |
| 73 | + * Creates a <code>DigestException</code> with the specified cause | |
| 74 | + * and a detail message of <tt>(cause==null ? null : cause.toString())</tt> | |
| 75 | + * (which typically contains the class and detail message of | |
| 76 | + * <tt>cause</tt>). | |
| 77 | + * | |
| 78 | + * @param cause the cause (which is saved for later retrieval by the | |
| 79 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 80 | + * and indicates that the cause is nonexistent or unknown.) | |
| 81 | + * @since 1.5 | |
| 82 | + */ | |
| 83 | + public DigestException(Throwable cause) { | |
| 84 | + super(cause); | |
| 85 | + } | |
| 86 | +} | |
Binary file not shown.
| @@ -0,0 +1,188 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.IOException; | |
| 29 | +import java.io.EOFException; | |
| 30 | +import java.io.InputStream; | |
| 31 | +import java.io.FilterInputStream; | |
| 32 | +import java.io.PrintStream; | |
| 33 | +import java.io.ByteArrayInputStream; | |
| 34 | + | |
| 35 | +/** | |
| 36 | + * A transparent stream that updates the associated message digest using | |
| 37 | + * the bits going through the stream. | |
| 38 | + * | |
| 39 | + * <p>To complete the message digest computation, call one of the | |
| 40 | + * <code>digest</code> methods on the associated message | |
| 41 | + * digest after your calls to one of this digest input stream's | |
| 42 | + * {@link #read() read} methods. | |
| 43 | + * | |
| 44 | + * <p>It is possible to turn this stream on or off (see | |
| 45 | + * {@link #on(boolean) on}). When it is on, a call to one of the | |
| 46 | + * <code>read</code> methods | |
| 47 | + * results in an update on the message digest. But when it is off, | |
| 48 | + * the message digest is not updated. The default is for the stream | |
| 49 | + * to be on. | |
| 50 | + * | |
| 51 | + * <p>Note that digest objects can compute only one digest (see | |
| 52 | + * {@link MessageDigest}), | |
| 53 | + * so that in order to compute intermediate digests, a caller should | |
| 54 | + * retain a handle onto the digest object, and clone it for each | |
| 55 | + * digest to be computed, leaving the orginal digest untouched. | |
| 56 | + * | |
| 57 | + * @see MessageDigest | |
| 58 | + * | |
| 59 | + * @see DigestOutputStream | |
| 60 | + * | |
| 61 | + * @author Benjamin Renaud | |
| 62 | + */ | |
| 63 | + | |
| 64 | +public class DigestInputStream extends FilterInputStream { | |
| 65 | + | |
| 66 | + /* NOTE: This should be made a generic UpdaterInputStream */ | |
| 67 | + | |
| 68 | + /* Are we on or off? */ | |
| 69 | + private boolean on = true; | |
| 70 | + | |
| 71 | + /** | |
| 72 | + * The message digest associated with this stream. | |
| 73 | + */ | |
| 74 | + protected MessageDigest digest; | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * Creates a digest input stream, using the specified input stream | |
| 78 | + * and message digest. | |
| 79 | + * | |
| 80 | + * @param stream the input stream. | |
| 81 | + * | |
| 82 | + * @param digest the message digest to associate with this stream. | |
| 83 | + */ | |
| 84 | + public DigestInputStream(InputStream stream, MessageDigest digest) { | |
| 85 | + super(stream); | |
| 86 | + setMessageDigest(digest); | |
| 87 | + } | |
| 88 | + | |
| 89 | + /** | |
| 90 | + * Returns the message digest associated with this stream. | |
| 91 | + * | |
| 92 | + * @return the message digest associated with this stream. | |
| 93 | + * @see #setMessageDigest(java.security.MessageDigest) | |
| 94 | + */ | |
| 95 | + public MessageDigest getMessageDigest() { | |
| 96 | + return digest; | |
| 97 | + } | |
| 98 | + | |
| 99 | + /** | |
| 100 | + * Associates the specified message digest with this stream. | |
| 101 | + * | |
| 102 | + * @param digest the message digest to be associated with this stream. | |
| 103 | + * @see #getMessageDigest() | |
| 104 | + */ | |
| 105 | + public void setMessageDigest(MessageDigest digest) { | |
| 106 | + this.digest = digest; | |
| 107 | + } | |
| 108 | + | |
| 109 | + /** | |
| 110 | + * Reads a byte, and updates the message digest (if the digest | |
| 111 | + * function is on). That is, this method reads a byte from the | |
| 112 | + * input stream, blocking until the byte is actually read. If the | |
| 113 | + * digest function is on (see {@link #on(boolean) on}), this method | |
| 114 | + * will then call <code>update</code> on the message digest associated | |
| 115 | + * with this stream, passing it the byte read. | |
| 116 | + * | |
| 117 | + * @return the byte read. | |
| 118 | + * | |
| 119 | + * @exception IOException if an I/O error occurs. | |
| 120 | + * | |
| 121 | + * @see MessageDigest#update(byte) | |
| 122 | + */ | |
| 123 | + public int read() throws IOException { | |
| 124 | + int ch = in.read(); | |
| 125 | + if (on && ch != -1) { | |
| 126 | + digest.update((byte)ch); | |
| 127 | + } | |
| 128 | + return ch; | |
| 129 | + } | |
| 130 | + | |
| 131 | + /** | |
| 132 | + * Reads into a byte array, and updates the message digest (if the | |
| 133 | + * digest function is on). That is, this method reads up to | |
| 134 | + * <code>len</code> bytes from the input stream into the array | |
| 135 | + * <code>b</code>, starting at offset <code>off</code>. This method | |
| 136 | + * blocks until the data is actually | |
| 137 | + * read. If the digest function is on (see | |
| 138 | + * {@link #on(boolean) on}), this method will then call <code>update</code> | |
| 139 | + * on the message digest associated with this stream, passing it | |
| 140 | + * the data. | |
| 141 | + * | |
| 142 | + * @param b the array into which the data is read. | |
| 143 | + * | |
| 144 | + * @param off the starting offset into <code>b</code> of where the | |
| 145 | + * data should be placed. | |
| 146 | + * | |
| 147 | + * @param len the maximum number of bytes to be read from the input | |
| 148 | + * stream into b, starting at offset <code>off</code>. | |
| 149 | + * | |
| 150 | + * @return the actual number of bytes read. This is less than | |
| 151 | + * <code>len</code> if the end of the stream is reached prior to | |
| 152 | + * reading <code>len</code> bytes. -1 is returned if no bytes were | |
| 153 | + * read because the end of the stream had already been reached when | |
| 154 | + * the call was made. | |
| 155 | + * | |
| 156 | + * @exception IOException if an I/O error occurs. | |
| 157 | + * | |
| 158 | + * @see MessageDigest#update(byte[], int, int) | |
| 159 | + */ | |
| 160 | + public int read(byte[] b, int off, int len) throws IOException { | |
| 161 | + int result = in.read(b, off, len); | |
| 162 | + if (on && result != -1) { | |
| 163 | + digest.update(b, off, result); | |
| 164 | + } | |
| 165 | + return result; | |
| 166 | + } | |
| 167 | + | |
| 168 | + /** | |
| 169 | + * Turns the digest function on or off. The default is on. When | |
| 170 | + * it is on, a call to one of the <code>read</code> methods results in an | |
| 171 | + * update on the message digest. But when it is off, the message | |
| 172 | + * digest is not updated. | |
| 173 | + * | |
| 174 | + * @param on true to turn the digest function on, false to turn | |
| 175 | + * it off. | |
| 176 | + */ | |
| 177 | + public void on(boolean on) { | |
| 178 | + this.on = on; | |
| 179 | + } | |
| 180 | + | |
| 181 | + /** | |
| 182 | + * Prints a string representation of this digest input stream and | |
| 183 | + * its associated message digest object. | |
| 184 | + */ | |
| 185 | + public String toString() { | |
| 186 | + return "[Digest Input Stream] " + digest.toString(); | |
| 187 | + } | |
| 188 | +} | |
Binary file not shown.
| @@ -0,0 +1,171 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.IOException; | |
| 29 | +import java.io.EOFException; | |
| 30 | +import java.io.OutputStream; | |
| 31 | +import java.io.FilterOutputStream; | |
| 32 | +import java.io.PrintStream; | |
| 33 | +import java.io.ByteArrayOutputStream; | |
| 34 | + | |
| 35 | +/** | |
| 36 | + * A transparent stream that updates the associated message digest using | |
| 37 | + * the bits going through the stream. | |
| 38 | + * | |
| 39 | + * <p>To complete the message digest computation, call one of the | |
| 40 | + * <code>digest</code> methods on the associated message | |
| 41 | + * digest after your calls to one of this digest ouput stream's | |
| 42 | + * {@link #write(int) write} methods. | |
| 43 | + * | |
| 44 | + * <p>It is possible to turn this stream on or off (see | |
| 45 | + * {@link #on(boolean) on}). When it is on, a call to one of the | |
| 46 | + * <code>write</code> methods results in | |
| 47 | + * an update on the message digest. But when it is off, the message | |
| 48 | + * digest is not updated. The default is for the stream to be on. | |
| 49 | + * | |
| 50 | + * @see MessageDigest | |
| 51 | + * @see DigestInputStream | |
| 52 | + * | |
| 53 | + * @author Benjamin Renaud | |
| 54 | + */ | |
| 55 | +public class DigestOutputStream extends FilterOutputStream { | |
| 56 | + | |
| 57 | + private boolean on = true; | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * The message digest associated with this stream. | |
| 61 | + */ | |
| 62 | + protected MessageDigest digest; | |
| 63 | + | |
| 64 | + /** | |
| 65 | + * Creates a digest output stream, using the specified output stream | |
| 66 | + * and message digest. | |
| 67 | + * | |
| 68 | + * @param stream the output stream. | |
| 69 | + * | |
| 70 | + * @param digest the message digest to associate with this stream. | |
| 71 | + */ | |
| 72 | + public DigestOutputStream(OutputStream stream, MessageDigest digest) { | |
| 73 | + super(stream); | |
| 74 | + setMessageDigest(digest); | |
| 75 | + } | |
| 76 | + | |
| 77 | + /** | |
| 78 | + * Returns the message digest associated with this stream. | |
| 79 | + * | |
| 80 | + * @return the message digest associated with this stream. | |
| 81 | + * @see #setMessageDigest(java.security.MessageDigest) | |
| 82 | + */ | |
| 83 | + public MessageDigest getMessageDigest() { | |
| 84 | + return digest; | |
| 85 | + } | |
| 86 | + | |
| 87 | + /** | |
| 88 | + * Associates the specified message digest with this stream. | |
| 89 | + * | |
| 90 | + * @param digest the message digest to be associated with this stream. | |
| 91 | + * @see #getMessageDigest() | |
| 92 | + */ | |
| 93 | + public void setMessageDigest(MessageDigest digest) { | |
| 94 | + this.digest = digest; | |
| 95 | + } | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * Updates the message digest (if the digest function is on) using | |
| 99 | + * the specified byte, and in any case writes the byte | |
| 100 | + * to the output stream. That is, if the digest function is on | |
| 101 | + * (see {@link #on(boolean) on}), this method calls | |
| 102 | + * <code>update</code> on the message digest associated with this | |
| 103 | + * stream, passing it the byte <code>b</code>. This method then | |
| 104 | + * writes the byte to the output stream, blocking until the byte | |
| 105 | + * is actually written. | |
| 106 | + * | |
| 107 | + * @param b the byte to be used for updating and writing to the | |
| 108 | + * output stream. | |
| 109 | + * | |
| 110 | + * @exception IOException if an I/O error occurs. | |
| 111 | + * | |
| 112 | + * @see MessageDigest#update(byte) | |
| 113 | + */ | |
| 114 | + public void write(int b) throws IOException { | |
| 115 | + if (on) { | |
| 116 | + digest.update((byte)b); | |
| 117 | + } | |
| 118 | + out.write(b); | |
| 119 | + } | |
| 120 | + | |
| 121 | + /** | |
| 122 | + * Updates the message digest (if the digest function is on) using | |
| 123 | + * the specified subarray, and in any case writes the subarray to | |
| 124 | + * the output stream. That is, if the digest function is on (see | |
| 125 | + * {@link #on(boolean) on}), this method calls <code>update</code> | |
| 126 | + * on the message digest associated with this stream, passing it | |
| 127 | + * the subarray specifications. This method then writes the subarray | |
| 128 | + * bytes to the output stream, blocking until the bytes are actually | |
| 129 | + * written. | |
| 130 | + * | |
| 131 | + * @param b the array containing the subarray to be used for updating | |
| 132 | + * and writing to the output stream. | |
| 133 | + * | |
| 134 | + * @param off the offset into <code>b</code> of the first byte to | |
| 135 | + * be updated and written. | |
| 136 | + * | |
| 137 | + * @param len the number of bytes of data to be updated and written | |
| 138 | + * from <code>b</code>, starting at offset <code>off</code>. | |
| 139 | + * | |
| 140 | + * @exception IOException if an I/O error occurs. | |
| 141 | + * | |
| 142 | + * @see MessageDigest#update(byte[], int, int) | |
| 143 | + */ | |
| 144 | + public void write(byte[] b, int off, int len) throws IOException { | |
| 145 | + if (on) { | |
| 146 | + digest.update(b, off, len); | |
| 147 | + } | |
| 148 | + out.write(b, off, len); | |
| 149 | + } | |
| 150 | + | |
| 151 | + /** | |
| 152 | + * Turns the digest function on or off. The default is on. When | |
| 153 | + * it is on, a call to one of the <code>write</code> methods results in an | |
| 154 | + * update on the message digest. But when it is off, the message | |
| 155 | + * digest is not updated. | |
| 156 | + * | |
| 157 | + * @param on true to turn the digest function on, false to turn it | |
| 158 | + * off. | |
| 159 | + */ | |
| 160 | + public void on(boolean on) { | |
| 161 | + this.on = on; | |
| 162 | + } | |
| 163 | + | |
| 164 | + /** | |
| 165 | + * Prints a string representation of this digest output stream and | |
| 166 | + * its associated message digest object. | |
| 167 | + */ | |
| 168 | + public String toString() { | |
| 169 | + return "[Digest Output Stream] " + digest.toString(); | |
| 170 | + } | |
| 171 | +} | |
Binary file not shown.
| @@ -0,0 +1,112 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * A <code>DomainCombiner</code> provides a means to dynamically | |
| 30 | + * update the ProtectionDomains associated with the current | |
| 31 | + * <code>AccessControlContext</code>. | |
| 32 | + * | |
| 33 | + * <p> A <code>DomainCombiner</code> is passed as a parameter to the | |
| 34 | + * appropriate constructor for <code>AccessControlContext</code>. | |
| 35 | + * The newly constructed context is then passed to the | |
| 36 | + * <code>AccessController.doPrivileged(..., context)</code> method | |
| 37 | + * to bind the provided context (and associated <code>DomainCombiner</code>) | |
| 38 | + * with the current execution Thread. Subsequent calls to | |
| 39 | + * <code>AccessController.getContext</code> or | |
| 40 | + * <code>AccessController.checkPermission</code> | |
| 41 | + * cause the <code>DomainCombiner.combine</code> to get invoked. | |
| 42 | + * | |
| 43 | + * <p> The combine method takes two arguments. The first argument represents | |
| 44 | + * an array of ProtectionDomains from the current execution Thread, | |
| 45 | + * since the most recent call to <code>AccessController.doPrivileged</code>. | |
| 46 | + * If no call to doPrivileged was made, then the first argument will contain | |
| 47 | + * all the ProtectionDomains from the current execution Thread. | |
| 48 | + * The second argument represents an array of inherited ProtectionDomains, | |
| 49 | + * which may be <code>null</code>. ProtectionDomains may be inherited | |
| 50 | + * from a parent Thread, or from a privileged context. If no call to | |
| 51 | + * doPrivileged was made, then the second argument will contain the | |
| 52 | + * ProtectionDomains inherited from the parent Thread. If one or more calls | |
| 53 | + * to doPrivileged were made, and the most recent call was to | |
| 54 | + * doPrivileged(action, context), then the second argument will contain the | |
| 55 | + * ProtectionDomains from the privileged context. If the most recent call | |
| 56 | + * was to doPrivileged(action), then there is no privileged context, | |
| 57 | + * and the second argument will be <code>null</code>. | |
| 58 | + * | |
| 59 | + * <p> The <code>combine</code> method investigates the two input arrays | |
| 60 | + * of ProtectionDomains and returns a single array containing the updated | |
| 61 | + * ProtectionDomains. In the simplest case, the <code>combine</code> | |
| 62 | + * method merges the two stacks into one. In more complex cases, | |
| 63 | + * the <code>combine</code> method returns a modified | |
| 64 | + * stack of ProtectionDomains. The modification may have added new | |
| 65 | + * ProtectionDomains, removed certain ProtectionDomains, or simply | |
| 66 | + * updated existing ProtectionDomains. Re-ordering and other optimizations | |
| 67 | + * to the ProtectionDomains are also permitted. Typically the | |
| 68 | + * <code>combine</code> method bases its updates on the information | |
| 69 | + * encapsulated in the <code>DomainCombiner</code>. | |
| 70 | + * | |
| 71 | + * <p> After the <code>AccessController.getContext</code> method | |
| 72 | + * receives the combined stack of ProtectionDomains back from | |
| 73 | + * the <code>DomainCombiner</code>, it returns a new | |
| 74 | + * AccessControlContext that has both the combined ProtectionDomains | |
| 75 | + * as well as the <code>DomainCombiner</code>. | |
| 76 | + * | |
| 77 | + * @see AccessController | |
| 78 | + * @see AccessControlContext | |
| 79 | + * @since 1.3 | |
| 80 | + */ | |
| 81 | +public interface DomainCombiner { | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * Modify or update the provided ProtectionDomains. | |
| 85 | + * ProtectionDomains may be added to or removed from the given | |
| 86 | + * ProtectionDomains. The ProtectionDomains may be re-ordered. | |
| 87 | + * Individual ProtectionDomains may be modified (with a new | |
| 88 | + * set of Permissions, for example). | |
| 89 | + * | |
| 90 | + * <p> | |
| 91 | + * | |
| 92 | + * @param currentDomains the ProtectionDomains associated with the | |
| 93 | + * current execution Thread, up to the most recent | |
| 94 | + * privileged <code>ProtectionDomain</code>. | |
| 95 | + * The ProtectionDomains are are listed in order of execution, | |
| 96 | + * with the most recently executing <code>ProtectionDomain</code> | |
| 97 | + * residing at the beginning of the array. This parameter may | |
| 98 | + * be <code>null</code> if the current execution Thread | |
| 99 | + * has no associated ProtectionDomains.<p> | |
| 100 | + * | |
| 101 | + * @param assignedDomains an array of inherited ProtectionDomains. | |
| 102 | + * ProtectionDomains may be inherited from a parent Thread, | |
| 103 | + * or from a privileged <code>AccessControlContext</code>. | |
| 104 | + * This parameter may be <code>null</code> | |
| 105 | + * if there are no inherited ProtectionDomains. | |
| 106 | + * | |
| 107 | + * @return a new array consisting of the updated ProtectionDomains, | |
| 108 | + * or <code>null</code>. | |
| 109 | + */ | |
| 110 | + ProtectionDomain[] combine(ProtectionDomain[] currentDomains, | |
| 111 | + ProtectionDomain[] assignedDomains); | |
| 112 | +} | |
Binary file not shown.
| @@ -0,0 +1,88 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * The <code>GeneralSecurityException</code> class is a generic | |
| 30 | + * security exception class that provides type safety for all the | |
| 31 | + * security-related exception classes that extend from it. | |
| 32 | + * | |
| 33 | + * @author Jan Luehe | |
| 34 | + */ | |
| 35 | + | |
| 36 | +public class GeneralSecurityException extends Exception { | |
| 37 | + | |
| 38 | + private static final long serialVersionUID = 894798122053539237L; | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * Constructs a GeneralSecurityException with no detail message. | |
| 42 | + */ | |
| 43 | + public GeneralSecurityException() { | |
| 44 | + super(); | |
| 45 | + } | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * Constructs a GeneralSecurityException with the specified detail | |
| 49 | + * message. | |
| 50 | + * A detail message is a String that describes this particular | |
| 51 | + * exception. | |
| 52 | + * | |
| 53 | + * @param msg the detail message. | |
| 54 | + */ | |
| 55 | + public GeneralSecurityException(String msg) { | |
| 56 | + super(msg); | |
| 57 | + } | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * Creates a <code>GeneralSecurityException</code> with the specified | |
| 61 | + * detail message and cause. | |
| 62 | + * | |
| 63 | + * @param message the detail message (which is saved for later retrieval | |
| 64 | + * by the {@link #getMessage()} method). | |
| 65 | + * @param cause the cause (which is saved for later retrieval by the | |
| 66 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 67 | + * and indicates that the cause is nonexistent or unknown.) | |
| 68 | + * @since 1.5 | |
| 69 | + */ | |
| 70 | + public GeneralSecurityException(String message, Throwable cause) { | |
| 71 | + super(message, cause); | |
| 72 | + } | |
| 73 | + | |
| 74 | + /** | |
| 75 | + * Creates a <code>GeneralSecurityException</code> with the specified cause | |
| 76 | + * and a detail message of <tt>(cause==null ? null : cause.toString())</tt> | |
| 77 | + * (which typically contains the class and detail message of | |
| 78 | + * <tt>cause</tt>). | |
| 79 | + * | |
| 80 | + * @param cause the cause (which is saved for later retrieval by the | |
| 81 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 82 | + * and indicates that the cause is nonexistent or unknown.) | |
| 83 | + * @since 1.5 | |
| 84 | + */ | |
| 85 | + public GeneralSecurityException(Throwable cause) { | |
| 86 | + super(cause); | |
| 87 | + } | |
| 88 | +} | |
Binary file not shown.
| @@ -0,0 +1,56 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * <p> This interface represents a guard, which is an object that is used | |
| 30 | + * to protect access to another object. | |
| 31 | + * | |
| 32 | + * <p>This interface contains a single method, <code>checkGuard</code>, | |
| 33 | + * with a single <code>object</code> argument. <code>checkGuard</code> is | |
| 34 | + * invoked (by the GuardedObject <code>getObject</code> method) | |
| 35 | + * to determine whether or not to allow access to the object. | |
| 36 | + * | |
| 37 | + * @see GuardedObject | |
| 38 | + * | |
| 39 | + * @author Roland Schemers | |
| 40 | + * @author Li Gong | |
| 41 | + */ | |
| 42 | + | |
| 43 | +public interface Guard { | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * Determines whether or not to allow access to the guarded object | |
| 47 | + * <code>object</code>. Returns silently if access is allowed. | |
| 48 | + * Otherwise, throws a SecurityException. | |
| 49 | + * | |
| 50 | + * @param object the object being protected by the guard. | |
| 51 | + * | |
| 52 | + * @exception SecurityException if access is denied. | |
| 53 | + * | |
| 54 | + */ | |
| 55 | + void checkGuard(Object object) throws SecurityException; | |
| 56 | +} | |
Binary file not shown.
| @@ -0,0 +1,102 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * A GuardedObject is an object that is used to protect access to | |
| 30 | + * another object. | |
| 31 | + * | |
| 32 | + * <p>A GuardedObject encapsulates a target object and a Guard object, | |
| 33 | + * such that access to the target object is possible | |
| 34 | + * only if the Guard object allows it. | |
| 35 | + * Once an object is encapsulated by a GuardedObject, | |
| 36 | + * access to that object is controlled by the <code>getObject</code> | |
| 37 | + * method, which invokes the | |
| 38 | + * <code>checkGuard</code> method on the Guard object that is | |
| 39 | + * guarding access. If access is not allowed, | |
| 40 | + * an exception is thrown. | |
| 41 | + * | |
| 42 | + * @see Guard | |
| 43 | + * @see Permission | |
| 44 | + * | |
| 45 | + * @author Roland Schemers | |
| 46 | + * @author Li Gong | |
| 47 | + */ | |
| 48 | + | |
| 49 | +public class GuardedObject implements java.io.Serializable { | |
| 50 | + | |
| 51 | + private static final long serialVersionUID = -5240450096227834308L; | |
| 52 | + | |
| 53 | + private Object object; // the object we are guarding | |
| 54 | + private Guard guard; // the guard | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * Constructs a GuardedObject using the specified object and guard. | |
| 58 | + * If the Guard object is null, then no restrictions will | |
| 59 | + * be placed on who can access the object. | |
| 60 | + * | |
| 61 | + * @param object the object to be guarded. | |
| 62 | + * | |
| 63 | + * @param guard the Guard object that guards access to the object. | |
| 64 | + */ | |
| 65 | + | |
| 66 | + public GuardedObject(Object object, Guard guard) | |
| 67 | + { | |
| 68 | + this.guard = guard; | |
| 69 | + this.object = object; | |
| 70 | + } | |
| 71 | + | |
| 72 | + /** | |
| 73 | + * Retrieves the guarded object, or throws an exception if access | |
| 74 | + * to the guarded object is denied by the guard. | |
| 75 | + * | |
| 76 | + * @return the guarded object. | |
| 77 | + * | |
| 78 | + * @exception SecurityException if access to the guarded object is | |
| 79 | + * denied. | |
| 80 | + */ | |
| 81 | + public Object getObject() | |
| 82 | + throws SecurityException | |
| 83 | + { | |
| 84 | + if (guard != null) | |
| 85 | + guard.checkGuard(object); | |
| 86 | + | |
| 87 | + return object; | |
| 88 | + } | |
| 89 | + | |
| 90 | + /** | |
| 91 | + * Writes this object out to a stream (i.e., serializes it). | |
| 92 | + * We check the guard if there is one. | |
| 93 | + */ | |
| 94 | + private void writeObject(java.io.ObjectOutputStream oos) | |
| 95 | + throws java.io.IOException | |
| 96 | + { | |
| 97 | + if (guard != null) | |
| 98 | + guard.checkGuard(object); | |
| 99 | + | |
| 100 | + oos.defaultWriteObject(); | |
| 101 | + } | |
| 102 | +} | |
Binary file not shown.
| @@ -0,0 +1,495 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.Serializable; | |
| 29 | +import java.util.*; | |
| 30 | + | |
| 31 | +/** | |
| 32 | + * <p>This class represents identities: real-world objects such as people, | |
| 33 | + * companies or organizations whose identities can be authenticated using | |
| 34 | + * their public keys. Identities may also be more abstract (or concrete) | |
| 35 | + * constructs, such as daemon threads or smart cards. | |
| 36 | + * | |
| 37 | + * <p>All Identity objects have a name and a public key. Names are | |
| 38 | + * immutable. Identities may also be scoped. That is, if an Identity is | |
| 39 | + * specified to have a particular scope, then the name and public | |
| 40 | + * key of the Identity are unique within that scope. | |
| 41 | + * | |
| 42 | + * <p>An Identity also has a set of certificates (all certifying its own | |
| 43 | + * public key). The Principal names specified in these certificates need | |
| 44 | + * not be the same, only the key. | |
| 45 | + * | |
| 46 | + * <p>An Identity can be subclassed, to include postal and email addresses, | |
| 47 | + * telephone numbers, images of faces and logos, and so on. | |
| 48 | + * | |
| 49 | + * @see IdentityScope | |
| 50 | + * @see Signer | |
| 51 | + * @see Principal | |
| 52 | + * | |
| 53 | + * @author Benjamin Renaud | |
| 54 | + * @deprecated This class is no longer used. Its functionality has been | |
| 55 | + * replaced by <code>java.security.KeyStore</code>, the | |
| 56 | + * <code>java.security.cert</code> package, and | |
| 57 | + * <code>java.security.Principal</code>. | |
| 58 | + */ | |
| 59 | +@Deprecated | |
| 60 | +public abstract class Identity implements Principal, Serializable { | |
| 61 | + | |
| 62 | + /** use serialVersionUID from JDK 1.1.x for interoperability */ | |
| 63 | + private static final long serialVersionUID = 3609922007826600659L; | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * The name for this identity. | |
| 67 | + * | |
| 68 | + * @serial | |
| 69 | + */ | |
| 70 | + private String name; | |
| 71 | + | |
| 72 | + /** | |
| 73 | + * The public key for this identity. | |
| 74 | + * | |
| 75 | + * @serial | |
| 76 | + */ | |
| 77 | + private PublicKey publicKey; | |
| 78 | + | |
| 79 | + /** | |
| 80 | + * Generic, descriptive information about the identity. | |
| 81 | + * | |
| 82 | + * @serial | |
| 83 | + */ | |
| 84 | + String info = "No further information available."; | |
| 85 | + | |
| 86 | + /** | |
| 87 | + * The scope of the identity. | |
| 88 | + * | |
| 89 | + * @serial | |
| 90 | + */ | |
| 91 | + IdentityScope scope; | |
| 92 | + | |
| 93 | + /** | |
| 94 | + * The certificates for this identity. | |
| 95 | + * | |
| 96 | + * @serial | |
| 97 | + */ | |
| 98 | + Vector<Certificate> certificates; | |
| 99 | + | |
| 100 | + /** | |
| 101 | + * Constructor for serialization only. | |
| 102 | + */ | |
| 103 | + protected Identity() { | |
| 104 | + this("restoring..."); | |
| 105 | + } | |
| 106 | + | |
| 107 | + /** | |
| 108 | + * Constructs an identity with the specified name and scope. | |
| 109 | + * | |
| 110 | + * @param name the identity name. | |
| 111 | + * @param scope the scope of the identity. | |
| 112 | + * | |
| 113 | + * @exception KeyManagementException if there is already an identity | |
| 114 | + * with the same name in the scope. | |
| 115 | + */ | |
| 116 | + public Identity(String name, IdentityScope scope) throws | |
| 117 | + KeyManagementException { | |
| 118 | + this(name); | |
| 119 | + if (scope != null) { | |
| 120 | + scope.addIdentity(this); | |
| 121 | + } | |
| 122 | + this.scope = scope; | |
| 123 | + } | |
| 124 | + | |
| 125 | + /** | |
| 126 | + * Constructs an identity with the specified name and no scope. | |
| 127 | + * | |
| 128 | + * @param name the identity name. | |
| 129 | + */ | |
| 130 | + public Identity(String name) { | |
| 131 | + this.name = name; | |
| 132 | + } | |
| 133 | + | |
| 134 | + /** | |
| 135 | + * Returns this identity's name. | |
| 136 | + * | |
| 137 | + * @return the name of this identity. | |
| 138 | + */ | |
| 139 | + public final String getName() { | |
| 140 | + return name; | |
| 141 | + } | |
| 142 | + | |
| 143 | + /** | |
| 144 | + * Returns this identity's scope. | |
| 145 | + * | |
| 146 | + * @return the scope of this identity. | |
| 147 | + */ | |
| 148 | + public final IdentityScope getScope() { | |
| 149 | + return scope; | |
| 150 | + } | |
| 151 | + | |
| 152 | + /** | |
| 153 | + * Returns this identity's public key. | |
| 154 | + * | |
| 155 | + * @return the public key for this identity. | |
| 156 | + * | |
| 157 | + * @see #setPublicKey | |
| 158 | + */ | |
| 159 | + public PublicKey getPublicKey() { | |
| 160 | + return publicKey; | |
| 161 | + } | |
| 162 | + | |
| 163 | + /** | |
| 164 | + * Sets this identity's public key. The old key and all of this | |
| 165 | + * identity's certificates are removed by this operation. | |
| 166 | + * | |
| 167 | + * <p>First, if there is a security manager, its <code>checkSecurityAccess</code> | |
| 168 | + * method is called with <code>"setIdentityPublicKey"</code> | |
| 169 | + * as its argument to see if it's ok to set the public key. | |
| 170 | + * | |
| 171 | + * @param key the public key for this identity. | |
| 172 | + * | |
| 173 | + * @exception KeyManagementException if another identity in the | |
| 174 | + * identity's scope has the same public key, or if another exception occurs. | |
| 175 | + * | |
| 176 | + * @exception SecurityException if a security manager exists and its | |
| 177 | + * <code>checkSecurityAccess</code> method doesn't allow | |
| 178 | + * setting the public key. | |
| 179 | + * | |
| 180 | + * @see #getPublicKey | |
| 181 | + * @see SecurityManager#checkSecurityAccess | |
| 182 | + */ | |
| 183 | + /* Should we throw an exception if this is already set? */ | |
| 184 | + public void setPublicKey(PublicKey key) throws KeyManagementException { | |
| 185 | + | |
| 186 | + check("setIdentityPublicKey"); | |
| 187 | + this.publicKey = key; | |
| 188 | + certificates = new Vector<Certificate>(); | |
| 189 | + } | |
| 190 | + | |
| 191 | + /** | |
| 192 | + * Specifies a general information string for this identity. | |
| 193 | + * | |
| 194 | + * <p>First, if there is a security manager, its <code>checkSecurityAccess</code> | |
| 195 | + * method is called with <code>"setIdentityInfo"</code> | |
| 196 | + * as its argument to see if it's ok to specify the information string. | |
| 197 | + * | |
| 198 | + * @param info the information string. | |
| 199 | + * | |
| 200 | + * @exception SecurityException if a security manager exists and its | |
| 201 | + * <code>checkSecurityAccess</code> method doesn't allow | |
| 202 | + * setting the information string. | |
| 203 | + * | |
| 204 | + * @see #getInfo | |
| 205 | + * @see SecurityManager#checkSecurityAccess | |
| 206 | + */ | |
| 207 | + public void setInfo(String info) { | |
| 208 | + check("setIdentityInfo"); | |
| 209 | + this.info = info; | |
| 210 | + } | |
| 211 | + | |
| 212 | + /** | |
| 213 | + * Returns general information previously specified for this identity. | |
| 214 | + * | |
| 215 | + * @return general information about this identity. | |
| 216 | + * | |
| 217 | + * @see #setInfo | |
| 218 | + */ | |
| 219 | + public String getInfo() { | |
| 220 | + return info; | |
| 221 | + } | |
| 222 | + | |
| 223 | + /** | |
| 224 | + * Adds a certificate for this identity. If the identity has a public | |
| 225 | + * key, the public key in the certificate must be the same, and if | |
| 226 | + * the identity does not have a public key, the identity's | |
| 227 | + * public key is set to be that specified in the certificate. | |
| 228 | + * | |
| 229 | + * <p>First, if there is a security manager, its <code>checkSecurityAccess</code> | |
| 230 | + * method is called with <code>"addIdentityCertificate"</code> | |
| 231 | + * as its argument to see if it's ok to add a certificate. | |
| 232 | + * | |
| 233 | + * @param certificate the certificate to be added. | |
| 234 | + * | |
| 235 | + * @exception KeyManagementException if the certificate is not valid, | |
| 236 | + * if the public key in the certificate being added conflicts with | |
| 237 | + * this identity's public key, or if another exception occurs. | |
| 238 | + * | |
| 239 | + * @exception SecurityException if a security manager exists and its | |
| 240 | + * <code>checkSecurityAccess</code> method doesn't allow | |
| 241 | + * adding a certificate. | |
| 242 | + * | |
| 243 | + * @see SecurityManager#checkSecurityAccess | |
| 244 | + */ | |
| 245 | + public void addCertificate(Certificate certificate) | |
| 246 | + throws KeyManagementException { | |
| 247 | + | |
| 248 | + check("addIdentityCertificate"); | |
| 249 | + | |
| 250 | + if (certificates == null) { | |
| 251 | + certificates = new Vector<Certificate>(); | |
| 252 | + } | |
| 253 | + if (publicKey != null) { | |
| 254 | + if (!keyEquals(publicKey, certificate.getPublicKey())) { | |
| 255 | + throw new KeyManagementException( | |
| 256 | + "public key different from cert public key"); | |
| 257 | + } | |
| 258 | + } else { | |
| 259 | + publicKey = certificate.getPublicKey(); | |
| 260 | + } | |
| 261 | + certificates.addElement(certificate); | |
| 262 | + } | |
| 263 | + | |
| 264 | + private boolean keyEquals(Key aKey, Key anotherKey) { | |
| 265 | + String aKeyFormat = aKey.getFormat(); | |
| 266 | + String anotherKeyFormat = anotherKey.getFormat(); | |
| 267 | + if ((aKeyFormat == null) ^ (anotherKeyFormat == null)) | |
| 268 | + return false; | |
| 269 | + if (aKeyFormat != null && anotherKeyFormat != null) | |
| 270 | + if (!aKeyFormat.equalsIgnoreCase(anotherKeyFormat)) | |
| 271 | + return false; | |
| 272 | + return java.util.Arrays.equals(aKey.getEncoded(), | |
| 273 | + anotherKey.getEncoded()); | |
| 274 | + } | |
| 275 | + | |
| 276 | + | |
| 277 | + /** | |
| 278 | + * Removes a certificate from this identity. | |
| 279 | + * | |
| 280 | + * <p>First, if there is a security manager, its <code>checkSecurityAccess</code> | |
| 281 | + * method is called with <code>"removeIdentityCertificate"</code> | |
| 282 | + * as its argument to see if it's ok to remove a certificate. | |
| 283 | + * | |
| 284 | + * @param certificate the certificate to be removed. | |
| 285 | + * | |
| 286 | + * @exception KeyManagementException if the certificate is | |
| 287 | + * missing, or if another exception occurs. | |
| 288 | + * | |
| 289 | + * @exception SecurityException if a security manager exists and its | |
| 290 | + * <code>checkSecurityAccess</code> method doesn't allow | |
| 291 | + * removing a certificate. | |
| 292 | + * | |
| 293 | + * @see SecurityManager#checkSecurityAccess | |
| 294 | + */ | |
| 295 | + public void removeCertificate(Certificate certificate) | |
| 296 | + throws KeyManagementException { | |
| 297 | + check("removeIdentityCertificate"); | |
| 298 | + if (certificates != null) { | |
| 299 | + certificates.removeElement(certificate); | |
| 300 | + } | |
| 301 | + } | |
| 302 | + | |
| 303 | + /** | |
| 304 | + * Returns a copy of all the certificates for this identity. | |
| 305 | + * | |
| 306 | + * @return a copy of all the certificates for this identity. | |
| 307 | + */ | |
| 308 | + public Certificate[] certificates() { | |
| 309 | + if (certificates == null) { | |
| 310 | + return new Certificate[0]; | |
| 311 | + } | |
| 312 | + int len = certificates.size(); | |
| 313 | + Certificate[] certs = new Certificate[len]; | |
| 314 | + certificates.copyInto(certs); | |
| 315 | + return certs; | |
| 316 | + } | |
| 317 | + | |
| 318 | + /** | |
| 319 | + * Tests for equality between the specified object and this identity. | |
| 320 | + * This first tests to see if the entities actually refer to the same | |
| 321 | + * object, in which case it returns true. Next, it checks to see if | |
| 322 | + * the entities have the same name and the same scope. If they do, | |
| 323 | + * the method returns true. Otherwise, it calls | |
| 324 | + * {@link #identityEquals(Identity) identityEquals}, which subclasses should | |
| 325 | + * override. | |
| 326 | + * | |
| 327 | + * @param identity the object to test for equality with this identity. | |
| 328 | + * | |
| 329 | + * @return true if the objects are considered equal, false otherwise. | |
| 330 | + * | |
| 331 | + * @see #identityEquals | |
| 332 | + */ | |
| 333 | + public final boolean equals(Object identity) { | |
| 334 | + | |
| 335 | + if (identity == this) { | |
| 336 | + return true; | |
| 337 | + } | |
| 338 | + | |
| 339 | + if (identity instanceof Identity) { | |
| 340 | + Identity i = (Identity)identity; | |
| 341 | + if (this.fullName().equals(i.fullName())) { | |
| 342 | + return true; | |
| 343 | + } else { | |
| 344 | + return identityEquals(i); | |
| 345 | + } | |
| 346 | + } | |
| 347 | + return false; | |
| 348 | + } | |
| 349 | + | |
| 350 | + /** | |
| 351 | + * Tests for equality between the specified identity and this identity. | |
| 352 | + * This method should be overriden by subclasses to test for equality. | |
| 353 | + * The default behavior is to return true if the names and public keys | |
| 354 | + * are equal. | |
| 355 | + * | |
| 356 | + * @param identity the identity to test for equality with this identity. | |
| 357 | + * | |
| 358 | + * @return true if the identities are considered equal, false | |
| 359 | + * otherwise. | |
| 360 | + * | |
| 361 | + * @see #equals | |
| 362 | + */ | |
| 363 | + protected boolean identityEquals(Identity identity) { | |
| 364 | + if (!name.equalsIgnoreCase(identity.name)) | |
| 365 | + return false; | |
| 366 | + | |
| 367 | + if ((publicKey == null) ^ (identity.publicKey == null)) | |
| 368 | + return false; | |
| 369 | + | |
| 370 | + if (publicKey != null && identity.publicKey != null) | |
| 371 | + if (!publicKey.equals(identity.publicKey)) | |
| 372 | + return false; | |
| 373 | + | |
| 374 | + return true; | |
| 375 | + | |
| 376 | + } | |
| 377 | + | |
| 378 | + /** | |
| 379 | + * Returns a parsable name for identity: identityName.scopeName | |
| 380 | + */ | |
| 381 | + String fullName() { | |
| 382 | + String parsable = name; | |
| 383 | + if (scope != null) { | |
| 384 | + parsable += "." + scope.getName(); | |
| 385 | + } | |
| 386 | + return parsable; | |
| 387 | + } | |
| 388 | + | |
| 389 | + /** | |
| 390 | + * Returns a short string describing this identity, telling its | |
| 391 | + * name and its scope (if any). | |
| 392 | + * | |
| 393 | + * <p>First, if there is a security manager, its <code>checkSecurityAccess</code> | |
| 394 | + * method is called with <code>"printIdentity"</code> | |
| 395 | + * as its argument to see if it's ok to return the string. | |
| 396 | + * | |
| 397 | + * @return information about this identity, such as its name and the | |
| 398 | + * name of its scope (if any). | |
| 399 | + * | |
| 400 | + * @exception SecurityException if a security manager exists and its | |
| 401 | + * <code>checkSecurityAccess</code> method doesn't allow | |
| 402 | + * returning a string describing this identity. | |
| 403 | + * | |
| 404 | + * @see SecurityManager#checkSecurityAccess | |
| 405 | + */ | |
| 406 | + public String toString() { | |
| 407 | + check("printIdentity"); | |
| 408 | + String printable = name; | |
| 409 | + if (scope != null) { | |
| 410 | + printable += "[" + scope.getName() + "]"; | |
| 411 | + } | |
| 412 | + return printable; | |
| 413 | + } | |
| 414 | + | |
| 415 | + /** | |
| 416 | + * Returns a string representation of this identity, with | |
| 417 | + * optionally more details than that provided by the | |
| 418 | + * <code>toString</code> method without any arguments. | |
| 419 | + * | |
| 420 | + * <p>First, if there is a security manager, its <code>checkSecurityAccess</code> | |
| 421 | + * method is called with <code>"printIdentity"</code> | |
| 422 | + * as its argument to see if it's ok to return the string. | |
| 423 | + * | |
| 424 | + * @param detailed whether or not to provide detailed information. | |
| 425 | + * | |
| 426 | + * @return information about this identity. If <code>detailed</code> | |
| 427 | + * is true, then this method returns more information than that | |
| 428 | + * provided by the <code>toString</code> method without any arguments. | |
| 429 | + * | |
| 430 | + * @exception SecurityException if a security manager exists and its | |
| 431 | + * <code>checkSecurityAccess</code> method doesn't allow | |
| 432 | + * returning a string describing this identity. | |
| 433 | + * | |
| 434 | + * @see #toString | |
| 435 | + * @see SecurityManager#checkSecurityAccess | |
| 436 | + */ | |
| 437 | + public String toString(boolean detailed) { | |
| 438 | + String out = toString(); | |
| 439 | + if (detailed) { | |
| 440 | + out += "\n"; | |
| 441 | + out += printKeys(); | |
| 442 | + out += "\n" + printCertificates(); | |
| 443 | + if (info != null) { | |
| 444 | + out += "\n\t" + info; | |
| 445 | + } else { | |
| 446 | + out += "\n\tno additional information available."; | |
| 447 | + } | |
| 448 | + } | |
| 449 | + return out; | |
| 450 | + } | |
| 451 | + | |
| 452 | + String printKeys() { | |
| 453 | + String key = ""; | |
| 454 | + if (publicKey != null) { | |
| 455 | + key = "\tpublic key initialized"; | |
| 456 | + } else { | |
| 457 | + key = "\tno public key"; | |
| 458 | + } | |
| 459 | + return key; | |
| 460 | + } | |
| 461 | + | |
| 462 | + String printCertificates() { | |
| 463 | + String out = ""; | |
| 464 | + if (certificates == null) { | |
| 465 | + return "\tno certificates"; | |
| 466 | + } else { | |
| 467 | + out += "\tcertificates: \n"; | |
| 468 | + | |
| 469 | + int i = 1; | |
| 470 | + for (Certificate cert : certificates) { | |
| 471 | + out += "\tcertificate " + i++ + | |
| 472 | + "\tfor : " + cert.getPrincipal() + "\n"; | |
| 473 | + out += "\t\t\tfrom : " + | |
| 474 | + cert.getGuarantor() + "\n"; | |
| 475 | + } | |
| 476 | + } | |
| 477 | + return out; | |
| 478 | + } | |
| 479 | + | |
| 480 | + /** | |
| 481 | + * Returns a hashcode for this identity. | |
| 482 | + * | |
| 483 | + * @return a hashcode for this identity. | |
| 484 | + */ | |
| 485 | + public int hashCode() { | |
| 486 | + return name.hashCode(); | |
| 487 | + } | |
| 488 | + | |
| 489 | + private static void check(String directive) { | |
| 490 | + SecurityManager security = System.getSecurityManager(); | |
| 491 | + if (security != null) { | |
| 492 | + security.checkSecurityAccess(directive); | |
| 493 | + } | |
| 494 | + } | |
| 495 | +} | |
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,257 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.Serializable; | |
| 29 | +import java.util.Enumeration; | |
| 30 | +import java.util.Properties; | |
| 31 | + | |
| 32 | +/** | |
| 33 | + * <p>This class represents a scope for identities. It is an Identity | |
| 34 | + * itself, and therefore has a name and can have a scope. It can also | |
| 35 | + * optionally have a public key and associated certificates. | |
| 36 | + * | |
| 37 | + * <p>An IdentityScope can contain Identity objects of all kinds, including | |
| 38 | + * Signers. All types of Identity objects can be retrieved, added, and | |
| 39 | + * removed using the same methods. Note that it is possible, and in fact | |
| 40 | + * expected, that different types of identity scopes will | |
| 41 | + * apply different policies for their various operations on the | |
| 42 | + * various types of Identities. | |
| 43 | + * | |
| 44 | + * <p>There is a one-to-one mapping between keys and identities, and | |
| 45 | + * there can only be one copy of one key per scope. For example, suppose | |
| 46 | + * <b>Acme Software, Inc</b> is a software publisher known to a user. | |
| 47 | + * Suppose it is an Identity, that is, it has a public key, and a set of | |
| 48 | + * associated certificates. It is named in the scope using the name | |
| 49 | + * "Acme Software". No other named Identity in the scope has the same | |
| 50 | + * public key. Of course, none has the same name as well. | |
| 51 | + * | |
| 52 | + * @see Identity | |
| 53 | + * @see Signer | |
| 54 | + * @see Principal | |
| 55 | + * @see Key | |
| 56 | + * | |
| 57 | + * @author Benjamin Renaud | |
| 58 | + * | |
| 59 | + * @deprecated This class is no longer used. Its functionality has been | |
| 60 | + * replaced by <code>java.security.KeyStore</code>, the | |
| 61 | + * <code>java.security.cert</code> package, and | |
| 62 | + * <code>java.security.Principal</code>. | |
| 63 | + */ | |
| 64 | +@Deprecated | |
| 65 | +public abstract | |
| 66 | +class IdentityScope extends Identity { | |
| 67 | + | |
| 68 | + private static final long serialVersionUID = -2337346281189773310L; | |
| 69 | + | |
| 70 | + /* The system's scope */ | |
| 71 | + private static IdentityScope scope; | |
| 72 | + | |
| 73 | + // initialize the system scope | |
| 74 | + private static void initializeSystemScope() { | |
| 75 | + | |
| 76 | + String classname = AccessController.doPrivileged( | |
| 77 | + new PrivilegedAction<String>() { | |
| 78 | + public String run() { | |
| 79 | + return Security.getProperty("system.scope"); | |
| 80 | + } | |
| 81 | + }); | |
| 82 | + | |
| 83 | + if (classname == null) { | |
| 84 | + return; | |
| 85 | + | |
| 86 | + } else { | |
| 87 | + | |
| 88 | + try { | |
| 89 | + Class.forName(classname); | |
| 90 | + } catch (ClassNotFoundException e) { | |
| 91 | + //Security.error("unable to establish a system scope from " + | |
| 92 | + // classname); | |
| 93 | + e.printStackTrace(); | |
| 94 | + } | |
| 95 | + } | |
| 96 | + } | |
| 97 | + | |
| 98 | + /** | |
| 99 | + * This constructor is used for serialization only and should not | |
| 100 | + * be used by subclasses. | |
| 101 | + */ | |
| 102 | + protected IdentityScope() { | |
| 103 | + this("restoring..."); | |
| 104 | + } | |
| 105 | + | |
| 106 | + /** | |
| 107 | + * Constructs a new identity scope with the specified name. | |
| 108 | + * | |
| 109 | + * @param name the scope name. | |
| 110 | + */ | |
| 111 | + public IdentityScope(String name) { | |
| 112 | + super(name); | |
| 113 | + } | |
| 114 | + | |
| 115 | + /** | |
| 116 | + * Constructs a new identity scope with the specified name and scope. | |
| 117 | + * | |
| 118 | + * @param name the scope name. | |
| 119 | + * @param scope the scope for the new identity scope. | |
| 120 | + * | |
| 121 | + * @exception KeyManagementException if there is already an identity | |
| 122 | + * with the same name in the scope. | |
| 123 | + */ | |
| 124 | + public IdentityScope(String name, IdentityScope scope) | |
| 125 | + throws KeyManagementException { | |
| 126 | + super(name, scope); | |
| 127 | + } | |
| 128 | + | |
| 129 | + /** | |
| 130 | + * Returns the system's identity scope. | |
| 131 | + * | |
| 132 | + * @return the system's identity scope, or {@code null} if none has been | |
| 133 | + * set. | |
| 134 | + * | |
| 135 | + * @see #setSystemScope | |
| 136 | + */ | |
| 137 | + public static IdentityScope getSystemScope() { | |
| 138 | + if (scope == null) { | |
| 139 | + initializeSystemScope(); | |
| 140 | + } | |
| 141 | + return scope; | |
| 142 | + } | |
| 143 | + | |
| 144 | + | |
| 145 | + /** | |
| 146 | + * Sets the system's identity scope. | |
| 147 | + * | |
| 148 | + * <p>First, if there is a security manager, its | |
| 149 | + * <code>checkSecurityAccess</code> | |
| 150 | + * method is called with <code>"setSystemScope"</code> | |
| 151 | + * as its argument to see if it's ok to set the identity scope. | |
| 152 | + * | |
| 153 | + * @param scope the scope to set. | |
| 154 | + * | |
| 155 | + * @exception SecurityException if a security manager exists and its | |
| 156 | + * <code>checkSecurityAccess</code> method doesn't allow | |
| 157 | + * setting the identity scope. | |
| 158 | + * | |
| 159 | + * @see #getSystemScope | |
| 160 | + * @see SecurityManager#checkSecurityAccess | |
| 161 | + */ | |
| 162 | + protected static void setSystemScope(IdentityScope scope) { | |
| 163 | + check("setSystemScope"); | |
| 164 | + IdentityScope.scope = scope; | |
| 165 | + } | |
| 166 | + | |
| 167 | + /** | |
| 168 | + * Returns the number of identities within this identity scope. | |
| 169 | + * | |
| 170 | + * @return the number of identities within this identity scope. | |
| 171 | + */ | |
| 172 | + public abstract int size(); | |
| 173 | + | |
| 174 | + /** | |
| 175 | + * Returns the identity in this scope with the specified name (if any). | |
| 176 | + * | |
| 177 | + * @param name the name of the identity to be retrieved. | |
| 178 | + * | |
| 179 | + * @return the identity named <code>name</code>, or null if there are | |
| 180 | + * no identities named <code>name</code> in this scope. | |
| 181 | + */ | |
| 182 | + public abstract Identity getIdentity(String name); | |
| 183 | + | |
| 184 | + /** | |
| 185 | + * Retrieves the identity whose name is the same as that of the | |
| 186 | + * specified principal. (Note: Identity implements Principal.) | |
| 187 | + * | |
| 188 | + * @param principal the principal corresponding to the identity | |
| 189 | + * to be retrieved. | |
| 190 | + * | |
| 191 | + * @return the identity whose name is the same as that of the | |
| 192 | + * principal, or null if there are no identities of the same name | |
| 193 | + * in this scope. | |
| 194 | + */ | |
| 195 | + public Identity getIdentity(Principal principal) { | |
| 196 | + return getIdentity(principal.getName()); | |
| 197 | + } | |
| 198 | + | |
| 199 | + /** | |
| 200 | + * Retrieves the identity with the specified public key. | |
| 201 | + * | |
| 202 | + * @param key the public key for the identity to be returned. | |
| 203 | + * | |
| 204 | + * @return the identity with the given key, or null if there are | |
| 205 | + * no identities in this scope with that key. | |
| 206 | + */ | |
| 207 | + public abstract Identity getIdentity(PublicKey key); | |
| 208 | + | |
| 209 | + /** | |
| 210 | + * Adds an identity to this identity scope. | |
| 211 | + * | |
| 212 | + * @param identity the identity to be added. | |
| 213 | + * | |
| 214 | + * @exception KeyManagementException if the identity is not | |
| 215 | + * valid, a name conflict occurs, another identity has the same | |
| 216 | + * public key as the identity being added, or another exception | |
| 217 | + * occurs. */ | |
| 218 | + public abstract void addIdentity(Identity identity) | |
| 219 | + throws KeyManagementException; | |
| 220 | + | |
| 221 | + /** | |
| 222 | + * Removes an identity from this identity scope. | |
| 223 | + * | |
| 224 | + * @param identity the identity to be removed. | |
| 225 | + * | |
| 226 | + * @exception KeyManagementException if the identity is missing, | |
| 227 | + * or another exception occurs. | |
| 228 | + */ | |
| 229 | + public abstract void removeIdentity(Identity identity) | |
| 230 | + throws KeyManagementException; | |
| 231 | + | |
| 232 | + /** | |
| 233 | + * Returns an enumeration of all identities in this identity scope. | |
| 234 | + * | |
| 235 | + * @return an enumeration of all identities in this identity scope. | |
| 236 | + */ | |
| 237 | + public abstract Enumeration<Identity> identities(); | |
| 238 | + | |
| 239 | + /** | |
| 240 | + * Returns a string representation of this identity scope, including | |
| 241 | + * its name, its scope name, and the number of identities in this | |
| 242 | + * identity scope. | |
| 243 | + * | |
| 244 | + * @return a string representation of this identity scope. | |
| 245 | + */ | |
| 246 | + public String toString() { | |
| 247 | + return super.toString() + "[" + size() + "]"; | |
| 248 | + } | |
| 249 | + | |
| 250 | + private static void check(String directive) { | |
| 251 | + SecurityManager security = System.getSecurityManager(); | |
| 252 | + if (security != null) { | |
| 253 | + security.checkSecurityAccess(directive); | |
| 254 | + } | |
| 255 | + } | |
| 256 | + | |
| 257 | +} | |
Binary file not shown.
| @@ -0,0 +1,97 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This is the exception for invalid or inappropriate algorithm parameters. | |
| 30 | + * | |
| 31 | + * @author Jan Luehe | |
| 32 | + * | |
| 33 | + * | |
| 34 | + * @see AlgorithmParameters | |
| 35 | + * @see java.security.spec.AlgorithmParameterSpec | |
| 36 | + * | |
| 37 | + * @since 1.2 | |
| 38 | + */ | |
| 39 | + | |
| 40 | +public class InvalidAlgorithmParameterException | |
| 41 | +extends GeneralSecurityException { | |
| 42 | + | |
| 43 | + private static final long serialVersionUID = 2864672297499471472L; | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * Constructs an InvalidAlgorithmParameterException with no detail | |
| 47 | + * message. | |
| 48 | + * A detail message is a String that describes this particular | |
| 49 | + * exception. | |
| 50 | + */ | |
| 51 | + public InvalidAlgorithmParameterException() { | |
| 52 | + super(); | |
| 53 | + } | |
| 54 | + | |
| 55 | + /** | |
| 56 | + * Constructs an InvalidAlgorithmParameterException with the specified | |
| 57 | + * detail message. | |
| 58 | + * A detail message is a String that describes this | |
| 59 | + * particular exception. | |
| 60 | + * | |
| 61 | + * @param msg the detail message. | |
| 62 | + */ | |
| 63 | + public InvalidAlgorithmParameterException(String msg) { | |
| 64 | + super(msg); | |
| 65 | + } | |
| 66 | + | |
| 67 | + /** | |
| 68 | + * Creates a <code>InvalidAlgorithmParameterException</code> with the | |
| 69 | + * specified detail message and cause. | |
| 70 | + * | |
| 71 | + * @param message the detail message (which is saved for later retrieval | |
| 72 | + * by the {@link #getMessage()} method). | |
| 73 | + * @param cause the cause (which is saved for later retrieval by the | |
| 74 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 75 | + * and indicates that the cause is nonexistent or unknown.) | |
| 76 | + * @since 1.5 | |
| 77 | + */ | |
| 78 | + public InvalidAlgorithmParameterException(String message, Throwable cause) { | |
| 79 | + super(message, cause); | |
| 80 | + } | |
| 81 | + | |
| 82 | + /** | |
| 83 | + * Creates a <code>InvalidAlgorithmParameterException</code> with the | |
| 84 | + * specified cause and a detail message of | |
| 85 | + * <tt>(cause==null ? null : cause.toString())</tt> | |
| 86 | + * (which typically contains the class and detail message of | |
| 87 | + * <tt>cause</tt>). | |
| 88 | + * | |
| 89 | + * @param cause the cause (which is saved for later retrieval by the | |
| 90 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 91 | + * and indicates that the cause is nonexistent or unknown.) | |
| 92 | + * @since 1.5 | |
| 93 | + */ | |
| 94 | + public InvalidAlgorithmParameterException(Throwable cause) { | |
| 95 | + super(cause); | |
| 96 | + } | |
| 97 | +} | |
Binary file not shown.
| @@ -0,0 +1,89 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | + | |
| 27 | +package java.security; | |
| 28 | + | |
| 29 | +/** | |
| 30 | + * This is the exception for invalid Keys (invalid encoding, wrong | |
| 31 | + * length, uninitialized, etc). | |
| 32 | + * | |
| 33 | + * @author Benjamin Renaud | |
| 34 | + */ | |
| 35 | + | |
| 36 | +public class InvalidKeyException extends KeyException { | |
| 37 | + | |
| 38 | + private static final long serialVersionUID = 5698479920593359816L; | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * Constructs an InvalidKeyException with no detail message. A | |
| 42 | + * detail message is a String that describes this particular | |
| 43 | + * exception. | |
| 44 | + */ | |
| 45 | + public InvalidKeyException() { | |
| 46 | + super(); | |
| 47 | + } | |
| 48 | + | |
| 49 | + /** | |
| 50 | + * Constructs an InvalidKeyException with the specified detail | |
| 51 | + * message. A detail message is a String that describes this | |
| 52 | + * particular exception. | |
| 53 | + * | |
| 54 | + * @param msg the detail message. | |
| 55 | + */ | |
| 56 | + public InvalidKeyException(String msg) { | |
| 57 | + super(msg); | |
| 58 | + } | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * Creates a <code>InvalidKeyException</code> with the specified | |
| 62 | + * detail message and cause. | |
| 63 | + * | |
| 64 | + * @param message the detail message (which is saved for later retrieval | |
| 65 | + * by the {@link #getMessage()} method). | |
| 66 | + * @param cause the cause (which is saved for later retrieval by the | |
| 67 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 68 | + * and indicates that the cause is nonexistent or unknown.) | |
| 69 | + * @since 1.5 | |
| 70 | + */ | |
| 71 | + public InvalidKeyException(String message, Throwable cause) { | |
| 72 | + super(message, cause); | |
| 73 | + } | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * Creates a <code>InvalidKeyException</code> with the specified cause | |
| 77 | + * and a detail message of <tt>(cause==null ? null : cause.toString())</tt> | |
| 78 | + * (which typically contains the class and detail message of | |
| 79 | + * <tt>cause</tt>). | |
| 80 | + * | |
| 81 | + * @param cause the cause (which is saved for later retrieval by the | |
| 82 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 83 | + * and indicates that the cause is nonexistent or unknown.) | |
| 84 | + * @since 1.5 | |
| 85 | + */ | |
| 86 | + public InvalidKeyException(Throwable cause) { | |
| 87 | + super(cause); | |
| 88 | + } | |
| 89 | +} | |
Binary file not shown.
| @@ -0,0 +1,59 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This exception, designed for use by the JCA/JCE engine classes, | |
| 30 | + * is thrown when an invalid parameter is passed | |
| 31 | + * to a method. | |
| 32 | + * | |
| 33 | + * @author Benjamin Renaud | |
| 34 | + */ | |
| 35 | + | |
| 36 | +public class InvalidParameterException extends IllegalArgumentException { | |
| 37 | + | |
| 38 | + private static final long serialVersionUID = -857968536935667808L; | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * Constructs an InvalidParameterException with no detail message. | |
| 42 | + * A detail message is a String that describes this particular | |
| 43 | + * exception. | |
| 44 | + */ | |
| 45 | + public InvalidParameterException() { | |
| 46 | + super(); | |
| 47 | + } | |
| 48 | + | |
| 49 | + /** | |
| 50 | + * Constructs an InvalidParameterException with the specified | |
| 51 | + * detail message. A detail message is a String that describes | |
| 52 | + * this particular exception. | |
| 53 | + * | |
| 54 | + * @param msg the detail message. | |
| 55 | + */ | |
| 56 | + public InvalidParameterException(String msg) { | |
| 57 | + super(msg); | |
| 58 | + } | |
| 59 | +} | |
Binary file not shown.
| @@ -0,0 +1,153 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * The Key interface is the top-level interface for all keys. It | |
| 30 | + * defines the functionality shared by all key objects. All keys | |
| 31 | + * have three characteristics: | |
| 32 | + * | |
| 33 | + * <UL> | |
| 34 | + * | |
| 35 | + * <LI>An Algorithm | |
| 36 | + * | |
| 37 | + * <P>This is the key algorithm for that key. The key algorithm is usually | |
| 38 | + * an encryption or asymmetric operation algorithm (such as DSA or | |
| 39 | + * RSA), which will work with those algorithms and with related | |
| 40 | + * algorithms (such as MD5 with RSA, SHA-1 with RSA, Raw DSA, etc.) | |
| 41 | + * The name of the algorithm of a key is obtained using the | |
| 42 | + * {@link #getAlgorithm() getAlgorithm} method.<P> | |
| 43 | + * | |
| 44 | + * <LI>An Encoded Form | |
| 45 | + * | |
| 46 | + * <P>This is an external encoded form for the key used when a standard | |
| 47 | + * representation of the key is needed outside the Java Virtual Machine, | |
| 48 | + * as when transmitting the key to some other party. The key | |
| 49 | + * is encoded according to a standard format (such as | |
| 50 | + * X.509 <code>SubjectPublicKeyInfo</code> or PKCS#8), and | |
| 51 | + * is returned using the {@link #getEncoded() getEncoded} method. | |
| 52 | + * Note: The syntax of the ASN.1 type <code>SubjectPublicKeyInfo</code> | |
| 53 | + * is defined as follows: | |
| 54 | + * | |
| 55 | + * <pre> | |
| 56 | + * SubjectPublicKeyInfo ::= SEQUENCE { | |
| 57 | + * algorithm AlgorithmIdentifier, | |
| 58 | + * subjectPublicKey BIT STRING } | |
| 59 | + * | |
| 60 | + * AlgorithmIdentifier ::= SEQUENCE { | |
| 61 | + * algorithm OBJECT IDENTIFIER, | |
| 62 | + * parameters ANY DEFINED BY algorithm OPTIONAL } | |
| 63 | + * </pre> | |
| 64 | + * | |
| 65 | + * For more information, see | |
| 66 | + * <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: | |
| 67 | + * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a>. | |
| 68 | + * <P> | |
| 69 | + * | |
| 70 | + * <LI>A Format | |
| 71 | + * | |
| 72 | + * <P>This is the name of the format of the encoded key. It is returned | |
| 73 | + * by the {@link #getFormat() getFormat} method.<P> | |
| 74 | + * | |
| 75 | + * </UL> | |
| 76 | + * | |
| 77 | + * Keys are generally obtained through key generators, certificates, | |
| 78 | + * or various Identity classes used to manage keys. | |
| 79 | + * Keys may also be obtained from key specifications (transparent | |
| 80 | + * representations of the underlying key material) through the use of a key | |
| 81 | + * factory (see {@link KeyFactory}). | |
| 82 | + * | |
| 83 | + * <p> A Key should use KeyRep as its serialized representation. | |
| 84 | + * Note that a serialized Key may contain sensitive information | |
| 85 | + * which should not be exposed in untrusted environments. See the | |
| 86 | + * <a href="../../../platform/serialization/spec/security.html"> | |
| 87 | + * Security Appendix</a> | |
| 88 | + * of the Serialization Specification for more information. | |
| 89 | + * | |
| 90 | + * @see PublicKey | |
| 91 | + * @see PrivateKey | |
| 92 | + * @see KeyPair | |
| 93 | + * @see KeyPairGenerator | |
| 94 | + * @see KeyFactory | |
| 95 | + * @see KeyRep | |
| 96 | + * @see java.security.spec.KeySpec | |
| 97 | + * @see Identity | |
| 98 | + * @see Signer | |
| 99 | + * | |
| 100 | + * @author Benjamin Renaud | |
| 101 | + */ | |
| 102 | + | |
| 103 | +public interface Key extends java.io.Serializable { | |
| 104 | + | |
| 105 | + // Declare serialVersionUID to be compatible with JDK1.1 | |
| 106 | + | |
| 107 | + /** | |
| 108 | + * The class fingerprint that is set to indicate | |
| 109 | + * serialization compatibility with a previous | |
| 110 | + * version of the class. | |
| 111 | + */ | |
| 112 | + static final long serialVersionUID = 6603384152749567654L; | |
| 113 | + | |
| 114 | + /** | |
| 115 | + * Returns the standard algorithm name for this key. For | |
| 116 | + * example, "DSA" would indicate that this key is a DSA key. | |
| 117 | + * See Appendix A in the <a href= | |
| 118 | + * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA"> | |
| 119 | + * Java Cryptography Architecture API Specification & Reference </a> | |
| 120 | + * for information about standard algorithm names. | |
| 121 | + * | |
| 122 | + * @return the name of the algorithm associated with this key. | |
| 123 | + */ | |
| 124 | + public String getAlgorithm(); | |
| 125 | + | |
| 126 | + /** | |
| 127 | + * Returns the name of the primary encoding format of this key, | |
| 128 | + * or null if this key does not support encoding. | |
| 129 | + * The primary encoding format is | |
| 130 | + * named in terms of the appropriate ASN.1 data format, if an | |
| 131 | + * ASN.1 specification for this key exists. | |
| 132 | + * For example, the name of the ASN.1 data format for public | |
| 133 | + * keys is <I>SubjectPublicKeyInfo</I>, as | |
| 134 | + * defined by the X.509 standard; in this case, the returned format is | |
| 135 | + * <code>"X.509"</code>. Similarly, | |
| 136 | + * the name of the ASN.1 data format for private keys is | |
| 137 | + * <I>PrivateKeyInfo</I>, | |
| 138 | + * as defined by the PKCS #8 standard; in this case, the returned format is | |
| 139 | + * <code>"PKCS#8"</code>. | |
| 140 | + * | |
| 141 | + * @return the primary encoding format of the key. | |
| 142 | + */ | |
| 143 | + public String getFormat(); | |
| 144 | + | |
| 145 | + /** | |
| 146 | + * Returns the key in its primary encoding format, or null | |
| 147 | + * if this key does not support encoding. | |
| 148 | + * | |
| 149 | + * @return the encoded key, or null if the key does not support | |
| 150 | + * encoding. | |
| 151 | + */ | |
| 152 | + public byte[] getEncoded(); | |
| 153 | +} | |
Binary file not shown.
| @@ -0,0 +1,90 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This is the basic key exception. | |
| 30 | + * | |
| 31 | + * @see Key | |
| 32 | + * @see InvalidKeyException | |
| 33 | + * @see KeyManagementException | |
| 34 | + * | |
| 35 | + * @author Benjamin Renaud | |
| 36 | + */ | |
| 37 | + | |
| 38 | +public class KeyException extends GeneralSecurityException { | |
| 39 | + | |
| 40 | + private static final long serialVersionUID = -7483676942812432108L; | |
| 41 | + | |
| 42 | + /** | |
| 43 | + * Constructs a KeyException with no detail message. A detail | |
| 44 | + * message is a String that describes this particular exception. | |
| 45 | + */ | |
| 46 | + public KeyException() { | |
| 47 | + super(); | |
| 48 | + } | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * Constructs a KeyException with the specified detail message. | |
| 52 | + * A detail message is a String that describes this particular | |
| 53 | + * exception. | |
| 54 | + * | |
| 55 | + * @param msg the detail message. | |
| 56 | + */ | |
| 57 | + public KeyException(String msg) { | |
| 58 | + super(msg); | |
| 59 | + } | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * Creates a <code>KeyException</code> with the specified | |
| 63 | + * detail message and cause. | |
| 64 | + * | |
| 65 | + * @param message the detail message (which is saved for later retrieval | |
| 66 | + * by the {@link #getMessage()} method). | |
| 67 | + * @param cause the cause (which is saved for later retrieval by the | |
| 68 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 69 | + * and indicates that the cause is nonexistent or unknown.) | |
| 70 | + * @since 1.5 | |
| 71 | + */ | |
| 72 | + public KeyException(String message, Throwable cause) { | |
| 73 | + super(message, cause); | |
| 74 | + } | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * Creates a <code>KeyException</code> with the specified cause | |
| 78 | + * and a detail message of <tt>(cause==null ? null : cause.toString())</tt> | |
| 79 | + * (which typically contains the class and detail message of | |
| 80 | + * <tt>cause</tt>). | |
| 81 | + * | |
| 82 | + * @param cause the cause (which is saved for later retrieval by the | |
| 83 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 84 | + * and indicates that the cause is nonexistent or unknown.) | |
| 85 | + * @since 1.5 | |
| 86 | + */ | |
| 87 | + public KeyException(Throwable cause) { | |
| 88 | + super(cause); | |
| 89 | + } | |
| 90 | +} | |
Binary file not shown.
| @@ -0,0 +1,474 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.util.*; | |
| 29 | + | |
| 30 | +import java.security.Provider.Service; | |
| 31 | +import java.security.spec.KeySpec; | |
| 32 | +import java.security.spec.InvalidKeySpecException; | |
| 33 | + | |
| 34 | +import sun.security.util.Debug; | |
| 35 | +import sun.security.jca.*; | |
| 36 | +import sun.security.jca.GetInstance.Instance; | |
| 37 | + | |
| 38 | +/** | |
| 39 | + * Key factories are used to convert <I>keys</I> (opaque | |
| 40 | + * cryptographic keys of type <code>Key</code>) into <I>key specifications</I> | |
| 41 | + * (transparent representations of the underlying key material), and vice | |
| 42 | + * versa. | |
| 43 | + * | |
| 44 | + * <P> Key factories are bi-directional. That is, they allow you to build an | |
| 45 | + * opaque key object from a given key specification (key material), or to | |
| 46 | + * retrieve the underlying key material of a key object in a suitable format. | |
| 47 | + * | |
| 48 | + * <P> Multiple compatible key specifications may exist for the same key. | |
| 49 | + * For example, a DSA public key may be specified using | |
| 50 | + * <code>DSAPublicKeySpec</code> or | |
| 51 | + * <code>X509EncodedKeySpec</code>. A key factory can be used to translate | |
| 52 | + * between compatible key specifications. | |
| 53 | + * | |
| 54 | + * <P> The following is an example of how to use a key factory in order to | |
| 55 | + * instantiate a DSA public key from its encoding. | |
| 56 | + * Assume Alice has received a digital signature from Bob. | |
| 57 | + * Bob also sent her his public key (in encoded format) to verify | |
| 58 | + * his signature. Alice then performs the following actions: | |
| 59 | + * | |
| 60 | + * <pre> | |
| 61 | + * X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey); | |
| 62 | + * KeyFactory keyFactory = KeyFactory.getInstance("DSA"); | |
| 63 | + * PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec); | |
| 64 | + * Signature sig = Signature.getInstance("DSA"); | |
| 65 | + * sig.initVerify(bobPubKey); | |
| 66 | + * sig.update(data); | |
| 67 | + * sig.verify(signature); | |
| 68 | + * </pre> | |
| 69 | + * | |
| 70 | + * <p> Every implementation of the Java platform is required to support the | |
| 71 | + * following standard <code>KeyFactory</code> algorithms: | |
| 72 | + * <ul> | |
| 73 | + * <li><tt>DiffieHellman</tt></li> | |
| 74 | + * <li><tt>DSA</tt></li> | |
| 75 | + * <li><tt>RSA</tt></li> | |
| 76 | + * </ul> | |
| 77 | + * These algorithms are described in the <a href= | |
| 78 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> | |
| 79 | + * KeyFactory section</a> of the | |
| 80 | + * Java Cryptography Architecture Standard Algorithm Name Documentation. | |
| 81 | + * Consult the release documentation for your implementation to see if any | |
| 82 | + * other algorithms are supported. | |
| 83 | + * | |
| 84 | + * @author Jan Luehe | |
| 85 | + * | |
| 86 | + * @see Key | |
| 87 | + * @see PublicKey | |
| 88 | + * @see PrivateKey | |
| 89 | + * @see java.security.spec.KeySpec | |
| 90 | + * @see java.security.spec.DSAPublicKeySpec | |
| 91 | + * @see java.security.spec.X509EncodedKeySpec | |
| 92 | + * | |
| 93 | + * @since 1.2 | |
| 94 | + */ | |
| 95 | + | |
| 96 | +public class KeyFactory { | |
| 97 | + | |
| 98 | + private static final Debug debug = | |
| 99 | + Debug.getInstance("jca", "KeyFactory"); | |
| 100 | + | |
| 101 | + // The algorithm associated with this key factory | |
| 102 | + private final String algorithm; | |
| 103 | + | |
| 104 | + // The provider | |
| 105 | + private Provider provider; | |
| 106 | + | |
| 107 | + // The provider implementation (delegate) | |
| 108 | + private volatile KeyFactorySpi spi; | |
| 109 | + | |
| 110 | + // lock for mutex during provider selection | |
| 111 | + private final Object lock = new Object(); | |
| 112 | + | |
| 113 | + // remaining services to try in provider selection | |
| 114 | + // null once provider is selected | |
| 115 | + private Iterator<Service> serviceIterator; | |
| 116 | + | |
| 117 | + /** | |
| 118 | + * Creates a KeyFactory object. | |
| 119 | + * | |
| 120 | + * @param keyFacSpi the delegate | |
| 121 | + * @param provider the provider | |
| 122 | + * @param algorithm the name of the algorithm | |
| 123 | + * to associate with this <tt>KeyFactory</tt> | |
| 124 | + */ | |
| 125 | + protected KeyFactory(KeyFactorySpi keyFacSpi, Provider provider, | |
| 126 | + String algorithm) { | |
| 127 | + this.spi = keyFacSpi; | |
| 128 | + this.provider = provider; | |
| 129 | + this.algorithm = algorithm; | |
| 130 | + } | |
| 131 | + | |
| 132 | + private KeyFactory(String algorithm) throws NoSuchAlgorithmException { | |
| 133 | + this.algorithm = algorithm; | |
| 134 | + List<Service> list = GetInstance.getServices("KeyFactory", algorithm); | |
| 135 | + serviceIterator = list.iterator(); | |
| 136 | + // fetch and instantiate initial spi | |
| 137 | + if (nextSpi(null) == null) { | |
| 138 | + throw new NoSuchAlgorithmException | |
| 139 | + (algorithm + " KeyFactory not available"); | |
| 140 | + } | |
| 141 | + } | |
| 142 | + | |
| 143 | + /** | |
| 144 | + * Returns a KeyFactory object that converts | |
| 145 | + * public/private keys of the specified algorithm. | |
| 146 | + * | |
| 147 | + * <p> This method traverses the list of registered security Providers, | |
| 148 | + * starting with the most preferred Provider. | |
| 149 | + * A new KeyFactory object encapsulating the | |
| 150 | + * KeyFactorySpi implementation from the first | |
| 151 | + * Provider that supports the specified algorithm is returned. | |
| 152 | + * | |
| 153 | + * <p> Note that the list of registered providers may be retrieved via | |
| 154 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 155 | + * | |
| 156 | + * @param algorithm the name of the requested key algorithm. | |
| 157 | + * See the KeyFactory section in the <a href= | |
| 158 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> | |
| 159 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 160 | + * for information about standard algorithm names. | |
| 161 | + * | |
| 162 | + * @return the new KeyFactory object. | |
| 163 | + * | |
| 164 | + * @exception NoSuchAlgorithmException if no Provider supports a | |
| 165 | + * KeyFactorySpi implementation for the | |
| 166 | + * specified algorithm. | |
| 167 | + * | |
| 168 | + * @see Provider | |
| 169 | + */ | |
| 170 | + public static KeyFactory getInstance(String algorithm) | |
| 171 | + throws NoSuchAlgorithmException { | |
| 172 | + return new KeyFactory(algorithm); | |
| 173 | + } | |
| 174 | + | |
| 175 | + /** | |
| 176 | + * Returns a KeyFactory object that converts | |
| 177 | + * public/private keys of the specified algorithm. | |
| 178 | + * | |
| 179 | + * <p> A new KeyFactory object encapsulating the | |
| 180 | + * KeyFactorySpi implementation from the specified provider | |
| 181 | + * is returned. The specified provider must be registered | |
| 182 | + * in the security provider list. | |
| 183 | + * | |
| 184 | + * <p> Note that the list of registered providers may be retrieved via | |
| 185 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 186 | + * | |
| 187 | + * @param algorithm the name of the requested key algorithm. | |
| 188 | + * See the KeyFactory section in the <a href= | |
| 189 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> | |
| 190 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 191 | + * for information about standard algorithm names. | |
| 192 | + * | |
| 193 | + * @param provider the name of the provider. | |
| 194 | + * | |
| 195 | + * @return the new KeyFactory object. | |
| 196 | + * | |
| 197 | + * @exception NoSuchAlgorithmException if a KeyFactorySpi | |
| 198 | + * implementation for the specified algorithm is not | |
| 199 | + * available from the specified provider. | |
| 200 | + * | |
| 201 | + * @exception NoSuchProviderException if the specified provider is not | |
| 202 | + * registered in the security provider list. | |
| 203 | + * | |
| 204 | + * @exception IllegalArgumentException if the provider name is null | |
| 205 | + * or empty. | |
| 206 | + * | |
| 207 | + * @see Provider | |
| 208 | + */ | |
| 209 | + public static KeyFactory getInstance(String algorithm, String provider) | |
| 210 | + throws NoSuchAlgorithmException, NoSuchProviderException { | |
| 211 | + Instance instance = GetInstance.getInstance("KeyFactory", | |
| 212 | + KeyFactorySpi.class, algorithm, provider); | |
| 213 | + return new KeyFactory((KeyFactorySpi)instance.impl, | |
| 214 | + instance.provider, algorithm); | |
| 215 | + } | |
| 216 | + | |
| 217 | + /** | |
| 218 | + * Returns a KeyFactory object that converts | |
| 219 | + * public/private keys of the specified algorithm. | |
| 220 | + * | |
| 221 | + * <p> A new KeyFactory object encapsulating the | |
| 222 | + * KeyFactorySpi implementation from the specified Provider | |
| 223 | + * object is returned. Note that the specified Provider object | |
| 224 | + * does not have to be registered in the provider list. | |
| 225 | + * | |
| 226 | + * @param algorithm the name of the requested key algorithm. | |
| 227 | + * See the KeyFactory section in the <a href= | |
| 228 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory"> | |
| 229 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 230 | + * for information about standard algorithm names. | |
| 231 | + * | |
| 232 | + * @param provider the provider. | |
| 233 | + * | |
| 234 | + * @return the new KeyFactory object. | |
| 235 | + * | |
| 236 | + * @exception NoSuchAlgorithmException if a KeyFactorySpi | |
| 237 | + * implementation for the specified algorithm is not available | |
| 238 | + * from the specified Provider object. | |
| 239 | + * | |
| 240 | + * @exception IllegalArgumentException if the specified provider is null. | |
| 241 | + * | |
| 242 | + * @see Provider | |
| 243 | + * | |
| 244 | + * @since 1.4 | |
| 245 | + */ | |
| 246 | + public static KeyFactory getInstance(String algorithm, Provider provider) | |
| 247 | + throws NoSuchAlgorithmException { | |
| 248 | + Instance instance = GetInstance.getInstance("KeyFactory", | |
| 249 | + KeyFactorySpi.class, algorithm, provider); | |
| 250 | + return new KeyFactory((KeyFactorySpi)instance.impl, | |
| 251 | + instance.provider, algorithm); | |
| 252 | + } | |
| 253 | + | |
| 254 | + /** | |
| 255 | + * Returns the provider of this key factory object. | |
| 256 | + * | |
| 257 | + * @return the provider of this key factory object | |
| 258 | + */ | |
| 259 | + public final Provider getProvider() { | |
| 260 | + synchronized (lock) { | |
| 261 | + // disable further failover after this call | |
| 262 | + serviceIterator = null; | |
| 263 | + return provider; | |
| 264 | + } | |
| 265 | + } | |
| 266 | + | |
| 267 | + /** | |
| 268 | + * Gets the name of the algorithm | |
| 269 | + * associated with this <tt>KeyFactory</tt>. | |
| 270 | + * | |
| 271 | + * @return the name of the algorithm associated with this | |
| 272 | + * <tt>KeyFactory</tt> | |
| 273 | + */ | |
| 274 | + public final String getAlgorithm() { | |
| 275 | + return this.algorithm; | |
| 276 | + } | |
| 277 | + | |
| 278 | + /** | |
| 279 | + * Update the active KeyFactorySpi of this class and return the next | |
| 280 | + * implementation for failover. If no more implemenations are | |
| 281 | + * available, this method returns null. However, the active spi of | |
| 282 | + * this class is never set to null. | |
| 283 | + */ | |
| 284 | + private KeyFactorySpi nextSpi(KeyFactorySpi oldSpi) { | |
| 285 | + synchronized (lock) { | |
| 286 | + // somebody else did a failover concurrently | |
| 287 | + // try that spi now | |
| 288 | + if ((oldSpi != null) && (oldSpi != spi)) { | |
| 289 | + return spi; | |
| 290 | + } | |
| 291 | + if (serviceIterator == null) { | |
| 292 | + return null; | |
| 293 | + } | |
| 294 | + while (serviceIterator.hasNext()) { | |
| 295 | + Service s = serviceIterator.next(); | |
| 296 | + try { | |
| 297 | + Object obj = s.newInstance(null); | |
| 298 | + if (obj instanceof KeyFactorySpi == false) { | |
| 299 | + continue; | |
| 300 | + } | |
| 301 | + KeyFactorySpi spi = (KeyFactorySpi)obj; | |
| 302 | + provider = s.getProvider(); | |
| 303 | + this.spi = spi; | |
| 304 | + return spi; | |
| 305 | + } catch (NoSuchAlgorithmException e) { | |
| 306 | + // ignore | |
| 307 | + } | |
| 308 | + } | |
| 309 | + serviceIterator = null; | |
| 310 | + return null; | |
| 311 | + } | |
| 312 | + } | |
| 313 | + | |
| 314 | + /** | |
| 315 | + * Generates a public key object from the provided key specification | |
| 316 | + * (key material). | |
| 317 | + * | |
| 318 | + * @param keySpec the specification (key material) of the public key. | |
| 319 | + * | |
| 320 | + * @return the public key. | |
| 321 | + * | |
| 322 | + * @exception InvalidKeySpecException if the given key specification | |
| 323 | + * is inappropriate for this key factory to produce a public key. | |
| 324 | + */ | |
| 325 | + public final PublicKey generatePublic(KeySpec keySpec) | |
| 326 | + throws InvalidKeySpecException { | |
| 327 | + if (serviceIterator == null) { | |
| 328 | + return spi.engineGeneratePublic(keySpec); | |
| 329 | + } | |
| 330 | + Exception failure = null; | |
| 331 | + KeyFactorySpi mySpi = spi; | |
| 332 | + do { | |
| 333 | + try { | |
| 334 | + return mySpi.engineGeneratePublic(keySpec); | |
| 335 | + } catch (Exception e) { | |
| 336 | + if (failure == null) { | |
| 337 | + failure = e; | |
| 338 | + } | |
| 339 | + mySpi = nextSpi(mySpi); | |
| 340 | + } | |
| 341 | + } while (mySpi != null); | |
| 342 | + if (failure instanceof RuntimeException) { | |
| 343 | + throw (RuntimeException)failure; | |
| 344 | + } | |
| 345 | + if (failure instanceof InvalidKeySpecException) { | |
| 346 | + throw (InvalidKeySpecException)failure; | |
| 347 | + } | |
| 348 | + throw new InvalidKeySpecException | |
| 349 | + ("Could not generate public key", failure); | |
| 350 | + } | |
| 351 | + | |
| 352 | + /** | |
| 353 | + * Generates a private key object from the provided key specification | |
| 354 | + * (key material). | |
| 355 | + * | |
| 356 | + * @param keySpec the specification (key material) of the private key. | |
| 357 | + * | |
| 358 | + * @return the private key. | |
| 359 | + * | |
| 360 | + * @exception InvalidKeySpecException if the given key specification | |
| 361 | + * is inappropriate for this key factory to produce a private key. | |
| 362 | + */ | |
| 363 | + public final PrivateKey generatePrivate(KeySpec keySpec) | |
| 364 | + throws InvalidKeySpecException { | |
| 365 | + if (serviceIterator == null) { | |
| 366 | + return spi.engineGeneratePrivate(keySpec); | |
| 367 | + } | |
| 368 | + Exception failure = null; | |
| 369 | + KeyFactorySpi mySpi = spi; | |
| 370 | + do { | |
| 371 | + try { | |
| 372 | + return mySpi.engineGeneratePrivate(keySpec); | |
| 373 | + } catch (Exception e) { | |
| 374 | + if (failure == null) { | |
| 375 | + failure = e; | |
| 376 | + } | |
| 377 | + mySpi = nextSpi(mySpi); | |
| 378 | + } | |
| 379 | + } while (mySpi != null); | |
| 380 | + if (failure instanceof RuntimeException) { | |
| 381 | + throw (RuntimeException)failure; | |
| 382 | + } | |
| 383 | + if (failure instanceof InvalidKeySpecException) { | |
| 384 | + throw (InvalidKeySpecException)failure; | |
| 385 | + } | |
| 386 | + throw new InvalidKeySpecException | |
| 387 | + ("Could not generate private key", failure); | |
| 388 | + } | |
| 389 | + | |
| 390 | + /** | |
| 391 | + * Returns a specification (key material) of the given key object. | |
| 392 | + * <code>keySpec</code> identifies the specification class in which | |
| 393 | + * the key material should be returned. It could, for example, be | |
| 394 | + * <code>DSAPublicKeySpec.class</code>, to indicate that the | |
| 395 | + * key material should be returned in an instance of the | |
| 396 | + * <code>DSAPublicKeySpec</code> class. | |
| 397 | + * | |
| 398 | + * @param key the key. | |
| 399 | + * | |
| 400 | + * @param keySpec the specification class in which | |
| 401 | + * the key material should be returned. | |
| 402 | + * | |
| 403 | + * @return the underlying key specification (key material) in an instance | |
| 404 | + * of the requested specification class. | |
| 405 | + * | |
| 406 | + * @exception InvalidKeySpecException if the requested key specification is | |
| 407 | + * inappropriate for the given key, or the given key cannot be processed | |
| 408 | + * (e.g., the given key has an unrecognized algorithm or format). | |
| 409 | + */ | |
| 410 | + public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec) | |
| 411 | + throws InvalidKeySpecException { | |
| 412 | + if (serviceIterator == null) { | |
| 413 | + return spi.engineGetKeySpec(key, keySpec); | |
| 414 | + } | |
| 415 | + Exception failure = null; | |
| 416 | + KeyFactorySpi mySpi = spi; | |
| 417 | + do { | |
| 418 | + try { | |
| 419 | + return mySpi.engineGetKeySpec(key, keySpec); | |
| 420 | + } catch (Exception e) { | |
| 421 | + if (failure == null) { | |
| 422 | + failure = e; | |
| 423 | + } | |
| 424 | + mySpi = nextSpi(mySpi); | |
| 425 | + } | |
| 426 | + } while (mySpi != null); | |
| 427 | + if (failure instanceof RuntimeException) { | |
| 428 | + throw (RuntimeException)failure; | |
| 429 | + } | |
| 430 | + if (failure instanceof InvalidKeySpecException) { | |
| 431 | + throw (InvalidKeySpecException)failure; | |
| 432 | + } | |
| 433 | + throw new InvalidKeySpecException | |
| 434 | + ("Could not get key spec", failure); | |
| 435 | + } | |
| 436 | + | |
| 437 | + /** | |
| 438 | + * Translates a key object, whose provider may be unknown or potentially | |
| 439 | + * untrusted, into a corresponding key object of this key factory. | |
| 440 | + * | |
| 441 | + * @param key the key whose provider is unknown or untrusted. | |
| 442 | + * | |
| 443 | + * @return the translated key. | |
| 444 | + * | |
| 445 | + * @exception InvalidKeyException if the given key cannot be processed | |
| 446 | + * by this key factory. | |
| 447 | + */ | |
| 448 | + public final Key translateKey(Key key) throws InvalidKeyException { | |
| 449 | + if (serviceIterator == null) { | |
| 450 | + return spi.engineTranslateKey(key); | |
| 451 | + } | |
| 452 | + Exception failure = null; | |
| 453 | + KeyFactorySpi mySpi = spi; | |
| 454 | + do { | |
| 455 | + try { | |
| 456 | + return mySpi.engineTranslateKey(key); | |
| 457 | + } catch (Exception e) { | |
| 458 | + if (failure == null) { | |
| 459 | + failure = e; | |
| 460 | + } | |
| 461 | + mySpi = nextSpi(mySpi); | |
| 462 | + } | |
| 463 | + } while (mySpi != null); | |
| 464 | + if (failure instanceof RuntimeException) { | |
| 465 | + throw (RuntimeException)failure; | |
| 466 | + } | |
| 467 | + if (failure instanceof InvalidKeyException) { | |
| 468 | + throw (InvalidKeyException)failure; | |
| 469 | + } | |
| 470 | + throw new InvalidKeyException | |
| 471 | + ("Could not translate key", failure); | |
| 472 | + } | |
| 473 | + | |
| 474 | +} | |
Binary file not shown.
| @@ -0,0 +1,140 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.security.spec.KeySpec; | |
| 29 | +import java.security.spec.InvalidKeySpecException; | |
| 30 | + | |
| 31 | +/** | |
| 32 | + * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) | |
| 33 | + * for the <code>KeyFactory</code> class. | |
| 34 | + * All the abstract methods in this class must be implemented by each | |
| 35 | + * cryptographic service provider who wishes to supply the implementation | |
| 36 | + * of a key factory for a particular algorithm. | |
| 37 | + * | |
| 38 | + * <P> Key factories are used to convert <I>keys</I> (opaque | |
| 39 | + * cryptographic keys of type <code>Key</code>) into <I>key specifications</I> | |
| 40 | + * (transparent representations of the underlying key material), and vice | |
| 41 | + * versa. | |
| 42 | + * | |
| 43 | + * <P> Key factories are bi-directional. That is, they allow you to build an | |
| 44 | + * opaque key object from a given key specification (key material), or to | |
| 45 | + * retrieve the underlying key material of a key object in a suitable format. | |
| 46 | + * | |
| 47 | + * <P> Multiple compatible key specifications may exist for the same key. | |
| 48 | + * For example, a DSA public key may be specified using | |
| 49 | + * <code>DSAPublicKeySpec</code> or | |
| 50 | + * <code>X509EncodedKeySpec</code>. A key factory can be used to translate | |
| 51 | + * between compatible key specifications. | |
| 52 | + * | |
| 53 | + * <P> A provider should document all the key specifications supported by its | |
| 54 | + * key factory. | |
| 55 | + * | |
| 56 | + * @author Jan Luehe | |
| 57 | + * | |
| 58 | + * | |
| 59 | + * @see KeyFactory | |
| 60 | + * @see Key | |
| 61 | + * @see PublicKey | |
| 62 | + * @see PrivateKey | |
| 63 | + * @see java.security.spec.KeySpec | |
| 64 | + * @see java.security.spec.DSAPublicKeySpec | |
| 65 | + * @see java.security.spec.X509EncodedKeySpec | |
| 66 | + * | |
| 67 | + * @since 1.2 | |
| 68 | + */ | |
| 69 | + | |
| 70 | +public abstract class KeyFactorySpi { | |
| 71 | + | |
| 72 | + /** | |
| 73 | + * Generates a public key object from the provided key | |
| 74 | + * specification (key material). | |
| 75 | + * | |
| 76 | + * @param keySpec the specification (key material) of the public key. | |
| 77 | + * | |
| 78 | + * @return the public key. | |
| 79 | + * | |
| 80 | + * @exception InvalidKeySpecException if the given key specification | |
| 81 | + * is inappropriate for this key factory to produce a public key. | |
| 82 | + */ | |
| 83 | + protected abstract PublicKey engineGeneratePublic(KeySpec keySpec) | |
| 84 | + throws InvalidKeySpecException; | |
| 85 | + | |
| 86 | + /** | |
| 87 | + * Generates a private key object from the provided key | |
| 88 | + * specification (key material). | |
| 89 | + * | |
| 90 | + * @param keySpec the specification (key material) of the private key. | |
| 91 | + * | |
| 92 | + * @return the private key. | |
| 93 | + * | |
| 94 | + * @exception InvalidKeySpecException if the given key specification | |
| 95 | + * is inappropriate for this key factory to produce a private key. | |
| 96 | + */ | |
| 97 | + protected abstract PrivateKey engineGeneratePrivate(KeySpec keySpec) | |
| 98 | + throws InvalidKeySpecException; | |
| 99 | + | |
| 100 | + /** | |
| 101 | + * Returns a specification (key material) of the given key | |
| 102 | + * object. | |
| 103 | + * <code>keySpec</code> identifies the specification class in which | |
| 104 | + * the key material should be returned. It could, for example, be | |
| 105 | + * <code>DSAPublicKeySpec.class</code>, to indicate that the | |
| 106 | + * key material should be returned in an instance of the | |
| 107 | + * <code>DSAPublicKeySpec</code> class. | |
| 108 | + * | |
| 109 | + * @param key the key. | |
| 110 | + * | |
| 111 | + * @param keySpec the specification class in which | |
| 112 | + * the key material should be returned. | |
| 113 | + * | |
| 114 | + * @return the underlying key specification (key material) in an instance | |
| 115 | + * of the requested specification class. | |
| 116 | + | |
| 117 | + * @exception InvalidKeySpecException if the requested key specification is | |
| 118 | + * inappropriate for the given key, or the given key cannot be dealt with | |
| 119 | + * (e.g., the given key has an unrecognized format). | |
| 120 | + */ | |
| 121 | + protected abstract <T extends KeySpec> | |
| 122 | + T engineGetKeySpec(Key key, Class<T> keySpec) | |
| 123 | + throws InvalidKeySpecException; | |
| 124 | + | |
| 125 | + /** | |
| 126 | + * Translates a key object, whose provider may be unknown or | |
| 127 | + * potentially untrusted, into a corresponding key object of this key | |
| 128 | + * factory. | |
| 129 | + * | |
| 130 | + * @param key the key whose provider is unknown or untrusted. | |
| 131 | + * | |
| 132 | + * @return the translated key. | |
| 133 | + * | |
| 134 | + * @exception InvalidKeyException if the given key cannot be processed | |
| 135 | + * by this key factory. | |
| 136 | + */ | |
| 137 | + protected abstract Key engineTranslateKey(Key key) | |
| 138 | + throws InvalidKeyException; | |
| 139 | + | |
| 140 | +} | |
Binary file not shown.
| @@ -0,0 +1,99 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This is the general key management exception for all operations | |
| 30 | + * dealing with key management. Examples of subclasses of | |
| 31 | + * KeyManagementException that developers might create for | |
| 32 | + * giving more detailed information could include: | |
| 33 | + * | |
| 34 | + * <ul> | |
| 35 | + * <li>KeyIDConflictException | |
| 36 | + * <li>KeyAuthorizationFailureException | |
| 37 | + * <li>ExpiredKeyException | |
| 38 | + * </ul> | |
| 39 | + * | |
| 40 | + * @author Benjamin Renaud | |
| 41 | + * | |
| 42 | + * @see Key | |
| 43 | + * @see KeyException | |
| 44 | + */ | |
| 45 | + | |
| 46 | +public class KeyManagementException extends KeyException { | |
| 47 | + | |
| 48 | + private static final long serialVersionUID = 947674216157062695L; | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * Constructs a KeyManagementException with no detail message. A | |
| 52 | + * detail message is a String that describes this particular | |
| 53 | + * exception. | |
| 54 | + */ | |
| 55 | + public KeyManagementException() { | |
| 56 | + super(); | |
| 57 | + } | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * Constructs a KeyManagementException with the specified detail | |
| 61 | + * message. A detail message is a String that describes this | |
| 62 | + * particular exception. | |
| 63 | + * | |
| 64 | + * @param msg the detail message. | |
| 65 | + */ | |
| 66 | + public KeyManagementException(String msg) { | |
| 67 | + super(msg); | |
| 68 | + } | |
| 69 | + | |
| 70 | + /** | |
| 71 | + * Creates a <code>KeyManagementException</code> with the specified | |
| 72 | + * detail message and cause. | |
| 73 | + * | |
| 74 | + * @param message the detail message (which is saved for later retrieval | |
| 75 | + * by the {@link #getMessage()} method). | |
| 76 | + * @param cause the cause (which is saved for later retrieval by the | |
| 77 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 78 | + * and indicates that the cause is nonexistent or unknown.) | |
| 79 | + * @since 1.5 | |
| 80 | + */ | |
| 81 | + public KeyManagementException(String message, Throwable cause) { | |
| 82 | + super(message, cause); | |
| 83 | + } | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * Creates a <code>KeyManagementException</code> with the specified cause | |
| 87 | + * and a detail message of <tt>(cause==null ? null : cause.toString())</tt> | |
| 88 | + * (which typically contains the class and detail message of | |
| 89 | + * <tt>cause</tt>). | |
| 90 | + * | |
| 91 | + * @param cause the cause (which is saved for later retrieval by the | |
| 92 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 93 | + * and indicates that the cause is nonexistent or unknown.) | |
| 94 | + * @since 1.5 | |
| 95 | + */ | |
| 96 | + public KeyManagementException(Throwable cause) { | |
| 97 | + super(cause); | |
| 98 | + } | |
| 99 | +} | |
Binary file not shown.
| @@ -0,0 +1,81 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.util.*; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * This class is a simple holder for a key pair (a public key and a | |
| 32 | + * private key). It does not enforce any security, and, when initialized, | |
| 33 | + * should be treated like a PrivateKey. | |
| 34 | + * | |
| 35 | + * @see PublicKey | |
| 36 | + * @see PrivateKey | |
| 37 | + * | |
| 38 | + * @author Benjamin Renaud | |
| 39 | + */ | |
| 40 | + | |
| 41 | +public final class KeyPair implements java.io.Serializable { | |
| 42 | + | |
| 43 | + private static final long serialVersionUID = -7565189502268009837L; | |
| 44 | + | |
| 45 | + private PrivateKey privateKey; | |
| 46 | + private PublicKey publicKey; | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * Constructs a key pair from the given public key and private key. | |
| 50 | + * | |
| 51 | + * <p>Note that this constructor only stores references to the public | |
| 52 | + * and private key components in the generated key pair. This is safe, | |
| 53 | + * because <code>Key</code> objects are immutable. | |
| 54 | + * | |
| 55 | + * @param publicKey the public key. | |
| 56 | + * | |
| 57 | + * @param privateKey the private key. | |
| 58 | + */ | |
| 59 | + public KeyPair(PublicKey publicKey, PrivateKey privateKey) { | |
| 60 | + this.publicKey = publicKey; | |
| 61 | + this.privateKey = privateKey; | |
| 62 | + } | |
| 63 | + | |
| 64 | + /** | |
| 65 | + * Returns a reference to the public key component of this key pair. | |
| 66 | + * | |
| 67 | + * @return a reference to the public key. | |
| 68 | + */ | |
| 69 | + public PublicKey getPublic() { | |
| 70 | + return publicKey; | |
| 71 | + } | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * Returns a reference to the private key component of this key pair. | |
| 75 | + * | |
| 76 | + * @return a reference to the private key. | |
| 77 | + */ | |
| 78 | + public PrivateKey getPrivate() { | |
| 79 | + return privateKey; | |
| 80 | + } | |
| 81 | +} | |
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,699 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.util.*; | |
| 29 | + | |
| 30 | +import java.security.spec.AlgorithmParameterSpec; | |
| 31 | + | |
| 32 | +import java.security.Provider.Service; | |
| 33 | + | |
| 34 | +import sun.security.jca.*; | |
| 35 | +import sun.security.jca.GetInstance.Instance; | |
| 36 | + | |
| 37 | +/** | |
| 38 | + * The KeyPairGenerator class is used to generate pairs of | |
| 39 | + * public and private keys. Key pair generators are constructed using the | |
| 40 | + * <code>getInstance</code> factory methods (static methods that | |
| 41 | + * return instances of a given class). | |
| 42 | + * | |
| 43 | + * <p>A Key pair generator for a particular algorithm creates a public/private | |
| 44 | + * key pair that can be used with this algorithm. It also associates | |
| 45 | + * algorithm-specific parameters with each of the generated keys. | |
| 46 | + * | |
| 47 | + * <p>There are two ways to generate a key pair: in an algorithm-independent | |
| 48 | + * manner, and in an algorithm-specific manner. | |
| 49 | + * The only difference between the two is the initialization of the object: | |
| 50 | + * | |
| 51 | + * <ul> | |
| 52 | + * <li><b>Algorithm-Independent Initialization</b> | |
| 53 | + * <p>All key pair generators share the concepts of a keysize and a | |
| 54 | + * source of randomness. The keysize is interpreted differently for different | |
| 55 | + * algorithms (e.g., in the case of the <i>DSA</i> algorithm, the keysize | |
| 56 | + * corresponds to the length of the modulus). | |
| 57 | + * There is an | |
| 58 | + * {@link #initialize(int, java.security.SecureRandom) initialize} | |
| 59 | + * method in this KeyPairGenerator class that takes these two universally | |
| 60 | + * shared types of arguments. There is also one that takes just a | |
| 61 | + * <code>keysize</code> argument, and uses the <code>SecureRandom</code> | |
| 62 | + * implementation of the highest-priority installed provider as the source | |
| 63 | + * of randomness. (If none of the installed providers supply an implementation | |
| 64 | + * of <code>SecureRandom</code>, a system-provided source of randomness is | |
| 65 | + * used.) | |
| 66 | + * | |
| 67 | + * <p>Since no other parameters are specified when you call the above | |
| 68 | + * algorithm-independent <code>initialize</code> methods, it is up to the | |
| 69 | + * provider what to do about the algorithm-specific parameters (if any) to be | |
| 70 | + * associated with each of the keys. | |
| 71 | + * | |
| 72 | + * <p>If the algorithm is the <i>DSA</i> algorithm, and the keysize (modulus | |
| 73 | + * size) is 512, 768, or 1024, then the <i>Sun</i> provider uses a set of | |
| 74 | + * precomputed values for the <code>p</code>, <code>q</code>, and | |
| 75 | + * <code>g</code> parameters. If the modulus size is not one of the above | |
| 76 | + * values, the <i>Sun</i> provider creates a new set of parameters. Other | |
| 77 | + * providers might have precomputed parameter sets for more than just the | |
| 78 | + * three modulus sizes mentioned above. Still others might not have a list of | |
| 79 | + * precomputed parameters at all and instead always create new parameter sets. | |
| 80 | + * <p> | |
| 81 | + * | |
| 82 | + * <li><b>Algorithm-Specific Initialization</b> | |
| 83 | + * <p>For situations where a set of algorithm-specific parameters already | |
| 84 | + * exists (e.g., so-called <i>community parameters</i> in DSA), there are two | |
| 85 | + * {@link #initialize(java.security.spec.AlgorithmParameterSpec) | |
| 86 | + * initialize} methods that have an <code>AlgorithmParameterSpec</code> | |
| 87 | + * argument. One also has a <code>SecureRandom</code> argument, while the | |
| 88 | + * the other uses the <code>SecureRandom</code> | |
| 89 | + * implementation of the highest-priority installed provider as the source | |
| 90 | + * of randomness. (If none of the installed providers supply an implementation | |
| 91 | + * of <code>SecureRandom</code>, a system-provided source of randomness is | |
| 92 | + * used.) | |
| 93 | + * </ul> | |
| 94 | + * | |
| 95 | + * <p>In case the client does not explicitly initialize the KeyPairGenerator | |
| 96 | + * (via a call to an <code>initialize</code> method), each provider must | |
| 97 | + * supply (and document) a default initialization. | |
| 98 | + * For example, the <i>Sun</i> provider uses a default modulus size (keysize) | |
| 99 | + * of 1024 bits. | |
| 100 | + * | |
| 101 | + * <p>Note that this class is abstract and extends from | |
| 102 | + * <code>KeyPairGeneratorSpi</code> for historical reasons. | |
| 103 | + * Application developers should only take notice of the methods defined in | |
| 104 | + * this <code>KeyPairGenerator</code> class; all the methods in | |
| 105 | + * the superclass are intended for cryptographic service providers who wish to | |
| 106 | + * supply their own implementations of key pair generators. | |
| 107 | + * | |
| 108 | + * <p> Every implementation of the Java platform is required to support the | |
| 109 | + * following standard <code>KeyPairGenerator</code> algorithms and keysizes in | |
| 110 | + * parentheses: | |
| 111 | + * <ul> | |
| 112 | + * <li><tt>DiffieHellman</tt> (1024)</li> | |
| 113 | + * <li><tt>DSA</tt> (1024)</li> | |
| 114 | + * <li><tt>RSA</tt> (1024, 2048)</li> | |
| 115 | + * </ul> | |
| 116 | + * These algorithms are described in the <a href= | |
| 117 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> | |
| 118 | + * KeyPairGenerator section</a> of the | |
| 119 | + * Java Cryptography Architecture Standard Algorithm Name Documentation. | |
| 120 | + * Consult the release documentation for your implementation to see if any | |
| 121 | + * other algorithms are supported. | |
| 122 | + * | |
| 123 | + * @author Benjamin Renaud | |
| 124 | + * | |
| 125 | + * @see java.security.spec.AlgorithmParameterSpec | |
| 126 | + */ | |
| 127 | + | |
| 128 | +public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { | |
| 129 | + | |
| 130 | + private final String algorithm; | |
| 131 | + | |
| 132 | + // The provider | |
| 133 | + Provider provider; | |
| 134 | + | |
| 135 | + /** | |
| 136 | + * Creates a KeyPairGenerator object for the specified algorithm. | |
| 137 | + * | |
| 138 | + * @param algorithm the standard string name of the algorithm. | |
| 139 | + * See the KeyPairGenerator section in the <a href= | |
| 140 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> | |
| 141 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 142 | + * for information about standard algorithm names. | |
| 143 | + */ | |
| 144 | + protected KeyPairGenerator(String algorithm) { | |
| 145 | + this.algorithm = algorithm; | |
| 146 | + } | |
| 147 | + | |
| 148 | + /** | |
| 149 | + * Returns the standard name of the algorithm for this key pair generator. | |
| 150 | + * See the KeyPairGenerator section in the <a href= | |
| 151 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> | |
| 152 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 153 | + * for information about standard algorithm names. | |
| 154 | + * | |
| 155 | + * @return the standard string name of the algorithm. | |
| 156 | + */ | |
| 157 | + public String getAlgorithm() { | |
| 158 | + return this.algorithm; | |
| 159 | + } | |
| 160 | + | |
| 161 | + private static KeyPairGenerator getInstance(Instance instance, | |
| 162 | + String algorithm) { | |
| 163 | + KeyPairGenerator kpg; | |
| 164 | + if (instance.impl instanceof KeyPairGenerator) { | |
| 165 | + kpg = (KeyPairGenerator)instance.impl; | |
| 166 | + } else { | |
| 167 | + KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)instance.impl; | |
| 168 | + kpg = new Delegate(spi, algorithm); | |
| 169 | + } | |
| 170 | + kpg.provider = instance.provider; | |
| 171 | + return kpg; | |
| 172 | + } | |
| 173 | + | |
| 174 | + /** | |
| 175 | + * Returns a KeyPairGenerator object that generates public/private | |
| 176 | + * key pairs for the specified algorithm. | |
| 177 | + * | |
| 178 | + * <p> This method traverses the list of registered security Providers, | |
| 179 | + * starting with the most preferred Provider. | |
| 180 | + * A new KeyPairGenerator object encapsulating the | |
| 181 | + * KeyPairGeneratorSpi implementation from the first | |
| 182 | + * Provider that supports the specified algorithm is returned. | |
| 183 | + * | |
| 184 | + * <p> Note that the list of registered providers may be retrieved via | |
| 185 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 186 | + * | |
| 187 | + * @param algorithm the standard string name of the algorithm. | |
| 188 | + * See the KeyPairGenerator section in the <a href= | |
| 189 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> | |
| 190 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 191 | + * for information about standard algorithm names. | |
| 192 | + * | |
| 193 | + * @return the new KeyPairGenerator object. | |
| 194 | + * | |
| 195 | + * @exception NoSuchAlgorithmException if no Provider supports a | |
| 196 | + * KeyPairGeneratorSpi implementation for the | |
| 197 | + * specified algorithm. | |
| 198 | + * | |
| 199 | + * @see Provider | |
| 200 | + */ | |
| 201 | + public static KeyPairGenerator getInstance(String algorithm) | |
| 202 | + throws NoSuchAlgorithmException { | |
| 203 | + List<Service> list = | |
| 204 | + GetInstance.getServices("KeyPairGenerator", algorithm); | |
| 205 | + Iterator<Service> t = list.iterator(); | |
| 206 | + if (t.hasNext() == false) { | |
| 207 | + throw new NoSuchAlgorithmException | |
| 208 | + (algorithm + " KeyPairGenerator not available"); | |
| 209 | + } | |
| 210 | + // find a working Spi or KeyPairGenerator subclass | |
| 211 | + NoSuchAlgorithmException failure = null; | |
| 212 | + do { | |
| 213 | + Service s = t.next(); | |
| 214 | + try { | |
| 215 | + Instance instance = | |
| 216 | + GetInstance.getInstance(s, KeyPairGeneratorSpi.class); | |
| 217 | + if (instance.impl instanceof KeyPairGenerator) { | |
| 218 | + return getInstance(instance, algorithm); | |
| 219 | + } else { | |
| 220 | + return new Delegate(instance, t, algorithm); | |
| 221 | + } | |
| 222 | + } catch (NoSuchAlgorithmException e) { | |
| 223 | + if (failure == null) { | |
| 224 | + failure = e; | |
| 225 | + } | |
| 226 | + } | |
| 227 | + } while (t.hasNext()); | |
| 228 | + throw failure; | |
| 229 | + } | |
| 230 | + | |
| 231 | + /** | |
| 232 | + * Returns a KeyPairGenerator object that generates public/private | |
| 233 | + * key pairs for the specified algorithm. | |
| 234 | + * | |
| 235 | + * <p> A new KeyPairGenerator object encapsulating the | |
| 236 | + * KeyPairGeneratorSpi implementation from the specified provider | |
| 237 | + * is returned. The specified provider must be registered | |
| 238 | + * in the security provider list. | |
| 239 | + * | |
| 240 | + * <p> Note that the list of registered providers may be retrieved via | |
| 241 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 242 | + * | |
| 243 | + * @param algorithm the standard string name of the algorithm. | |
| 244 | + * See the KeyPairGenerator section in the <a href= | |
| 245 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> | |
| 246 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 247 | + * for information about standard algorithm names. | |
| 248 | + * | |
| 249 | + * @param provider the string name of the provider. | |
| 250 | + * | |
| 251 | + * @return the new KeyPairGenerator object. | |
| 252 | + * | |
| 253 | + * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi | |
| 254 | + * implementation for the specified algorithm is not | |
| 255 | + * available from the specified provider. | |
| 256 | + * | |
| 257 | + * @exception NoSuchProviderException if the specified provider is not | |
| 258 | + * registered in the security provider list. | |
| 259 | + * | |
| 260 | + * @exception IllegalArgumentException if the provider name is null | |
| 261 | + * or empty. | |
| 262 | + * | |
| 263 | + * @see Provider | |
| 264 | + */ | |
| 265 | + public static KeyPairGenerator getInstance(String algorithm, | |
| 266 | + String provider) | |
| 267 | + throws NoSuchAlgorithmException, NoSuchProviderException { | |
| 268 | + Instance instance = GetInstance.getInstance("KeyPairGenerator", | |
| 269 | + KeyPairGeneratorSpi.class, algorithm, provider); | |
| 270 | + return getInstance(instance, algorithm); | |
| 271 | + } | |
| 272 | + | |
| 273 | + /** | |
| 274 | + * Returns a KeyPairGenerator object that generates public/private | |
| 275 | + * key pairs for the specified algorithm. | |
| 276 | + * | |
| 277 | + * <p> A new KeyPairGenerator object encapsulating the | |
| 278 | + * KeyPairGeneratorSpi implementation from the specified Provider | |
| 279 | + * object is returned. Note that the specified Provider object | |
| 280 | + * does not have to be registered in the provider list. | |
| 281 | + * | |
| 282 | + * @param algorithm the standard string name of the algorithm. | |
| 283 | + * See the KeyPairGenerator section in the <a href= | |
| 284 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator"> | |
| 285 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 286 | + * for information about standard algorithm names. | |
| 287 | + * | |
| 288 | + * @param provider the provider. | |
| 289 | + * | |
| 290 | + * @return the new KeyPairGenerator object. | |
| 291 | + * | |
| 292 | + * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi | |
| 293 | + * implementation for the specified algorithm is not available | |
| 294 | + * from the specified Provider object. | |
| 295 | + * | |
| 296 | + * @exception IllegalArgumentException if the specified provider is null. | |
| 297 | + * | |
| 298 | + * @see Provider | |
| 299 | + * | |
| 300 | + * @since 1.4 | |
| 301 | + */ | |
| 302 | + public static KeyPairGenerator getInstance(String algorithm, | |
| 303 | + Provider provider) throws NoSuchAlgorithmException { | |
| 304 | + Instance instance = GetInstance.getInstance("KeyPairGenerator", | |
| 305 | + KeyPairGeneratorSpi.class, algorithm, provider); | |
| 306 | + return getInstance(instance, algorithm); | |
| 307 | + } | |
| 308 | + | |
| 309 | + /** | |
| 310 | + * Returns the provider of this key pair generator object. | |
| 311 | + * | |
| 312 | + * @return the provider of this key pair generator object | |
| 313 | + */ | |
| 314 | + public final Provider getProvider() { | |
| 315 | + disableFailover(); | |
| 316 | + return this.provider; | |
| 317 | + } | |
| 318 | + | |
| 319 | + void disableFailover() { | |
| 320 | + // empty, overridden in Delegate | |
| 321 | + } | |
| 322 | + | |
| 323 | + /** | |
| 324 | + * Initializes the key pair generator for a certain keysize using | |
| 325 | + * a default parameter set and the <code>SecureRandom</code> | |
| 326 | + * implementation of the highest-priority installed provider as the source | |
| 327 | + * of randomness. | |
| 328 | + * (If none of the installed providers supply an implementation of | |
| 329 | + * <code>SecureRandom</code>, a system-provided source of randomness is | |
| 330 | + * used.) | |
| 331 | + * | |
| 332 | + * @param keysize the keysize. This is an | |
| 333 | + * algorithm-specific metric, such as modulus length, specified in | |
| 334 | + * number of bits. | |
| 335 | + * | |
| 336 | + * @exception InvalidParameterException if the <code>keysize</code> is not | |
| 337 | + * supported by this KeyPairGenerator object. | |
| 338 | + */ | |
| 339 | + public void initialize(int keysize) { | |
| 340 | + initialize(keysize, JCAUtil.getSecureRandom()); | |
| 341 | + } | |
| 342 | + | |
| 343 | + /** | |
| 344 | + * Initializes the key pair generator for a certain keysize with | |
| 345 | + * the given source of randomness (and a default parameter set). | |
| 346 | + * | |
| 347 | + * @param keysize the keysize. This is an | |
| 348 | + * algorithm-specific metric, such as modulus length, specified in | |
| 349 | + * number of bits. | |
| 350 | + * @param random the source of randomness. | |
| 351 | + * | |
| 352 | + * @exception InvalidParameterException if the <code>keysize</code> is not | |
| 353 | + * supported by this KeyPairGenerator object. | |
| 354 | + * | |
| 355 | + * @since 1.2 | |
| 356 | + */ | |
| 357 | + public void initialize(int keysize, SecureRandom random) { | |
| 358 | + // This does nothing, because either | |
| 359 | + // 1. the implementation object returned by getInstance() is an | |
| 360 | + // instance of KeyPairGenerator which has its own | |
| 361 | + // initialize(keysize, random) method, so the application would | |
| 362 | + // be calling that method directly, or | |
| 363 | + // 2. the implementation returned by getInstance() is an instance | |
| 364 | + // of Delegate, in which case initialize(keysize, random) is | |
| 365 | + // overridden to call the corresponding SPI method. | |
| 366 | + // (This is a special case, because the API and SPI method have the | |
| 367 | + // same name.) | |
| 368 | + } | |
| 369 | + | |
| 370 | + /** | |
| 371 | + * Initializes the key pair generator using the specified parameter | |
| 372 | + * set and the <code>SecureRandom</code> | |
| 373 | + * implementation of the highest-priority installed provider as the source | |
| 374 | + * of randomness. | |
| 375 | + * (If none of the installed providers supply an implementation of | |
| 376 | + * <code>SecureRandom</code>, a system-provided source of randomness is | |
| 377 | + * used.). | |
| 378 | + * | |
| 379 | + * <p>This concrete method has been added to this previously-defined | |
| 380 | + * abstract class. | |
| 381 | + * This method calls the KeyPairGeneratorSpi | |
| 382 | + * {@link KeyPairGeneratorSpi#initialize( | |
| 383 | + * java.security.spec.AlgorithmParameterSpec, | |
| 384 | + * java.security.SecureRandom) initialize} method, | |
| 385 | + * passing it <code>params</code> and a source of randomness (obtained | |
| 386 | + * from the highest-priority installed provider or system-provided if none | |
| 387 | + * of the installed providers supply one). | |
| 388 | + * That <code>initialize</code> method always throws an | |
| 389 | + * UnsupportedOperationException if it is not overridden by the provider. | |
| 390 | + * | |
| 391 | + * @param params the parameter set used to generate the keys. | |
| 392 | + * | |
| 393 | + * @exception InvalidAlgorithmParameterException if the given parameters | |
| 394 | + * are inappropriate for this key pair generator. | |
| 395 | + * | |
| 396 | + * @since 1.2 | |
| 397 | + */ | |
| 398 | + public void initialize(AlgorithmParameterSpec params) | |
| 399 | + throws InvalidAlgorithmParameterException { | |
| 400 | + initialize(params, JCAUtil.getSecureRandom()); | |
| 401 | + } | |
| 402 | + | |
| 403 | + /** | |
| 404 | + * Initializes the key pair generator with the given parameter | |
| 405 | + * set and source of randomness. | |
| 406 | + * | |
| 407 | + * <p>This concrete method has been added to this previously-defined | |
| 408 | + * abstract class. | |
| 409 | + * This method calls the KeyPairGeneratorSpi {@link | |
| 410 | + * KeyPairGeneratorSpi#initialize( | |
| 411 | + * java.security.spec.AlgorithmParameterSpec, | |
| 412 | + * java.security.SecureRandom) initialize} method, | |
| 413 | + * passing it <code>params</code> and <code>random</code>. | |
| 414 | + * That <code>initialize</code> | |
| 415 | + * method always throws an | |
| 416 | + * UnsupportedOperationException if it is not overridden by the provider. | |
| 417 | + * | |
| 418 | + * @param params the parameter set used to generate the keys. | |
| 419 | + * @param random the source of randomness. | |
| 420 | + * | |
| 421 | + * @exception InvalidAlgorithmParameterException if the given parameters | |
| 422 | + * are inappropriate for this key pair generator. | |
| 423 | + * | |
| 424 | + * @since 1.2 | |
| 425 | + */ | |
| 426 | + public void initialize(AlgorithmParameterSpec params, | |
| 427 | + SecureRandom random) | |
| 428 | + throws InvalidAlgorithmParameterException | |
| 429 | + { | |
| 430 | + // This does nothing, because either | |
| 431 | + // 1. the implementation object returned by getInstance() is an | |
| 432 | + // instance of KeyPairGenerator which has its own | |
| 433 | + // initialize(params, random) method, so the application would | |
| 434 | + // be calling that method directly, or | |
| 435 | + // 2. the implementation returned by getInstance() is an instance | |
| 436 | + // of Delegate, in which case initialize(params, random) is | |
| 437 | + // overridden to call the corresponding SPI method. | |
| 438 | + // (This is a special case, because the API and SPI method have the | |
| 439 | + // same name.) | |
| 440 | + } | |
| 441 | + | |
| 442 | + /** | |
| 443 | + * Generates a key pair. | |
| 444 | + * | |
| 445 | + * <p>If this KeyPairGenerator has not been initialized explicitly, | |
| 446 | + * provider-specific defaults will be used for the size and other | |
| 447 | + * (algorithm-specific) values of the generated keys. | |
| 448 | + * | |
| 449 | + * <p>This will generate a new key pair every time it is called. | |
| 450 | + * | |
| 451 | + * <p>This method is functionally equivalent to | |
| 452 | + * {@link #generateKeyPair() generateKeyPair}. | |
| 453 | + * | |
| 454 | + * @return the generated key pair | |
| 455 | + * | |
| 456 | + * @since 1.2 | |
| 457 | + */ | |
| 458 | + public final KeyPair genKeyPair() { | |
| 459 | + return generateKeyPair(); | |
| 460 | + } | |
| 461 | + | |
| 462 | + /** | |
| 463 | + * Generates a key pair. | |
| 464 | + * | |
| 465 | + * <p>If this KeyPairGenerator has not been initialized explicitly, | |
| 466 | + * provider-specific defaults will be used for the size and other | |
| 467 | + * (algorithm-specific) values of the generated keys. | |
| 468 | + * | |
| 469 | + * <p>This will generate a new key pair every time it is called. | |
| 470 | + * | |
| 471 | + * <p>This method is functionally equivalent to | |
| 472 | + * {@link #genKeyPair() genKeyPair}. | |
| 473 | + * | |
| 474 | + * @return the generated key pair | |
| 475 | + */ | |
| 476 | + public KeyPair generateKeyPair() { | |
| 477 | + // This does nothing (except returning null), because either: | |
| 478 | + // | |
| 479 | + // 1. the implementation object returned by getInstance() is an | |
| 480 | + // instance of KeyPairGenerator which has its own implementation | |
| 481 | + // of generateKeyPair (overriding this one), so the application | |
| 482 | + // would be calling that method directly, or | |
| 483 | + // | |
| 484 | + // 2. the implementation returned by getInstance() is an instance | |
| 485 | + // of Delegate, in which case generateKeyPair is | |
| 486 | + // overridden to invoke the corresponding SPI method. | |
| 487 | + // | |
| 488 | + // (This is a special case, because in JDK 1.1.x the generateKeyPair | |
| 489 | + // method was used both as an API and a SPI method.) | |
| 490 | + return null; | |
| 491 | + } | |
| 492 | + | |
| 493 | + | |
| 494 | + /* | |
| 495 | + * The following class allows providers to extend from KeyPairGeneratorSpi | |
| 496 | + * rather than from KeyPairGenerator. It represents a KeyPairGenerator | |
| 497 | + * with an encapsulated, provider-supplied SPI object (of type | |
| 498 | + * KeyPairGeneratorSpi). | |
| 499 | + * If the provider implementation is an instance of KeyPairGeneratorSpi, | |
| 500 | + * the getInstance() methods above return an instance of this class, with | |
| 501 | + * the SPI object encapsulated. | |
| 502 | + * | |
| 503 | + * Note: All SPI methods from the original KeyPairGenerator class have been | |
| 504 | + * moved up the hierarchy into a new class (KeyPairGeneratorSpi), which has | |
| 505 | + * been interposed in the hierarchy between the API (KeyPairGenerator) | |
| 506 | + * and its original parent (Object). | |
| 507 | + */ | |
| 508 | + | |
| 509 | + // | |
| 510 | + // error failover notes: | |
| 511 | + // | |
| 512 | + // . we failover if the implementation throws an error during init | |
| 513 | + // by retrying the init on other providers | |
| 514 | + // | |
| 515 | + // . we also failover if the init succeeded but the subsequent call | |
| 516 | + // to generateKeyPair() fails. In order for this to work, we need | |
| 517 | + // to remember the parameters to the last successful call to init | |
| 518 | + // and initialize() the next spi using them. | |
| 519 | + // | |
| 520 | + // . although not specified, KeyPairGenerators could be thread safe, | |
| 521 | + // so we make sure we do not interfere with that | |
| 522 | + // | |
| 523 | + // . failover is not available, if: | |
| 524 | + // . getInstance(algorithm, provider) was used | |
| 525 | + // . a provider extends KeyPairGenerator rather than | |
| 526 | + // KeyPairGeneratorSpi (JDK 1.1 style) | |
| 527 | + // . once getProvider() is called | |
| 528 | + // | |
| 529 | + | |
| 530 | + private static final class Delegate extends KeyPairGenerator { | |
| 531 | + | |
| 532 | + // The provider implementation (delegate) | |
| 533 | + private volatile KeyPairGeneratorSpi spi; | |
| 534 | + | |
| 535 | + private final Object lock = new Object(); | |
| 536 | + | |
| 537 | + private Iterator<Service> serviceIterator; | |
| 538 | + | |
| 539 | + private final static int I_NONE = 1; | |
| 540 | + private final static int I_SIZE = 2; | |
| 541 | + private final static int I_PARAMS = 3; | |
| 542 | + | |
| 543 | + private int initType; | |
| 544 | + private int initKeySize; | |
| 545 | + private AlgorithmParameterSpec initParams; | |
| 546 | + private SecureRandom initRandom; | |
| 547 | + | |
| 548 | + // constructor | |
| 549 | + Delegate(KeyPairGeneratorSpi spi, String algorithm) { | |
| 550 | + super(algorithm); | |
| 551 | + this.spi = spi; | |
| 552 | + } | |
| 553 | + | |
| 554 | + Delegate(Instance instance, Iterator<Service> serviceIterator, | |
| 555 | + String algorithm) { | |
| 556 | + super(algorithm); | |
| 557 | + spi = (KeyPairGeneratorSpi)instance.impl; | |
| 558 | + provider = instance.provider; | |
| 559 | + this.serviceIterator = serviceIterator; | |
| 560 | + initType = I_NONE; | |
| 561 | + } | |
| 562 | + | |
| 563 | + /** | |
| 564 | + * Update the active spi of this class and return the next | |
| 565 | + * implementation for failover. If no more implemenations are | |
| 566 | + * available, this method returns null. However, the active spi of | |
| 567 | + * this class is never set to null. | |
| 568 | + */ | |
| 569 | + private KeyPairGeneratorSpi nextSpi(KeyPairGeneratorSpi oldSpi, | |
| 570 | + boolean reinit) { | |
| 571 | + synchronized (lock) { | |
| 572 | + // somebody else did a failover concurrently | |
| 573 | + // try that spi now | |
| 574 | + if ((oldSpi != null) && (oldSpi != spi)) { | |
| 575 | + return spi; | |
| 576 | + } | |
| 577 | + if (serviceIterator == null) { | |
| 578 | + return null; | |
| 579 | + } | |
| 580 | + while (serviceIterator.hasNext()) { | |
| 581 | + Service s = serviceIterator.next(); | |
| 582 | + try { | |
| 583 | + Object inst = s.newInstance(null); | |
| 584 | + // ignore non-spis | |
| 585 | + if (inst instanceof KeyPairGeneratorSpi == false) { | |
| 586 | + continue; | |
| 587 | + } | |
| 588 | + if (inst instanceof KeyPairGenerator) { | |
| 589 | + continue; | |
| 590 | + } | |
| 591 | + KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)inst; | |
| 592 | + if (reinit) { | |
| 593 | + if (initType == I_SIZE) { | |
| 594 | + spi.initialize(initKeySize, initRandom); | |
| 595 | + } else if (initType == I_PARAMS) { | |
| 596 | + spi.initialize(initParams, initRandom); | |
| 597 | + } else if (initType != I_NONE) { | |
| 598 | + throw new AssertionError | |
| 599 | + ("KeyPairGenerator initType: " + initType); | |
| 600 | + } | |
| 601 | + } | |
| 602 | + provider = s.getProvider(); | |
| 603 | + this.spi = spi; | |
| 604 | + return spi; | |
| 605 | + } catch (Exception e) { | |
| 606 | + // ignore | |
| 607 | + } | |
| 608 | + } | |
| 609 | + disableFailover(); | |
| 610 | + return null; | |
| 611 | + } | |
| 612 | + } | |
| 613 | + | |
| 614 | + void disableFailover() { | |
| 615 | + serviceIterator = null; | |
| 616 | + initType = 0; | |
| 617 | + initParams = null; | |
| 618 | + initRandom = null; | |
| 619 | + } | |
| 620 | + | |
| 621 | + // engine method | |
| 622 | + public void initialize(int keysize, SecureRandom random) { | |
| 623 | + if (serviceIterator == null) { | |
| 624 | + spi.initialize(keysize, random); | |
| 625 | + return; | |
| 626 | + } | |
| 627 | + RuntimeException failure = null; | |
| 628 | + KeyPairGeneratorSpi mySpi = spi; | |
| 629 | + do { | |
| 630 | + try { | |
| 631 | + mySpi.initialize(keysize, random); | |
| 632 | + initType = I_SIZE; | |
| 633 | + initKeySize = keysize; | |
| 634 | + initParams = null; | |
| 635 | + initRandom = random; | |
| 636 | + return; | |
| 637 | + } catch (RuntimeException e) { | |
| 638 | + if (failure == null) { | |
| 639 | + failure = e; | |
| 640 | + } | |
| 641 | + mySpi = nextSpi(mySpi, false); | |
| 642 | + } | |
| 643 | + } while (mySpi != null); | |
| 644 | + throw failure; | |
| 645 | + } | |
| 646 | + | |
| 647 | + // engine method | |
| 648 | + public void initialize(AlgorithmParameterSpec params, | |
| 649 | + SecureRandom random) throws InvalidAlgorithmParameterException { | |
| 650 | + if (serviceIterator == null) { | |
| 651 | + spi.initialize(params, random); | |
| 652 | + return; | |
| 653 | + } | |
| 654 | + Exception failure = null; | |
| 655 | + KeyPairGeneratorSpi mySpi = spi; | |
| 656 | + do { | |
| 657 | + try { | |
| 658 | + mySpi.initialize(params, random); | |
| 659 | + initType = I_PARAMS; | |
| 660 | + initKeySize = 0; | |
| 661 | + initParams = params; | |
| 662 | + initRandom = random; | |
| 663 | + return; | |
| 664 | + } catch (Exception e) { | |
| 665 | + if (failure == null) { | |
| 666 | + failure = e; | |
| 667 | + } | |
| 668 | + mySpi = nextSpi(mySpi, false); | |
| 669 | + } | |
| 670 | + } while (mySpi != null); | |
| 671 | + if (failure instanceof RuntimeException) { | |
| 672 | + throw (RuntimeException)failure; | |
| 673 | + } | |
| 674 | + // must be an InvalidAlgorithmParameterException | |
| 675 | + throw (InvalidAlgorithmParameterException)failure; | |
| 676 | + } | |
| 677 | + | |
| 678 | + // engine method | |
| 679 | + public KeyPair generateKeyPair() { | |
| 680 | + if (serviceIterator == null) { | |
| 681 | + return spi.generateKeyPair(); | |
| 682 | + } | |
| 683 | + RuntimeException failure = null; | |
| 684 | + KeyPairGeneratorSpi mySpi = spi; | |
| 685 | + do { | |
| 686 | + try { | |
| 687 | + return mySpi.generateKeyPair(); | |
| 688 | + } catch (RuntimeException e) { | |
| 689 | + if (failure == null) { | |
| 690 | + failure = e; | |
| 691 | + } | |
| 692 | + mySpi = nextSpi(mySpi, true); | |
| 693 | + } | |
| 694 | + } while (mySpi != null); | |
| 695 | + throw failure; | |
| 696 | + } | |
| 697 | + } | |
| 698 | + | |
| 699 | +} | |
Binary file not shown.
| @@ -0,0 +1,106 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.security.spec.AlgorithmParameterSpec; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * <p> This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) | |
| 32 | + * for the <code>KeyPairGenerator</code> class, which is used to generate | |
| 33 | + * pairs of public and private keys. | |
| 34 | + * | |
| 35 | + * <p> All the abstract methods in this class must be implemented by each | |
| 36 | + * cryptographic service provider who wishes to supply the implementation | |
| 37 | + * of a key pair generator for a particular algorithm. | |
| 38 | + * | |
| 39 | + * <p> In case the client does not explicitly initialize the KeyPairGenerator | |
| 40 | + * (via a call to an <code>initialize</code> method), each provider must | |
| 41 | + * supply (and document) a default initialization. | |
| 42 | + * For example, the <i>Sun</i> provider uses a default modulus size (keysize) | |
| 43 | + * of 1024 bits. | |
| 44 | + * | |
| 45 | + * @author Benjamin Renaud | |
| 46 | + * | |
| 47 | + * | |
| 48 | + * @see KeyPairGenerator | |
| 49 | + * @see java.security.spec.AlgorithmParameterSpec | |
| 50 | + */ | |
| 51 | + | |
| 52 | +public abstract class KeyPairGeneratorSpi { | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * Initializes the key pair generator for a certain keysize, using | |
| 56 | + * the default parameter set. | |
| 57 | + * | |
| 58 | + * @param keysize the keysize. This is an | |
| 59 | + * algorithm-specific metric, such as modulus length, specified in | |
| 60 | + * number of bits. | |
| 61 | + * | |
| 62 | + * @param random the source of randomness for this generator. | |
| 63 | + * | |
| 64 | + * @exception InvalidParameterException if the <code>keysize</code> is not | |
| 65 | + * supported by this KeyPairGeneratorSpi object. | |
| 66 | + */ | |
| 67 | + public abstract void initialize(int keysize, SecureRandom random); | |
| 68 | + | |
| 69 | + /** | |
| 70 | + * Initializes the key pair generator using the specified parameter | |
| 71 | + * set and user-provided source of randomness. | |
| 72 | + * | |
| 73 | + * <p>This concrete method has been added to this previously-defined | |
| 74 | + * abstract class. (For backwards compatibility, it cannot be abstract.) | |
| 75 | + * It may be overridden by a provider to initialize the key pair | |
| 76 | + * generator. Such an override | |
| 77 | + * is expected to throw an InvalidAlgorithmParameterException if | |
| 78 | + * a parameter is inappropriate for this key pair generator. | |
| 79 | + * If this method is not overridden, it always throws an | |
| 80 | + * UnsupportedOperationException. | |
| 81 | + * | |
| 82 | + * @param params the parameter set used to generate the keys. | |
| 83 | + * | |
| 84 | + * @param random the source of randomness for this generator. | |
| 85 | + * | |
| 86 | + * @exception InvalidAlgorithmParameterException if the given parameters | |
| 87 | + * are inappropriate for this key pair generator. | |
| 88 | + * | |
| 89 | + * @since 1.2 | |
| 90 | + */ | |
| 91 | + public void initialize(AlgorithmParameterSpec params, | |
| 92 | + SecureRandom random) | |
| 93 | + throws InvalidAlgorithmParameterException { | |
| 94 | + throw new UnsupportedOperationException(); | |
| 95 | + } | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * Generates a key pair. Unless an initialization method is called | |
| 99 | + * using a KeyPairGenerator interface, algorithm-specific defaults | |
| 100 | + * will be used. This will generate a new key pair every time it | |
| 101 | + * is called. | |
| 102 | + * | |
| 103 | + * @return the newly generated <tt>KeyPair</tt> | |
| 104 | + */ | |
| 105 | + public abstract KeyPair generateKeyPair(); | |
| 106 | +} | |
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,195 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.*; | |
| 29 | + | |
| 30 | +import java.security.spec.PKCS8EncodedKeySpec; | |
| 31 | +import java.security.spec.X509EncodedKeySpec; | |
| 32 | +import java.security.spec.InvalidKeySpecException; | |
| 33 | + | |
| 34 | +import javax.crypto.SecretKeyFactory; | |
| 35 | +import javax.crypto.spec.SecretKeySpec; | |
| 36 | + | |
| 37 | +/** | |
| 38 | + * Standardized representation for serialized Key objects. | |
| 39 | + * | |
| 40 | + * <p> | |
| 41 | + * | |
| 42 | + * Note that a serialized Key may contain sensitive information | |
| 43 | + * which should not be exposed in untrusted environments. See the | |
| 44 | + * <a href="../../../platform/serialization/spec/security.html"> | |
| 45 | + * Security Appendix</a> | |
| 46 | + * of the Serialization Specification for more information. | |
| 47 | + * | |
| 48 | + * @see Key | |
| 49 | + * @see KeyFactory | |
| 50 | + * @see javax.crypto.spec.SecretKeySpec | |
| 51 | + * @see java.security.spec.X509EncodedKeySpec | |
| 52 | + * @see java.security.spec.PKCS8EncodedKeySpec | |
| 53 | + * | |
| 54 | + * @since 1.5 | |
| 55 | + */ | |
| 56 | + | |
| 57 | +public class KeyRep implements Serializable { | |
| 58 | + | |
| 59 | + private static final long serialVersionUID = -4757683898830641853L; | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * Key type. | |
| 63 | + * | |
| 64 | + * @since 1.5 | |
| 65 | + */ | |
| 66 | + public static enum Type { | |
| 67 | + | |
| 68 | + /** Type for secret keys. */ | |
| 69 | + SECRET, | |
| 70 | + | |
| 71 | + /** Type for public keys. */ | |
| 72 | + PUBLIC, | |
| 73 | + | |
| 74 | + /** Type for private keys. */ | |
| 75 | + PRIVATE, | |
| 76 | + | |
| 77 | + } | |
| 78 | + | |
| 79 | + private static final String PKCS8 = "PKCS#8"; | |
| 80 | + private static final String X509 = "X.509"; | |
| 81 | + private static final String RAW = "RAW"; | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * Either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE | |
| 85 | + * | |
| 86 | + * @serial | |
| 87 | + */ | |
| 88 | + private Type type; | |
| 89 | + | |
| 90 | + /** | |
| 91 | + * The Key algorithm | |
| 92 | + * | |
| 93 | + * @serial | |
| 94 | + */ | |
| 95 | + private String algorithm; | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * The Key encoding format | |
| 99 | + * | |
| 100 | + * @serial | |
| 101 | + */ | |
| 102 | + private String format; | |
| 103 | + | |
| 104 | + /** | |
| 105 | + * The encoded Key bytes | |
| 106 | + * | |
| 107 | + * @serial | |
| 108 | + */ | |
| 109 | + private byte[] encoded; | |
| 110 | + | |
| 111 | + /** | |
| 112 | + * Construct the alternate Key class. | |
| 113 | + * | |
| 114 | + * <p> | |
| 115 | + * | |
| 116 | + * @param type either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE | |
| 117 | + * @param algorithm the algorithm returned from | |
| 118 | + * <code>Key.getAlgorithm()</code> | |
| 119 | + * @param format the encoding format returned from | |
| 120 | + * <code>Key.getFormat()</code> | |
| 121 | + * @param encoded the encoded bytes returned from | |
| 122 | + * <code>Key.getEncoded()</code> | |
| 123 | + * | |
| 124 | + * @exception NullPointerException | |
| 125 | + * if type is <code>null</code>, | |
| 126 | + * if algorithm is <code>null</code>, | |
| 127 | + * if format is <code>null</code>, | |
| 128 | + * or if encoded is <code>null</code> | |
| 129 | + */ | |
| 130 | + public KeyRep(Type type, String algorithm, | |
| 131 | + String format, byte[] encoded) { | |
| 132 | + | |
| 133 | + if (type == null || algorithm == null || | |
| 134 | + format == null || encoded == null) { | |
| 135 | + throw new NullPointerException("invalid null input(s)"); | |
| 136 | + } | |
| 137 | + | |
| 138 | + this.type = type; | |
| 139 | + this.algorithm = algorithm; | |
| 140 | + this.format = format.toUpperCase(); | |
| 141 | + this.encoded = encoded.clone(); | |
| 142 | + } | |
| 143 | + | |
| 144 | + /** | |
| 145 | + * Resolve the Key object. | |
| 146 | + * | |
| 147 | + * <p> This method supports three Type/format combinations: | |
| 148 | + * <ul> | |
| 149 | + * <li> Type.SECRET/"RAW" - returns a SecretKeySpec object | |
| 150 | + * constructed using encoded key bytes and algorithm | |
| 151 | + * <li> Type.PUBLIC/"X.509" - gets a KeyFactory instance for | |
| 152 | + * the key algorithm, constructs an X509EncodedKeySpec with the | |
| 153 | + * encoded key bytes, and generates a public key from the spec | |
| 154 | + * <li> Type.PRIVATE/"PKCS#8" - gets a KeyFactory instance for | |
| 155 | + * the key algorithm, constructs a PKCS8EncodedKeySpec with the | |
| 156 | + * encoded key bytes, and generates a private key from the spec | |
| 157 | + * </ul> | |
| 158 | + * | |
| 159 | + * <p> | |
| 160 | + * | |
| 161 | + * @return the resolved Key object | |
| 162 | + * | |
| 163 | + * @exception ObjectStreamException if the Type/format | |
| 164 | + * combination is unrecognized, if the algorithm, key format, or | |
| 165 | + * encoded key bytes are unrecognized/invalid, of if the | |
| 166 | + * resolution of the key fails for any reason | |
| 167 | + */ | |
| 168 | + protected Object readResolve() throws ObjectStreamException { | |
| 169 | + try { | |
| 170 | + if (type == Type.SECRET && RAW.equals(format)) { | |
| 171 | + return new SecretKeySpec(encoded, algorithm); | |
| 172 | + } else if (type == Type.PUBLIC && X509.equals(format)) { | |
| 173 | + KeyFactory f = KeyFactory.getInstance(algorithm); | |
| 174 | + return f.generatePublic(new X509EncodedKeySpec(encoded)); | |
| 175 | + } else if (type == Type.PRIVATE && PKCS8.equals(format)) { | |
| 176 | + KeyFactory f = KeyFactory.getInstance(algorithm); | |
| 177 | + return f.generatePrivate(new PKCS8EncodedKeySpec(encoded)); | |
| 178 | + } else { | |
| 179 | + throw new NotSerializableException | |
| 180 | + ("unrecognized type/format combination: " + | |
| 181 | + type + "/" + format); | |
| 182 | + } | |
| 183 | + } catch (NotSerializableException nse) { | |
| 184 | + throw nse; | |
| 185 | + } catch (Exception e) { | |
| 186 | + NotSerializableException nse = new NotSerializableException | |
| 187 | + ("java.security.Key: " + | |
| 188 | + "[" + type + "] " + | |
| 189 | + "[" + algorithm + "] " + | |
| 190 | + "[" + format + "]"); | |
| 191 | + nse.initCause(e); | |
| 192 | + throw nse; | |
| 193 | + } | |
| 194 | + } | |
| 195 | +} | |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,1769 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.*; | |
| 29 | +import java.security.cert.Certificate; | |
| 30 | +import java.security.cert.X509Certificate; | |
| 31 | +import java.security.cert.CertificateException; | |
| 32 | +import java.util.*; | |
| 33 | +import javax.crypto.SecretKey; | |
| 34 | + | |
| 35 | +import javax.security.auth.callback.*; | |
| 36 | + | |
| 37 | +/** | |
| 38 | + * This class represents a storage facility for cryptographic | |
| 39 | + * keys and certificates. | |
| 40 | + * | |
| 41 | + * <p> A <code>KeyStore</code> manages different types of entries. | |
| 42 | + * Each type of entry implements the <code>KeyStore.Entry</code> interface. | |
| 43 | + * Three basic <code>KeyStore.Entry</code> implementations are provided: | |
| 44 | + * | |
| 45 | + * <ul> | |
| 46 | + * <li><b>KeyStore.PrivateKeyEntry</b> | |
| 47 | + * <p> This type of entry holds a cryptographic <code>PrivateKey</code>, | |
| 48 | + * which is optionally stored in a protected format to prevent | |
| 49 | + * unauthorized access. It is also accompanied by a certificate chain | |
| 50 | + * for the corresponding public key. | |
| 51 | + * | |
| 52 | + * <p> Private keys and certificate chains are used by a given entity for | |
| 53 | + * self-authentication. Applications for this authentication include software | |
| 54 | + * distribution organizations which sign JAR files as part of releasing | |
| 55 | + * and/or licensing software. | |
| 56 | + * | |
| 57 | + * <li><b>KeyStore.SecretKeyEntry</b> | |
| 58 | + * <p> This type of entry holds a cryptographic <code>SecretKey</code>, | |
| 59 | + * which is optionally stored in a protected format to prevent | |
| 60 | + * unauthorized access. | |
| 61 | + * | |
| 62 | + * <li><b>KeyStore.TrustedCertificateEntry</b> | |
| 63 | + * <p> This type of entry contains a single public key <code>Certificate</code> | |
| 64 | + * belonging to another party. It is called a <i>trusted certificate</i> | |
| 65 | + * because the keystore owner trusts that the public key in the certificate | |
| 66 | + * indeed belongs to the identity identified by the <i>subject</i> (owner) | |
| 67 | + * of the certificate. | |
| 68 | + * | |
| 69 | + * <p>This type of entry can be used to authenticate other parties. | |
| 70 | + * </ul> | |
| 71 | + * | |
| 72 | + * <p> Each entry in a keystore is identified by an "alias" string. In the | |
| 73 | + * case of private keys and their associated certificate chains, these strings | |
| 74 | + * distinguish among the different ways in which the entity may authenticate | |
| 75 | + * itself. For example, the entity may authenticate itself using different | |
| 76 | + * certificate authorities, or using different public key algorithms. | |
| 77 | + * | |
| 78 | + * <p> Whether aliases are case sensitive is implementation dependent. In order | |
| 79 | + * to avoid problems, it is recommended not to use aliases in a KeyStore that | |
| 80 | + * only differ in case. | |
| 81 | + * | |
| 82 | + * <p> Whether keystores are persistent, and the mechanisms used by the | |
| 83 | + * keystore if it is persistent, are not specified here. This allows | |
| 84 | + * use of a variety of techniques for protecting sensitive (e.g., private or | |
| 85 | + * secret) keys. Smart cards or other integrated cryptographic engines | |
| 86 | + * (SafeKeyper) are one option, and simpler mechanisms such as files may also | |
| 87 | + * be used (in a variety of formats). | |
| 88 | + * | |
| 89 | + * <p> Typical ways to request a KeyStore object include | |
| 90 | + * relying on the default type and providing a specific keystore type. | |
| 91 | + * | |
| 92 | + * <ul> | |
| 93 | + * <li>To rely on the default type: | |
| 94 | + * <pre> | |
| 95 | + * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); | |
| 96 | + * </pre> | |
| 97 | + * The system will return a keystore implementation for the default type. | |
| 98 | + * <p> | |
| 99 | + * | |
| 100 | + * <li>To provide a specific keystore type: | |
| 101 | + * <pre> | |
| 102 | + * KeyStore ks = KeyStore.getInstance("JKS"); | |
| 103 | + * </pre> | |
| 104 | + * The system will return the most preferred implementation of the | |
| 105 | + * specified keystore type available in the environment. <p> | |
| 106 | + * </ul> | |
| 107 | + * | |
| 108 | + * <p> Before a keystore can be accessed, it must be | |
| 109 | + * {@link #load(java.io.InputStream, char[]) loaded}. | |
| 110 | + * <pre> | |
| 111 | + * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); | |
| 112 | + * | |
| 113 | + * // get user password and file input stream | |
| 114 | + * char[] password = getPassword(); | |
| 115 | + * | |
| 116 | + * java.io.FileInputStream fis = null; | |
| 117 | + * try { | |
| 118 | + * fis = new java.io.FileInputStream("keyStoreName"); | |
| 119 | + * ks.load(fis, password); | |
| 120 | + * } finally { | |
| 121 | + * if (fis != null) { | |
| 122 | + * fis.close(); | |
| 123 | + * } | |
| 124 | + * } | |
| 125 | + * </pre> | |
| 126 | + * | |
| 127 | + * To create an empty keystore using the above <code>load</code> method, | |
| 128 | + * pass <code>null</code> as the <code>InputStream</code> argument. | |
| 129 | + * | |
| 130 | + * <p> Once the keystore has been loaded, it is possible | |
| 131 | + * to read existing entries from the keystore, or to write new entries | |
| 132 | + * into the keystore: | |
| 133 | + * <pre> | |
| 134 | + * KeyStore.ProtectionParameter protParam = | |
| 135 | + * new KeyStore.PasswordProtection(password); | |
| 136 | + * | |
| 137 | + * // get my private key | |
| 138 | + * KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) | |
| 139 | + * ks.getEntry("privateKeyAlias", protParam); | |
| 140 | + * PrivateKey myPrivateKey = pkEntry.getPrivateKey(); | |
| 141 | + * | |
| 142 | + * // save my secret key | |
| 143 | + * javax.crypto.SecretKey mySecretKey; | |
| 144 | + * KeyStore.SecretKeyEntry skEntry = | |
| 145 | + * new KeyStore.SecretKeyEntry(mySecretKey); | |
| 146 | + * ks.setEntry("secretKeyAlias", skEntry, protParam); | |
| 147 | + * | |
| 148 | + * // store away the keystore | |
| 149 | + * java.io.FileOutputStream fos = null; | |
| 150 | + * try { | |
| 151 | + * fos = new java.io.FileOutputStream("newKeyStoreName"); | |
| 152 | + * ks.store(fos, password); | |
| 153 | + * } finally { | |
| 154 | + * if (fos != null) { | |
| 155 | + * fos.close(); | |
| 156 | + * } | |
| 157 | + * } | |
| 158 | + * </pre> | |
| 159 | + * | |
| 160 | + * Note that although the same password may be used to | |
| 161 | + * load the keystore, to protect the private key entry, | |
| 162 | + * to protect the secret key entry, and to store the keystore | |
| 163 | + * (as is shown in the sample code above), | |
| 164 | + * different passwords or other protection parameters | |
| 165 | + * may also be used. | |
| 166 | + * | |
| 167 | + * <p> Every implementation of the Java platform is required to support | |
| 168 | + * the following standard <code>KeyStore</code> type: | |
| 169 | + * <ul> | |
| 170 | + * <li><tt>PKCS12</tt></li> | |
| 171 | + * </ul> | |
| 172 | + * This type is described in the <a href= | |
| 173 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> | |
| 174 | + * KeyStore section</a> of the | |
| 175 | + * Java Cryptography Architecture Standard Algorithm Name Documentation. | |
| 176 | + * Consult the release documentation for your implementation to see if any | |
| 177 | + * other types are supported. | |
| 178 | + * | |
| 179 | + * @author Jan Luehe | |
| 180 | + * | |
| 181 | + * @see java.security.PrivateKey | |
| 182 | + * @see javax.crypto.SecretKey | |
| 183 | + * @see java.security.cert.Certificate | |
| 184 | + * | |
| 185 | + * @since 1.2 | |
| 186 | + */ | |
| 187 | + | |
| 188 | +public class KeyStore { | |
| 189 | + | |
| 190 | + /* | |
| 191 | + * Constant to lookup in the Security properties file to determine | |
| 192 | + * the default keystore type. | |
| 193 | + * In the Security properties file, the default keystore type is given as: | |
| 194 | + * <pre> | |
| 195 | + * keystore.type=jks | |
| 196 | + * </pre> | |
| 197 | + */ | |
| 198 | + private static final String KEYSTORE_TYPE = "keystore.type"; | |
| 199 | + | |
| 200 | + // The keystore type | |
| 201 | + private String type; | |
| 202 | + | |
| 203 | + // The provider | |
| 204 | + private Provider provider; | |
| 205 | + | |
| 206 | + // The provider implementation | |
| 207 | + private KeyStoreSpi keyStoreSpi; | |
| 208 | + | |
| 209 | + // Has this keystore been initialized (loaded)? | |
| 210 | + private boolean initialized = false; | |
| 211 | + | |
| 212 | + /** | |
| 213 | + * A marker interface for <code>KeyStore</code> | |
| 214 | + * {@link #load(KeyStore.LoadStoreParameter) load} | |
| 215 | + * and | |
| 216 | + * {@link #store(KeyStore.LoadStoreParameter) store} | |
| 217 | + * parameters. | |
| 218 | + * | |
| 219 | + * @since 1.5 | |
| 220 | + */ | |
| 221 | + public static interface LoadStoreParameter { | |
| 222 | + /** | |
| 223 | + * Gets the parameter used to protect keystore data. | |
| 224 | + * | |
| 225 | + * @return the parameter used to protect keystore data, or null | |
| 226 | + */ | |
| 227 | + public ProtectionParameter getProtectionParameter(); | |
| 228 | + } | |
| 229 | + | |
| 230 | + /** | |
| 231 | + * A marker interface for keystore protection parameters. | |
| 232 | + * | |
| 233 | + * <p> The information stored in a <code>ProtectionParameter</code> | |
| 234 | + * object protects the contents of a keystore. | |
| 235 | + * For example, protection parameters may be used to check | |
| 236 | + * the integrity of keystore data, or to protect the | |
| 237 | + * confidentiality of sensitive keystore data | |
| 238 | + * (such as a <code>PrivateKey</code>). | |
| 239 | + * | |
| 240 | + * @since 1.5 | |
| 241 | + */ | |
| 242 | + public static interface ProtectionParameter { } | |
| 243 | + | |
| 244 | + /** | |
| 245 | + * A password-based implementation of <code>ProtectionParameter</code>. | |
| 246 | + * | |
| 247 | + * @since 1.5 | |
| 248 | + */ | |
| 249 | + public static class PasswordProtection implements | |
| 250 | + ProtectionParameter, javax.security.auth.Destroyable { | |
| 251 | + | |
| 252 | + private final char[] password; | |
| 253 | + private volatile boolean destroyed = false; | |
| 254 | + | |
| 255 | + /** | |
| 256 | + * Creates a password parameter. | |
| 257 | + * | |
| 258 | + * <p> The specified <code>password</code> is cloned before it is stored | |
| 259 | + * in the new <code>PasswordProtection</code> object. | |
| 260 | + * | |
| 261 | + * @param password the password, which may be <code>null</code> | |
| 262 | + */ | |
| 263 | + public PasswordProtection(char[] password) { | |
| 264 | + this.password = (password == null) ? null : password.clone(); | |
| 265 | + } | |
| 266 | + | |
| 267 | + /** | |
| 268 | + * Gets the password. | |
| 269 | + * | |
| 270 | + * <p>Note that this method returns a reference to the password. | |
| 271 | + * If a clone of the array is created it is the caller's | |
| 272 | + * responsibility to zero out the password information | |
| 273 | + * after it is no longer needed. | |
| 274 | + * | |
| 275 | + * @see #destroy() | |
| 276 | + * @return the password, which may be <code>null</code> | |
| 277 | + * @exception IllegalStateException if the password has | |
| 278 | + * been cleared (destroyed) | |
| 279 | + */ | |
| 280 | + public synchronized char[] getPassword() { | |
| 281 | + if (destroyed) { | |
| 282 | + throw new IllegalStateException("password has been cleared"); | |
| 283 | + } | |
| 284 | + return password; | |
| 285 | + } | |
| 286 | + | |
| 287 | + /** | |
| 288 | + * Clears the password. | |
| 289 | + * | |
| 290 | + * @exception DestroyFailedException if this method was unable | |
| 291 | + * to clear the password | |
| 292 | + */ | |
| 293 | + public synchronized void destroy() | |
| 294 | + throws javax.security.auth.DestroyFailedException { | |
| 295 | + destroyed = true; | |
| 296 | + if (password != null) { | |
| 297 | + Arrays.fill(password, ' '); | |
| 298 | + } | |
| 299 | + } | |
| 300 | + | |
| 301 | + /** | |
| 302 | + * Determines if password has been cleared. | |
| 303 | + * | |
| 304 | + * @return true if the password has been cleared, false otherwise | |
| 305 | + */ | |
| 306 | + public synchronized boolean isDestroyed() { | |
| 307 | + return destroyed; | |
| 308 | + } | |
| 309 | + } | |
| 310 | + | |
| 311 | + /** | |
| 312 | + * A ProtectionParameter encapsulating a CallbackHandler. | |
| 313 | + * | |
| 314 | + * @since 1.5 | |
| 315 | + */ | |
| 316 | + public static class CallbackHandlerProtection | |
| 317 | + implements ProtectionParameter { | |
| 318 | + | |
| 319 | + private final CallbackHandler handler; | |
| 320 | + | |
| 321 | + /** | |
| 322 | + * Constructs a new CallbackHandlerProtection from a | |
| 323 | + * CallbackHandler. | |
| 324 | + * | |
| 325 | + * @param handler the CallbackHandler | |
| 326 | + * @exception NullPointerException if handler is null | |
| 327 | + */ | |
| 328 | + public CallbackHandlerProtection(CallbackHandler handler) { | |
| 329 | + if (handler == null) { | |
| 330 | + throw new NullPointerException("handler must not be null"); | |
| 331 | + } | |
| 332 | + this.handler = handler; | |
| 333 | + } | |
| 334 | + | |
| 335 | + /** | |
| 336 | + * Returns the CallbackHandler. | |
| 337 | + * | |
| 338 | + * @return the CallbackHandler. | |
| 339 | + */ | |
| 340 | + public CallbackHandler getCallbackHandler() { | |
| 341 | + return handler; | |
| 342 | + } | |
| 343 | + | |
| 344 | + } | |
| 345 | + | |
| 346 | + /** | |
| 347 | + * A marker interface for <code>KeyStore</code> entry types. | |
| 348 | + * | |
| 349 | + * @since 1.5 | |
| 350 | + */ | |
| 351 | + public static interface Entry { } | |
| 352 | + | |
| 353 | + /** | |
| 354 | + * A <code>KeyStore</code> entry that holds a <code>PrivateKey</code> | |
| 355 | + * and corresponding certificate chain. | |
| 356 | + * | |
| 357 | + * @since 1.5 | |
| 358 | + */ | |
| 359 | + public static final class PrivateKeyEntry implements Entry { | |
| 360 | + | |
| 361 | + private final PrivateKey privKey; | |
| 362 | + private final Certificate[] chain; | |
| 363 | + | |
| 364 | + /** | |
| 365 | + * Constructs a <code>PrivateKeyEntry</code> with a | |
| 366 | + * <code>PrivateKey</code> and corresponding certificate chain. | |
| 367 | + * | |
| 368 | + * <p> The specified <code>chain</code> is cloned before it is stored | |
| 369 | + * in the new <code>PrivateKeyEntry</code> object. | |
| 370 | + * | |
| 371 | + * @param privateKey the <code>PrivateKey</code> | |
| 372 | + * @param chain an array of <code>Certificate</code>s | |
| 373 | + * representing the certificate chain. | |
| 374 | + * The chain must be ordered and contain a | |
| 375 | + * <code>Certificate</code> at index 0 | |
| 376 | + * corresponding to the private key. | |
| 377 | + * | |
| 378 | + * @exception NullPointerException if | |
| 379 | + * <code>privateKey</code> or <code>chain</code> | |
| 380 | + * is <code>null</code> | |
| 381 | + * @exception IllegalArgumentException if the specified chain has a | |
| 382 | + * length of 0, if the specified chain does not contain | |
| 383 | + * <code>Certificate</code>s of the same type, | |
| 384 | + * or if the <code>PrivateKey</code> algorithm | |
| 385 | + * does not match the algorithm of the <code>PublicKey</code> | |
| 386 | + * in the end entity <code>Certificate</code> (at index 0) | |
| 387 | + */ | |
| 388 | + public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain) { | |
| 389 | + if (privateKey == null || chain == null) { | |
| 390 | + throw new NullPointerException("invalid null input"); | |
| 391 | + } | |
| 392 | + if (chain.length == 0) { | |
| 393 | + throw new IllegalArgumentException | |
| 394 | + ("invalid zero-length input chain"); | |
| 395 | + } | |
| 396 | + | |
| 397 | + Certificate[] clonedChain = chain.clone(); | |
| 398 | + String certType = clonedChain[0].getType(); | |
| 399 | + for (int i = 1; i < clonedChain.length; i++) { | |
| 400 | + if (!certType.equals(clonedChain[i].getType())) { | |
| 401 | + throw new IllegalArgumentException | |
| 402 | + ("chain does not contain certificates " + | |
| 403 | + "of the same type"); | |
| 404 | + } | |
| 405 | + } | |
| 406 | + if (!privateKey.getAlgorithm().equals | |
| 407 | + (clonedChain[0].getPublicKey().getAlgorithm())) { | |
| 408 | + throw new IllegalArgumentException | |
| 409 | + ("private key algorithm does not match " + | |
| 410 | + "algorithm of public key in end entity " + | |
| 411 | + "certificate (at index 0)"); | |
| 412 | + } | |
| 413 | + this.privKey = privateKey; | |
| 414 | + | |
| 415 | + if (clonedChain[0] instanceof X509Certificate && | |
| 416 | + !(clonedChain instanceof X509Certificate[])) { | |
| 417 | + | |
| 418 | + this.chain = new X509Certificate[clonedChain.length]; | |
| 419 | + System.arraycopy(clonedChain, 0, | |
| 420 | + this.chain, 0, clonedChain.length); | |
| 421 | + } else { | |
| 422 | + this.chain = clonedChain; | |
| 423 | + } | |
| 424 | + } | |
| 425 | + | |
| 426 | + /** | |
| 427 | + * Gets the <code>PrivateKey</code> from this entry. | |
| 428 | + * | |
| 429 | + * @return the <code>PrivateKey</code> from this entry | |
| 430 | + */ | |
| 431 | + public PrivateKey getPrivateKey() { | |
| 432 | + return privKey; | |
| 433 | + } | |
| 434 | + | |
| 435 | + /** | |
| 436 | + * Gets the <code>Certificate</code> chain from this entry. | |
| 437 | + * | |
| 438 | + * <p> The stored chain is cloned before being returned. | |
| 439 | + * | |
| 440 | + * @return an array of <code>Certificate</code>s corresponding | |
| 441 | + * to the certificate chain for the public key. | |
| 442 | + * If the certificates are of type X.509, | |
| 443 | + * the runtime type of the returned array is | |
| 444 | + * <code>X509Certificate[]</code>. | |
| 445 | + */ | |
| 446 | + public Certificate[] getCertificateChain() { | |
| 447 | + return chain.clone(); | |
| 448 | + } | |
| 449 | + | |
| 450 | + /** | |
| 451 | + * Gets the end entity <code>Certificate</code> | |
| 452 | + * from the certificate chain in this entry. | |
| 453 | + * | |
| 454 | + * @return the end entity <code>Certificate</code> (at index 0) | |
| 455 | + * from the certificate chain in this entry. | |
| 456 | + * If the certificate is of type X.509, | |
| 457 | + * the runtime type of the returned certificate is | |
| 458 | + * <code>X509Certificate</code>. | |
| 459 | + */ | |
| 460 | + public Certificate getCertificate() { | |
| 461 | + return chain[0]; | |
| 462 | + } | |
| 463 | + | |
| 464 | + /** | |
| 465 | + * Returns a string representation of this PrivateKeyEntry. | |
| 466 | + * @return a string representation of this PrivateKeyEntry. | |
| 467 | + */ | |
| 468 | + public String toString() { | |
| 469 | + StringBuilder sb = new StringBuilder(); | |
| 470 | + sb.append("Private key entry and certificate chain with " | |
| 471 | + + chain.length + " elements:\r\n"); | |
| 472 | + for (Certificate cert : chain) { | |
| 473 | + sb.append(cert); | |
| 474 | + sb.append("\r\n"); | |
| 475 | + } | |
| 476 | + return sb.toString(); | |
| 477 | + } | |
| 478 | + | |
| 479 | + } | |
| 480 | + | |
| 481 | + /** | |
| 482 | + * A <code>KeyStore</code> entry that holds a <code>SecretKey</code>. | |
| 483 | + * | |
| 484 | + * @since 1.5 | |
| 485 | + */ | |
| 486 | + public static final class SecretKeyEntry implements Entry { | |
| 487 | + | |
| 488 | + private final SecretKey sKey; | |
| 489 | + | |
| 490 | + /** | |
| 491 | + * Constructs a <code>SecretKeyEntry</code> with a | |
| 492 | + * <code>SecretKey</code>. | |
| 493 | + * | |
| 494 | + * @param secretKey the <code>SecretKey</code> | |
| 495 | + * | |
| 496 | + * @exception NullPointerException if <code>secretKey</code> | |
| 497 | + * is <code>null</code> | |
| 498 | + */ | |
| 499 | + public SecretKeyEntry(SecretKey secretKey) { | |
| 500 | + if (secretKey == null) { | |
| 501 | + throw new NullPointerException("invalid null input"); | |
| 502 | + } | |
| 503 | + this.sKey = secretKey; | |
| 504 | + } | |
| 505 | + | |
| 506 | + /** | |
| 507 | + * Gets the <code>SecretKey</code> from this entry. | |
| 508 | + * | |
| 509 | + * @return the <code>SecretKey</code> from this entry | |
| 510 | + */ | |
| 511 | + public SecretKey getSecretKey() { | |
| 512 | + return sKey; | |
| 513 | + } | |
| 514 | + | |
| 515 | + /** | |
| 516 | + * Returns a string representation of this SecretKeyEntry. | |
| 517 | + * @return a string representation of this SecretKeyEntry. | |
| 518 | + */ | |
| 519 | + public String toString() { | |
| 520 | + return "Secret key entry with algorithm " + sKey.getAlgorithm(); | |
| 521 | + } | |
| 522 | + } | |
| 523 | + | |
| 524 | + /** | |
| 525 | + * A <code>KeyStore</code> entry that holds a trusted | |
| 526 | + * <code>Certificate</code>. | |
| 527 | + * | |
| 528 | + * @since 1.5 | |
| 529 | + */ | |
| 530 | + public static final class TrustedCertificateEntry implements Entry { | |
| 531 | + | |
| 532 | + private final Certificate cert; | |
| 533 | + | |
| 534 | + /** | |
| 535 | + * Constructs a <code>TrustedCertificateEntry</code> with a | |
| 536 | + * trusted <code>Certificate</code>. | |
| 537 | + * | |
| 538 | + * @param trustedCert the trusted <code>Certificate</code> | |
| 539 | + * | |
| 540 | + * @exception NullPointerException if | |
| 541 | + * <code>trustedCert</code> is <code>null</code> | |
| 542 | + */ | |
| 543 | + public TrustedCertificateEntry(Certificate trustedCert) { | |
| 544 | + if (trustedCert == null) { | |
| 545 | + throw new NullPointerException("invalid null input"); | |
| 546 | + } | |
| 547 | + this.cert = trustedCert; | |
| 548 | + } | |
| 549 | + | |
| 550 | + /** | |
| 551 | + * Gets the trusted <code>Certficate</code> from this entry. | |
| 552 | + * | |
| 553 | + * @return the trusted <code>Certificate</code> from this entry | |
| 554 | + */ | |
| 555 | + public Certificate getTrustedCertificate() { | |
| 556 | + return cert; | |
| 557 | + } | |
| 558 | + | |
| 559 | + /** | |
| 560 | + * Returns a string representation of this TrustedCertificateEntry. | |
| 561 | + * @return a string representation of this TrustedCertificateEntry. | |
| 562 | + */ | |
| 563 | + public String toString() { | |
| 564 | + return "Trusted certificate entry:\r\n" + cert.toString(); | |
| 565 | + } | |
| 566 | + } | |
| 567 | + | |
| 568 | + /** | |
| 569 | + * Creates a KeyStore object of the given type, and encapsulates the given | |
| 570 | + * provider implementation (SPI object) in it. | |
| 571 | + * | |
| 572 | + * @param keyStoreSpi the provider implementation. | |
| 573 | + * @param provider the provider. | |
| 574 | + * @param type the keystore type. | |
| 575 | + */ | |
| 576 | + protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type) | |
| 577 | + { | |
| 578 | + this.keyStoreSpi = keyStoreSpi; | |
| 579 | + this.provider = provider; | |
| 580 | + this.type = type; | |
| 581 | + } | |
| 582 | + | |
| 583 | + /** | |
| 584 | + * Returns a keystore object of the specified type. | |
| 585 | + * | |
| 586 | + * <p> This method traverses the list of registered security Providers, | |
| 587 | + * starting with the most preferred Provider. | |
| 588 | + * A new KeyStore object encapsulating the | |
| 589 | + * KeyStoreSpi implementation from the first | |
| 590 | + * Provider that supports the specified type is returned. | |
| 591 | + * | |
| 592 | + * <p> Note that the list of registered providers may be retrieved via | |
| 593 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 594 | + * | |
| 595 | + * @param type the type of keystore. | |
| 596 | + * See the KeyStore section in the <a href= | |
| 597 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> | |
| 598 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 599 | + * for information about standard keystore types. | |
| 600 | + * | |
| 601 | + * @return a keystore object of the specified type. | |
| 602 | + * | |
| 603 | + * @exception KeyStoreException if no Provider supports a | |
| 604 | + * KeyStoreSpi implementation for the | |
| 605 | + * specified type. | |
| 606 | + * | |
| 607 | + * @see Provider | |
| 608 | + */ | |
| 609 | + public static KeyStore getInstance(String type) | |
| 610 | + throws KeyStoreException | |
| 611 | + { | |
| 612 | + try { | |
| 613 | + Object[] objs = Security.getImpl(type, "KeyStore", (String)null); | |
| 614 | + return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); | |
| 615 | + } catch (NoSuchAlgorithmException nsae) { | |
| 616 | + throw new KeyStoreException(type + " not found", nsae); | |
| 617 | + } catch (NoSuchProviderException nspe) { | |
| 618 | + throw new KeyStoreException(type + " not found", nspe); | |
| 619 | + } | |
| 620 | + } | |
| 621 | + | |
| 622 | + /** | |
| 623 | + * Returns a keystore object of the specified type. | |
| 624 | + * | |
| 625 | + * <p> A new KeyStore object encapsulating the | |
| 626 | + * KeyStoreSpi implementation from the specified provider | |
| 627 | + * is returned. The specified provider must be registered | |
| 628 | + * in the security provider list. | |
| 629 | + * | |
| 630 | + * <p> Note that the list of registered providers may be retrieved via | |
| 631 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 632 | + * | |
| 633 | + * @param type the type of keystore. | |
| 634 | + * See the KeyStore section in the <a href= | |
| 635 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> | |
| 636 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 637 | + * for information about standard keystore types. | |
| 638 | + * | |
| 639 | + * @param provider the name of the provider. | |
| 640 | + * | |
| 641 | + * @return a keystore object of the specified type. | |
| 642 | + * | |
| 643 | + * @exception KeyStoreException if a KeyStoreSpi | |
| 644 | + * implementation for the specified type is not | |
| 645 | + * available from the specified provider. | |
| 646 | + * | |
| 647 | + * @exception NoSuchProviderException if the specified provider is not | |
| 648 | + * registered in the security provider list. | |
| 649 | + * | |
| 650 | + * @exception IllegalArgumentException if the provider name is null | |
| 651 | + * or empty. | |
| 652 | + * | |
| 653 | + * @see Provider | |
| 654 | + */ | |
| 655 | + public static KeyStore getInstance(String type, String provider) | |
| 656 | + throws KeyStoreException, NoSuchProviderException | |
| 657 | + { | |
| 658 | + if (provider == null || provider.length() == 0) | |
| 659 | + throw new IllegalArgumentException("missing provider"); | |
| 660 | + try { | |
| 661 | + Object[] objs = Security.getImpl(type, "KeyStore", provider); | |
| 662 | + return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); | |
| 663 | + } catch (NoSuchAlgorithmException nsae) { | |
| 664 | + throw new KeyStoreException(type + " not found", nsae); | |
| 665 | + } | |
| 666 | + } | |
| 667 | + | |
| 668 | + /** | |
| 669 | + * Returns a keystore object of the specified type. | |
| 670 | + * | |
| 671 | + * <p> A new KeyStore object encapsulating the | |
| 672 | + * KeyStoreSpi implementation from the specified Provider | |
| 673 | + * object is returned. Note that the specified Provider object | |
| 674 | + * does not have to be registered in the provider list. | |
| 675 | + * | |
| 676 | + * @param type the type of keystore. | |
| 677 | + * See the KeyStore section in the <a href= | |
| 678 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> | |
| 679 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 680 | + * for information about standard keystore types. | |
| 681 | + * | |
| 682 | + * @param provider the provider. | |
| 683 | + * | |
| 684 | + * @return a keystore object of the specified type. | |
| 685 | + * | |
| 686 | + * @exception KeyStoreException if KeyStoreSpi | |
| 687 | + * implementation for the specified type is not available | |
| 688 | + * from the specified Provider object. | |
| 689 | + * | |
| 690 | + * @exception IllegalArgumentException if the specified provider is null. | |
| 691 | + * | |
| 692 | + * @see Provider | |
| 693 | + * | |
| 694 | + * @since 1.4 | |
| 695 | + */ | |
| 696 | + public static KeyStore getInstance(String type, Provider provider) | |
| 697 | + throws KeyStoreException | |
| 698 | + { | |
| 699 | + if (provider == null) | |
| 700 | + throw new IllegalArgumentException("missing provider"); | |
| 701 | + try { | |
| 702 | + Object[] objs = Security.getImpl(type, "KeyStore", provider); | |
| 703 | + return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); | |
| 704 | + } catch (NoSuchAlgorithmException nsae) { | |
| 705 | + throw new KeyStoreException(type + " not found", nsae); | |
| 706 | + } | |
| 707 | + } | |
| 708 | + | |
| 709 | + /** | |
| 710 | + * Returns the default keystore type as specified in the Java security | |
| 711 | + * properties file, or the string | |
| 712 | + * "jks" (acronym for "Java keystore") | |
| 713 | + * if no such property exists. | |
| 714 | + * The Java security properties file is located in the file named | |
| 715 | + * <JAVA_HOME>/lib/security/java.security. | |
| 716 | + * <JAVA_HOME> refers to the value of the java.home system property, | |
| 717 | + * and specifies the directory where the JRE is installed. | |
| 718 | + * | |
| 719 | + * <p>The default keystore type can be used by applications that do not | |
| 720 | + * want to use a hard-coded keystore type when calling one of the | |
| 721 | + * <code>getInstance</code> methods, and want to provide a default keystore | |
| 722 | + * type in case a user does not specify its own. | |
| 723 | + * | |
| 724 | + * <p>The default keystore type can be changed by setting the value of the | |
| 725 | + * "keystore.type" security property (in the Java security properties | |
| 726 | + * file) to the desired keystore type. | |
| 727 | + * | |
| 728 | + * @return the default keystore type as specified in the | |
| 729 | + * Java security properties file, or the string "jks" | |
| 730 | + * if no such property exists. | |
| 731 | + */ | |
| 732 | + public final static String getDefaultType() { | |
| 733 | + String kstype; | |
| 734 | + kstype = AccessController.doPrivileged(new PrivilegedAction<String>() { | |
| 735 | + public String run() { | |
| 736 | + return Security.getProperty(KEYSTORE_TYPE); | |
| 737 | + } | |
| 738 | + }); | |
| 739 | + if (kstype == null) { | |
| 740 | + kstype = "jks"; | |
| 741 | + } | |
| 742 | + return kstype; | |
| 743 | + } | |
| 744 | + | |
| 745 | + /** | |
| 746 | + * Returns the provider of this keystore. | |
| 747 | + * | |
| 748 | + * @return the provider of this keystore. | |
| 749 | + */ | |
| 750 | + public final Provider getProvider() | |
| 751 | + { | |
| 752 | + return this.provider; | |
| 753 | + } | |
| 754 | + | |
| 755 | + /** | |
| 756 | + * Returns the type of this keystore. | |
| 757 | + * | |
| 758 | + * @return the type of this keystore. | |
| 759 | + */ | |
| 760 | + public final String getType() | |
| 761 | + { | |
| 762 | + return this.type; | |
| 763 | + } | |
| 764 | + | |
| 765 | + /** | |
| 766 | + * Returns the key associated with the given alias, using the given | |
| 767 | + * password to recover it. The key must have been associated with | |
| 768 | + * the alias by a call to <code>setKeyEntry</code>, | |
| 769 | + * or by a call to <code>setEntry</code> with a | |
| 770 | + * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>. | |
| 771 | + * | |
| 772 | + * @param alias the alias name | |
| 773 | + * @param password the password for recovering the key | |
| 774 | + * | |
| 775 | + * @return the requested key, or null if the given alias does not exist | |
| 776 | + * or does not identify a key-related entry. | |
| 777 | + * | |
| 778 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 779 | + * (loaded). | |
| 780 | + * @exception NoSuchAlgorithmException if the algorithm for recovering the | |
| 781 | + * key cannot be found | |
| 782 | + * @exception UnrecoverableKeyException if the key cannot be recovered | |
| 783 | + * (e.g., the given password is wrong). | |
| 784 | + */ | |
| 785 | + public final Key getKey(String alias, char[] password) | |
| 786 | + throws KeyStoreException, NoSuchAlgorithmException, | |
| 787 | + UnrecoverableKeyException | |
| 788 | + { | |
| 789 | + if (!initialized) { | |
| 790 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 791 | + } | |
| 792 | + return keyStoreSpi.engineGetKey(alias, password); | |
| 793 | + } | |
| 794 | + | |
| 795 | + /** | |
| 796 | + * Returns the certificate chain associated with the given alias. | |
| 797 | + * The certificate chain must have been associated with the alias | |
| 798 | + * by a call to <code>setKeyEntry</code>, | |
| 799 | + * or by a call to <code>setEntry</code> with a | |
| 800 | + * <code>PrivateKeyEntry</code>. | |
| 801 | + * | |
| 802 | + * @param alias the alias name | |
| 803 | + * | |
| 804 | + * @return the certificate chain (ordered with the user's certificate first | |
| 805 | + * followed by zero or more certificate authorities), or null if the given alias | |
| 806 | + * does not exist or does not contain a certificate chain | |
| 807 | + * | |
| 808 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 809 | + * (loaded). | |
| 810 | + */ | |
| 811 | + public final Certificate[] getCertificateChain(String alias) | |
| 812 | + throws KeyStoreException | |
| 813 | + { | |
| 814 | + if (!initialized) { | |
| 815 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 816 | + } | |
| 817 | + return keyStoreSpi.engineGetCertificateChain(alias); | |
| 818 | + } | |
| 819 | + | |
| 820 | + /** | |
| 821 | + * Returns the certificate associated with the given alias. | |
| 822 | + * | |
| 823 | + * <p> If the given alias name identifies an entry | |
| 824 | + * created by a call to <code>setCertificateEntry</code>, | |
| 825 | + * or created by a call to <code>setEntry</code> with a | |
| 826 | + * <code>TrustedCertificateEntry</code>, | |
| 827 | + * then the trusted certificate contained in that entry is returned. | |
| 828 | + * | |
| 829 | + * <p> If the given alias name identifies an entry | |
| 830 | + * created by a call to <code>setKeyEntry</code>, | |
| 831 | + * or created by a call to <code>setEntry</code> with a | |
| 832 | + * <code>PrivateKeyEntry</code>, | |
| 833 | + * then the first element of the certificate chain in that entry | |
| 834 | + * is returned. | |
| 835 | + * | |
| 836 | + * @param alias the alias name | |
| 837 | + * | |
| 838 | + * @return the certificate, or null if the given alias does not exist or | |
| 839 | + * does not contain a certificate. | |
| 840 | + * | |
| 841 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 842 | + * (loaded). | |
| 843 | + */ | |
| 844 | + public final Certificate getCertificate(String alias) | |
| 845 | + throws KeyStoreException | |
| 846 | + { | |
| 847 | + if (!initialized) { | |
| 848 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 849 | + } | |
| 850 | + return keyStoreSpi.engineGetCertificate(alias); | |
| 851 | + } | |
| 852 | + | |
| 853 | + /** | |
| 854 | + * Returns the creation date of the entry identified by the given alias. | |
| 855 | + * | |
| 856 | + * @param alias the alias name | |
| 857 | + * | |
| 858 | + * @return the creation date of this entry, or null if the given alias does | |
| 859 | + * not exist | |
| 860 | + * | |
| 861 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 862 | + * (loaded). | |
| 863 | + */ | |
| 864 | + public final Date getCreationDate(String alias) | |
| 865 | + throws KeyStoreException | |
| 866 | + { | |
| 867 | + if (!initialized) { | |
| 868 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 869 | + } | |
| 870 | + return keyStoreSpi.engineGetCreationDate(alias); | |
| 871 | + } | |
| 872 | + | |
| 873 | + /** | |
| 874 | + * Assigns the given key to the given alias, protecting it with the given | |
| 875 | + * password. | |
| 876 | + * | |
| 877 | + * <p>If the given key is of type <code>java.security.PrivateKey</code>, | |
| 878 | + * it must be accompanied by a certificate chain certifying the | |
| 879 | + * corresponding public key. | |
| 880 | + * | |
| 881 | + * <p>If the given alias already exists, the keystore information | |
| 882 | + * associated with it is overridden by the given key (and possibly | |
| 883 | + * certificate chain). | |
| 884 | + * | |
| 885 | + * @param alias the alias name | |
| 886 | + * @param key the key to be associated with the alias | |
| 887 | + * @param password the password to protect the key | |
| 888 | + * @param chain the certificate chain for the corresponding public | |
| 889 | + * key (only required if the given key is of type | |
| 890 | + * <code>java.security.PrivateKey</code>). | |
| 891 | + * | |
| 892 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 893 | + * (loaded), the given key cannot be protected, or this operation fails | |
| 894 | + * for some other reason | |
| 895 | + */ | |
| 896 | + public final void setKeyEntry(String alias, Key key, char[] password, | |
| 897 | + Certificate[] chain) | |
| 898 | + throws KeyStoreException | |
| 899 | + { | |
| 900 | + if (!initialized) { | |
| 901 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 902 | + } | |
| 903 | + if ((key instanceof PrivateKey) && | |
| 904 | + (chain == null || chain.length == 0)) { | |
| 905 | + throw new IllegalArgumentException("Private key must be " | |
| 906 | + + "accompanied by certificate " | |
| 907 | + + "chain"); | |
| 908 | + } | |
| 909 | + keyStoreSpi.engineSetKeyEntry(alias, key, password, chain); | |
| 910 | + } | |
| 911 | + | |
| 912 | + /** | |
| 913 | + * Assigns the given key (that has already been protected) to the given | |
| 914 | + * alias. | |
| 915 | + * | |
| 916 | + * <p>If the protected key is of type | |
| 917 | + * <code>java.security.PrivateKey</code>, it must be accompanied by a | |
| 918 | + * certificate chain certifying the corresponding public key. If the | |
| 919 | + * underlying keystore implementation is of type <code>jks</code>, | |
| 920 | + * <code>key</code> must be encoded as an | |
| 921 | + * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard. | |
| 922 | + * | |
| 923 | + * <p>If the given alias already exists, the keystore information | |
| 924 | + * associated with it is overridden by the given key (and possibly | |
| 925 | + * certificate chain). | |
| 926 | + * | |
| 927 | + * @param alias the alias name | |
| 928 | + * @param key the key (in protected format) to be associated with the alias | |
| 929 | + * @param chain the certificate chain for the corresponding public | |
| 930 | + * key (only useful if the protected key is of type | |
| 931 | + * <code>java.security.PrivateKey</code>). | |
| 932 | + * | |
| 933 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 934 | + * (loaded), or if this operation fails for some other reason. | |
| 935 | + */ | |
| 936 | + public final void setKeyEntry(String alias, byte[] key, | |
| 937 | + Certificate[] chain) | |
| 938 | + throws KeyStoreException | |
| 939 | + { | |
| 940 | + if (!initialized) { | |
| 941 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 942 | + } | |
| 943 | + keyStoreSpi.engineSetKeyEntry(alias, key, chain); | |
| 944 | + } | |
| 945 | + | |
| 946 | + /** | |
| 947 | + * Assigns the given trusted certificate to the given alias. | |
| 948 | + * | |
| 949 | + * <p> If the given alias identifies an existing entry | |
| 950 | + * created by a call to <code>setCertificateEntry</code>, | |
| 951 | + * or created by a call to <code>setEntry</code> with a | |
| 952 | + * <code>TrustedCertificateEntry</code>, | |
| 953 | + * the trusted certificate in the existing entry | |
| 954 | + * is overridden by the given certificate. | |
| 955 | + * | |
| 956 | + * @param alias the alias name | |
| 957 | + * @param cert the certificate | |
| 958 | + * | |
| 959 | + * @exception KeyStoreException if the keystore has not been initialized, | |
| 960 | + * or the given alias already exists and does not identify an | |
| 961 | + * entry containing a trusted certificate, | |
| 962 | + * or this operation fails for some other reason. | |
| 963 | + */ | |
| 964 | + public final void setCertificateEntry(String alias, Certificate cert) | |
| 965 | + throws KeyStoreException | |
| 966 | + { | |
| 967 | + if (!initialized) { | |
| 968 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 969 | + } | |
| 970 | + keyStoreSpi.engineSetCertificateEntry(alias, cert); | |
| 971 | + } | |
| 972 | + | |
| 973 | + /** | |
| 974 | + * Deletes the entry identified by the given alias from this keystore. | |
| 975 | + * | |
| 976 | + * @param alias the alias name | |
| 977 | + * | |
| 978 | + * @exception KeyStoreException if the keystore has not been initialized, | |
| 979 | + * or if the entry cannot be removed. | |
| 980 | + */ | |
| 981 | + public final void deleteEntry(String alias) | |
| 982 | + throws KeyStoreException | |
| 983 | + { | |
| 984 | + if (!initialized) { | |
| 985 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 986 | + } | |
| 987 | + keyStoreSpi.engineDeleteEntry(alias); | |
| 988 | + } | |
| 989 | + | |
| 990 | + /** | |
| 991 | + * Lists all the alias names of this keystore. | |
| 992 | + * | |
| 993 | + * @return enumeration of the alias names | |
| 994 | + * | |
| 995 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 996 | + * (loaded). | |
| 997 | + */ | |
| 998 | + public final Enumeration<String> aliases() | |
| 999 | + throws KeyStoreException | |
| 1000 | + { | |
| 1001 | + if (!initialized) { | |
| 1002 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 1003 | + } | |
| 1004 | + return keyStoreSpi.engineAliases(); | |
| 1005 | + } | |
| 1006 | + | |
| 1007 | + /** | |
| 1008 | + * Checks if the given alias exists in this keystore. | |
| 1009 | + * | |
| 1010 | + * @param alias the alias name | |
| 1011 | + * | |
| 1012 | + * @return true if the alias exists, false otherwise | |
| 1013 | + * | |
| 1014 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 1015 | + * (loaded). | |
| 1016 | + */ | |
| 1017 | + public final boolean containsAlias(String alias) | |
| 1018 | + throws KeyStoreException | |
| 1019 | + { | |
| 1020 | + if (!initialized) { | |
| 1021 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 1022 | + } | |
| 1023 | + return keyStoreSpi.engineContainsAlias(alias); | |
| 1024 | + } | |
| 1025 | + | |
| 1026 | + /** | |
| 1027 | + * Retrieves the number of entries in this keystore. | |
| 1028 | + * | |
| 1029 | + * @return the number of entries in this keystore | |
| 1030 | + * | |
| 1031 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 1032 | + * (loaded). | |
| 1033 | + */ | |
| 1034 | + public final int size() | |
| 1035 | + throws KeyStoreException | |
| 1036 | + { | |
| 1037 | + if (!initialized) { | |
| 1038 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 1039 | + } | |
| 1040 | + return keyStoreSpi.engineSize(); | |
| 1041 | + } | |
| 1042 | + | |
| 1043 | + /** | |
| 1044 | + * Returns true if the entry identified by the given alias | |
| 1045 | + * was created by a call to <code>setKeyEntry</code>, | |
| 1046 | + * or created by a call to <code>setEntry</code> with a | |
| 1047 | + * <code>PrivateKeyEntry</code> or a <code>SecretKeyEntry</code>. | |
| 1048 | + * | |
| 1049 | + * @param alias the alias for the keystore entry to be checked | |
| 1050 | + * | |
| 1051 | + * @return true if the entry identified by the given alias is a | |
| 1052 | + * key-related entry, false otherwise. | |
| 1053 | + * | |
| 1054 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 1055 | + * (loaded). | |
| 1056 | + */ | |
| 1057 | + public final boolean isKeyEntry(String alias) | |
| 1058 | + throws KeyStoreException | |
| 1059 | + { | |
| 1060 | + if (!initialized) { | |
| 1061 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 1062 | + } | |
| 1063 | + return keyStoreSpi.engineIsKeyEntry(alias); | |
| 1064 | + } | |
| 1065 | + | |
| 1066 | + /** | |
| 1067 | + * Returns true if the entry identified by the given alias | |
| 1068 | + * was created by a call to <code>setCertificateEntry</code>, | |
| 1069 | + * or created by a call to <code>setEntry</code> with a | |
| 1070 | + * <code>TrustedCertificateEntry</code>. | |
| 1071 | + * | |
| 1072 | + * @param alias the alias for the keystore entry to be checked | |
| 1073 | + * | |
| 1074 | + * @return true if the entry identified by the given alias contains a | |
| 1075 | + * trusted certificate, false otherwise. | |
| 1076 | + * | |
| 1077 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 1078 | + * (loaded). | |
| 1079 | + */ | |
| 1080 | + public final boolean isCertificateEntry(String alias) | |
| 1081 | + throws KeyStoreException | |
| 1082 | + { | |
| 1083 | + if (!initialized) { | |
| 1084 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 1085 | + } | |
| 1086 | + return keyStoreSpi.engineIsCertificateEntry(alias); | |
| 1087 | + } | |
| 1088 | + | |
| 1089 | + /** | |
| 1090 | + * Returns the (alias) name of the first keystore entry whose certificate | |
| 1091 | + * matches the given certificate. | |
| 1092 | + * | |
| 1093 | + * <p> This method attempts to match the given certificate with each | |
| 1094 | + * keystore entry. If the entry being considered was | |
| 1095 | + * created by a call to <code>setCertificateEntry</code>, | |
| 1096 | + * or created by a call to <code>setEntry</code> with a | |
| 1097 | + * <code>TrustedCertificateEntry</code>, | |
| 1098 | + * then the given certificate is compared to that entry's certificate. | |
| 1099 | + * | |
| 1100 | + * <p> If the entry being considered was | |
| 1101 | + * created by a call to <code>setKeyEntry</code>, | |
| 1102 | + * or created by a call to <code>setEntry</code> with a | |
| 1103 | + * <code>PrivateKeyEntry</code>, | |
| 1104 | + * then the given certificate is compared to the first | |
| 1105 | + * element of that entry's certificate chain. | |
| 1106 | + * | |
| 1107 | + * @param cert the certificate to match with. | |
| 1108 | + * | |
| 1109 | + * @return the alias name of the first entry with a matching certificate, | |
| 1110 | + * or null if no such entry exists in this keystore. | |
| 1111 | + * | |
| 1112 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 1113 | + * (loaded). | |
| 1114 | + */ | |
| 1115 | + public final String getCertificateAlias(Certificate cert) | |
| 1116 | + throws KeyStoreException | |
| 1117 | + { | |
| 1118 | + if (!initialized) { | |
| 1119 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 1120 | + } | |
| 1121 | + return keyStoreSpi.engineGetCertificateAlias(cert); | |
| 1122 | + } | |
| 1123 | + | |
| 1124 | + /** | |
| 1125 | + * Stores this keystore to the given output stream, and protects its | |
| 1126 | + * integrity with the given password. | |
| 1127 | + * | |
| 1128 | + * @param stream the output stream to which this keystore is written. | |
| 1129 | + * @param password the password to generate the keystore integrity check | |
| 1130 | + * | |
| 1131 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 1132 | + * (loaded). | |
| 1133 | + * @exception IOException if there was an I/O problem with data | |
| 1134 | + * @exception NoSuchAlgorithmException if the appropriate data integrity | |
| 1135 | + * algorithm could not be found | |
| 1136 | + * @exception CertificateException if any of the certificates included in | |
| 1137 | + * the keystore data could not be stored | |
| 1138 | + */ | |
| 1139 | + public final void store(OutputStream stream, char[] password) | |
| 1140 | + throws KeyStoreException, IOException, NoSuchAlgorithmException, | |
| 1141 | + CertificateException | |
| 1142 | + { | |
| 1143 | + if (!initialized) { | |
| 1144 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 1145 | + } | |
| 1146 | + keyStoreSpi.engineStore(stream, password); | |
| 1147 | + } | |
| 1148 | + | |
| 1149 | + /** | |
| 1150 | + * Stores this keystore using the given <code>LoadStoreParameter</code>. | |
| 1151 | + * | |
| 1152 | + * @param param the <code>LoadStoreParameter</code> | |
| 1153 | + * that specifies how to store the keystore, | |
| 1154 | + * which may be <code>null</code> | |
| 1155 | + * | |
| 1156 | + * @exception IllegalArgumentException if the given | |
| 1157 | + * <code>LoadStoreParameter</code> | |
| 1158 | + * input is not recognized | |
| 1159 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 1160 | + * (loaded) | |
| 1161 | + * @exception IOException if there was an I/O problem with data | |
| 1162 | + * @exception NoSuchAlgorithmException if the appropriate data integrity | |
| 1163 | + * algorithm could not be found | |
| 1164 | + * @exception CertificateException if any of the certificates included in | |
| 1165 | + * the keystore data could not be stored | |
| 1166 | + * | |
| 1167 | + * @since 1.5 | |
| 1168 | + */ | |
| 1169 | + public final void store(LoadStoreParameter param) | |
| 1170 | + throws KeyStoreException, IOException, | |
| 1171 | + NoSuchAlgorithmException, CertificateException { | |
| 1172 | + if (!initialized) { | |
| 1173 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 1174 | + } | |
| 1175 | + keyStoreSpi.engineStore(param); | |
| 1176 | + } | |
| 1177 | + | |
| 1178 | + /** | |
| 1179 | + * Loads this KeyStore from the given input stream. | |
| 1180 | + * | |
| 1181 | + * <p>A password may be given to unlock the keystore | |
| 1182 | + * (e.g. the keystore resides on a hardware token device), | |
| 1183 | + * or to check the integrity of the keystore data. | |
| 1184 | + * If a password is not given for integrity checking, | |
| 1185 | + * then integrity checking is not performed. | |
| 1186 | + * | |
| 1187 | + * <p>In order to create an empty keystore, or if the keystore cannot | |
| 1188 | + * be initialized from a stream, pass <code>null</code> | |
| 1189 | + * as the <code>stream</code> argument. | |
| 1190 | + * | |
| 1191 | + * <p> Note that if this keystore has already been loaded, it is | |
| 1192 | + * reinitialized and loaded again from the given input stream. | |
| 1193 | + * | |
| 1194 | + * @param stream the input stream from which the keystore is loaded, | |
| 1195 | + * or <code>null</code> | |
| 1196 | + * @param password the password used to check the integrity of | |
| 1197 | + * the keystore, the password used to unlock the keystore, | |
| 1198 | + * or <code>null</code> | |
| 1199 | + * | |
| 1200 | + * @exception IOException if there is an I/O or format problem with the | |
| 1201 | + * keystore data, if a password is required but not given, | |
| 1202 | + * or if the given password was incorrect. If the error is due to a | |
| 1203 | + * wrong password, the {@link Throwable#getCause cause} of the | |
| 1204 | + * <code>IOException</code> should be an | |
| 1205 | + * <code>UnrecoverableKeyException</code> | |
| 1206 | + * @exception NoSuchAlgorithmException if the algorithm used to check | |
| 1207 | + * the integrity of the keystore cannot be found | |
| 1208 | + * @exception CertificateException if any of the certificates in the | |
| 1209 | + * keystore could not be loaded | |
| 1210 | + */ | |
| 1211 | + public final void load(InputStream stream, char[] password) | |
| 1212 | + throws IOException, NoSuchAlgorithmException, CertificateException | |
| 1213 | + { | |
| 1214 | + keyStoreSpi.engineLoad(stream, password); | |
| 1215 | + initialized = true; | |
| 1216 | + } | |
| 1217 | + | |
| 1218 | + /** | |
| 1219 | + * Loads this keystore using the given <code>LoadStoreParameter</code>. | |
| 1220 | + * | |
| 1221 | + * <p> Note that if this KeyStore has already been loaded, it is | |
| 1222 | + * reinitialized and loaded again from the given parameter. | |
| 1223 | + * | |
| 1224 | + * @param param the <code>LoadStoreParameter</code> | |
| 1225 | + * that specifies how to load the keystore, | |
| 1226 | + * which may be <code>null</code> | |
| 1227 | + * | |
| 1228 | + * @exception IllegalArgumentException if the given | |
| 1229 | + * <code>LoadStoreParameter</code> | |
| 1230 | + * input is not recognized | |
| 1231 | + * @exception IOException if there is an I/O or format problem with the | |
| 1232 | + * keystore data. If the error is due to an incorrect | |
| 1233 | + * <code>ProtectionParameter</code> (e.g. wrong password) | |
| 1234 | + * the {@link Throwable#getCause cause} of the | |
| 1235 | + * <code>IOException</code> should be an | |
| 1236 | + * <code>UnrecoverableKeyException</code> | |
| 1237 | + * @exception NoSuchAlgorithmException if the algorithm used to check | |
| 1238 | + * the integrity of the keystore cannot be found | |
| 1239 | + * @exception CertificateException if any of the certificates in the | |
| 1240 | + * keystore could not be loaded | |
| 1241 | + * | |
| 1242 | + * @since 1.5 | |
| 1243 | + */ | |
| 1244 | + public final void load(LoadStoreParameter param) | |
| 1245 | + throws IOException, NoSuchAlgorithmException, | |
| 1246 | + CertificateException { | |
| 1247 | + | |
| 1248 | + keyStoreSpi.engineLoad(param); | |
| 1249 | + initialized = true; | |
| 1250 | + } | |
| 1251 | + | |
| 1252 | + /** | |
| 1253 | + * Gets a keystore <code>Entry</code> for the specified alias | |
| 1254 | + * with the specified protection parameter. | |
| 1255 | + * | |
| 1256 | + * @param alias get the keystore <code>Entry</code> for this alias | |
| 1257 | + * @param protParam the <code>ProtectionParameter</code> | |
| 1258 | + * used to protect the <code>Entry</code>, | |
| 1259 | + * which may be <code>null</code> | |
| 1260 | + * | |
| 1261 | + * @return the keystore <code>Entry</code> for the specified alias, | |
| 1262 | + * or <code>null</code> if there is no such entry | |
| 1263 | + * | |
| 1264 | + * @exception NullPointerException if | |
| 1265 | + * <code>alias</code> is <code>null</code> | |
| 1266 | + * @exception NoSuchAlgorithmException if the algorithm for recovering the | |
| 1267 | + * entry cannot be found | |
| 1268 | + * @exception UnrecoverableEntryException if the specified | |
| 1269 | + * <code>protParam</code> were insufficient or invalid | |
| 1270 | + * @exception UnrecoverableKeyException if the entry is a | |
| 1271 | + * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code> | |
| 1272 | + * and the specified <code>protParam</code> does not contain | |
| 1273 | + * the information needed to recover the key (e.g. wrong password) | |
| 1274 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 1275 | + * (loaded). | |
| 1276 | + * @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter) | |
| 1277 | + * | |
| 1278 | + * @since 1.5 | |
| 1279 | + */ | |
| 1280 | + public final Entry getEntry(String alias, ProtectionParameter protParam) | |
| 1281 | + throws NoSuchAlgorithmException, UnrecoverableEntryException, | |
| 1282 | + KeyStoreException { | |
| 1283 | + | |
| 1284 | + if (alias == null) { | |
| 1285 | + throw new NullPointerException("invalid null input"); | |
| 1286 | + } | |
| 1287 | + if (!initialized) { | |
| 1288 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 1289 | + } | |
| 1290 | + return keyStoreSpi.engineGetEntry(alias, protParam); | |
| 1291 | + } | |
| 1292 | + | |
| 1293 | + /** | |
| 1294 | + * Saves a keystore <code>Entry</code> under the specified alias. | |
| 1295 | + * The protection parameter is used to protect the | |
| 1296 | + * <code>Entry</code>. | |
| 1297 | + * | |
| 1298 | + * <p> If an entry already exists for the specified alias, | |
| 1299 | + * it is overridden. | |
| 1300 | + * | |
| 1301 | + * @param alias save the keystore <code>Entry</code> under this alias | |
| 1302 | + * @param entry the <code>Entry</code> to save | |
| 1303 | + * @param protParam the <code>ProtectionParameter</code> | |
| 1304 | + * used to protect the <code>Entry</code>, | |
| 1305 | + * which may be <code>null</code> | |
| 1306 | + * | |
| 1307 | + * @exception NullPointerException if | |
| 1308 | + * <code>alias</code> or <code>entry</code> | |
| 1309 | + * is <code>null</code> | |
| 1310 | + * @exception KeyStoreException if the keystore has not been initialized | |
| 1311 | + * (loaded), or if this operation fails for some other reason | |
| 1312 | + * | |
| 1313 | + * @see #getEntry(String, KeyStore.ProtectionParameter) | |
| 1314 | + * | |
| 1315 | + * @since 1.5 | |
| 1316 | + */ | |
| 1317 | + public final void setEntry(String alias, Entry entry, | |
| 1318 | + ProtectionParameter protParam) | |
| 1319 | + throws KeyStoreException { | |
| 1320 | + if (alias == null || entry == null) { | |
| 1321 | + throw new NullPointerException("invalid null input"); | |
| 1322 | + } | |
| 1323 | + if (!initialized) { | |
| 1324 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 1325 | + } | |
| 1326 | + keyStoreSpi.engineSetEntry(alias, entry, protParam); | |
| 1327 | + } | |
| 1328 | + | |
| 1329 | + /** | |
| 1330 | + * Determines if the keystore <code>Entry</code> for the specified | |
| 1331 | + * <code>alias</code> is an instance or subclass of the specified | |
| 1332 | + * <code>entryClass</code>. | |
| 1333 | + * | |
| 1334 | + * @param alias the alias name | |
| 1335 | + * @param entryClass the entry class | |
| 1336 | + * | |
| 1337 | + * @return true if the keystore <code>Entry</code> for the specified | |
| 1338 | + * <code>alias</code> is an instance or subclass of the | |
| 1339 | + * specified <code>entryClass</code>, false otherwise | |
| 1340 | + * | |
| 1341 | + * @exception NullPointerException if | |
| 1342 | + * <code>alias</code> or <code>entryClass</code> | |
| 1343 | + * is <code>null</code> | |
| 1344 | + * @exception KeyStoreException if the keystore has not been | |
| 1345 | + * initialized (loaded) | |
| 1346 | + * | |
| 1347 | + * @since 1.5 | |
| 1348 | + */ | |
| 1349 | + public final boolean | |
| 1350 | + entryInstanceOf(String alias, | |
| 1351 | + Class<? extends KeyStore.Entry> entryClass) | |
| 1352 | + throws KeyStoreException | |
| 1353 | + { | |
| 1354 | + | |
| 1355 | + if (alias == null || entryClass == null) { | |
| 1356 | + throw new NullPointerException("invalid null input"); | |
| 1357 | + } | |
| 1358 | + if (!initialized) { | |
| 1359 | + throw new KeyStoreException("Uninitialized keystore"); | |
| 1360 | + } | |
| 1361 | + return keyStoreSpi.engineEntryInstanceOf(alias, entryClass); | |
| 1362 | + } | |
| 1363 | + | |
| 1364 | + /** | |
| 1365 | + * A description of a to-be-instantiated KeyStore object. | |
| 1366 | + * | |
| 1367 | + * <p>An instance of this class encapsulates the information needed to | |
| 1368 | + * instantiate and initialize a KeyStore object. That process is | |
| 1369 | + * triggered when the {@linkplain #getKeyStore} method is called. | |
| 1370 | + * | |
| 1371 | + * <p>This makes it possible to decouple configuration from KeyStore | |
| 1372 | + * object creation and e.g. delay a password prompt until it is | |
| 1373 | + * needed. | |
| 1374 | + * | |
| 1375 | + * @see KeyStore | |
| 1376 | + * @see javax.net.ssl.KeyStoreBuilderParameters | |
| 1377 | + * @since 1.5 | |
| 1378 | + */ | |
| 1379 | + public static abstract class Builder { | |
| 1380 | + | |
| 1381 | + // maximum times to try the callbackhandler if the password is wrong | |
| 1382 | + static final int MAX_CALLBACK_TRIES = 3; | |
| 1383 | + | |
| 1384 | + /** | |
| 1385 | + * Construct a new Builder. | |
| 1386 | + */ | |
| 1387 | + protected Builder() { | |
| 1388 | + // empty | |
| 1389 | + } | |
| 1390 | + | |
| 1391 | + /** | |
| 1392 | + * Returns the KeyStore described by this object. | |
| 1393 | + * | |
| 1394 | + * @exception KeyStoreException if an error occured during the | |
| 1395 | + * operation, for example if the KeyStore could not be | |
| 1396 | + * instantiated or loaded | |
| 1397 | + */ | |
| 1398 | + public abstract KeyStore getKeyStore() throws KeyStoreException; | |
| 1399 | + | |
| 1400 | + /** | |
| 1401 | + * Returns the ProtectionParameters that should be used to obtain | |
| 1402 | + * the {@link KeyStore.Entry Entry} with the given alias. | |
| 1403 | + * The <code>getKeyStore</code> method must be invoked before this | |
| 1404 | + * method may be called. | |
| 1405 | + * | |
| 1406 | + * @return the ProtectionParameters that should be used to obtain | |
| 1407 | + * the {@link KeyStore.Entry Entry} with the given alias. | |
| 1408 | + * @param alias the alias of the KeyStore entry | |
| 1409 | + * @throws NullPointerException if alias is null | |
| 1410 | + * @throws KeyStoreException if an error occured during the | |
| 1411 | + * operation | |
| 1412 | + * @throws IllegalStateException if the getKeyStore method has | |
| 1413 | + * not been invoked prior to calling this method | |
| 1414 | + */ | |
| 1415 | + public abstract ProtectionParameter getProtectionParameter(String alias) | |
| 1416 | + throws KeyStoreException; | |
| 1417 | + | |
| 1418 | + /** | |
| 1419 | + * Returns a new Builder that encapsulates the given KeyStore. | |
| 1420 | + * The {@linkplain #getKeyStore} method of the returned object | |
| 1421 | + * will return <code>keyStore</code>, the {@linkplain | |
| 1422 | + * #getProtectionParameter getProtectionParameter()} method will | |
| 1423 | + * return <code>protectionParameters</code>. | |
| 1424 | + * | |
| 1425 | + * <p> This is useful if an existing KeyStore object needs to be | |
| 1426 | + * used with Builder-based APIs. | |
| 1427 | + * | |
| 1428 | + * @return a new Builder object | |
| 1429 | + * @param keyStore the KeyStore to be encapsulated | |
| 1430 | + * @param protectionParameter the ProtectionParameter used to | |
| 1431 | + * protect the KeyStore entries | |
| 1432 | + * @throws NullPointerException if keyStore or | |
| 1433 | + * protectionParameters is null | |
| 1434 | + * @throws IllegalArgumentException if the keyStore has not been | |
| 1435 | + * initialized | |
| 1436 | + */ | |
| 1437 | + public static Builder newInstance(final KeyStore keyStore, | |
| 1438 | + final ProtectionParameter protectionParameter) { | |
| 1439 | + if ((keyStore == null) || (protectionParameter == null)) { | |
| 1440 | + throw new NullPointerException(); | |
| 1441 | + } | |
| 1442 | + if (keyStore.initialized == false) { | |
| 1443 | + throw new IllegalArgumentException("KeyStore not initialized"); | |
| 1444 | + } | |
| 1445 | + return new Builder() { | |
| 1446 | + private volatile boolean getCalled; | |
| 1447 | + | |
| 1448 | + public KeyStore getKeyStore() { | |
| 1449 | + getCalled = true; | |
| 1450 | + return keyStore; | |
| 1451 | + } | |
| 1452 | + | |
| 1453 | + public ProtectionParameter getProtectionParameter(String alias) | |
| 1454 | + { | |
| 1455 | + if (alias == null) { | |
| 1456 | + throw new NullPointerException(); | |
| 1457 | + } | |
| 1458 | + if (getCalled == false) { | |
| 1459 | + throw new IllegalStateException | |
| 1460 | + ("getKeyStore() must be called first"); | |
| 1461 | + } | |
| 1462 | + return protectionParameter; | |
| 1463 | + } | |
| 1464 | + }; | |
| 1465 | + } | |
| 1466 | + | |
| 1467 | + /** | |
| 1468 | + * Returns a new Builder object. | |
| 1469 | + * | |
| 1470 | + * <p>The first call to the {@link #getKeyStore} method on the returned | |
| 1471 | + * builder will create a KeyStore of type <code>type</code> and call | |
| 1472 | + * its {@link KeyStore#load load()} method. | |
| 1473 | + * The <code>inputStream</code> argument is constructed from | |
| 1474 | + * <code>file</code>. | |
| 1475 | + * If <code>protection</code> is a | |
| 1476 | + * <code>PasswordProtection</code>, the password is obtained by | |
| 1477 | + * calling the <code>getPassword</code> method. | |
| 1478 | + * Otherwise, if <code>protection</code> is a | |
| 1479 | + * <code>CallbackHandlerProtection</code>, the password is obtained | |
| 1480 | + * by invoking the CallbackHandler. | |
| 1481 | + * | |
| 1482 | + * <p>Subsequent calls to {@link #getKeyStore} return the same object | |
| 1483 | + * as the initial call. If the initial call to failed with a | |
| 1484 | + * KeyStoreException, subsequent calls also throw a | |
| 1485 | + * KeyStoreException. | |
| 1486 | + * | |
| 1487 | + * <p>The KeyStore is instantiated from <code>provider</code> if | |
| 1488 | + * non-null. Otherwise, all installed providers are searched. | |
| 1489 | + * | |
| 1490 | + * <p>Calls to {@link #getProtectionParameter getProtectionParameter()} | |
| 1491 | + * will return a {@link KeyStore.PasswordProtection PasswordProtection} | |
| 1492 | + * object encapsulating the password that was used to invoke the | |
| 1493 | + * <code>load</code> method. | |
| 1494 | + * | |
| 1495 | + * <p><em>Note</em> that the {@link #getKeyStore} method is executed | |
| 1496 | + * within the {@link AccessControlContext} of the code invoking this | |
| 1497 | + * method. | |
| 1498 | + * | |
| 1499 | + * @return a new Builder object | |
| 1500 | + * @param type the type of KeyStore to be constructed | |
| 1501 | + * @param provider the provider from which the KeyStore is to | |
| 1502 | + * be instantiated (or null) | |
| 1503 | + * @param file the File that contains the KeyStore data | |
| 1504 | + * @param protection the ProtectionParameter securing the KeyStore data | |
| 1505 | + * @throws NullPointerException if type, file or protection is null | |
| 1506 | + * @throws IllegalArgumentException if protection is not an instance | |
| 1507 | + * of either PasswordProtection or CallbackHandlerProtection; or | |
| 1508 | + * if file does not exist or does not refer to a normal file | |
| 1509 | + */ | |
| 1510 | + public static Builder newInstance(String type, Provider provider, | |
| 1511 | + File file, ProtectionParameter protection) { | |
| 1512 | + if ((type == null) || (file == null) || (protection == null)) { | |
| 1513 | + throw new NullPointerException(); | |
| 1514 | + } | |
| 1515 | + if ((protection instanceof PasswordProtection == false) && | |
| 1516 | + (protection instanceof CallbackHandlerProtection == false)) { | |
| 1517 | + throw new IllegalArgumentException | |
| 1518 | + ("Protection must be PasswordProtection or " + | |
| 1519 | + "CallbackHandlerProtection"); | |
| 1520 | + } | |
| 1521 | + if (file.isFile() == false) { | |
| 1522 | + throw new IllegalArgumentException | |
| 1523 | + ("File does not exist or it does not refer " + | |
| 1524 | + "to a normal file: " + file); | |
| 1525 | + } | |
| 1526 | + return new FileBuilder(type, provider, file, protection, | |
| 1527 | + AccessController.getContext()); | |
| 1528 | + } | |
| 1529 | + | |
| 1530 | + private static final class FileBuilder extends Builder { | |
| 1531 | + | |
| 1532 | + private final String type; | |
| 1533 | + private final Provider provider; | |
| 1534 | + private final File file; | |
| 1535 | + private ProtectionParameter protection; | |
| 1536 | + private ProtectionParameter keyProtection; | |
| 1537 | + private final AccessControlContext context; | |
| 1538 | + | |
| 1539 | + private KeyStore keyStore; | |
| 1540 | + | |
| 1541 | + private Throwable oldException; | |
| 1542 | + | |
| 1543 | + FileBuilder(String type, Provider provider, File file, | |
| 1544 | + ProtectionParameter protection, | |
| 1545 | + AccessControlContext context) { | |
| 1546 | + this.type = type; | |
| 1547 | + this.provider = provider; | |
| 1548 | + this.file = file; | |
| 1549 | + this.protection = protection; | |
| 1550 | + this.context = context; | |
| 1551 | + } | |
| 1552 | + | |
| 1553 | + public synchronized KeyStore getKeyStore() throws KeyStoreException | |
| 1554 | + { | |
| 1555 | + if (keyStore != null) { | |
| 1556 | + return keyStore; | |
| 1557 | + } | |
| 1558 | + if (oldException != null) { | |
| 1559 | + throw new KeyStoreException | |
| 1560 | + ("Previous KeyStore instantiation failed", | |
| 1561 | + oldException); | |
| 1562 | + } | |
| 1563 | + PrivilegedExceptionAction<KeyStore> action = | |
| 1564 | + new PrivilegedExceptionAction<KeyStore>() { | |
| 1565 | + public KeyStore run() throws Exception { | |
| 1566 | + if (protection instanceof CallbackHandlerProtection == false) { | |
| 1567 | + return run0(); | |
| 1568 | + } | |
| 1569 | + // when using a CallbackHandler, | |
| 1570 | + // reprompt if the password is wrong | |
| 1571 | + int tries = 0; | |
| 1572 | + while (true) { | |
| 1573 | + tries++; | |
| 1574 | + try { | |
| 1575 | + return run0(); | |
| 1576 | + } catch (IOException e) { | |
| 1577 | + if ((tries < MAX_CALLBACK_TRIES) | |
| 1578 | + && (e.getCause() instanceof UnrecoverableKeyException)) { | |
| 1579 | + continue; | |
| 1580 | + } | |
| 1581 | + throw e; | |
| 1582 | + } | |
| 1583 | + } | |
| 1584 | + } | |
| 1585 | + public KeyStore run0() throws Exception { | |
| 1586 | + KeyStore ks; | |
| 1587 | + if (provider == null) { | |
| 1588 | + ks = KeyStore.getInstance(type); | |
| 1589 | + } else { | |
| 1590 | + ks = KeyStore.getInstance(type, provider); | |
| 1591 | + } | |
| 1592 | + InputStream in = null; | |
| 1593 | + char[] password = null; | |
| 1594 | + try { | |
| 1595 | + in = new FileInputStream(file); | |
| 1596 | + if (protection instanceof PasswordProtection) { | |
| 1597 | + password = | |
| 1598 | + ((PasswordProtection)protection).getPassword(); | |
| 1599 | + keyProtection = protection; | |
| 1600 | + } else { | |
| 1601 | + CallbackHandler handler = | |
| 1602 | + ((CallbackHandlerProtection)protection) | |
| 1603 | + .getCallbackHandler(); | |
| 1604 | + PasswordCallback callback = new PasswordCallback | |
| 1605 | + ("Password for keystore " + file.getName(), | |
| 1606 | + false); | |
| 1607 | + handler.handle(new Callback[] {callback}); | |
| 1608 | + password = callback.getPassword(); | |
| 1609 | + if (password == null) { | |
| 1610 | + throw new KeyStoreException("No password" + | |
| 1611 | + " provided"); | |
| 1612 | + } | |
| 1613 | + callback.clearPassword(); | |
| 1614 | + keyProtection = new PasswordProtection(password); | |
| 1615 | + } | |
| 1616 | + ks.load(in, password); | |
| 1617 | + return ks; | |
| 1618 | + } finally { | |
| 1619 | + if (in != null) { | |
| 1620 | + in.close(); | |
| 1621 | + } | |
| 1622 | + } | |
| 1623 | + } | |
| 1624 | + }; | |
| 1625 | + try { | |
| 1626 | + keyStore = AccessController.doPrivileged(action, context); | |
| 1627 | + return keyStore; | |
| 1628 | + } catch (PrivilegedActionException e) { | |
| 1629 | + oldException = e.getCause(); | |
| 1630 | + throw new KeyStoreException | |
| 1631 | + ("KeyStore instantiation failed", oldException); | |
| 1632 | + } | |
| 1633 | + } | |
| 1634 | + | |
| 1635 | + public synchronized ProtectionParameter | |
| 1636 | + getProtectionParameter(String alias) { | |
| 1637 | + if (alias == null) { | |
| 1638 | + throw new NullPointerException(); | |
| 1639 | + } | |
| 1640 | + if (keyStore == null) { | |
| 1641 | + throw new IllegalStateException | |
| 1642 | + ("getKeyStore() must be called first"); | |
| 1643 | + } | |
| 1644 | + return keyProtection; | |
| 1645 | + } | |
| 1646 | + } | |
| 1647 | + | |
| 1648 | + /** | |
| 1649 | + * Returns a new Builder object. | |
| 1650 | + * | |
| 1651 | + * <p>Each call to the {@link #getKeyStore} method on the returned | |
| 1652 | + * builder will return a new KeyStore object of type <code>type</code>. | |
| 1653 | + * Its {@link KeyStore#load(KeyStore.LoadStoreParameter) load()} | |
| 1654 | + * method is invoked using a | |
| 1655 | + * <code>LoadStoreParameter</code> that encapsulates | |
| 1656 | + * <code>protection</code>. | |
| 1657 | + * | |
| 1658 | + * <p>The KeyStore is instantiated from <code>provider</code> if | |
| 1659 | + * non-null. Otherwise, all installed providers are searched. | |
| 1660 | + * | |
| 1661 | + * <p>Calls to {@link #getProtectionParameter getProtectionParameter()} | |
| 1662 | + * will return <code>protection</code>. | |
| 1663 | + * | |
| 1664 | + * <p><em>Note</em> that the {@link #getKeyStore} method is executed | |
| 1665 | + * within the {@link AccessControlContext} of the code invoking this | |
| 1666 | + * method. | |
| 1667 | + * | |
| 1668 | + * @return a new Builder object | |
| 1669 | + * @param type the type of KeyStore to be constructed | |
| 1670 | + * @param provider the provider from which the KeyStore is to | |
| 1671 | + * be instantiated (or null) | |
| 1672 | + * @param protection the ProtectionParameter securing the Keystore | |
| 1673 | + * @throws NullPointerException if type or protection is null | |
| 1674 | + */ | |
| 1675 | + public static Builder newInstance(final String type, | |
| 1676 | + final Provider provider, final ProtectionParameter protection) { | |
| 1677 | + if ((type == null) || (protection == null)) { | |
| 1678 | + throw new NullPointerException(); | |
| 1679 | + } | |
| 1680 | + final AccessControlContext context = AccessController.getContext(); | |
| 1681 | + return new Builder() { | |
| 1682 | + private volatile boolean getCalled; | |
| 1683 | + private IOException oldException; | |
| 1684 | + | |
| 1685 | + private final PrivilegedExceptionAction<KeyStore> action | |
| 1686 | + = new PrivilegedExceptionAction<KeyStore>() { | |
| 1687 | + | |
| 1688 | + public KeyStore run() throws Exception { | |
| 1689 | + KeyStore ks; | |
| 1690 | + if (provider == null) { | |
| 1691 | + ks = KeyStore.getInstance(type); | |
| 1692 | + } else { | |
| 1693 | + ks = KeyStore.getInstance(type, provider); | |
| 1694 | + } | |
| 1695 | + LoadStoreParameter param = new SimpleLoadStoreParameter(protection); | |
| 1696 | + if (protection instanceof CallbackHandlerProtection == false) { | |
| 1697 | + ks.load(param); | |
| 1698 | + } else { | |
| 1699 | + // when using a CallbackHandler, | |
| 1700 | + // reprompt if the password is wrong | |
| 1701 | + int tries = 0; | |
| 1702 | + while (true) { | |
| 1703 | + tries++; | |
| 1704 | + try { | |
| 1705 | + ks.load(param); | |
| 1706 | + break; | |
| 1707 | + } catch (IOException e) { | |
| 1708 | + if (e.getCause() instanceof UnrecoverableKeyException) { | |
| 1709 | + if (tries < MAX_CALLBACK_TRIES) { | |
| 1710 | + continue; | |
| 1711 | + } else { | |
| 1712 | + oldException = e; | |
| 1713 | + } | |
| 1714 | + } | |
| 1715 | + throw e; | |
| 1716 | + } | |
| 1717 | + } | |
| 1718 | + } | |
| 1719 | + getCalled = true; | |
| 1720 | + return ks; | |
| 1721 | + } | |
| 1722 | + }; | |
| 1723 | + | |
| 1724 | + public synchronized KeyStore getKeyStore() | |
| 1725 | + throws KeyStoreException { | |
| 1726 | + if (oldException != null) { | |
| 1727 | + throw new KeyStoreException | |
| 1728 | + ("Previous KeyStore instantiation failed", | |
| 1729 | + oldException); | |
| 1730 | + } | |
| 1731 | + try { | |
| 1732 | + return AccessController.doPrivileged(action); | |
| 1733 | + } catch (PrivilegedActionException e) { | |
| 1734 | + Throwable cause = e.getCause(); | |
| 1735 | + throw new KeyStoreException | |
| 1736 | + ("KeyStore instantiation failed", cause); | |
| 1737 | + } | |
| 1738 | + } | |
| 1739 | + | |
| 1740 | + public ProtectionParameter getProtectionParameter(String alias) | |
| 1741 | + { | |
| 1742 | + if (alias == null) { | |
| 1743 | + throw new NullPointerException(); | |
| 1744 | + } | |
| 1745 | + if (getCalled == false) { | |
| 1746 | + throw new IllegalStateException | |
| 1747 | + ("getKeyStore() must be called first"); | |
| 1748 | + } | |
| 1749 | + return protection; | |
| 1750 | + } | |
| 1751 | + }; | |
| 1752 | + } | |
| 1753 | + | |
| 1754 | + } | |
| 1755 | + | |
| 1756 | + static class SimpleLoadStoreParameter implements LoadStoreParameter { | |
| 1757 | + | |
| 1758 | + private final ProtectionParameter protection; | |
| 1759 | + | |
| 1760 | + SimpleLoadStoreParameter(ProtectionParameter protection) { | |
| 1761 | + this.protection = protection; | |
| 1762 | + } | |
| 1763 | + | |
| 1764 | + public ProtectionParameter getProtectionParameter() { | |
| 1765 | + return protection; | |
| 1766 | + } | |
| 1767 | + } | |
| 1768 | + | |
| 1769 | +} | |
Binary file not shown.
| @@ -0,0 +1,90 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This is the generic KeyStore exception. | |
| 30 | + * | |
| 31 | + * @author Jan Luehe | |
| 32 | + * | |
| 33 | + * | |
| 34 | + * @since 1.2 | |
| 35 | + */ | |
| 36 | + | |
| 37 | +public class KeyStoreException extends GeneralSecurityException { | |
| 38 | + | |
| 39 | + private static final long serialVersionUID = -1119353179322377262L; | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * Constructs a KeyStoreException with no detail message. (A | |
| 43 | + * detail message is a String that describes this particular | |
| 44 | + * exception.) | |
| 45 | + */ | |
| 46 | + public KeyStoreException() { | |
| 47 | + super(); | |
| 48 | + } | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * Constructs a KeyStoreException with the specified detail | |
| 52 | + * message. (A detail message is a String that describes this | |
| 53 | + * particular exception.) | |
| 54 | + * | |
| 55 | + * @param msg the detail message. | |
| 56 | + */ | |
| 57 | + public KeyStoreException(String msg) { | |
| 58 | + super(msg); | |
| 59 | + } | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * Creates a <code>KeyStoreException</code> with the specified | |
| 63 | + * detail message and cause. | |
| 64 | + * | |
| 65 | + * @param message the detail message (which is saved for later retrieval | |
| 66 | + * by the {@link #getMessage()} method). | |
| 67 | + * @param cause the cause (which is saved for later retrieval by the | |
| 68 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 69 | + * and indicates that the cause is nonexistent or unknown.) | |
| 70 | + * @since 1.5 | |
| 71 | + */ | |
| 72 | + public KeyStoreException(String message, Throwable cause) { | |
| 73 | + super(message, cause); | |
| 74 | + } | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * Creates a <code>KeyStoreException</code> with the specified cause | |
| 78 | + * and a detail message of <tt>(cause==null ? null : cause.toString())</tt> | |
| 79 | + * (which typically contains the class and detail message of | |
| 80 | + * <tt>cause</tt>). | |
| 81 | + * | |
| 82 | + * @param cause the cause (which is saved for later retrieval by the | |
| 83 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 84 | + * and indicates that the cause is nonexistent or unknown.) | |
| 85 | + * @since 1.5 | |
| 86 | + */ | |
| 87 | + public KeyStoreException(Throwable cause) { | |
| 88 | + super(cause); | |
| 89 | + } | |
| 90 | +} | |
Binary file not shown.
| @@ -0,0 +1,593 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.*; | |
| 29 | +import java.util.*; | |
| 30 | + | |
| 31 | +import java.security.KeyStore.*; | |
| 32 | +import java.security.cert.Certificate; | |
| 33 | +import java.security.cert.CertificateException; | |
| 34 | + | |
| 35 | +import javax.crypto.SecretKey; | |
| 36 | + | |
| 37 | +import javax.security.auth.callback.*; | |
| 38 | + | |
| 39 | +/** | |
| 40 | + * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) | |
| 41 | + * for the <code>KeyStore</code> class. | |
| 42 | + * All the abstract methods in this class must be implemented by each | |
| 43 | + * cryptographic service provider who wishes to supply the implementation | |
| 44 | + * of a keystore for a particular keystore type. | |
| 45 | + * | |
| 46 | + * @author Jan Luehe | |
| 47 | + * | |
| 48 | + * | |
| 49 | + * @see KeyStore | |
| 50 | + * | |
| 51 | + * @since 1.2 | |
| 52 | + */ | |
| 53 | + | |
| 54 | +public abstract class KeyStoreSpi { | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * Returns the key associated with the given alias, using the given | |
| 58 | + * password to recover it. The key must have been associated with | |
| 59 | + * the alias by a call to <code>setKeyEntry</code>, | |
| 60 | + * or by a call to <code>setEntry</code> with a | |
| 61 | + * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>. | |
| 62 | + * | |
| 63 | + * @param alias the alias name | |
| 64 | + * @param password the password for recovering the key | |
| 65 | + * | |
| 66 | + * @return the requested key, or null if the given alias does not exist | |
| 67 | + * or does not identify a key-related entry. | |
| 68 | + * | |
| 69 | + * @exception NoSuchAlgorithmException if the algorithm for recovering the | |
| 70 | + * key cannot be found | |
| 71 | + * @exception UnrecoverableKeyException if the key cannot be recovered | |
| 72 | + * (e.g., the given password is wrong). | |
| 73 | + */ | |
| 74 | + public abstract Key engineGetKey(String alias, char[] password) | |
| 75 | + throws NoSuchAlgorithmException, UnrecoverableKeyException; | |
| 76 | + | |
| 77 | + /** | |
| 78 | + * Returns the certificate chain associated with the given alias. | |
| 79 | + * The certificate chain must have been associated with the alias | |
| 80 | + * by a call to <code>setKeyEntry</code>, | |
| 81 | + * or by a call to <code>setEntry</code> with a | |
| 82 | + * <code>PrivateKeyEntry</code>. | |
| 83 | + * | |
| 84 | + * @param alias the alias name | |
| 85 | + * | |
| 86 | + * @return the certificate chain (ordered with the user's certificate first | |
| 87 | + * and the root certificate authority last), or null if the given alias | |
| 88 | + * does not exist or does not contain a certificate chain | |
| 89 | + */ | |
| 90 | + public abstract Certificate[] engineGetCertificateChain(String alias); | |
| 91 | + | |
| 92 | + /** | |
| 93 | + * Returns the certificate associated with the given alias. | |
| 94 | + * | |
| 95 | + * <p> If the given alias name identifies an entry | |
| 96 | + * created by a call to <code>setCertificateEntry</code>, | |
| 97 | + * or created by a call to <code>setEntry</code> with a | |
| 98 | + * <code>TrustedCertificateEntry</code>, | |
| 99 | + * then the trusted certificate contained in that entry is returned. | |
| 100 | + * | |
| 101 | + * <p> If the given alias name identifies an entry | |
| 102 | + * created by a call to <code>setKeyEntry</code>, | |
| 103 | + * or created by a call to <code>setEntry</code> with a | |
| 104 | + * <code>PrivateKeyEntry</code>, | |
| 105 | + * then the first element of the certificate chain in that entry | |
| 106 | + * (if a chain exists) is returned. | |
| 107 | + * | |
| 108 | + * @param alias the alias name | |
| 109 | + * | |
| 110 | + * @return the certificate, or null if the given alias does not exist or | |
| 111 | + * does not contain a certificate. | |
| 112 | + */ | |
| 113 | + public abstract Certificate engineGetCertificate(String alias); | |
| 114 | + | |
| 115 | + /** | |
| 116 | + * Returns the creation date of the entry identified by the given alias. | |
| 117 | + * | |
| 118 | + * @param alias the alias name | |
| 119 | + * | |
| 120 | + * @return the creation date of this entry, or null if the given alias does | |
| 121 | + * not exist | |
| 122 | + */ | |
| 123 | + public abstract Date engineGetCreationDate(String alias); | |
| 124 | + | |
| 125 | + /** | |
| 126 | + * Assigns the given key to the given alias, protecting it with the given | |
| 127 | + * password. | |
| 128 | + * | |
| 129 | + * <p>If the given key is of type <code>java.security.PrivateKey</code>, | |
| 130 | + * it must be accompanied by a certificate chain certifying the | |
| 131 | + * corresponding public key. | |
| 132 | + * | |
| 133 | + * <p>If the given alias already exists, the keystore information | |
| 134 | + * associated with it is overridden by the given key (and possibly | |
| 135 | + * certificate chain). | |
| 136 | + * | |
| 137 | + * @param alias the alias name | |
| 138 | + * @param key the key to be associated with the alias | |
| 139 | + * @param password the password to protect the key | |
| 140 | + * @param chain the certificate chain for the corresponding public | |
| 141 | + * key (only required if the given key is of type | |
| 142 | + * <code>java.security.PrivateKey</code>). | |
| 143 | + * | |
| 144 | + * @exception KeyStoreException if the given key cannot be protected, or | |
| 145 | + * this operation fails for some other reason | |
| 146 | + */ | |
| 147 | + public abstract void engineSetKeyEntry(String alias, Key key, | |
| 148 | + char[] password, | |
| 149 | + Certificate[] chain) | |
| 150 | + throws KeyStoreException; | |
| 151 | + | |
| 152 | + /** | |
| 153 | + * Assigns the given key (that has already been protected) to the given | |
| 154 | + * alias. | |
| 155 | + * | |
| 156 | + * <p>If the protected key is of type | |
| 157 | + * <code>java.security.PrivateKey</code>, | |
| 158 | + * it must be accompanied by a certificate chain certifying the | |
| 159 | + * corresponding public key. | |
| 160 | + * | |
| 161 | + * <p>If the given alias already exists, the keystore information | |
| 162 | + * associated with it is overridden by the given key (and possibly | |
| 163 | + * certificate chain). | |
| 164 | + * | |
| 165 | + * @param alias the alias name | |
| 166 | + * @param key the key (in protected format) to be associated with the alias | |
| 167 | + * @param chain the certificate chain for the corresponding public | |
| 168 | + * key (only useful if the protected key is of type | |
| 169 | + * <code>java.security.PrivateKey</code>). | |
| 170 | + * | |
| 171 | + * @exception KeyStoreException if this operation fails. | |
| 172 | + */ | |
| 173 | + public abstract void engineSetKeyEntry(String alias, byte[] key, | |
| 174 | + Certificate[] chain) | |
| 175 | + throws KeyStoreException; | |
| 176 | + | |
| 177 | + /** | |
| 178 | + * Assigns the given certificate to the given alias. | |
| 179 | + * | |
| 180 | + * <p> If the given alias identifies an existing entry | |
| 181 | + * created by a call to <code>setCertificateEntry</code>, | |
| 182 | + * or created by a call to <code>setEntry</code> with a | |
| 183 | + * <code>TrustedCertificateEntry</code>, | |
| 184 | + * the trusted certificate in the existing entry | |
| 185 | + * is overridden by the given certificate. | |
| 186 | + * | |
| 187 | + * @param alias the alias name | |
| 188 | + * @param cert the certificate | |
| 189 | + * | |
| 190 | + * @exception KeyStoreException if the given alias already exists and does | |
| 191 | + * not identify an entry containing a trusted certificate, | |
| 192 | + * or this operation fails for some other reason. | |
| 193 | + */ | |
| 194 | + public abstract void engineSetCertificateEntry(String alias, | |
| 195 | + Certificate cert) | |
| 196 | + throws KeyStoreException; | |
| 197 | + | |
| 198 | + /** | |
| 199 | + * Deletes the entry identified by the given alias from this keystore. | |
| 200 | + * | |
| 201 | + * @param alias the alias name | |
| 202 | + * | |
| 203 | + * @exception KeyStoreException if the entry cannot be removed. | |
| 204 | + */ | |
| 205 | + public abstract void engineDeleteEntry(String alias) | |
| 206 | + throws KeyStoreException; | |
| 207 | + | |
| 208 | + /** | |
| 209 | + * Lists all the alias names of this keystore. | |
| 210 | + * | |
| 211 | + * @return enumeration of the alias names | |
| 212 | + */ | |
| 213 | + public abstract Enumeration<String> engineAliases(); | |
| 214 | + | |
| 215 | + /** | |
| 216 | + * Checks if the given alias exists in this keystore. | |
| 217 | + * | |
| 218 | + * @param alias the alias name | |
| 219 | + * | |
| 220 | + * @return true if the alias exists, false otherwise | |
| 221 | + */ | |
| 222 | + public abstract boolean engineContainsAlias(String alias); | |
| 223 | + | |
| 224 | + /** | |
| 225 | + * Retrieves the number of entries in this keystore. | |
| 226 | + * | |
| 227 | + * @return the number of entries in this keystore | |
| 228 | + */ | |
| 229 | + public abstract int engineSize(); | |
| 230 | + | |
| 231 | + /** | |
| 232 | + * Returns true if the entry identified by the given alias | |
| 233 | + * was created by a call to <code>setKeyEntry</code>, | |
| 234 | + * or created by a call to <code>setEntry</code> with a | |
| 235 | + * <code>PrivateKeyEntry</code> or a <code>SecretKeyEntry</code>. | |
| 236 | + * | |
| 237 | + * @param alias the alias for the keystore entry to be checked | |
| 238 | + * | |
| 239 | + * @return true if the entry identified by the given alias is a | |
| 240 | + * key-related, false otherwise. | |
| 241 | + */ | |
| 242 | + public abstract boolean engineIsKeyEntry(String alias); | |
| 243 | + | |
| 244 | + /** | |
| 245 | + * Returns true if the entry identified by the given alias | |
| 246 | + * was created by a call to <code>setCertificateEntry</code>, | |
| 247 | + * or created by a call to <code>setEntry</code> with a | |
| 248 | + * <code>TrustedCertificateEntry</code>. | |
| 249 | + * | |
| 250 | + * @param alias the alias for the keystore entry to be checked | |
| 251 | + * | |
| 252 | + * @return true if the entry identified by the given alias contains a | |
| 253 | + * trusted certificate, false otherwise. | |
| 254 | + */ | |
| 255 | + public abstract boolean engineIsCertificateEntry(String alias); | |
| 256 | + | |
| 257 | + /** | |
| 258 | + * Returns the (alias) name of the first keystore entry whose certificate | |
| 259 | + * matches the given certificate. | |
| 260 | + * | |
| 261 | + * <p>This method attempts to match the given certificate with each | |
| 262 | + * keystore entry. If the entry being considered was | |
| 263 | + * created by a call to <code>setCertificateEntry</code>, | |
| 264 | + * or created by a call to <code>setEntry</code> with a | |
| 265 | + * <code>TrustedCertificateEntry</code>, | |
| 266 | + * then the given certificate is compared to that entry's certificate. | |
| 267 | + * | |
| 268 | + * <p> If the entry being considered was | |
| 269 | + * created by a call to <code>setKeyEntry</code>, | |
| 270 | + * or created by a call to <code>setEntry</code> with a | |
| 271 | + * <code>PrivateKeyEntry</code>, | |
| 272 | + * then the given certificate is compared to the first | |
| 273 | + * element of that entry's certificate chain. | |
| 274 | + * | |
| 275 | + * @param cert the certificate to match with. | |
| 276 | + * | |
| 277 | + * @return the alias name of the first entry with matching certificate, | |
| 278 | + * or null if no such entry exists in this keystore. | |
| 279 | + */ | |
| 280 | + public abstract String engineGetCertificateAlias(Certificate cert); | |
| 281 | + | |
| 282 | + /** | |
| 283 | + * Stores this keystore to the given output stream, and protects its | |
| 284 | + * integrity with the given password. | |
| 285 | + * | |
| 286 | + * @param stream the output stream to which this keystore is written. | |
| 287 | + * @param password the password to generate the keystore integrity check | |
| 288 | + * | |
| 289 | + * @exception IOException if there was an I/O problem with data | |
| 290 | + * @exception NoSuchAlgorithmException if the appropriate data integrity | |
| 291 | + * algorithm could not be found | |
| 292 | + * @exception CertificateException if any of the certificates included in | |
| 293 | + * the keystore data could not be stored | |
| 294 | + */ | |
| 295 | + public abstract void engineStore(OutputStream stream, char[] password) | |
| 296 | + throws IOException, NoSuchAlgorithmException, CertificateException; | |
| 297 | + | |
| 298 | + /** | |
| 299 | + * Stores this keystore using the given | |
| 300 | + * <code>KeyStore.LoadStoreParmeter</code>. | |
| 301 | + * | |
| 302 | + * @param param the <code>KeyStore.LoadStoreParmeter</code> | |
| 303 | + * that specifies how to store the keystore, | |
| 304 | + * which may be <code>null</code> | |
| 305 | + * | |
| 306 | + * @exception IllegalArgumentException if the given | |
| 307 | + * <code>KeyStore.LoadStoreParmeter</code> | |
| 308 | + * input is not recognized | |
| 309 | + * @exception IOException if there was an I/O problem with data | |
| 310 | + * @exception NoSuchAlgorithmException if the appropriate data integrity | |
| 311 | + * algorithm could not be found | |
| 312 | + * @exception CertificateException if any of the certificates included in | |
| 313 | + * the keystore data could not be stored | |
| 314 | + * | |
| 315 | + * @since 1.5 | |
| 316 | + */ | |
| 317 | + public void engineStore(KeyStore.LoadStoreParameter param) | |
| 318 | + throws IOException, NoSuchAlgorithmException, | |
| 319 | + CertificateException { | |
| 320 | + throw new UnsupportedOperationException(); | |
| 321 | + } | |
| 322 | + | |
| 323 | + /** | |
| 324 | + * Loads the keystore from the given input stream. | |
| 325 | + * | |
| 326 | + * <p>A password may be given to unlock the keystore | |
| 327 | + * (e.g. the keystore resides on a hardware token device), | |
| 328 | + * or to check the integrity of the keystore data. | |
| 329 | + * If a password is not given for integrity checking, | |
| 330 | + * then integrity checking is not performed. | |
| 331 | + * | |
| 332 | + * @param stream the input stream from which the keystore is loaded, | |
| 333 | + * or <code>null</code> | |
| 334 | + * @param password the password used to check the integrity of | |
| 335 | + * the keystore, the password used to unlock the keystore, | |
| 336 | + * or <code>null</code> | |
| 337 | + * | |
| 338 | + * @exception IOException if there is an I/O or format problem with the | |
| 339 | + * keystore data, if a password is required but not given, | |
| 340 | + * or if the given password was incorrect. If the error is due to a | |
| 341 | + * wrong password, the {@link Throwable#getCause cause} of the | |
| 342 | + * <code>IOException</code> should be an | |
| 343 | + * <code>UnrecoverableKeyException</code> | |
| 344 | + * @exception NoSuchAlgorithmException if the algorithm used to check | |
| 345 | + * the integrity of the keystore cannot be found | |
| 346 | + * @exception CertificateException if any of the certificates in the | |
| 347 | + * keystore could not be loaded | |
| 348 | + */ | |
| 349 | + public abstract void engineLoad(InputStream stream, char[] password) | |
| 350 | + throws IOException, NoSuchAlgorithmException, CertificateException; | |
| 351 | + | |
| 352 | + /** | |
| 353 | + * Loads the keystore using the given | |
| 354 | + * <code>KeyStore.LoadStoreParameter</code>. | |
| 355 | + * | |
| 356 | + * <p> Note that if this KeyStore has already been loaded, it is | |
| 357 | + * reinitialized and loaded again from the given parameter. | |
| 358 | + * | |
| 359 | + * @param param the <code>KeyStore.LoadStoreParameter</code> | |
| 360 | + * that specifies how to load the keystore, | |
| 361 | + * which may be <code>null</code> | |
| 362 | + * | |
| 363 | + * @exception IllegalArgumentException if the given | |
| 364 | + * <code>KeyStore.LoadStoreParameter</code> | |
| 365 | + * input is not recognized | |
| 366 | + * @exception IOException if there is an I/O or format problem with the | |
| 367 | + * keystore data. If the error is due to an incorrect | |
| 368 | + * <code>ProtectionParameter</code> (e.g. wrong password) | |
| 369 | + * the {@link Throwable#getCause cause} of the | |
| 370 | + * <code>IOException</code> should be an | |
| 371 | + * <code>UnrecoverableKeyException</code> | |
| 372 | + * @exception NoSuchAlgorithmException if the algorithm used to check | |
| 373 | + * the integrity of the keystore cannot be found | |
| 374 | + * @exception CertificateException if any of the certificates in the | |
| 375 | + * keystore could not be loaded | |
| 376 | + * | |
| 377 | + * @since 1.5 | |
| 378 | + */ | |
| 379 | + public void engineLoad(KeyStore.LoadStoreParameter param) | |
| 380 | + throws IOException, NoSuchAlgorithmException, | |
| 381 | + CertificateException { | |
| 382 | + | |
| 383 | + if (param == null) { | |
| 384 | + engineLoad((InputStream)null, (char[])null); | |
| 385 | + return; | |
| 386 | + } | |
| 387 | + | |
| 388 | + if (param instanceof KeyStore.SimpleLoadStoreParameter) { | |
| 389 | + ProtectionParameter protection = param.getProtectionParameter(); | |
| 390 | + char[] password; | |
| 391 | + if (protection instanceof PasswordProtection) { | |
| 392 | + password = ((PasswordProtection)protection).getPassword(); | |
| 393 | + } else if (protection instanceof CallbackHandlerProtection) { | |
| 394 | + CallbackHandler handler = | |
| 395 | + ((CallbackHandlerProtection)protection).getCallbackHandler(); | |
| 396 | + PasswordCallback callback = | |
| 397 | + new PasswordCallback("Password: ", false); | |
| 398 | + try { | |
| 399 | + handler.handle(new Callback[] {callback}); | |
| 400 | + } catch (UnsupportedCallbackException e) { | |
| 401 | + throw new NoSuchAlgorithmException | |
| 402 | + ("Could not obtain password", e); | |
| 403 | + } | |
| 404 | + password = callback.getPassword(); | |
| 405 | + callback.clearPassword(); | |
| 406 | + if (password == null) { | |
| 407 | + throw new NoSuchAlgorithmException | |
| 408 | + ("No password provided"); | |
| 409 | + } | |
| 410 | + } else { | |
| 411 | + throw new NoSuchAlgorithmException("ProtectionParameter must" | |
| 412 | + + " be PasswordProtection or CallbackHandlerProtection"); | |
| 413 | + } | |
| 414 | + engineLoad(null, password); | |
| 415 | + return; | |
| 416 | + } | |
| 417 | + | |
| 418 | + throw new UnsupportedOperationException(); | |
| 419 | + } | |
| 420 | + | |
| 421 | + /** | |
| 422 | + * Gets a <code>KeyStore.Entry</code> for the specified alias | |
| 423 | + * with the specified protection parameter. | |
| 424 | + * | |
| 425 | + * @param alias get the <code>KeyStore.Entry</code> for this alias | |
| 426 | + * @param protParam the <code>ProtectionParameter</code> | |
| 427 | + * used to protect the <code>Entry</code>, | |
| 428 | + * which may be <code>null</code> | |
| 429 | + * | |
| 430 | + * @return the <code>KeyStore.Entry</code> for the specified alias, | |
| 431 | + * or <code>null</code> if there is no such entry | |
| 432 | + * | |
| 433 | + * @exception KeyStoreException if the operation failed | |
| 434 | + * @exception NoSuchAlgorithmException if the algorithm for recovering the | |
| 435 | + * entry cannot be found | |
| 436 | + * @exception UnrecoverableEntryException if the specified | |
| 437 | + * <code>protParam</code> were insufficient or invalid | |
| 438 | + * @exception UnrecoverableKeyException if the entry is a | |
| 439 | + * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code> | |
| 440 | + * and the specified <code>protParam</code> does not contain | |
| 441 | + * the information needed to recover the key (e.g. wrong password) | |
| 442 | + * | |
| 443 | + * @since 1.5 | |
| 444 | + */ | |
| 445 | + public KeyStore.Entry engineGetEntry(String alias, | |
| 446 | + KeyStore.ProtectionParameter protParam) | |
| 447 | + throws KeyStoreException, NoSuchAlgorithmException, | |
| 448 | + UnrecoverableEntryException { | |
| 449 | + | |
| 450 | + if (!engineContainsAlias(alias)) { | |
| 451 | + return null; | |
| 452 | + } | |
| 453 | + | |
| 454 | + if (protParam == null) { | |
| 455 | + if (engineIsCertificateEntry(alias)) { | |
| 456 | + return new KeyStore.TrustedCertificateEntry | |
| 457 | + (engineGetCertificate(alias)); | |
| 458 | + } else { | |
| 459 | + throw new UnrecoverableKeyException | |
| 460 | + ("requested entry requires a password"); | |
| 461 | + } | |
| 462 | + } | |
| 463 | + | |
| 464 | + if (protParam instanceof KeyStore.PasswordProtection) { | |
| 465 | + if (engineIsCertificateEntry(alias)) { | |
| 466 | + throw new UnsupportedOperationException | |
| 467 | + ("trusted certificate entries are not password-protected"); | |
| 468 | + } else if (engineIsKeyEntry(alias)) { | |
| 469 | + KeyStore.PasswordProtection pp = | |
| 470 | + (KeyStore.PasswordProtection)protParam; | |
| 471 | + char[] password = pp.getPassword(); | |
| 472 | + | |
| 473 | + Key key = engineGetKey(alias, password); | |
| 474 | + if (key instanceof PrivateKey) { | |
| 475 | + Certificate[] chain = engineGetCertificateChain(alias); | |
| 476 | + return new KeyStore.PrivateKeyEntry((PrivateKey)key, chain); | |
| 477 | + } else if (key instanceof SecretKey) { | |
| 478 | + return new KeyStore.SecretKeyEntry((SecretKey)key); | |
| 479 | + } | |
| 480 | + } | |
| 481 | + } | |
| 482 | + | |
| 483 | + throw new UnsupportedOperationException(); | |
| 484 | + } | |
| 485 | + | |
| 486 | + /** | |
| 487 | + * Saves a <code>KeyStore.Entry</code> under the specified alias. | |
| 488 | + * The specified protection parameter is used to protect the | |
| 489 | + * <code>Entry</code>. | |
| 490 | + * | |
| 491 | + * <p> If an entry already exists for the specified alias, | |
| 492 | + * it is overridden. | |
| 493 | + * | |
| 494 | + * @param alias save the <code>KeyStore.Entry</code> under this alias | |
| 495 | + * @param entry the <code>Entry</code> to save | |
| 496 | + * @param protParam the <code>ProtectionParameter</code> | |
| 497 | + * used to protect the <code>Entry</code>, | |
| 498 | + * which may be <code>null</code> | |
| 499 | + * | |
| 500 | + * @exception KeyStoreException if this operation fails | |
| 501 | + * | |
| 502 | + * @since 1.5 | |
| 503 | + */ | |
| 504 | + public void engineSetEntry(String alias, KeyStore.Entry entry, | |
| 505 | + KeyStore.ProtectionParameter protParam) | |
| 506 | + throws KeyStoreException { | |
| 507 | + | |
| 508 | + // get password | |
| 509 | + if (protParam != null && | |
| 510 | + !(protParam instanceof KeyStore.PasswordProtection)) { | |
| 511 | + throw new KeyStoreException("unsupported protection parameter"); | |
| 512 | + } | |
| 513 | + KeyStore.PasswordProtection pProtect = null; | |
| 514 | + if (protParam != null) { | |
| 515 | + pProtect = (KeyStore.PasswordProtection)protParam; | |
| 516 | + } | |
| 517 | + | |
| 518 | + // set entry | |
| 519 | + if (entry instanceof KeyStore.TrustedCertificateEntry) { | |
| 520 | + if (protParam != null && pProtect.getPassword() != null) { | |
| 521 | + // pre-1.5 style setCertificateEntry did not allow password | |
| 522 | + throw new KeyStoreException | |
| 523 | + ("trusted certificate entries are not password-protected"); | |
| 524 | + } else { | |
| 525 | + KeyStore.TrustedCertificateEntry tce = | |
| 526 | + (KeyStore.TrustedCertificateEntry)entry; | |
| 527 | + engineSetCertificateEntry(alias, tce.getTrustedCertificate()); | |
| 528 | + return; | |
| 529 | + } | |
| 530 | + } else if (entry instanceof KeyStore.PrivateKeyEntry) { | |
| 531 | + if (pProtect == null || pProtect.getPassword() == null) { | |
| 532 | + // pre-1.5 style setKeyEntry required password | |
| 533 | + throw new KeyStoreException | |
| 534 | + ("non-null password required to create PrivateKeyEntry"); | |
| 535 | + } else { | |
| 536 | + engineSetKeyEntry | |
| 537 | + (alias, | |
| 538 | + ((KeyStore.PrivateKeyEntry)entry).getPrivateKey(), | |
| 539 | + pProtect.getPassword(), | |
| 540 | + ((KeyStore.PrivateKeyEntry)entry).getCertificateChain()); | |
| 541 | + return; | |
| 542 | + } | |
| 543 | + } else if (entry instanceof KeyStore.SecretKeyEntry) { | |
| 544 | + if (pProtect == null || pProtect.getPassword() == null) { | |
| 545 | + // pre-1.5 style setKeyEntry required password | |
| 546 | + throw new KeyStoreException | |
| 547 | + ("non-null password required to create SecretKeyEntry"); | |
| 548 | + } else { | |
| 549 | + engineSetKeyEntry | |
| 550 | + (alias, | |
| 551 | + ((KeyStore.SecretKeyEntry)entry).getSecretKey(), | |
| 552 | + pProtect.getPassword(), | |
| 553 | + (Certificate[])null); | |
| 554 | + return; | |
| 555 | + } | |
| 556 | + } | |
| 557 | + | |
| 558 | + throw new KeyStoreException | |
| 559 | + ("unsupported entry type: " + entry.getClass().getName()); | |
| 560 | + } | |
| 561 | + | |
| 562 | + /** | |
| 563 | + * Determines if the keystore <code>Entry</code> for the specified | |
| 564 | + * <code>alias</code> is an instance or subclass of the specified | |
| 565 | + * <code>entryClass</code>. | |
| 566 | + * | |
| 567 | + * @param alias the alias name | |
| 568 | + * @param entryClass the entry class | |
| 569 | + * | |
| 570 | + * @return true if the keystore <code>Entry</code> for the specified | |
| 571 | + * <code>alias</code> is an instance or subclass of the | |
| 572 | + * specified <code>entryClass</code>, false otherwise | |
| 573 | + * | |
| 574 | + * @since 1.5 | |
| 575 | + */ | |
| 576 | + public boolean | |
| 577 | + engineEntryInstanceOf(String alias, | |
| 578 | + Class<? extends KeyStore.Entry> entryClass) | |
| 579 | + { | |
| 580 | + if (entryClass == KeyStore.TrustedCertificateEntry.class) { | |
| 581 | + return engineIsCertificateEntry(alias); | |
| 582 | + } | |
| 583 | + if (entryClass == KeyStore.PrivateKeyEntry.class) { | |
| 584 | + return engineIsKeyEntry(alias) && | |
| 585 | + engineGetCertificate(alias) != null; | |
| 586 | + } | |
| 587 | + if (entryClass == KeyStore.SecretKeyEntry.class) { | |
| 588 | + return engineIsKeyEntry(alias) && | |
| 589 | + engineGetCertificate(alias) == null; | |
| 590 | + } | |
| 591 | + return false; | |
| 592 | + } | |
| 593 | +} | |
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,588 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.util.*; | |
| 29 | +import java.lang.*; | |
| 30 | +import java.io.IOException; | |
| 31 | +import java.io.ByteArrayOutputStream; | |
| 32 | +import java.io.PrintStream; | |
| 33 | +import java.io.InputStream; | |
| 34 | +import java.io.ByteArrayInputStream; | |
| 35 | + | |
| 36 | +import java.nio.ByteBuffer; | |
| 37 | + | |
| 38 | +/** | |
| 39 | + * This MessageDigest class provides applications the functionality of a | |
| 40 | + * message digest algorithm, such as SHA-1 or SHA-256. | |
| 41 | + * Message digests are secure one-way hash functions that take arbitrary-sized | |
| 42 | + * data and output a fixed-length hash value. | |
| 43 | + * | |
| 44 | + * <p>A MessageDigest object starts out initialized. The data is | |
| 45 | + * processed through it using the {@link #update(byte) update} | |
| 46 | + * methods. At any point {@link #reset() reset} can be called | |
| 47 | + * to reset the digest. Once all the data to be updated has been | |
| 48 | + * updated, one of the {@link #digest() digest} methods should | |
| 49 | + * be called to complete the hash computation. | |
| 50 | + * | |
| 51 | + * <p>The <code>digest</code> method can be called once for a given number | |
| 52 | + * of updates. After <code>digest</code> has been called, the MessageDigest | |
| 53 | + * object is reset to its initialized state. | |
| 54 | + * | |
| 55 | + * <p>Implementations are free to implement the Cloneable interface. | |
| 56 | + * Client applications can test cloneability by attempting cloning | |
| 57 | + * and catching the CloneNotSupportedException: <p> | |
| 58 | + * | |
| 59 | +* <pre> | |
| 60 | +* MessageDigest md = MessageDigest.getInstance("SHA"); | |
| 61 | +* | |
| 62 | +* try { | |
| 63 | +* md.update(toChapter1); | |
| 64 | +* MessageDigest tc1 = md.clone(); | |
| 65 | +* byte[] toChapter1Digest = tc1.digest(); | |
| 66 | +* md.update(toChapter2); | |
| 67 | +* ...etc. | |
| 68 | +* } catch (CloneNotSupportedException cnse) { | |
| 69 | +* throw new DigestException("couldn't make digest of partial content"); | |
| 70 | +* } | |
| 71 | +* </pre> | |
| 72 | + * | |
| 73 | + * <p>Note that if a given implementation is not cloneable, it is | |
| 74 | + * still possible to compute intermediate digests by instantiating | |
| 75 | + * several instances, if the number of digests is known in advance. | |
| 76 | + * | |
| 77 | + * <p>Note that this class is abstract and extends from | |
| 78 | + * <code>MessageDigestSpi</code> for historical reasons. | |
| 79 | + * Application developers should only take notice of the methods defined in | |
| 80 | + * this <code>MessageDigest</code> class; all the methods in | |
| 81 | + * the superclass are intended for cryptographic service providers who wish to | |
| 82 | + * supply their own implementations of message digest algorithms. | |
| 83 | + * | |
| 84 | + * <p> Every implementation of the Java platform is required to support | |
| 85 | + * the following standard <code>MessageDigest</code> algorithms: | |
| 86 | + * <ul> | |
| 87 | + * <li><tt>MD5</tt></li> | |
| 88 | + * <li><tt>SHA-1</tt></li> | |
| 89 | + * <li><tt>SHA-256</tt></li> | |
| 90 | + * </ul> | |
| 91 | + * These algorithms are described in the <a href= | |
| 92 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> | |
| 93 | + * MessageDigest section</a> of the | |
| 94 | + * Java Cryptography Architecture Standard Algorithm Name Documentation. | |
| 95 | + * Consult the release documentation for your implementation to see if any | |
| 96 | + * other algorithms are supported. | |
| 97 | + * | |
| 98 | + * @author Benjamin Renaud | |
| 99 | + * | |
| 100 | + * @see DigestInputStream | |
| 101 | + * @see DigestOutputStream | |
| 102 | + */ | |
| 103 | + | |
| 104 | +public abstract class MessageDigest extends MessageDigestSpi { | |
| 105 | + | |
| 106 | + private String algorithm; | |
| 107 | + | |
| 108 | + // The state of this digest | |
| 109 | + private static final int INITIAL = 0; | |
| 110 | + private static final int IN_PROGRESS = 1; | |
| 111 | + private int state = INITIAL; | |
| 112 | + | |
| 113 | + // The provider | |
| 114 | + private Provider provider; | |
| 115 | + | |
| 116 | + /** | |
| 117 | + * Creates a message digest with the specified algorithm name. | |
| 118 | + * | |
| 119 | + * @param algorithm the standard name of the digest algorithm. | |
| 120 | + * See the MessageDigest section in the <a href= | |
| 121 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> | |
| 122 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 123 | + * for information about standard algorithm names. | |
| 124 | + */ | |
| 125 | + protected MessageDigest(String algorithm) { | |
| 126 | + this.algorithm = algorithm; | |
| 127 | + } | |
| 128 | + | |
| 129 | + /** | |
| 130 | + * Returns a MessageDigest object that implements the specified digest | |
| 131 | + * algorithm. | |
| 132 | + * | |
| 133 | + * <p> This method traverses the list of registered security Providers, | |
| 134 | + * starting with the most preferred Provider. | |
| 135 | + * A new MessageDigest object encapsulating the | |
| 136 | + * MessageDigestSpi implementation from the first | |
| 137 | + * Provider that supports the specified algorithm is returned. | |
| 138 | + * | |
| 139 | + * <p> Note that the list of registered providers may be retrieved via | |
| 140 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 141 | + * | |
| 142 | + * @param algorithm the name of the algorithm requested. | |
| 143 | + * See the MessageDigest section in the <a href= | |
| 144 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> | |
| 145 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 146 | + * for information about standard algorithm names. | |
| 147 | + * | |
| 148 | + * @return a Message Digest object that implements the specified algorithm. | |
| 149 | + * | |
| 150 | + * @exception NoSuchAlgorithmException if no Provider supports a | |
| 151 | + * MessageDigestSpi implementation for the | |
| 152 | + * specified algorithm. | |
| 153 | + * | |
| 154 | + * @see Provider | |
| 155 | + */ | |
| 156 | + public static MessageDigest getInstance(String algorithm) | |
| 157 | + throws NoSuchAlgorithmException { | |
| 158 | + try { | |
| 159 | + Object[] objs = Security.getImpl(algorithm, "MessageDigest", | |
| 160 | + (String)null); | |
| 161 | + if (objs[0] instanceof MessageDigest) { | |
| 162 | + MessageDigest md = (MessageDigest)objs[0]; | |
| 163 | + md.provider = (Provider)objs[1]; | |
| 164 | + return md; | |
| 165 | + } else { | |
| 166 | + MessageDigest delegate = | |
| 167 | + new Delegate((MessageDigestSpi)objs[0], algorithm); | |
| 168 | + delegate.provider = (Provider)objs[1]; | |
| 169 | + return delegate; | |
| 170 | + } | |
| 171 | + } catch(NoSuchProviderException e) { | |
| 172 | + throw new NoSuchAlgorithmException(algorithm + " not found"); | |
| 173 | + } | |
| 174 | + } | |
| 175 | + | |
| 176 | + /** | |
| 177 | + * Returns a MessageDigest object that implements the specified digest | |
| 178 | + * algorithm. | |
| 179 | + * | |
| 180 | + * <p> A new MessageDigest object encapsulating the | |
| 181 | + * MessageDigestSpi implementation from the specified provider | |
| 182 | + * is returned. The specified provider must be registered | |
| 183 | + * in the security provider list. | |
| 184 | + * | |
| 185 | + * <p> Note that the list of registered providers may be retrieved via | |
| 186 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 187 | + * | |
| 188 | + * @param algorithm the name of the algorithm requested. | |
| 189 | + * See the MessageDigest section in the <a href= | |
| 190 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> | |
| 191 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 192 | + * for information about standard algorithm names. | |
| 193 | + * | |
| 194 | + * @param provider the name of the provider. | |
| 195 | + * | |
| 196 | + * @return a MessageDigest object that implements the specified algorithm. | |
| 197 | + * | |
| 198 | + * @exception NoSuchAlgorithmException if a MessageDigestSpi | |
| 199 | + * implementation for the specified algorithm is not | |
| 200 | + * available from the specified provider. | |
| 201 | + * | |
| 202 | + * @exception NoSuchProviderException if the specified provider is not | |
| 203 | + * registered in the security provider list. | |
| 204 | + * | |
| 205 | + * @exception IllegalArgumentException if the provider name is null | |
| 206 | + * or empty. | |
| 207 | + * | |
| 208 | + * @see Provider | |
| 209 | + */ | |
| 210 | + public static MessageDigest getInstance(String algorithm, String provider) | |
| 211 | + throws NoSuchAlgorithmException, NoSuchProviderException | |
| 212 | + { | |
| 213 | + if (provider == null || provider.length() == 0) | |
| 214 | + throw new IllegalArgumentException("missing provider"); | |
| 215 | + Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider); | |
| 216 | + if (objs[0] instanceof MessageDigest) { | |
| 217 | + MessageDigest md = (MessageDigest)objs[0]; | |
| 218 | + md.provider = (Provider)objs[1]; | |
| 219 | + return md; | |
| 220 | + } else { | |
| 221 | + MessageDigest delegate = | |
| 222 | + new Delegate((MessageDigestSpi)objs[0], algorithm); | |
| 223 | + delegate.provider = (Provider)objs[1]; | |
| 224 | + return delegate; | |
| 225 | + } | |
| 226 | + } | |
| 227 | + | |
| 228 | + /** | |
| 229 | + * Returns a MessageDigest object that implements the specified digest | |
| 230 | + * algorithm. | |
| 231 | + * | |
| 232 | + * <p> A new MessageDigest object encapsulating the | |
| 233 | + * MessageDigestSpi implementation from the specified Provider | |
| 234 | + * object is returned. Note that the specified Provider object | |
| 235 | + * does not have to be registered in the provider list. | |
| 236 | + * | |
| 237 | + * @param algorithm the name of the algorithm requested. | |
| 238 | + * See the MessageDigest section in the <a href= | |
| 239 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> | |
| 240 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 241 | + * for information about standard algorithm names. | |
| 242 | + * | |
| 243 | + * @param provider the provider. | |
| 244 | + * | |
| 245 | + * @return a MessageDigest object that implements the specified algorithm. | |
| 246 | + * | |
| 247 | + * @exception NoSuchAlgorithmException if a MessageDigestSpi | |
| 248 | + * implementation for the specified algorithm is not available | |
| 249 | + * from the specified Provider object. | |
| 250 | + * | |
| 251 | + * @exception IllegalArgumentException if the specified provider is null. | |
| 252 | + * | |
| 253 | + * @see Provider | |
| 254 | + * | |
| 255 | + * @since 1.4 | |
| 256 | + */ | |
| 257 | + public static MessageDigest getInstance(String algorithm, | |
| 258 | + Provider provider) | |
| 259 | + throws NoSuchAlgorithmException | |
| 260 | + { | |
| 261 | + if (provider == null) | |
| 262 | + throw new IllegalArgumentException("missing provider"); | |
| 263 | + Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider); | |
| 264 | + if (objs[0] instanceof MessageDigest) { | |
| 265 | + MessageDigest md = (MessageDigest)objs[0]; | |
| 266 | + md.provider = (Provider)objs[1]; | |
| 267 | + return md; | |
| 268 | + } else { | |
| 269 | + MessageDigest delegate = | |
| 270 | + new Delegate((MessageDigestSpi)objs[0], algorithm); | |
| 271 | + delegate.provider = (Provider)objs[1]; | |
| 272 | + return delegate; | |
| 273 | + } | |
| 274 | + } | |
| 275 | + | |
| 276 | + /** | |
| 277 | + * Returns the provider of this message digest object. | |
| 278 | + * | |
| 279 | + * @return the provider of this message digest object | |
| 280 | + */ | |
| 281 | + public final Provider getProvider() { | |
| 282 | + return this.provider; | |
| 283 | + } | |
| 284 | + | |
| 285 | + /** | |
| 286 | + * Updates the digest using the specified byte. | |
| 287 | + * | |
| 288 | + * @param input the byte with which to update the digest. | |
| 289 | + */ | |
| 290 | + public void update(byte input) { | |
| 291 | + engineUpdate(input); | |
| 292 | + state = IN_PROGRESS; | |
| 293 | + } | |
| 294 | + | |
| 295 | + /** | |
| 296 | + * Updates the digest using the specified array of bytes, starting | |
| 297 | + * at the specified offset. | |
| 298 | + * | |
| 299 | + * @param input the array of bytes. | |
| 300 | + * | |
| 301 | + * @param offset the offset to start from in the array of bytes. | |
| 302 | + * | |
| 303 | + * @param len the number of bytes to use, starting at | |
| 304 | + * <code>offset</code>. | |
| 305 | + */ | |
| 306 | + public void update(byte[] input, int offset, int len) { | |
| 307 | + if (input == null) { | |
| 308 | + throw new IllegalArgumentException("No input buffer given"); | |
| 309 | + } | |
| 310 | + if (input.length - offset < len) { | |
| 311 | + throw new IllegalArgumentException("Input buffer too short"); | |
| 312 | + } | |
| 313 | + engineUpdate(input, offset, len); | |
| 314 | + state = IN_PROGRESS; | |
| 315 | + } | |
| 316 | + | |
| 317 | + /** | |
| 318 | + * Updates the digest using the specified array of bytes. | |
| 319 | + * | |
| 320 | + * @param input the array of bytes. | |
| 321 | + */ | |
| 322 | + public void update(byte[] input) { | |
| 323 | + engineUpdate(input, 0, input.length); | |
| 324 | + state = IN_PROGRESS; | |
| 325 | + } | |
| 326 | + | |
| 327 | + /** | |
| 328 | + * Update the digest using the specified ByteBuffer. The digest is | |
| 329 | + * updated using the <code>input.remaining()</code> bytes starting | |
| 330 | + * at <code>input.position()</code>. | |
| 331 | + * Upon return, the buffer's position will be equal to its limit; | |
| 332 | + * its limit will not have changed. | |
| 333 | + * | |
| 334 | + * @param input the ByteBuffer | |
| 335 | + * @since 1.5 | |
| 336 | + */ | |
| 337 | + public final void update(ByteBuffer input) { | |
| 338 | + if (input == null) { | |
| 339 | + throw new NullPointerException(); | |
| 340 | + } | |
| 341 | + engineUpdate(input); | |
| 342 | + state = IN_PROGRESS; | |
| 343 | + } | |
| 344 | + | |
| 345 | + /** | |
| 346 | + * Completes the hash computation by performing final operations | |
| 347 | + * such as padding. The digest is reset after this call is made. | |
| 348 | + * | |
| 349 | + * @return the array of bytes for the resulting hash value. | |
| 350 | + */ | |
| 351 | + public byte[] digest() { | |
| 352 | + /* Resetting is the responsibility of implementors. */ | |
| 353 | + byte[] result = engineDigest(); | |
| 354 | + state = INITIAL; | |
| 355 | + return result; | |
| 356 | + } | |
| 357 | + | |
| 358 | + /** | |
| 359 | + * Completes the hash computation by performing final operations | |
| 360 | + * such as padding. The digest is reset after this call is made. | |
| 361 | + * | |
| 362 | + * @param buf output buffer for the computed digest | |
| 363 | + * | |
| 364 | + * @param offset offset into the output buffer to begin storing the digest | |
| 365 | + * | |
| 366 | + * @param len number of bytes within buf allotted for the digest | |
| 367 | + * | |
| 368 | + * @return the number of bytes placed into <code>buf</code> | |
| 369 | + * | |
| 370 | + * @exception DigestException if an error occurs. | |
| 371 | + */ | |
| 372 | + public int digest(byte[] buf, int offset, int len) throws DigestException { | |
| 373 | + if (buf == null) { | |
| 374 | + throw new IllegalArgumentException("No output buffer given"); | |
| 375 | + } | |
| 376 | + if (buf.length - offset < len) { | |
| 377 | + throw new IllegalArgumentException | |
| 378 | + ("Output buffer too small for specified offset and length"); | |
| 379 | + } | |
| 380 | + int numBytes = engineDigest(buf, offset, len); | |
| 381 | + state = INITIAL; | |
| 382 | + return numBytes; | |
| 383 | + } | |
| 384 | + | |
| 385 | + /** | |
| 386 | + * Performs a final update on the digest using the specified array | |
| 387 | + * of bytes, then completes the digest computation. That is, this | |
| 388 | + * method first calls {@link #update(byte[]) update(input)}, | |
| 389 | + * passing the <i>input</i> array to the <code>update</code> method, | |
| 390 | + * then calls {@link #digest() digest()}. | |
| 391 | + * | |
| 392 | + * @param input the input to be updated before the digest is | |
| 393 | + * completed. | |
| 394 | + * | |
| 395 | + * @return the array of bytes for the resulting hash value. | |
| 396 | + */ | |
| 397 | + public byte[] digest(byte[] input) { | |
| 398 | + update(input); | |
| 399 | + return digest(); | |
| 400 | + } | |
| 401 | + | |
| 402 | + /** | |
| 403 | + * Returns a string representation of this message digest object. | |
| 404 | + */ | |
| 405 | + public String toString() { | |
| 406 | + ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
| 407 | + PrintStream p = new PrintStream(baos); | |
| 408 | + p.print(algorithm+" Message Digest from "+provider.getName()+", "); | |
| 409 | + switch (state) { | |
| 410 | + case INITIAL: | |
| 411 | + p.print("<initialized>"); | |
| 412 | + break; | |
| 413 | + case IN_PROGRESS: | |
| 414 | + p.print("<in progress>"); | |
| 415 | + break; | |
| 416 | + } | |
| 417 | + p.println(); | |
| 418 | + return (baos.toString()); | |
| 419 | + } | |
| 420 | + | |
| 421 | + /** | |
| 422 | + * Compares two digests for equality. Does a simple byte compare. | |
| 423 | + * | |
| 424 | + * @param digesta one of the digests to compare. | |
| 425 | + * | |
| 426 | + * @param digestb the other digest to compare. | |
| 427 | + * | |
| 428 | + * @return true if the digests are equal, false otherwise. | |
| 429 | + */ | |
| 430 | + public static boolean isEqual(byte[] digesta, byte[] digestb) { | |
| 431 | + if (digesta.length != digestb.length) { | |
| 432 | + return false; | |
| 433 | + } | |
| 434 | + | |
| 435 | + int result = 0; | |
| 436 | + // time-constant comparison | |
| 437 | + for (int i = 0; i < digesta.length; i++) { | |
| 438 | + result |= digesta[i] ^ digestb[i]; | |
| 439 | + } | |
| 440 | + return result == 0; | |
| 441 | + } | |
| 442 | + | |
| 443 | + /** | |
| 444 | + * Resets the digest for further use. | |
| 445 | + */ | |
| 446 | + public void reset() { | |
| 447 | + engineReset(); | |
| 448 | + state = INITIAL; | |
| 449 | + } | |
| 450 | + | |
| 451 | + /** | |
| 452 | + * Returns a string that identifies the algorithm, independent of | |
| 453 | + * implementation details. The name should be a standard | |
| 454 | + * Java Security name (such as "SHA", "MD5", and so on). | |
| 455 | + * See the MessageDigest section in the <a href= | |
| 456 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest"> | |
| 457 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 458 | + * for information about standard algorithm names. | |
| 459 | + * | |
| 460 | + * @return the name of the algorithm | |
| 461 | + */ | |
| 462 | + public final String getAlgorithm() { | |
| 463 | + return this.algorithm; | |
| 464 | + } | |
| 465 | + | |
| 466 | + /** | |
| 467 | + * Returns the length of the digest in bytes, or 0 if this operation is | |
| 468 | + * not supported by the provider and the implementation is not cloneable. | |
| 469 | + * | |
| 470 | + * @return the digest length in bytes, or 0 if this operation is not | |
| 471 | + * supported by the provider and the implementation is not cloneable. | |
| 472 | + * | |
| 473 | + * @since 1.2 | |
| 474 | + */ | |
| 475 | + public final int getDigestLength() { | |
| 476 | + int digestLen = engineGetDigestLength(); | |
| 477 | + if (digestLen == 0) { | |
| 478 | + try { | |
| 479 | + MessageDigest md = (MessageDigest)clone(); | |
| 480 | + byte[] digest = md.digest(); | |
| 481 | + return digest.length; | |
| 482 | + } catch (CloneNotSupportedException e) { | |
| 483 | + return digestLen; | |
| 484 | + } | |
| 485 | + } | |
| 486 | + return digestLen; | |
| 487 | + } | |
| 488 | + | |
| 489 | + /** | |
| 490 | + * Returns a clone if the implementation is cloneable. | |
| 491 | + * | |
| 492 | + * @return a clone if the implementation is cloneable. | |
| 493 | + * | |
| 494 | + * @exception CloneNotSupportedException if this is called on an | |
| 495 | + * implementation that does not support <code>Cloneable</code>. | |
| 496 | + */ | |
| 497 | + public Object clone() throws CloneNotSupportedException { | |
| 498 | + if (this instanceof Cloneable) { | |
| 499 | + return super.clone(); | |
| 500 | + } else { | |
| 501 | + throw new CloneNotSupportedException(); | |
| 502 | + } | |
| 503 | + } | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + /* | |
| 509 | + * The following class allows providers to extend from MessageDigestSpi | |
| 510 | + * rather than from MessageDigest. It represents a MessageDigest with an | |
| 511 | + * encapsulated, provider-supplied SPI object (of type MessageDigestSpi). | |
| 512 | + * If the provider implementation is an instance of MessageDigestSpi, | |
| 513 | + * the getInstance() methods above return an instance of this class, with | |
| 514 | + * the SPI object encapsulated. | |
| 515 | + * | |
| 516 | + * Note: All SPI methods from the original MessageDigest class have been | |
| 517 | + * moved up the hierarchy into a new class (MessageDigestSpi), which has | |
| 518 | + * been interposed in the hierarchy between the API (MessageDigest) | |
| 519 | + * and its original parent (Object). | |
| 520 | + */ | |
| 521 | + | |
| 522 | + static class Delegate extends MessageDigest { | |
| 523 | + | |
| 524 | + // The provider implementation (delegate) | |
| 525 | + private MessageDigestSpi digestSpi; | |
| 526 | + | |
| 527 | + // constructor | |
| 528 | + public Delegate(MessageDigestSpi digestSpi, String algorithm) { | |
| 529 | + super(algorithm); | |
| 530 | + this.digestSpi = digestSpi; | |
| 531 | + } | |
| 532 | + | |
| 533 | + /** | |
| 534 | + * Returns a clone if the delegate is cloneable. | |
| 535 | + * | |
| 536 | + * @return a clone if the delegate is cloneable. | |
| 537 | + * | |
| 538 | + * @exception CloneNotSupportedException if this is called on a | |
| 539 | + * delegate that does not support <code>Cloneable</code>. | |
| 540 | + */ | |
| 541 | + public Object clone() throws CloneNotSupportedException { | |
| 542 | + if (digestSpi instanceof Cloneable) { | |
| 543 | + MessageDigestSpi digestSpiClone = | |
| 544 | + (MessageDigestSpi)digestSpi.clone(); | |
| 545 | + // Because 'algorithm', 'provider', and 'state' are private | |
| 546 | + // members of our supertype, we must perform a cast to | |
| 547 | + // access them. | |
| 548 | + MessageDigest that = | |
| 549 | + new Delegate(digestSpiClone, | |
| 550 | + ((MessageDigest)this).algorithm); | |
| 551 | + that.provider = ((MessageDigest)this).provider; | |
| 552 | + that.state = ((MessageDigest)this).state; | |
| 553 | + return that; | |
| 554 | + } else { | |
| 555 | + throw new CloneNotSupportedException(); | |
| 556 | + } | |
| 557 | + } | |
| 558 | + | |
| 559 | + protected int engineGetDigestLength() { | |
| 560 | + return digestSpi.engineGetDigestLength(); | |
| 561 | + } | |
| 562 | + | |
| 563 | + protected void engineUpdate(byte input) { | |
| 564 | + digestSpi.engineUpdate(input); | |
| 565 | + } | |
| 566 | + | |
| 567 | + protected void engineUpdate(byte[] input, int offset, int len) { | |
| 568 | + digestSpi.engineUpdate(input, offset, len); | |
| 569 | + } | |
| 570 | + | |
| 571 | + protected void engineUpdate(ByteBuffer input) { | |
| 572 | + digestSpi.engineUpdate(input); | |
| 573 | + } | |
| 574 | + | |
| 575 | + protected byte[] engineDigest() { | |
| 576 | + return digestSpi.engineDigest(); | |
| 577 | + } | |
| 578 | + | |
| 579 | + protected int engineDigest(byte[] buf, int offset, int len) | |
| 580 | + throws DigestException { | |
| 581 | + return digestSpi.engineDigest(buf, offset, len); | |
| 582 | + } | |
| 583 | + | |
| 584 | + protected void engineReset() { | |
| 585 | + digestSpi.engineReset(); | |
| 586 | + } | |
| 587 | + } | |
| 588 | +} | |
Binary file not shown.
| @@ -0,0 +1,206 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.nio.ByteBuffer; | |
| 29 | + | |
| 30 | +import sun.security.jca.JCAUtil; | |
| 31 | + | |
| 32 | +/** | |
| 33 | + * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) | |
| 34 | + * for the <code>MessageDigest</code> class, which provides the functionality | |
| 35 | + * of a message digest algorithm, such as MD5 or SHA. Message digests are | |
| 36 | + * secure one-way hash functions that take arbitrary-sized data and output a | |
| 37 | + * fixed-length hash value. | |
| 38 | + * | |
| 39 | + * <p> All the abstract methods in this class must be implemented by a | |
| 40 | + * cryptographic service provider who wishes to supply the implementation | |
| 41 | + * of a particular message digest algorithm. | |
| 42 | + * | |
| 43 | + * <p> Implementations are free to implement the Cloneable interface. | |
| 44 | + * | |
| 45 | + * @author Benjamin Renaud | |
| 46 | + * | |
| 47 | + * | |
| 48 | + * @see MessageDigest | |
| 49 | + */ | |
| 50 | + | |
| 51 | +public abstract class MessageDigestSpi { | |
| 52 | + | |
| 53 | + // for re-use in engineUpdate(ByteBuffer input) | |
| 54 | + private byte[] tempArray; | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * Returns the digest length in bytes. | |
| 58 | + * | |
| 59 | + * <p>This concrete method has been added to this previously-defined | |
| 60 | + * abstract class. (For backwards compatibility, it cannot be abstract.) | |
| 61 | + * | |
| 62 | + * <p>The default behavior is to return 0. | |
| 63 | + * | |
| 64 | + * <p>This method may be overridden by a provider to return the digest | |
| 65 | + * length. | |
| 66 | + * | |
| 67 | + * @return the digest length in bytes. | |
| 68 | + * | |
| 69 | + * @since 1.2 | |
| 70 | + */ | |
| 71 | + protected int engineGetDigestLength() { | |
| 72 | + return 0; | |
| 73 | + } | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * Updates the digest using the specified byte. | |
| 77 | + * | |
| 78 | + * @param input the byte to use for the update. | |
| 79 | + */ | |
| 80 | + protected abstract void engineUpdate(byte input); | |
| 81 | + | |
| 82 | + /** | |
| 83 | + * Updates the digest using the specified array of bytes, | |
| 84 | + * starting at the specified offset. | |
| 85 | + * | |
| 86 | + * @param input the array of bytes to use for the update. | |
| 87 | + * | |
| 88 | + * @param offset the offset to start from in the array of bytes. | |
| 89 | + * | |
| 90 | + * @param len the number of bytes to use, starting at | |
| 91 | + * <code>offset</code>. | |
| 92 | + */ | |
| 93 | + protected abstract void engineUpdate(byte[] input, int offset, int len); | |
| 94 | + | |
| 95 | + /** | |
| 96 | + * Update the digest using the specified ByteBuffer. The digest is | |
| 97 | + * updated using the <code>input.remaining()</code> bytes starting | |
| 98 | + * at <code>input.position()</code>. | |
| 99 | + * Upon return, the buffer's position will be equal to its limit; | |
| 100 | + * its limit will not have changed. | |
| 101 | + * | |
| 102 | + * @param input the ByteBuffer | |
| 103 | + * @since 1.5 | |
| 104 | + */ | |
| 105 | + protected void engineUpdate(ByteBuffer input) { | |
| 106 | + if (input.hasRemaining() == false) { | |
| 107 | + return; | |
| 108 | + } | |
| 109 | + if (input.hasArray()) { | |
| 110 | + byte[] b = input.array(); | |
| 111 | + int ofs = input.arrayOffset(); | |
| 112 | + int pos = input.position(); | |
| 113 | + int lim = input.limit(); | |
| 114 | + engineUpdate(b, ofs + pos, lim - pos); | |
| 115 | + input.position(lim); | |
| 116 | + } else { | |
| 117 | + int len = input.remaining(); | |
| 118 | + int n = JCAUtil.getTempArraySize(len); | |
| 119 | + if ((tempArray == null) || (n > tempArray.length)) { | |
| 120 | + tempArray = new byte[n]; | |
| 121 | + } | |
| 122 | + while (len > 0) { | |
| 123 | + int chunk = Math.min(len, tempArray.length); | |
| 124 | + input.get(tempArray, 0, chunk); | |
| 125 | + engineUpdate(tempArray, 0, chunk); | |
| 126 | + len -= chunk; | |
| 127 | + } | |
| 128 | + } | |
| 129 | + } | |
| 130 | + | |
| 131 | + /** | |
| 132 | + * Completes the hash computation by performing final | |
| 133 | + * operations such as padding. Once <code>engineDigest</code> has | |
| 134 | + * been called, the engine should be reset (see | |
| 135 | + * {@link #engineReset() engineReset}). | |
| 136 | + * Resetting is the responsibility of the | |
| 137 | + * engine implementor. | |
| 138 | + * | |
| 139 | + * @return the array of bytes for the resulting hash value. | |
| 140 | + */ | |
| 141 | + protected abstract byte[] engineDigest(); | |
| 142 | + | |
| 143 | + /** | |
| 144 | + * Completes the hash computation by performing final | |
| 145 | + * operations such as padding. Once <code>engineDigest</code> has | |
| 146 | + * been called, the engine should be reset (see | |
| 147 | + * {@link #engineReset() engineReset}). | |
| 148 | + * Resetting is the responsibility of the | |
| 149 | + * engine implementor. | |
| 150 | + * | |
| 151 | + * This method should be abstract, but we leave it concrete for | |
| 152 | + * binary compatibility. Knowledgeable providers should override this | |
| 153 | + * method. | |
| 154 | + * | |
| 155 | + * @param buf the output buffer in which to store the digest | |
| 156 | + * | |
| 157 | + * @param offset offset to start from in the output buffer | |
| 158 | + * | |
| 159 | + * @param len number of bytes within buf allotted for the digest. | |
| 160 | + * Both this default implementation and the SUN provider do not | |
| 161 | + * return partial digests. The presence of this parameter is solely | |
| 162 | + * for consistency in our API's. If the value of this parameter is less | |
| 163 | + * than the actual digest length, the method will throw a DigestException. | |
| 164 | + * This parameter is ignored if its value is greater than or equal to | |
| 165 | + * the actual digest length. | |
| 166 | + * | |
| 167 | + * @return the length of the digest stored in the output buffer. | |
| 168 | + * | |
| 169 | + * @exception DigestException if an error occurs. | |
| 170 | + * | |
| 171 | + * @since 1.2 | |
| 172 | + */ | |
| 173 | + protected int engineDigest(byte[] buf, int offset, int len) | |
| 174 | + throws DigestException { | |
| 175 | + | |
| 176 | + byte[] digest = engineDigest(); | |
| 177 | + if (len < digest.length) | |
| 178 | + throw new DigestException("partial digests not returned"); | |
| 179 | + if (buf.length - offset < digest.length) | |
| 180 | + throw new DigestException("insufficient space in the output " | |
| 181 | + + "buffer to store the digest"); | |
| 182 | + System.arraycopy(digest, 0, buf, offset, digest.length); | |
| 183 | + return digest.length; | |
| 184 | + } | |
| 185 | + | |
| 186 | + /** | |
| 187 | + * Resets the digest for further use. | |
| 188 | + */ | |
| 189 | + protected abstract void engineReset(); | |
| 190 | + | |
| 191 | + /** | |
| 192 | + * Returns a clone if the implementation is cloneable. | |
| 193 | + * | |
| 194 | + * @return a clone if the implementation is cloneable. | |
| 195 | + * | |
| 196 | + * @exception CloneNotSupportedException if this is called on an | |
| 197 | + * implementation that does not support <code>Cloneable</code>. | |
| 198 | + */ | |
| 199 | + public Object clone() throws CloneNotSupportedException { | |
| 200 | + if (this instanceof Cloneable) { | |
| 201 | + return super.clone(); | |
| 202 | + } else { | |
| 203 | + throw new CloneNotSupportedException(); | |
| 204 | + } | |
| 205 | + } | |
| 206 | +} | |
Binary file not shown.
| @@ -0,0 +1,89 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This exception is thrown when a particular cryptographic algorithm is | |
| 30 | + * requested but is not available in the environment. | |
| 31 | + * | |
| 32 | + * @author Benjamin Renaud | |
| 33 | + */ | |
| 34 | + | |
| 35 | +public class NoSuchAlgorithmException extends GeneralSecurityException { | |
| 36 | + | |
| 37 | + private static final long serialVersionUID = -7443947487218346562L; | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * Constructs a NoSuchAlgorithmException with no detail | |
| 41 | + * message. A detail message is a String that describes this | |
| 42 | + * particular exception. | |
| 43 | + */ | |
| 44 | + public NoSuchAlgorithmException() { | |
| 45 | + super(); | |
| 46 | + } | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * Constructs a NoSuchAlgorithmException with the specified | |
| 50 | + * detail message. A detail message is a String that describes | |
| 51 | + * this particular exception, which may, for example, specify which | |
| 52 | + * algorithm is not available. | |
| 53 | + * | |
| 54 | + * @param msg the detail message. | |
| 55 | + */ | |
| 56 | + public NoSuchAlgorithmException(String msg) { | |
| 57 | + super(msg); | |
| 58 | + } | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * Creates a <code>NoSuchAlgorithmException</code> with the specified | |
| 62 | + * detail message and cause. | |
| 63 | + * | |
| 64 | + * @param message the detail message (which is saved for later retrieval | |
| 65 | + * by the {@link #getMessage()} method). | |
| 66 | + * @param cause the cause (which is saved for later retrieval by the | |
| 67 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 68 | + * and indicates that the cause is nonexistent or unknown.) | |
| 69 | + * @since 1.5 | |
| 70 | + */ | |
| 71 | + public NoSuchAlgorithmException(String message, Throwable cause) { | |
| 72 | + super(message, cause); | |
| 73 | + } | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * Creates a <code>NoSuchAlgorithmException</code> with the specified cause | |
| 77 | + * and a detail message of <tt>(cause==null ? null : cause.toString())</tt> | |
| 78 | + * (which typically contains the class and detail message of | |
| 79 | + * <tt>cause</tt>). | |
| 80 | + * | |
| 81 | + * @param cause the cause (which is saved for later retrieval by the | |
| 82 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 83 | + * and indicates that the cause is nonexistent or unknown.) | |
| 84 | + * @since 1.5 | |
| 85 | + */ | |
| 86 | + public NoSuchAlgorithmException(Throwable cause) { | |
| 87 | + super(cause); | |
| 88 | + } | |
| 89 | +} | |
Binary file not shown.
| @@ -0,0 +1,58 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This exception is thrown when a particular security provider is | |
| 30 | + * requested but is not available in the environment. | |
| 31 | + * | |
| 32 | + * @author Benjamin Renaud | |
| 33 | + */ | |
| 34 | + | |
| 35 | +public class NoSuchProviderException extends GeneralSecurityException { | |
| 36 | + | |
| 37 | + private static final long serialVersionUID = 8488111756688534474L; | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * Constructs a NoSuchProviderException with no detail message. A | |
| 41 | + * detail message is a String that describes this particular | |
| 42 | + * exception. | |
| 43 | + */ | |
| 44 | + public NoSuchProviderException() { | |
| 45 | + super(); | |
| 46 | + } | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * Constructs a NoSuchProviderException with the specified detail | |
| 50 | + * message. A detail message is a String that describes this | |
| 51 | + * particular exception. | |
| 52 | + * | |
| 53 | + * @param msg the detail message. | |
| 54 | + */ | |
| 55 | + public NoSuchProviderException(String msg) { | |
| 56 | + super(msg); | |
| 57 | + } | |
| 58 | +} | |
Binary file not shown.
| @@ -0,0 +1,231 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * Abstract class for representing access to a system resource. | |
| 30 | + * All permissions have a name (whose interpretation depends on the subclass), | |
| 31 | + * as well as abstract functions for defining the semantics of the | |
| 32 | + * particular Permission subclass. | |
| 33 | + * | |
| 34 | + * <p>Most Permission objects also include an "actions" list that tells the actions | |
| 35 | + * that are permitted for the object. For example, | |
| 36 | + * for a <code>java.io.FilePermission</code> object, the permission name is | |
| 37 | + * the pathname of a file (or directory), and the actions list | |
| 38 | + * (such as "read, write") specifies which actions are granted for the | |
| 39 | + * specified file (or for files in the specified directory). | |
| 40 | + * The actions list is optional for Permission objects, such as | |
| 41 | + * <code>java.lang.RuntimePermission</code>, | |
| 42 | + * that don't need such a list; you either have the named permission (such | |
| 43 | + * as "system.exit") or you don't. | |
| 44 | + * | |
| 45 | + * <p>An important method that must be implemented by each subclass is | |
| 46 | + * the <code>implies</code> method to compare Permissions. Basically, | |
| 47 | + * "permission p1 implies permission p2" means that | |
| 48 | + * if one is granted permission p1, one is naturally granted permission p2. | |
| 49 | + * Thus, this is not an equality test, but rather more of a | |
| 50 | + * subset test. | |
| 51 | + * | |
| 52 | + * <P> Permission objects are similar to String objects in that they | |
| 53 | + * are immutable once they have been created. Subclasses should not | |
| 54 | + * provide methods that can change the state of a permission | |
| 55 | + * once it has been created. | |
| 56 | + * | |
| 57 | + * @see Permissions | |
| 58 | + * @see PermissionCollection | |
| 59 | + * | |
| 60 | + * | |
| 61 | + * @author Marianne Mueller | |
| 62 | + * @author Roland Schemers | |
| 63 | + */ | |
| 64 | + | |
| 65 | +public abstract class Permission implements Guard, java.io.Serializable { | |
| 66 | + | |
| 67 | + private static final long serialVersionUID = -5636570222231596674L; | |
| 68 | + | |
| 69 | + private String name; | |
| 70 | + | |
| 71 | + /** | |
| 72 | + * Constructs a permission with the specified name. | |
| 73 | + * | |
| 74 | + * @param name name of the Permission object being created. | |
| 75 | + * | |
| 76 | + */ | |
| 77 | + | |
| 78 | + public Permission(String name) { | |
| 79 | + this.name = name; | |
| 80 | + } | |
| 81 | + | |
| 82 | + /** | |
| 83 | + * Implements the guard interface for a permission. The | |
| 84 | + * <code>SecurityManager.checkPermission</code> method is called, | |
| 85 | + * passing this permission object as the permission to check. | |
| 86 | + * Returns silently if access is granted. Otherwise, throws | |
| 87 | + * a SecurityException. | |
| 88 | + * | |
| 89 | + * @param object the object being guarded (currently ignored). | |
| 90 | + * | |
| 91 | + * @throws SecurityException | |
| 92 | + * if a security manager exists and its | |
| 93 | + * <code>checkPermission</code> method doesn't allow access. | |
| 94 | + * | |
| 95 | + * @see Guard | |
| 96 | + * @see GuardedObject | |
| 97 | + * @see SecurityManager#checkPermission | |
| 98 | + * | |
| 99 | + */ | |
| 100 | + public void checkGuard(Object object) throws SecurityException { | |
| 101 | + SecurityManager sm = System.getSecurityManager(); | |
| 102 | + if (sm != null) sm.checkPermission(this); | |
| 103 | + } | |
| 104 | + | |
| 105 | + /** | |
| 106 | + * Checks if the specified permission's actions are "implied by" | |
| 107 | + * this object's actions. | |
| 108 | + * <P> | |
| 109 | + * This must be implemented by subclasses of Permission, as they are the | |
| 110 | + * only ones that can impose semantics on a Permission object. | |
| 111 | + * | |
| 112 | + * <p>The <code>implies</code> method is used by the AccessController to determine | |
| 113 | + * whether or not a requested permission is implied by another permission that | |
| 114 | + * is known to be valid in the current execution context. | |
| 115 | + * | |
| 116 | + * @param permission the permission to check against. | |
| 117 | + * | |
| 118 | + * @return true if the specified permission is implied by this object, | |
| 119 | + * false if not. | |
| 120 | + */ | |
| 121 | + | |
| 122 | + public abstract boolean implies(Permission permission); | |
| 123 | + | |
| 124 | + /** | |
| 125 | + * Checks two Permission objects for equality. | |
| 126 | + * <P> | |
| 127 | + * Do not use the <code>equals</code> method for making access control | |
| 128 | + * decisions; use the <code>implies</code> method. | |
| 129 | + * | |
| 130 | + * @param obj the object we are testing for equality with this object. | |
| 131 | + * | |
| 132 | + * @return true if both Permission objects are equivalent. | |
| 133 | + */ | |
| 134 | + | |
| 135 | + public abstract boolean equals(Object obj); | |
| 136 | + | |
| 137 | + /** | |
| 138 | + * Returns the hash code value for this Permission object. | |
| 139 | + * <P> | |
| 140 | + * The required <code>hashCode</code> behavior for Permission Objects is | |
| 141 | + * the following: <p> | |
| 142 | + * <ul> | |
| 143 | + * <li>Whenever it is invoked on the same Permission object more than | |
| 144 | + * once during an execution of a Java application, the | |
| 145 | + * <code>hashCode</code> method | |
| 146 | + * must consistently return the same integer. This integer need not | |
| 147 | + * remain consistent from one execution of an application to another | |
| 148 | + * execution of the same application. <p> | |
| 149 | + * <li>If two Permission objects are equal according to the | |
| 150 | + * <code>equals</code> | |
| 151 | + * method, then calling the <code>hashCode</code> method on each of the | |
| 152 | + * two Permission objects must produce the same integer result. | |
| 153 | + * </ul> | |
| 154 | + * | |
| 155 | + * @return a hash code value for this object. | |
| 156 | + */ | |
| 157 | + | |
| 158 | + public abstract int hashCode(); | |
| 159 | + | |
| 160 | + /** | |
| 161 | + * Returns the name of this Permission. | |
| 162 | + * For example, in the case of a <code>java.io.FilePermission</code>, | |
| 163 | + * the name will be a pathname. | |
| 164 | + * | |
| 165 | + * @return the name of this Permission. | |
| 166 | + * | |
| 167 | + */ | |
| 168 | + | |
| 169 | + public final String getName() { | |
| 170 | + return name; | |
| 171 | + } | |
| 172 | + | |
| 173 | + /** | |
| 174 | + * Returns the actions as a String. This is abstract | |
| 175 | + * so subclasses can defer creating a String representation until | |
| 176 | + * one is needed. Subclasses should always return actions in what they | |
| 177 | + * consider to be their | |
| 178 | + * canonical form. For example, two FilePermission objects created via | |
| 179 | + * the following: | |
| 180 | + * | |
| 181 | + * <pre> | |
| 182 | + * perm1 = new FilePermission(p1,"read,write"); | |
| 183 | + * perm2 = new FilePermission(p2,"write,read"); | |
| 184 | + * </pre> | |
| 185 | + * | |
| 186 | + * both return | |
| 187 | + * "read,write" when the <code>getActions</code> method is invoked. | |
| 188 | + * | |
| 189 | + * @return the actions of this Permission. | |
| 190 | + * | |
| 191 | + */ | |
| 192 | + | |
| 193 | + public abstract String getActions(); | |
| 194 | + | |
| 195 | + /** | |
| 196 | + * Returns an empty PermissionCollection for a given Permission object, or null if | |
| 197 | + * one is not defined. Subclasses of class Permission should | |
| 198 | + * override this if they need to store their permissions in a particular | |
| 199 | + * PermissionCollection object in order to provide the correct semantics | |
| 200 | + * when the <code>PermissionCollection.implies</code> method is called. | |
| 201 | + * If null is returned, | |
| 202 | + * then the caller of this method is free to store permissions of this | |
| 203 | + * type in any PermissionCollection they choose (one that uses a Hashtable, | |
| 204 | + * one that uses a Vector, etc). | |
| 205 | + * | |
| 206 | + * @return a new PermissionCollection object for this type of Permission, or | |
| 207 | + * null if one is not defined. | |
| 208 | + */ | |
| 209 | + | |
| 210 | + public PermissionCollection newPermissionCollection() { | |
| 211 | + return null; | |
| 212 | + } | |
| 213 | + | |
| 214 | + /** | |
| 215 | + * Returns a string describing this Permission. The convention is to | |
| 216 | + * specify the class name, the permission name, and the actions in | |
| 217 | + * the following format: '("ClassName" "name" "actions")', or | |
| 218 | + * '("ClassName" "name")' if actions list is null or empty. | |
| 219 | + * | |
| 220 | + * @return information about this Permission. | |
| 221 | + */ | |
| 222 | + public String toString() { | |
| 223 | + String actions = getActions(); | |
| 224 | + if ((actions == null) || (actions.length() == 0)) { // OPTIONAL | |
| 225 | + return "(\"" + getClass().getName() + "\" \"" + name + "\")"; | |
| 226 | + } else { | |
| 227 | + return "(\"" + getClass().getName() + "\" \"" + name + | |
| 228 | + "\" \"" + actions + "\")"; | |
| 229 | + } | |
| 230 | + } | |
| 231 | +} | |
Binary file not shown.
| @@ -0,0 +1,196 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.util.*; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * Abstract class representing a collection of Permission objects. | |
| 32 | + * | |
| 33 | + * <p>With a PermissionCollection, you can: | |
| 34 | + * <UL> | |
| 35 | + * <LI> add a permission to the collection using the <code>add</code> method. | |
| 36 | + * <LI> check to see if a particular permission is implied in the | |
| 37 | + * collection, using the <code>implies</code> method. | |
| 38 | + * <LI> enumerate all the permissions, using the <code>elements</code> method. | |
| 39 | + * </UL> | |
| 40 | + * <P> | |
| 41 | + * | |
| 42 | + * <p>When it is desirable to group together a number of Permission objects | |
| 43 | + * of the same type, the <code>newPermissionCollection</code> method on that | |
| 44 | + * particular type of Permission object should first be called. The default | |
| 45 | + * behavior (from the Permission class) is to simply return null. | |
| 46 | + * Subclasses of class Permission override the method if they need to store | |
| 47 | + * their permissions in a particular PermissionCollection object in order | |
| 48 | + * to provide the correct semantics when the | |
| 49 | + * <code>PermissionCollection.implies</code> method is called. | |
| 50 | + * If a non-null value is returned, that PermissionCollection must be used. | |
| 51 | + * If null is returned, then the caller of <code>newPermissionCollection</code> | |
| 52 | + * is free to store permissions of the | |
| 53 | + * given type in any PermissionCollection they choose | |
| 54 | + * (one that uses a Hashtable, one that uses a Vector, etc). | |
| 55 | + * | |
| 56 | + * <p>The PermissionCollection returned by the | |
| 57 | + * <code>Permission.newPermissionCollection</code> | |
| 58 | + * method is a homogeneous collection, which stores only Permission objects | |
| 59 | + * for a given Permission type. A PermissionCollection may also be | |
| 60 | + * heterogeneous. For example, Permissions is a PermissionCollection | |
| 61 | + * subclass that represents a collection of PermissionCollections. | |
| 62 | + * That is, its members are each a homogeneous PermissionCollection. | |
| 63 | + * For example, a Permissions object might have a FilePermissionCollection | |
| 64 | + * for all the FilePermission objects, a SocketPermissionCollection for all the | |
| 65 | + * SocketPermission objects, and so on. Its <code>add</code> method adds a | |
| 66 | + * permission to the appropriate collection. | |
| 67 | + * | |
| 68 | + * <p>Whenever a permission is added to a heterogeneous PermissionCollection | |
| 69 | + * such as Permissions, and the PermissionCollection doesn't yet contain a | |
| 70 | + * PermissionCollection of the specified permission's type, the | |
| 71 | + * PermissionCollection should call | |
| 72 | + * the <code>newPermissionCollection</code> method on the permission's class | |
| 73 | + * to see if it requires a special PermissionCollection. If | |
| 74 | + * <code>newPermissionCollection</code> | |
| 75 | + * returns null, the PermissionCollection | |
| 76 | + * is free to store the permission in any type of PermissionCollection it | |
| 77 | + * desires (one using a Hashtable, one using a Vector, etc.). For example, | |
| 78 | + * the Permissions object uses a default PermissionCollection implementation | |
| 79 | + * that stores the permission objects in a Hashtable. | |
| 80 | + * | |
| 81 | + * <p> Subclass implementations of PermissionCollection should assume | |
| 82 | + * that they may be called simultaneously from multiple threads, | |
| 83 | + * and therefore should be synchronized properly. Furthermore, | |
| 84 | + * Enumerations returned via the <code>elements</code> method are | |
| 85 | + * not <em>fail-fast</em>. Modifications to a collection should not be | |
| 86 | + * performed while enumerating over that collection. | |
| 87 | + * | |
| 88 | + * @see Permission | |
| 89 | + * @see Permissions | |
| 90 | + * | |
| 91 | + * | |
| 92 | + * @author Roland Schemers | |
| 93 | + */ | |
| 94 | + | |
| 95 | +public abstract class PermissionCollection implements java.io.Serializable { | |
| 96 | + | |
| 97 | + private static final long serialVersionUID = -6727011328946861783L; | |
| 98 | + | |
| 99 | + // when set, add will throw an exception. | |
| 100 | + private volatile boolean readOnly; | |
| 101 | + | |
| 102 | + /** | |
| 103 | + * Adds a permission object to the current collection of permission objects. | |
| 104 | + * | |
| 105 | + * @param permission the Permission object to add. | |
| 106 | + * | |
| 107 | + * @exception SecurityException - if this PermissionCollection object | |
| 108 | + * has been marked readonly | |
| 109 | + * @exception IllegalArgumentException - if this PermissionCollection | |
| 110 | + * object is a homogeneous collection and the permission | |
| 111 | + * is not of the correct type. | |
| 112 | + */ | |
| 113 | + public abstract void add(Permission permission); | |
| 114 | + | |
| 115 | + /** | |
| 116 | + * Checks to see if the specified permission is implied by | |
| 117 | + * the collection of Permission objects held in this PermissionCollection. | |
| 118 | + * | |
| 119 | + * @param permission the Permission object to compare. | |
| 120 | + * | |
| 121 | + * @return true if "permission" is implied by the permissions in | |
| 122 | + * the collection, false if not. | |
| 123 | + */ | |
| 124 | + public abstract boolean implies(Permission permission); | |
| 125 | + | |
| 126 | + /** | |
| 127 | + * Returns an enumeration of all the Permission objects in the collection. | |
| 128 | + * | |
| 129 | + * @return an enumeration of all the Permissions. | |
| 130 | + */ | |
| 131 | + public abstract Enumeration<Permission> elements(); | |
| 132 | + | |
| 133 | + /** | |
| 134 | + * Marks this PermissionCollection object as "readonly". After | |
| 135 | + * a PermissionCollection object | |
| 136 | + * is marked as readonly, no new Permission objects can be added to it | |
| 137 | + * using <code>add</code>. | |
| 138 | + */ | |
| 139 | + public void setReadOnly() { | |
| 140 | + readOnly = true; | |
| 141 | + } | |
| 142 | + | |
| 143 | + /** | |
| 144 | + * Returns true if this PermissionCollection object is marked as readonly. | |
| 145 | + * If it is readonly, no new Permission objects can be added to it | |
| 146 | + * using <code>add</code>. | |
| 147 | + * | |
| 148 | + * <p>By default, the object is <i>not</i> readonly. It can be set to | |
| 149 | + * readonly by a call to <code>setReadOnly</code>. | |
| 150 | + * | |
| 151 | + * @return true if this PermissionCollection object is marked as readonly, | |
| 152 | + * false otherwise. | |
| 153 | + */ | |
| 154 | + public boolean isReadOnly() { | |
| 155 | + return readOnly; | |
| 156 | + } | |
| 157 | + | |
| 158 | + /** | |
| 159 | + * Returns a string describing this PermissionCollection object, | |
| 160 | + * providing information about all the permissions it contains. | |
| 161 | + * The format is: | |
| 162 | + * <pre> | |
| 163 | + * super.toString() ( | |
| 164 | + * // enumerate all the Permission | |
| 165 | + * // objects and call toString() on them, | |
| 166 | + * // one per line.. | |
| 167 | + * )</pre> | |
| 168 | + * | |
| 169 | + * <code>super.toString</code> is a call to the <code>toString</code> | |
| 170 | + * method of this | |
| 171 | + * object's superclass, which is Object. The result is | |
| 172 | + * this PermissionCollection's type name followed by this object's | |
| 173 | + * hashcode, thus enabling clients to differentiate different | |
| 174 | + * PermissionCollections object, even if they contain the same permissions. | |
| 175 | + * | |
| 176 | + * @return information about this PermissionCollection object, | |
| 177 | + * as described above. | |
| 178 | + * | |
| 179 | + */ | |
| 180 | + public String toString() { | |
| 181 | + Enumeration<Permission> enum_ = elements(); | |
| 182 | + StringBuilder sb = new StringBuilder(); | |
| 183 | + sb.append(super.toString()+" (\n"); | |
| 184 | + while (enum_.hasMoreElements()) { | |
| 185 | + try { | |
| 186 | + sb.append(" "); | |
| 187 | + sb.append(enum_.nextElement().toString()); | |
| 188 | + sb.append("\n"); | |
| 189 | + } catch (NoSuchElementException e){ | |
| 190 | + // ignore | |
| 191 | + } | |
| 192 | + } | |
| 193 | + sb.append(")\n"); | |
| 194 | + return sb.toString(); | |
| 195 | + } | |
| 196 | +} | |
Binary file not shown.
| @@ -0,0 +1,598 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.util.Enumeration; | |
| 29 | +import java.util.Hashtable; | |
| 30 | +import java.util.NoSuchElementException; | |
| 31 | +import java.util.Map; | |
| 32 | +import java.util.HashMap; | |
| 33 | +import java.util.List; | |
| 34 | +import java.util.ArrayList; | |
| 35 | +import java.util.Iterator; | |
| 36 | +import java.util.Collections; | |
| 37 | +import java.io.Serializable; | |
| 38 | +import java.io.ObjectStreamField; | |
| 39 | +import java.io.ObjectOutputStream; | |
| 40 | +import java.io.ObjectInputStream; | |
| 41 | +import java.io.IOException; | |
| 42 | + | |
| 43 | + | |
| 44 | +/** | |
| 45 | + * This class represents a heterogeneous collection of Permissions. That is, | |
| 46 | + * it contains different types of Permission objects, organized into | |
| 47 | + * PermissionCollections. For example, if any | |
| 48 | + * <code>java.io.FilePermission</code> objects are added to an instance of | |
| 49 | + * this class, they are all stored in a single | |
| 50 | + * PermissionCollection. It is the PermissionCollection returned by a call to | |
| 51 | + * the <code>newPermissionCollection</code> method in the FilePermission class. | |
| 52 | + * Similarly, any <code>java.lang.RuntimePermission</code> objects are | |
| 53 | + * stored in the PermissionCollection returned by a call to the | |
| 54 | + * <code>newPermissionCollection</code> method in the | |
| 55 | + * RuntimePermission class. Thus, this class represents a collection of | |
| 56 | + * PermissionCollections. | |
| 57 | + * | |
| 58 | + * <p>When the <code>add</code> method is called to add a Permission, the | |
| 59 | + * Permission is stored in the appropriate PermissionCollection. If no such | |
| 60 | + * collection exists yet, the Permission object's class is determined and the | |
| 61 | + * <code>newPermissionCollection</code> method is called on that class to create | |
| 62 | + * the PermissionCollection and add it to the Permissions object. If | |
| 63 | + * <code>newPermissionCollection</code> returns null, then a default | |
| 64 | + * PermissionCollection that uses a hashtable will be created and used. Each | |
| 65 | + * hashtable entry stores a Permission object as both the key and the value. | |
| 66 | + * | |
| 67 | + * <p> Enumerations returned via the <code>elements</code> method are | |
| 68 | + * not <em>fail-fast</em>. Modifications to a collection should not be | |
| 69 | + * performed while enumerating over that collection. | |
| 70 | + * | |
| 71 | + * @see Permission | |
| 72 | + * @see PermissionCollection | |
| 73 | + * @see AllPermission | |
| 74 | + * | |
| 75 | + * | |
| 76 | + * @author Marianne Mueller | |
| 77 | + * @author Roland Schemers | |
| 78 | + * | |
| 79 | + * @serial exclude | |
| 80 | + */ | |
| 81 | + | |
| 82 | +public final class Permissions extends PermissionCollection | |
| 83 | +implements Serializable | |
| 84 | +{ | |
| 85 | + /** | |
| 86 | + * Key is permissions Class, value is PermissionCollection for that class. | |
| 87 | + * Not serialized; see serialization section at end of class. | |
| 88 | + */ | |
| 89 | + private transient Map<Class<?>, PermissionCollection> permsMap; | |
| 90 | + | |
| 91 | + // optimization. keep track of whether unresolved permissions need to be | |
| 92 | + // checked | |
| 93 | + private transient boolean hasUnresolved = false; | |
| 94 | + | |
| 95 | + // optimization. keep track of the AllPermission collection | |
| 96 | + // - package private for ProtectionDomain optimization | |
| 97 | + PermissionCollection allPermission; | |
| 98 | + | |
| 99 | + /** | |
| 100 | + * Creates a new Permissions object containing no PermissionCollections. | |
| 101 | + */ | |
| 102 | + public Permissions() { | |
| 103 | + permsMap = new HashMap<Class<?>, PermissionCollection>(11); | |
| 104 | + allPermission = null; | |
| 105 | + } | |
| 106 | + | |
| 107 | + /** | |
| 108 | + * Adds a permission object to the PermissionCollection for the class the | |
| 109 | + * permission belongs to. For example, if <i>permission</i> is a | |
| 110 | + * FilePermission, it is added to the FilePermissionCollection stored | |
| 111 | + * in this Permissions object. | |
| 112 | + * | |
| 113 | + * This method creates | |
| 114 | + * a new PermissionCollection object (and adds the permission to it) | |
| 115 | + * if an appropriate collection does not yet exist. <p> | |
| 116 | + * | |
| 117 | + * @param permission the Permission object to add. | |
| 118 | + * | |
| 119 | + * @exception SecurityException if this Permissions object is | |
| 120 | + * marked as readonly. | |
| 121 | + * | |
| 122 | + * @see PermissionCollection#isReadOnly() | |
| 123 | + */ | |
| 124 | + | |
| 125 | + public void add(Permission permission) { | |
| 126 | + if (isReadOnly()) | |
| 127 | + throw new SecurityException( | |
| 128 | + "attempt to add a Permission to a readonly Permissions object"); | |
| 129 | + | |
| 130 | + PermissionCollection pc; | |
| 131 | + | |
| 132 | + synchronized (this) { | |
| 133 | + pc = getPermissionCollection(permission, true); | |
| 134 | + pc.add(permission); | |
| 135 | + } | |
| 136 | + | |
| 137 | + // No sync; staleness -> optimizations delayed, which is OK | |
| 138 | + if (permission instanceof AllPermission) { | |
| 139 | + allPermission = pc; | |
| 140 | + } | |
| 141 | + if (permission instanceof UnresolvedPermission) { | |
| 142 | + hasUnresolved = true; | |
| 143 | + } | |
| 144 | + } | |
| 145 | + | |
| 146 | + /** | |
| 147 | + * Checks to see if this object's PermissionCollection for permissions of | |
| 148 | + * the specified permission's class implies the permissions | |
| 149 | + * expressed in the <i>permission</i> object. Returns true if the | |
| 150 | + * combination of permissions in the appropriate PermissionCollection | |
| 151 | + * (e.g., a FilePermissionCollection for a FilePermission) together | |
| 152 | + * imply the specified permission. | |
| 153 | + * | |
| 154 | + * <p>For example, suppose there is a FilePermissionCollection in this | |
| 155 | + * Permissions object, and it contains one FilePermission that specifies | |
| 156 | + * "read" access for all files in all subdirectories of the "/tmp" | |
| 157 | + * directory, and another FilePermission that specifies "write" access | |
| 158 | + * for all files in the "/tmp/scratch/foo" directory. | |
| 159 | + * Then if the <code>implies</code> method | |
| 160 | + * is called with a permission specifying both "read" and "write" access | |
| 161 | + * to files in the "/tmp/scratch/foo" directory, <code>true</code> is | |
| 162 | + * returned. | |
| 163 | + * | |
| 164 | + * <p>Additionally, if this PermissionCollection contains the | |
| 165 | + * AllPermission, this method will always return true. | |
| 166 | + * <p> | |
| 167 | + * @param permission the Permission object to check. | |
| 168 | + * | |
| 169 | + * @return true if "permission" is implied by the permissions in the | |
| 170 | + * PermissionCollection it | |
| 171 | + * belongs to, false if not. | |
| 172 | + */ | |
| 173 | + | |
| 174 | + public boolean implies(Permission permission) { | |
| 175 | + // No sync; staleness -> skip optimization, which is OK | |
| 176 | + if (allPermission != null) { | |
| 177 | + return true; // AllPermission has already been added | |
| 178 | + } else { | |
| 179 | + synchronized (this) { | |
| 180 | + PermissionCollection pc = getPermissionCollection(permission, | |
| 181 | + false); | |
| 182 | + if (pc != null) { | |
| 183 | + return pc.implies(permission); | |
| 184 | + } else { | |
| 185 | + // none found | |
| 186 | + return false; | |
| 187 | + } | |
| 188 | + } | |
| 189 | + } | |
| 190 | + } | |
| 191 | + | |
| 192 | + /** | |
| 193 | + * Returns an enumeration of all the Permission objects in all the | |
| 194 | + * PermissionCollections in this Permissions object. | |
| 195 | + * | |
| 196 | + * @return an enumeration of all the Permissions. | |
| 197 | + */ | |
| 198 | + | |
| 199 | + public Enumeration<Permission> elements() { | |
| 200 | + // go through each Permissions in the hash table | |
| 201 | + // and call their elements() function. | |
| 202 | + | |
| 203 | + synchronized (this) { | |
| 204 | + return new PermissionsEnumerator(permsMap.values().iterator()); | |
| 205 | + } | |
| 206 | + } | |
| 207 | + | |
| 208 | + /** | |
| 209 | + * Gets the PermissionCollection in this Permissions object for | |
| 210 | + * permissions whose type is the same as that of <i>p</i>. | |
| 211 | + * For example, if <i>p</i> is a FilePermission, | |
| 212 | + * the FilePermissionCollection | |
| 213 | + * stored in this Permissions object will be returned. | |
| 214 | + * | |
| 215 | + * If createEmpty is true, | |
| 216 | + * this method creates a new PermissionCollection object for the specified | |
| 217 | + * type of permission objects if one does not yet exist. | |
| 218 | + * To do so, it first calls the <code>newPermissionCollection</code> method | |
| 219 | + * on <i>p</i>. Subclasses of class Permission | |
| 220 | + * override that method if they need to store their permissions in a | |
| 221 | + * particular PermissionCollection object in order to provide the | |
| 222 | + * correct semantics when the <code>PermissionCollection.implies</code> | |
| 223 | + * method is called. | |
| 224 | + * If the call returns a PermissionCollection, that collection is stored | |
| 225 | + * in this Permissions object. If the call returns null and createEmpty | |
| 226 | + * is true, then | |
| 227 | + * this method instantiates and stores a default PermissionCollection | |
| 228 | + * that uses a hashtable to store its permission objects. | |
| 229 | + * | |
| 230 | + * createEmpty is ignored when creating empty PermissionCollection | |
| 231 | + * for unresolved permissions because of the overhead of determining the | |
| 232 | + * PermissionCollection to use. | |
| 233 | + * | |
| 234 | + * createEmpty should be set to false when this method is invoked from | |
| 235 | + * implies() because it incurs the additional overhead of creating and | |
| 236 | + * adding an empty PermissionCollection that will just return false. | |
| 237 | + * It should be set to true when invoked from add(). | |
| 238 | + */ | |
| 239 | + private PermissionCollection getPermissionCollection(Permission p, | |
| 240 | + boolean createEmpty) { | |
| 241 | + Class c = p.getClass(); | |
| 242 | + | |
| 243 | + PermissionCollection pc = permsMap.get(c); | |
| 244 | + | |
| 245 | + if (!hasUnresolved && !createEmpty) { | |
| 246 | + return pc; | |
| 247 | + } else if (pc == null) { | |
| 248 | + | |
| 249 | + // Check for unresolved permissions | |
| 250 | + pc = (hasUnresolved ? getUnresolvedPermissions(p) : null); | |
| 251 | + | |
| 252 | + // if still null, create a new collection | |
| 253 | + if (pc == null && createEmpty) { | |
| 254 | + | |
| 255 | + pc = p.newPermissionCollection(); | |
| 256 | + | |
| 257 | + // still no PermissionCollection? | |
| 258 | + // We'll give them a PermissionsHash. | |
| 259 | + if (pc == null) | |
| 260 | + pc = new PermissionsHash(); | |
| 261 | + } | |
| 262 | + | |
| 263 | + if (pc != null) { | |
| 264 | + permsMap.put(c, pc); | |
| 265 | + } | |
| 266 | + } | |
| 267 | + return pc; | |
| 268 | + } | |
| 269 | + | |
| 270 | + /** | |
| 271 | + * Resolves any unresolved permissions of type p. | |
| 272 | + * | |
| 273 | + * @param p the type of unresolved permission to resolve | |
| 274 | + * | |
| 275 | + * @return PermissionCollection containing the unresolved permissions, | |
| 276 | + * or null if there were no unresolved permissions of type p. | |
| 277 | + * | |
| 278 | + */ | |
| 279 | + private PermissionCollection getUnresolvedPermissions(Permission p) | |
| 280 | + { | |
| 281 | + // Called from within synchronized method so permsMap doesn't need lock | |
| 282 | + | |
| 283 | + UnresolvedPermissionCollection uc = | |
| 284 | + (UnresolvedPermissionCollection) permsMap.get(UnresolvedPermission.class); | |
| 285 | + | |
| 286 | + // we have no unresolved permissions if uc is null | |
| 287 | + if (uc == null) | |
| 288 | + return null; | |
| 289 | + | |
| 290 | + List<UnresolvedPermission> unresolvedPerms = | |
| 291 | + uc.getUnresolvedPermissions(p); | |
| 292 | + | |
| 293 | + // we have no unresolved permissions of this type if unresolvedPerms is null | |
| 294 | + if (unresolvedPerms == null) | |
| 295 | + return null; | |
| 296 | + | |
| 297 | + java.security.cert.Certificate certs[] = null; | |
| 298 | + | |
| 299 | + Object signers[] = p.getClass().getSigners(); | |
| 300 | + | |
| 301 | + int n = 0; | |
| 302 | + if (signers != null) { | |
| 303 | + for (int j=0; j < signers.length; j++) { | |
| 304 | + if (signers[j] instanceof java.security.cert.Certificate) { | |
| 305 | + n++; | |
| 306 | + } | |
| 307 | + } | |
| 308 | + certs = new java.security.cert.Certificate[n]; | |
| 309 | + n = 0; | |
| 310 | + for (int j=0; j < signers.length; j++) { | |
| 311 | + if (signers[j] instanceof java.security.cert.Certificate) { | |
| 312 | + certs[n++] = (java.security.cert.Certificate)signers[j]; | |
| 313 | + } | |
| 314 | + } | |
| 315 | + } | |
| 316 | + | |
| 317 | + PermissionCollection pc = null; | |
| 318 | + synchronized (unresolvedPerms) { | |
| 319 | + int len = unresolvedPerms.size(); | |
| 320 | + for (int i = 0; i < len; i++) { | |
| 321 | + UnresolvedPermission up = unresolvedPerms.get(i); | |
| 322 | + Permission perm = up.resolve(p, certs); | |
| 323 | + if (perm != null) { | |
| 324 | + if (pc == null) { | |
| 325 | + pc = p.newPermissionCollection(); | |
| 326 | + if (pc == null) | |
| 327 | + pc = new PermissionsHash(); | |
| 328 | + } | |
| 329 | + pc.add(perm); | |
| 330 | + } | |
| 331 | + } | |
| 332 | + } | |
| 333 | + return pc; | |
| 334 | + } | |
| 335 | + | |
| 336 | + private static final long serialVersionUID = 4858622370623524688L; | |
| 337 | + | |
| 338 | + // Need to maintain serialization interoperability with earlier releases, | |
| 339 | + // which had the serializable field: | |
| 340 | + // private Hashtable perms; | |
| 341 | + | |
| 342 | + /** | |
| 343 | + * @serialField perms java.util.Hashtable | |
| 344 | + * A table of the Permission classes and PermissionCollections. | |
| 345 | + * @serialField allPermission java.security.PermissionCollection | |
| 346 | + */ | |
| 347 | + private static final ObjectStreamField[] serialPersistentFields = { | |
| 348 | + new ObjectStreamField("perms", Hashtable.class), | |
| 349 | + new ObjectStreamField("allPermission", PermissionCollection.class), | |
| 350 | + }; | |
| 351 | + | |
| 352 | + /** | |
| 353 | + * @serialData Default fields. | |
| 354 | + */ | |
| 355 | + /* | |
| 356 | + * Writes the contents of the permsMap field out as a Hashtable for | |
| 357 | + * serialization compatibility with earlier releases. allPermission | |
| 358 | + * unchanged. | |
| 359 | + */ | |
| 360 | + private void writeObject(ObjectOutputStream out) throws IOException { | |
| 361 | + // Don't call out.defaultWriteObject() | |
| 362 | + | |
| 363 | + // Copy perms into a Hashtable | |
| 364 | + Hashtable<Class<?>, PermissionCollection> perms = | |
| 365 | + new Hashtable<>(permsMap.size()*2); // no sync; estimate | |
| 366 | + synchronized (this) { | |
| 367 | + perms.putAll(permsMap); | |
| 368 | + } | |
| 369 | + | |
| 370 | + // Write out serializable fields | |
| 371 | + ObjectOutputStream.PutField pfields = out.putFields(); | |
| 372 | + | |
| 373 | + pfields.put("allPermission", allPermission); // no sync; staleness OK | |
| 374 | + pfields.put("perms", perms); | |
| 375 | + out.writeFields(); | |
| 376 | + } | |
| 377 | + | |
| 378 | + /* | |
| 379 | + * Reads in a Hashtable of Class/PermissionCollections and saves them in the | |
| 380 | + * permsMap field. Reads in allPermission. | |
| 381 | + */ | |
| 382 | + private void readObject(ObjectInputStream in) throws IOException, | |
| 383 | + ClassNotFoundException { | |
| 384 | + // Don't call defaultReadObject() | |
| 385 | + | |
| 386 | + // Read in serialized fields | |
| 387 | + ObjectInputStream.GetField gfields = in.readFields(); | |
| 388 | + | |
| 389 | + // Get allPermission | |
| 390 | + allPermission = (PermissionCollection) gfields.get("allPermission", null); | |
| 391 | + | |
| 392 | + // Get permissions | |
| 393 | + Hashtable<Class<?>, PermissionCollection> perms = | |
| 394 | + (Hashtable<Class<?>, PermissionCollection>)gfields.get("perms", null); | |
| 395 | + permsMap = new HashMap<Class<?>, PermissionCollection>(perms.size()*2); | |
| 396 | + permsMap.putAll(perms); | |
| 397 | + | |
| 398 | + // Set hasUnresolved | |
| 399 | + UnresolvedPermissionCollection uc = | |
| 400 | + (UnresolvedPermissionCollection) permsMap.get(UnresolvedPermission.class); | |
| 401 | + hasUnresolved = (uc != null && uc.elements().hasMoreElements()); | |
| 402 | + } | |
| 403 | +} | |
| 404 | + | |
| 405 | +final class PermissionsEnumerator implements Enumeration<Permission> { | |
| 406 | + | |
| 407 | + // all the perms | |
| 408 | + private Iterator<PermissionCollection> perms; | |
| 409 | + // the current set | |
| 410 | + private Enumeration<Permission> permset; | |
| 411 | + | |
| 412 | + PermissionsEnumerator(Iterator<PermissionCollection> e) { | |
| 413 | + perms = e; | |
| 414 | + permset = getNextEnumWithMore(); | |
| 415 | + } | |
| 416 | + | |
| 417 | + // No need to synchronize; caller should sync on object as required | |
| 418 | + public boolean hasMoreElements() { | |
| 419 | + // if we enter with permissionimpl null, we know | |
| 420 | + // there are no more left. | |
| 421 | + | |
| 422 | + if (permset == null) | |
| 423 | + return false; | |
| 424 | + | |
| 425 | + // try to see if there are any left in the current one | |
| 426 | + | |
| 427 | + if (permset.hasMoreElements()) | |
| 428 | + return true; | |
| 429 | + | |
| 430 | + // get the next one that has something in it... | |
| 431 | + permset = getNextEnumWithMore(); | |
| 432 | + | |
| 433 | + // if it is null, we are done! | |
| 434 | + return (permset != null); | |
| 435 | + } | |
| 436 | + | |
| 437 | + // No need to synchronize; caller should sync on object as required | |
| 438 | + public Permission nextElement() { | |
| 439 | + | |
| 440 | + // hasMoreElements will update permset to the next permset | |
| 441 | + // with something in it... | |
| 442 | + | |
| 443 | + if (hasMoreElements()) { | |
| 444 | + return permset.nextElement(); | |
| 445 | + } else { | |
| 446 | + throw new NoSuchElementException("PermissionsEnumerator"); | |
| 447 | + } | |
| 448 | + | |
| 449 | + } | |
| 450 | + | |
| 451 | + private Enumeration<Permission> getNextEnumWithMore() { | |
| 452 | + while (perms.hasNext()) { | |
| 453 | + PermissionCollection pc = perms.next(); | |
| 454 | + Enumeration<Permission> next =pc.elements(); | |
| 455 | + if (next.hasMoreElements()) | |
| 456 | + return next; | |
| 457 | + } | |
| 458 | + return null; | |
| 459 | + | |
| 460 | + } | |
| 461 | +} | |
| 462 | + | |
| 463 | +/** | |
| 464 | + * A PermissionsHash stores a homogeneous set of permissions in a hashtable. | |
| 465 | + * | |
| 466 | + * @see Permission | |
| 467 | + * @see Permissions | |
| 468 | + * | |
| 469 | + * | |
| 470 | + * @author Roland Schemers | |
| 471 | + * | |
| 472 | + * @serial include | |
| 473 | + */ | |
| 474 | + | |
| 475 | +final class PermissionsHash extends PermissionCollection | |
| 476 | +implements Serializable | |
| 477 | +{ | |
| 478 | + /** | |
| 479 | + * Key and value are (same) permissions objects. | |
| 480 | + * Not serialized; see serialization section at end of class. | |
| 481 | + */ | |
| 482 | + private transient Map<Permission, Permission> permsMap; | |
| 483 | + | |
| 484 | + /** | |
| 485 | + * Create an empty PermissionsHash object. | |
| 486 | + */ | |
| 487 | + | |
| 488 | + PermissionsHash() { | |
| 489 | + permsMap = new HashMap<Permission, Permission>(11); | |
| 490 | + } | |
| 491 | + | |
| 492 | + /** | |
| 493 | + * Adds a permission to the PermissionsHash. | |
| 494 | + * | |
| 495 | + * @param permission the Permission object to add. | |
| 496 | + */ | |
| 497 | + | |
| 498 | + public void add(Permission permission) { | |
| 499 | + synchronized (this) { | |
| 500 | + permsMap.put(permission, permission); | |
| 501 | + } | |
| 502 | + } | |
| 503 | + | |
| 504 | + /** | |
| 505 | + * Check and see if this set of permissions implies the permissions | |
| 506 | + * expressed in "permission". | |
| 507 | + * | |
| 508 | + * @param permission the Permission object to compare | |
| 509 | + * | |
| 510 | + * @return true if "permission" is a proper subset of a permission in | |
| 511 | + * the set, false if not. | |
| 512 | + */ | |
| 513 | + | |
| 514 | + public boolean implies(Permission permission) { | |
| 515 | + // attempt a fast lookup and implies. If that fails | |
| 516 | + // then enumerate through all the permissions. | |
| 517 | + synchronized (this) { | |
| 518 | + Permission p = permsMap.get(permission); | |
| 519 | + | |
| 520 | + // If permission is found, then p.equals(permission) | |
| 521 | + if (p == null) { | |
| 522 | + for (Permission p_ : permsMap.values()) { | |
| 523 | + if (p_.implies(permission)) | |
| 524 | + return true; | |
| 525 | + } | |
| 526 | + return false; | |
| 527 | + } else { | |
| 528 | + return true; | |
| 529 | + } | |
| 530 | + } | |
| 531 | + } | |
| 532 | + | |
| 533 | + /** | |
| 534 | + * Returns an enumeration of all the Permission objects in the container. | |
| 535 | + * | |
| 536 | + * @return an enumeration of all the Permissions. | |
| 537 | + */ | |
| 538 | + | |
| 539 | + public Enumeration<Permission> elements() { | |
| 540 | + // Convert Iterator of Map values into an Enumeration | |
| 541 | + synchronized (this) { | |
| 542 | + return Collections.enumeration(permsMap.values()); | |
| 543 | + } | |
| 544 | + } | |
| 545 | + | |
| 546 | + private static final long serialVersionUID = -8491988220802933440L; | |
| 547 | + // Need to maintain serialization interoperability with earlier releases, | |
| 548 | + // which had the serializable field: | |
| 549 | + // private Hashtable perms; | |
| 550 | + /** | |
| 551 | + * @serialField perms java.util.Hashtable | |
| 552 | + * A table of the Permissions (both key and value are same). | |
| 553 | + */ | |
| 554 | + private static final ObjectStreamField[] serialPersistentFields = { | |
| 555 | + new ObjectStreamField("perms", Hashtable.class), | |
| 556 | + }; | |
| 557 | + | |
| 558 | + /** | |
| 559 | + * @serialData Default fields. | |
| 560 | + */ | |
| 561 | + /* | |
| 562 | + * Writes the contents of the permsMap field out as a Hashtable for | |
| 563 | + * serialization compatibility with earlier releases. | |
| 564 | + */ | |
| 565 | + private void writeObject(ObjectOutputStream out) throws IOException { | |
| 566 | + // Don't call out.defaultWriteObject() | |
| 567 | + | |
| 568 | + // Copy perms into a Hashtable | |
| 569 | + Hashtable<Permission, Permission> perms = | |
| 570 | + new Hashtable<>(permsMap.size()*2); | |
| 571 | + synchronized (this) { | |
| 572 | + perms.putAll(permsMap); | |
| 573 | + } | |
| 574 | + | |
| 575 | + // Write out serializable fields | |
| 576 | + ObjectOutputStream.PutField pfields = out.putFields(); | |
| 577 | + pfields.put("perms", perms); | |
| 578 | + out.writeFields(); | |
| 579 | + } | |
| 580 | + | |
| 581 | + /* | |
| 582 | + * Reads in a Hashtable of Permission/Permission and saves them in the | |
| 583 | + * permsMap field. | |
| 584 | + */ | |
| 585 | + private void readObject(ObjectInputStream in) throws IOException, | |
| 586 | + ClassNotFoundException { | |
| 587 | + // Don't call defaultReadObject() | |
| 588 | + | |
| 589 | + // Read in serialized fields | |
| 590 | + ObjectInputStream.GetField gfields = in.readFields(); | |
| 591 | + | |
| 592 | + // Get permissions | |
| 593 | + Hashtable<Permission, Permission> perms = | |
| 594 | + (Hashtable<Permission, Permission>)gfields.get("perms", null); | |
| 595 | + permsMap = new HashMap<Permission, Permission>(perms.size()*2); | |
| 596 | + permsMap.putAll(perms); | |
| 597 | + } | |
| 598 | +} | |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,835 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | + | |
| 27 | +package java.security; | |
| 28 | + | |
| 29 | +import java.io.*; | |
| 30 | +import java.lang.RuntimePermission; | |
| 31 | +import java.lang.reflect.*; | |
| 32 | +import java.net.MalformedURLException; | |
| 33 | +import java.net.URL; | |
| 34 | +import java.util.Enumeration; | |
| 35 | +import java.util.Hashtable; | |
| 36 | +import java.util.PropertyPermission; | |
| 37 | +import java.util.StringTokenizer; | |
| 38 | +import java.util.Vector; | |
| 39 | +import java.util.WeakHashMap; | |
| 40 | +import sun.security.jca.GetInstance; | |
| 41 | +import sun.security.util.Debug; | |
| 42 | +import sun.security.util.SecurityConstants; | |
| 43 | + | |
| 44 | + | |
| 45 | +/** | |
| 46 | + * A Policy object is responsible for determining whether code executing | |
| 47 | + * in the Java runtime environment has permission to perform a | |
| 48 | + * security-sensitive operation. | |
| 49 | + * | |
| 50 | + * <p> There is only one Policy object installed in the runtime at any | |
| 51 | + * given time. A Policy object can be installed by calling the | |
| 52 | + * <code>setPolicy</code> method. The installed Policy object can be | |
| 53 | + * obtained by calling the <code>getPolicy</code> method. | |
| 54 | + * | |
| 55 | + * <p> If no Policy object has been installed in the runtime, a call to | |
| 56 | + * <code>getPolicy</code> installs an instance of the default Policy | |
| 57 | + * implementation (a default subclass implementation of this abstract class). | |
| 58 | + * The default Policy implementation can be changed by setting the value | |
| 59 | + * of the "policy.provider" security property (in the Java security properties | |
| 60 | + * file) to the fully qualified name of the desired Policy subclass | |
| 61 | + * implementation. The Java security properties file is located in the | |
| 62 | + * file named <JAVA_HOME>/lib/security/java.security. | |
| 63 | + * <JAVA_HOME> refers to the value of the java.home system property, | |
| 64 | + * and specifies the directory where the JRE is installed. | |
| 65 | + * | |
| 66 | + * <p> Application code can directly subclass Policy to provide a custom | |
| 67 | + * implementation. In addition, an instance of a Policy object can be | |
| 68 | + * constructed by invoking one of the <code>getInstance</code> factory methods | |
| 69 | + * with a standard type. The default policy type is "JavaPolicy". | |
| 70 | + * | |
| 71 | + * <p> Once a Policy instance has been installed (either by default, or by | |
| 72 | + * calling <code>setPolicy</code>), | |
| 73 | + * the Java runtime invokes its <code>implies</code> when it needs to | |
| 74 | + * determine whether executing code (encapsulated in a ProtectionDomain) | |
| 75 | + * can perform SecurityManager-protected operations. How a Policy object | |
| 76 | + * retrieves its policy data is up to the Policy implementation itself. | |
| 77 | + * The policy data may be stored, for example, in a flat ASCII file, | |
| 78 | + * in a serialized binary file of the Policy class, or in a database. | |
| 79 | + * | |
| 80 | + * <p> The <code>refresh</code> method causes the policy object to | |
| 81 | + * refresh/reload its data. This operation is implementation-dependent. | |
| 82 | + * For example, if the policy object stores its data in configuration files, | |
| 83 | + * calling <code>refresh</code> will cause it to re-read the configuration | |
| 84 | + * policy files. If a refresh operation is not supported, this method does | |
| 85 | + * nothing. Note that refreshed policy may not have an effect on classes | |
| 86 | + * in a particular ProtectionDomain. This is dependent on the Policy | |
| 87 | + * provider's implementation of the <code>implies</code> | |
| 88 | + * method and its PermissionCollection caching strategy. | |
| 89 | + * | |
| 90 | + * @author Roland Schemers | |
| 91 | + * @author Gary Ellison | |
| 92 | + * @see java.security.Provider | |
| 93 | + * @see java.security.ProtectionDomain | |
| 94 | + * @see java.security.Permission | |
| 95 | + */ | |
| 96 | + | |
| 97 | +public abstract class Policy { | |
| 98 | + | |
| 99 | + /** | |
| 100 | + * A read-only empty PermissionCollection instance. | |
| 101 | + * @since 1.6 | |
| 102 | + */ | |
| 103 | + public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION = | |
| 104 | + new UnsupportedEmptyCollection(); | |
| 105 | + | |
| 106 | + /** the system-wide policy. */ | |
| 107 | + private static Policy policy; // package private for AccessControlContext | |
| 108 | + | |
| 109 | + private static final Debug debug = Debug.getInstance("policy"); | |
| 110 | + | |
| 111 | + // Cache mapping ProtectionDomain.Key to PermissionCollection | |
| 112 | + private WeakHashMap<ProtectionDomain.Key, PermissionCollection> pdMapping; | |
| 113 | + | |
| 114 | + /** package private for AccessControlContext */ | |
| 115 | + static boolean isSet() | |
| 116 | + { | |
| 117 | + return policy != null; | |
| 118 | + } | |
| 119 | + | |
| 120 | + private static void checkPermission(String type) { | |
| 121 | + SecurityManager sm = System.getSecurityManager(); | |
| 122 | + if (sm != null) { | |
| 123 | + sm.checkPermission(new SecurityPermission("createPolicy." + type)); | |
| 124 | + } | |
| 125 | + } | |
| 126 | + | |
| 127 | + /** | |
| 128 | + * Returns the installed Policy object. This value should not be cached, | |
| 129 | + * as it may be changed by a call to <code>setPolicy</code>. | |
| 130 | + * This method first calls | |
| 131 | + * <code>SecurityManager.checkPermission</code> with a | |
| 132 | + * <code>SecurityPermission("getPolicy")</code> permission | |
| 133 | + * to ensure it's ok to get the Policy object. | |
| 134 | + * | |
| 135 | + * @return the installed Policy. | |
| 136 | + * | |
| 137 | + * @throws SecurityException | |
| 138 | + * if a security manager exists and its | |
| 139 | + * <code>checkPermission</code> method doesn't allow | |
| 140 | + * getting the Policy object. | |
| 141 | + * | |
| 142 | + * @see SecurityManager#checkPermission(Permission) | |
| 143 | + * @see #setPolicy(java.security.Policy) | |
| 144 | + */ | |
| 145 | + public static Policy getPolicy() | |
| 146 | + { | |
| 147 | + SecurityManager sm = System.getSecurityManager(); | |
| 148 | + if (sm != null) | |
| 149 | + sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION); | |
| 150 | + return getPolicyNoCheck(); | |
| 151 | + } | |
| 152 | + | |
| 153 | + /** | |
| 154 | + * Returns the installed Policy object, skipping the security check. | |
| 155 | + * Used by SecureClassLoader and getPolicy. | |
| 156 | + * | |
| 157 | + * @return the installed Policy. | |
| 158 | + * | |
| 159 | + */ | |
| 160 | + static synchronized Policy getPolicyNoCheck() | |
| 161 | + { | |
| 162 | + if (policy == null) { | |
| 163 | + String policy_class = null; | |
| 164 | + policy_class = AccessController.doPrivileged( | |
| 165 | + new PrivilegedAction<String>() { | |
| 166 | + public String run() { | |
| 167 | + return Security.getProperty("policy.provider"); | |
| 168 | + } | |
| 169 | + }); | |
| 170 | + if (policy_class == null) { | |
| 171 | + policy_class = "sun.security.provider.PolicyFile"; | |
| 172 | + } | |
| 173 | + | |
| 174 | + try { | |
| 175 | + policy = (Policy) | |
| 176 | + Class.forName(policy_class).newInstance(); | |
| 177 | + } catch (Exception e) { | |
| 178 | + /* | |
| 179 | + * The policy_class seems to be an extension | |
| 180 | + * so we have to bootstrap loading it via a policy | |
| 181 | + * provider that is on the bootclasspath | |
| 182 | + * If it loads then shift gears to using the configured | |
| 183 | + * provider. | |
| 184 | + */ | |
| 185 | + | |
| 186 | + // install the bootstrap provider to avoid recursion | |
| 187 | + policy = new sun.security.provider.PolicyFile(); | |
| 188 | + | |
| 189 | + final String pc = policy_class; | |
| 190 | + Policy p = AccessController.doPrivileged( | |
| 191 | + new PrivilegedAction<Policy>() { | |
| 192 | + public Policy run() { | |
| 193 | + try { | |
| 194 | + ClassLoader cl = | |
| 195 | + ClassLoader.getSystemClassLoader(); | |
| 196 | + // we want the extension loader | |
| 197 | + ClassLoader extcl = null; | |
| 198 | + while (cl != null) { | |
| 199 | + extcl = cl; | |
| 200 | + cl = cl.getParent(); | |
| 201 | + } | |
| 202 | + return (extcl != null ? (Policy)Class.forName( | |
| 203 | + pc, true, extcl).newInstance() : null); | |
| 204 | + } catch (Exception e) { | |
| 205 | + if (debug != null) { | |
| 206 | + debug.println("policy provider " + | |
| 207 | + pc + | |
| 208 | + " not available"); | |
| 209 | + e.printStackTrace(); | |
| 210 | + } | |
| 211 | + return null; | |
| 212 | + } | |
| 213 | + } | |
| 214 | + }); | |
| 215 | + /* | |
| 216 | + * if it loaded install it as the policy provider. Otherwise | |
| 217 | + * continue to use the system default implementation | |
| 218 | + */ | |
| 219 | + if (p != null) { | |
| 220 | + policy = p; | |
| 221 | + } else { | |
| 222 | + if (debug != null) { | |
| 223 | + debug.println("using sun.security.provider.PolicyFile"); | |
| 224 | + } | |
| 225 | + } | |
| 226 | + } | |
| 227 | + } | |
| 228 | + return policy; | |
| 229 | + } | |
| 230 | + | |
| 231 | + /** | |
| 232 | + * Sets the system-wide Policy object. This method first calls | |
| 233 | + * <code>SecurityManager.checkPermission</code> with a | |
| 234 | + * <code>SecurityPermission("setPolicy")</code> | |
| 235 | + * permission to ensure it's ok to set the Policy. | |
| 236 | + * | |
| 237 | + * @param p the new system Policy object. | |
| 238 | + * | |
| 239 | + * @throws SecurityException | |
| 240 | + * if a security manager exists and its | |
| 241 | + * <code>checkPermission</code> method doesn't allow | |
| 242 | + * setting the Policy. | |
| 243 | + * | |
| 244 | + * @see SecurityManager#checkPermission(Permission) | |
| 245 | + * @see #getPolicy() | |
| 246 | + * | |
| 247 | + */ | |
| 248 | + public static void setPolicy(Policy p) | |
| 249 | + { | |
| 250 | + SecurityManager sm = System.getSecurityManager(); | |
| 251 | + if (sm != null) sm.checkPermission( | |
| 252 | + new SecurityPermission("setPolicy")); | |
| 253 | + if (p != null) { | |
| 254 | + initPolicy(p); | |
| 255 | + } | |
| 256 | + synchronized (Policy.class) { | |
| 257 | + Policy.policy = p; | |
| 258 | + } | |
| 259 | + } | |
| 260 | + | |
| 261 | + /** | |
| 262 | + * Initialize superclass state such that a legacy provider can | |
| 263 | + * handle queries for itself. | |
| 264 | + * | |
| 265 | + * @since 1.4 | |
| 266 | + */ | |
| 267 | + private static void initPolicy (final Policy p) { | |
| 268 | + /* | |
| 269 | + * A policy provider not on the bootclasspath could trigger | |
| 270 | + * security checks fulfilling a call to either Policy.implies | |
| 271 | + * or Policy.getPermissions. If this does occur the provider | |
| 272 | + * must be able to answer for it's own ProtectionDomain | |
| 273 | + * without triggering additional security checks, otherwise | |
| 274 | + * the policy implementation will end up in an infinite | |
| 275 | + * recursion. | |
| 276 | + * | |
| 277 | + * To mitigate this, the provider can collect it's own | |
| 278 | + * ProtectionDomain and associate a PermissionCollection while | |
| 279 | + * it is being installed. The currently installed policy | |
| 280 | + * provider (if there is one) will handle calls to | |
| 281 | + * Policy.implies or Policy.getPermissions during this | |
| 282 | + * process. | |
| 283 | + * | |
| 284 | + * This Policy superclass caches away the ProtectionDomain and | |
| 285 | + * statically binds permissions so that legacy Policy | |
| 286 | + * implementations will continue to function. | |
| 287 | + */ | |
| 288 | + | |
| 289 | + ProtectionDomain policyDomain = | |
| 290 | + AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() { | |
| 291 | + public ProtectionDomain run() { | |
| 292 | + return p.getClass().getProtectionDomain(); | |
| 293 | + } | |
| 294 | + }); | |
| 295 | + | |
| 296 | + /* | |
| 297 | + * Collect the permissions granted to this protection domain | |
| 298 | + * so that the provider can be security checked while processing | |
| 299 | + * calls to Policy.implies or Policy.getPermissions. | |
| 300 | + */ | |
| 301 | + PermissionCollection policyPerms = null; | |
| 302 | + synchronized (p) { | |
| 303 | + if (p.pdMapping == null) { | |
| 304 | + p.pdMapping = | |
| 305 | + new WeakHashMap<ProtectionDomain.Key, PermissionCollection>(); | |
| 306 | + } | |
| 307 | + } | |
| 308 | + | |
| 309 | + if (policyDomain.getCodeSource() != null) { | |
| 310 | + if (Policy.isSet()) { | |
| 311 | + policyPerms = policy.getPermissions(policyDomain); | |
| 312 | + } | |
| 313 | + | |
| 314 | + if (policyPerms == null) { // assume it has all | |
| 315 | + policyPerms = new Permissions(); | |
| 316 | + policyPerms.add(SecurityConstants.ALL_PERMISSION); | |
| 317 | + } | |
| 318 | + | |
| 319 | + synchronized (p.pdMapping) { | |
| 320 | + // cache of pd to permissions | |
| 321 | + p.pdMapping.put(policyDomain.key, policyPerms); | |
| 322 | + } | |
| 323 | + } | |
| 324 | + return; | |
| 325 | + } | |
| 326 | + | |
| 327 | + | |
| 328 | + /** | |
| 329 | + * Returns a Policy object of the specified type. | |
| 330 | + * | |
| 331 | + * <p> This method traverses the list of registered security providers, | |
| 332 | + * starting with the most preferred Provider. | |
| 333 | + * A new Policy object encapsulating the | |
| 334 | + * PolicySpi implementation from the first | |
| 335 | + * Provider that supports the specified type is returned. | |
| 336 | + * | |
| 337 | + * <p> Note that the list of registered providers may be retrieved via | |
| 338 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 339 | + * | |
| 340 | + * @param type the specified Policy type. See the Policy section in the | |
| 341 | + * <a href= | |
| 342 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Policy"> | |
| 343 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 344 | + * for a list of standard Policy types. | |
| 345 | + * | |
| 346 | + * @param params parameters for the Policy, which may be null. | |
| 347 | + * | |
| 348 | + * @return the new Policy object. | |
| 349 | + * | |
| 350 | + * @exception SecurityException if the caller does not have permission | |
| 351 | + * to get a Policy instance for the specified type. | |
| 352 | + * | |
| 353 | + * @exception NullPointerException if the specified type is null. | |
| 354 | + * | |
| 355 | + * @exception IllegalArgumentException if the specified parameters | |
| 356 | + * are not understood by the PolicySpi implementation | |
| 357 | + * from the selected Provider. | |
| 358 | + * | |
| 359 | + * @exception NoSuchAlgorithmException if no Provider supports a PolicySpi | |
| 360 | + * implementation for the specified type. | |
| 361 | + * | |
| 362 | + * @see Provider | |
| 363 | + * @since 1.6 | |
| 364 | + */ | |
| 365 | + public static Policy getInstance(String type, Policy.Parameters params) | |
| 366 | + throws NoSuchAlgorithmException { | |
| 367 | + | |
| 368 | + checkPermission(type); | |
| 369 | + try { | |
| 370 | + GetInstance.Instance instance = GetInstance.getInstance("Policy", | |
| 371 | + PolicySpi.class, | |
| 372 | + type, | |
| 373 | + params); | |
| 374 | + return new PolicyDelegate((PolicySpi)instance.impl, | |
| 375 | + instance.provider, | |
| 376 | + type, | |
| 377 | + params); | |
| 378 | + } catch (NoSuchAlgorithmException nsae) { | |
| 379 | + return handleException(nsae); | |
| 380 | + } | |
| 381 | + } | |
| 382 | + | |
| 383 | + /** | |
| 384 | + * Returns a Policy object of the specified type. | |
| 385 | + * | |
| 386 | + * <p> A new Policy object encapsulating the | |
| 387 | + * PolicySpi implementation from the specified provider | |
| 388 | + * is returned. The specified provider must be registered | |
| 389 | + * in the provider list. | |
| 390 | + * | |
| 391 | + * <p> Note that the list of registered providers may be retrieved via | |
| 392 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 393 | + * | |
| 394 | + * @param type the specified Policy type. See the Policy section in the | |
| 395 | + * <a href= | |
| 396 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Policy"> | |
| 397 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 398 | + * for a list of standard Policy types. | |
| 399 | + * | |
| 400 | + * @param params parameters for the Policy, which may be null. | |
| 401 | + * | |
| 402 | + * @param provider the provider. | |
| 403 | + * | |
| 404 | + * @return the new Policy object. | |
| 405 | + * | |
| 406 | + * @exception SecurityException if the caller does not have permission | |
| 407 | + * to get a Policy instance for the specified type. | |
| 408 | + * | |
| 409 | + * @exception NullPointerException if the specified type is null. | |
| 410 | + * | |
| 411 | + * @exception IllegalArgumentException if the specified provider | |
| 412 | + * is null or empty, | |
| 413 | + * or if the specified parameters are not understood by | |
| 414 | + * the PolicySpi implementation from the specified provider. | |
| 415 | + * | |
| 416 | + * @exception NoSuchProviderException if the specified provider is not | |
| 417 | + * registered in the security provider list. | |
| 418 | + * | |
| 419 | + * @exception NoSuchAlgorithmException if the specified provider does not | |
| 420 | + * support a PolicySpi implementation for the specified type. | |
| 421 | + * | |
| 422 | + * @see Provider | |
| 423 | + * @since 1.6 | |
| 424 | + */ | |
| 425 | + public static Policy getInstance(String type, | |
| 426 | + Policy.Parameters params, | |
| 427 | + String provider) | |
| 428 | + throws NoSuchProviderException, NoSuchAlgorithmException { | |
| 429 | + | |
| 430 | + if (provider == null || provider.length() == 0) { | |
| 431 | + throw new IllegalArgumentException("missing provider"); | |
| 432 | + } | |
| 433 | + | |
| 434 | + checkPermission(type); | |
| 435 | + try { | |
| 436 | + GetInstance.Instance instance = GetInstance.getInstance("Policy", | |
| 437 | + PolicySpi.class, | |
| 438 | + type, | |
| 439 | + params, | |
| 440 | + provider); | |
| 441 | + return new PolicyDelegate((PolicySpi)instance.impl, | |
| 442 | + instance.provider, | |
| 443 | + type, | |
| 444 | + params); | |
| 445 | + } catch (NoSuchAlgorithmException nsae) { | |
| 446 | + return handleException (nsae); | |
| 447 | + } | |
| 448 | + } | |
| 449 | + | |
| 450 | + /** | |
| 451 | + * Returns a Policy object of the specified type. | |
| 452 | + * | |
| 453 | + * <p> A new Policy object encapsulating the | |
| 454 | + * PolicySpi implementation from the specified Provider | |
| 455 | + * object is returned. Note that the specified Provider object | |
| 456 | + * does not have to be registered in the provider list. | |
| 457 | + * | |
| 458 | + * @param type the specified Policy type. See the Policy section in the | |
| 459 | + * <a href= | |
| 460 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Policy"> | |
| 461 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 462 | + * for a list of standard Policy types. | |
| 463 | + * | |
| 464 | + * @param params parameters for the Policy, which may be null. | |
| 465 | + * | |
| 466 | + * @param provider the Provider. | |
| 467 | + * | |
| 468 | + * @return the new Policy object. | |
| 469 | + * | |
| 470 | + * @exception SecurityException if the caller does not have permission | |
| 471 | + * to get a Policy instance for the specified type. | |
| 472 | + * | |
| 473 | + * @exception NullPointerException if the specified type is null. | |
| 474 | + * | |
| 475 | + * @exception IllegalArgumentException if the specified Provider is null, | |
| 476 | + * or if the specified parameters are not understood by | |
| 477 | + * the PolicySpi implementation from the specified Provider. | |
| 478 | + * | |
| 479 | + * @exception NoSuchAlgorithmException if the specified Provider does not | |
| 480 | + * support a PolicySpi implementation for the specified type. | |
| 481 | + * | |
| 482 | + * @see Provider | |
| 483 | + * @since 1.6 | |
| 484 | + */ | |
| 485 | + public static Policy getInstance(String type, | |
| 486 | + Policy.Parameters params, | |
| 487 | + Provider provider) | |
| 488 | + throws NoSuchAlgorithmException { | |
| 489 | + | |
| 490 | + if (provider == null) { | |
| 491 | + throw new IllegalArgumentException("missing provider"); | |
| 492 | + } | |
| 493 | + | |
| 494 | + checkPermission(type); | |
| 495 | + try { | |
| 496 | + GetInstance.Instance instance = GetInstance.getInstance("Policy", | |
| 497 | + PolicySpi.class, | |
| 498 | + type, | |
| 499 | + params, | |
| 500 | + provider); | |
| 501 | + return new PolicyDelegate((PolicySpi)instance.impl, | |
| 502 | + instance.provider, | |
| 503 | + type, | |
| 504 | + params); | |
| 505 | + } catch (NoSuchAlgorithmException nsae) { | |
| 506 | + return handleException (nsae); | |
| 507 | + } | |
| 508 | + } | |
| 509 | + | |
| 510 | + private static Policy handleException(NoSuchAlgorithmException nsae) | |
| 511 | + throws NoSuchAlgorithmException { | |
| 512 | + Throwable cause = nsae.getCause(); | |
| 513 | + if (cause instanceof IllegalArgumentException) { | |
| 514 | + throw (IllegalArgumentException)cause; | |
| 515 | + } | |
| 516 | + throw nsae; | |
| 517 | + } | |
| 518 | + | |
| 519 | + /** | |
| 520 | + * Return the Provider of this Policy. | |
| 521 | + * | |
| 522 | + * <p> This Policy instance will only have a Provider if it | |
| 523 | + * was obtained via a call to <code>Policy.getInstance</code>. | |
| 524 | + * Otherwise this method returns null. | |
| 525 | + * | |
| 526 | + * @return the Provider of this Policy, or null. | |
| 527 | + * | |
| 528 | + * @since 1.6 | |
| 529 | + */ | |
| 530 | + public Provider getProvider() { | |
| 531 | + return null; | |
| 532 | + } | |
| 533 | + | |
| 534 | + /** | |
| 535 | + * Return the type of this Policy. | |
| 536 | + * | |
| 537 | + * <p> This Policy instance will only have a type if it | |
| 538 | + * was obtained via a call to <code>Policy.getInstance</code>. | |
| 539 | + * Otherwise this method returns null. | |
| 540 | + * | |
| 541 | + * @return the type of this Policy, or null. | |
| 542 | + * | |
| 543 | + * @since 1.6 | |
| 544 | + */ | |
| 545 | + public String getType() { | |
| 546 | + return null; | |
| 547 | + } | |
| 548 | + | |
| 549 | + /** | |
| 550 | + * Return Policy parameters. | |
| 551 | + * | |
| 552 | + * <p> This Policy instance will only have parameters if it | |
| 553 | + * was obtained via a call to <code>Policy.getInstance</code>. | |
| 554 | + * Otherwise this method returns null. | |
| 555 | + * | |
| 556 | + * @return Policy parameters, or null. | |
| 557 | + * | |
| 558 | + * @since 1.6 | |
| 559 | + */ | |
| 560 | + public Policy.Parameters getParameters() { | |
| 561 | + return null; | |
| 562 | + } | |
| 563 | + | |
| 564 | + /** | |
| 565 | + * Return a PermissionCollection object containing the set of | |
| 566 | + * permissions granted to the specified CodeSource. | |
| 567 | + * | |
| 568 | + * <p> Applications are discouraged from calling this method | |
| 569 | + * since this operation may not be supported by all policy implementations. | |
| 570 | + * Applications should solely rely on the <code>implies</code> method | |
| 571 | + * to perform policy checks. If an application absolutely must call | |
| 572 | + * a getPermissions method, it should call | |
| 573 | + * <code>getPermissions(ProtectionDomain)</code>. | |
| 574 | + * | |
| 575 | + * <p> The default implementation of this method returns | |
| 576 | + * Policy.UNSUPPORTED_EMPTY_COLLECTION. This method can be | |
| 577 | + * overridden if the policy implementation can return a set of | |
| 578 | + * permissions granted to a CodeSource. | |
| 579 | + * | |
| 580 | + * @param codesource the CodeSource to which the returned | |
| 581 | + * PermissionCollection has been granted. | |
| 582 | + * | |
| 583 | + * @return a set of permissions granted to the specified CodeSource. | |
| 584 | + * If this operation is supported, the returned | |
| 585 | + * set of permissions must be a new mutable instance | |
| 586 | + * and it must support heterogeneous Permission types. | |
| 587 | + * If this operation is not supported, | |
| 588 | + * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned. | |
| 589 | + */ | |
| 590 | + public PermissionCollection getPermissions(CodeSource codesource) { | |
| 591 | + return Policy.UNSUPPORTED_EMPTY_COLLECTION; | |
| 592 | + } | |
| 593 | + | |
| 594 | + /** | |
| 595 | + * Return a PermissionCollection object containing the set of | |
| 596 | + * permissions granted to the specified ProtectionDomain. | |
| 597 | + * | |
| 598 | + * <p> Applications are discouraged from calling this method | |
| 599 | + * since this operation may not be supported by all policy implementations. | |
| 600 | + * Applications should rely on the <code>implies</code> method | |
| 601 | + * to perform policy checks. | |
| 602 | + * | |
| 603 | + * <p> The default implementation of this method first retrieves | |
| 604 | + * the permissions returned via <code>getPermissions(CodeSource)</code> | |
| 605 | + * (the CodeSource is taken from the specified ProtectionDomain), | |
| 606 | + * as well as the permissions located inside the specified ProtectionDomain. | |
| 607 | + * All of these permissions are then combined and returned in a new | |
| 608 | + * PermissionCollection object. If <code>getPermissions(CodeSource)</code> | |
| 609 | + * returns Policy.UNSUPPORTED_EMPTY_COLLECTION, then this method | |
| 610 | + * returns the permissions contained inside the specified ProtectionDomain | |
| 611 | + * in a new PermissionCollection object. | |
| 612 | + * | |
| 613 | + * <p> This method can be overridden if the policy implementation | |
| 614 | + * supports returning a set of permissions granted to a ProtectionDomain. | |
| 615 | + * | |
| 616 | + * @param domain the ProtectionDomain to which the returned | |
| 617 | + * PermissionCollection has been granted. | |
| 618 | + * | |
| 619 | + * @return a set of permissions granted to the specified ProtectionDomain. | |
| 620 | + * If this operation is supported, the returned | |
| 621 | + * set of permissions must be a new mutable instance | |
| 622 | + * and it must support heterogeneous Permission types. | |
| 623 | + * If this operation is not supported, | |
| 624 | + * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned. | |
| 625 | + * | |
| 626 | + * @since 1.4 | |
| 627 | + */ | |
| 628 | + public PermissionCollection getPermissions(ProtectionDomain domain) { | |
| 629 | + PermissionCollection pc = null; | |
| 630 | + | |
| 631 | + if (domain == null) | |
| 632 | + return new Permissions(); | |
| 633 | + | |
| 634 | + if (pdMapping == null) { | |
| 635 | + initPolicy(this); | |
| 636 | + } | |
| 637 | + | |
| 638 | + synchronized (pdMapping) { | |
| 639 | + pc = pdMapping.get(domain.key); | |
| 640 | + } | |
| 641 | + | |
| 642 | + if (pc != null) { | |
| 643 | + Permissions perms = new Permissions(); | |
| 644 | + synchronized (pc) { | |
| 645 | + for (Enumeration<Permission> e = pc.elements() ; e.hasMoreElements() ;) { | |
| 646 | + perms.add(e.nextElement()); | |
| 647 | + } | |
| 648 | + } | |
| 649 | + return perms; | |
| 650 | + } | |
| 651 | + | |
| 652 | + pc = getPermissions(domain.getCodeSource()); | |
| 653 | + if (pc == null || pc == UNSUPPORTED_EMPTY_COLLECTION) { | |
| 654 | + pc = new Permissions(); | |
| 655 | + } | |
| 656 | + | |
| 657 | + addStaticPerms(pc, domain.getPermissions()); | |
| 658 | + return pc; | |
| 659 | + } | |
| 660 | + | |
| 661 | + /** | |
| 662 | + * add static permissions to provided permission collection | |
| 663 | + */ | |
| 664 | + private void addStaticPerms(PermissionCollection perms, | |
| 665 | + PermissionCollection statics) { | |
| 666 | + if (statics != null) { | |
| 667 | + synchronized (statics) { | |
| 668 | + Enumeration<Permission> e = statics.elements(); | |
| 669 | + while (e.hasMoreElements()) { | |
| 670 | + perms.add(e.nextElement()); | |
| 671 | + } | |
| 672 | + } | |
| 673 | + } | |
| 674 | + } | |
| 675 | + | |
| 676 | + /** | |
| 677 | + * Evaluates the global policy for the permissions granted to | |
| 678 | + * the ProtectionDomain and tests whether the permission is | |
| 679 | + * granted. | |
| 680 | + * | |
| 681 | + * @param domain the ProtectionDomain to test | |
| 682 | + * @param permission the Permission object to be tested for implication. | |
| 683 | + * | |
| 684 | + * @return true if "permission" is a proper subset of a permission | |
| 685 | + * granted to this ProtectionDomain. | |
| 686 | + * | |
| 687 | + * @see java.security.ProtectionDomain | |
| 688 | + * @since 1.4 | |
| 689 | + */ | |
| 690 | + public boolean implies(ProtectionDomain domain, Permission permission) { | |
| 691 | + PermissionCollection pc; | |
| 692 | + | |
| 693 | + if (pdMapping == null) { | |
| 694 | + initPolicy(this); | |
| 695 | + } | |
| 696 | + | |
| 697 | + synchronized (pdMapping) { | |
| 698 | + pc = pdMapping.get(domain.key); | |
| 699 | + } | |
| 700 | + | |
| 701 | + if (pc != null) { | |
| 702 | + return pc.implies(permission); | |
| 703 | + } | |
| 704 | + | |
| 705 | + pc = getPermissions(domain); | |
| 706 | + if (pc == null) { | |
| 707 | + return false; | |
| 708 | + } | |
| 709 | + | |
| 710 | + synchronized (pdMapping) { | |
| 711 | + // cache it | |
| 712 | + pdMapping.put(domain.key, pc); | |
| 713 | + } | |
| 714 | + | |
| 715 | + return pc.implies(permission); | |
| 716 | + } | |
| 717 | + | |
| 718 | + /** | |
| 719 | + * Refreshes/reloads the policy configuration. The behavior of this method | |
| 720 | + * depends on the implementation. For example, calling <code>refresh</code> | |
| 721 | + * on a file-based policy will cause the file to be re-read. | |
| 722 | + * | |
| 723 | + * <p> The default implementation of this method does nothing. | |
| 724 | + * This method should be overridden if a refresh operation is supported | |
| 725 | + * by the policy implementation. | |
| 726 | + */ | |
| 727 | + public void refresh() { } | |
| 728 | + | |
| 729 | + /** | |
| 730 | + * This subclass is returned by the getInstance calls. All Policy calls | |
| 731 | + * are delegated to the underlying PolicySpi. | |
| 732 | + */ | |
| 733 | + private static class PolicyDelegate extends Policy { | |
| 734 | + | |
| 735 | + private PolicySpi spi; | |
| 736 | + private Provider p; | |
| 737 | + private String type; | |
| 738 | + private Policy.Parameters params; | |
| 739 | + | |
| 740 | + private PolicyDelegate(PolicySpi spi, Provider p, | |
| 741 | + String type, Policy.Parameters params) { | |
| 742 | + this.spi = spi; | |
| 743 | + this.p = p; | |
| 744 | + this.type = type; | |
| 745 | + this.params = params; | |
| 746 | + } | |
| 747 | + | |
| 748 | + @Override public String getType() { return type; } | |
| 749 | + | |
| 750 | + @Override public Policy.Parameters getParameters() { return params; } | |
| 751 | + | |
| 752 | + @Override public Provider getProvider() { return p; } | |
| 753 | + | |
| 754 | + @Override | |
| 755 | + public PermissionCollection getPermissions(CodeSource codesource) { | |
| 756 | + return spi.engineGetPermissions(codesource); | |
| 757 | + } | |
| 758 | + @Override | |
| 759 | + public PermissionCollection getPermissions(ProtectionDomain domain) { | |
| 760 | + return spi.engineGetPermissions(domain); | |
| 761 | + } | |
| 762 | + @Override | |
| 763 | + public boolean implies(ProtectionDomain domain, Permission perm) { | |
| 764 | + return spi.engineImplies(domain, perm); | |
| 765 | + } | |
| 766 | + @Override | |
| 767 | + public void refresh() { | |
| 768 | + spi.engineRefresh(); | |
| 769 | + } | |
| 770 | + } | |
| 771 | + | |
| 772 | + /** | |
| 773 | + * This represents a marker interface for Policy parameters. | |
| 774 | + * | |
| 775 | + * @since 1.6 | |
| 776 | + */ | |
| 777 | + public static interface Parameters { } | |
| 778 | + | |
| 779 | + /** | |
| 780 | + * This class represents a read-only empty PermissionCollection object that | |
| 781 | + * is returned from the <code>getPermissions(CodeSource)</code> and | |
| 782 | + * <code>getPermissions(ProtectionDomain)</code> | |
| 783 | + * methods in the Policy class when those operations are not | |
| 784 | + * supported by the Policy implementation. | |
| 785 | + */ | |
| 786 | + private static class UnsupportedEmptyCollection | |
| 787 | + extends PermissionCollection { | |
| 788 | + | |
| 789 | + private Permissions perms; | |
| 790 | + | |
| 791 | + /** | |
| 792 | + * Create a read-only empty PermissionCollection object. | |
| 793 | + */ | |
| 794 | + public UnsupportedEmptyCollection() { | |
| 795 | + this.perms = new Permissions(); | |
| 796 | + perms.setReadOnly(); | |
| 797 | + } | |
| 798 | + | |
| 799 | + /** | |
| 800 | + * Adds a permission object to the current collection of permission | |
| 801 | + * objects. | |
| 802 | + * | |
| 803 | + * @param permission the Permission object to add. | |
| 804 | + * | |
| 805 | + * @exception SecurityException - if this PermissionCollection object | |
| 806 | + * has been marked readonly | |
| 807 | + */ | |
| 808 | + @Override public void add(Permission permission) { | |
| 809 | + perms.add(permission); | |
| 810 | + } | |
| 811 | + | |
| 812 | + /** | |
| 813 | + * Checks to see if the specified permission is implied by the | |
| 814 | + * collection of Permission objects held in this PermissionCollection. | |
| 815 | + * | |
| 816 | + * @param permission the Permission object to compare. | |
| 817 | + * | |
| 818 | + * @return true if "permission" is implied by the permissions in | |
| 819 | + * the collection, false if not. | |
| 820 | + */ | |
| 821 | + @Override public boolean implies(Permission permission) { | |
| 822 | + return perms.implies(permission); | |
| 823 | + } | |
| 824 | + | |
| 825 | + /** | |
| 826 | + * Returns an enumeration of all the Permission objects in the | |
| 827 | + * collection. | |
| 828 | + * | |
| 829 | + * @return an enumeration of all the Permissions. | |
| 830 | + */ | |
| 831 | + @Override public Enumeration<Permission> elements() { | |
| 832 | + return perms.elements(); | |
| 833 | + } | |
| 834 | + } | |
| 835 | +} | |
Binary file not shown.
| @@ -0,0 +1,118 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | + | |
| 27 | +package java.security; | |
| 28 | + | |
| 29 | +/** | |
| 30 | + * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) | |
| 31 | + * for the <code>Policy</code> class. | |
| 32 | + * All the abstract methods in this class must be implemented by each | |
| 33 | + * service provider who wishes to supply a Policy implementation. | |
| 34 | + * | |
| 35 | + * <p> Subclass implementations of this abstract class must provide | |
| 36 | + * a public constructor that takes a <code>Policy.Parameters</code> | |
| 37 | + * object as an input parameter. This constructor also must throw | |
| 38 | + * an IllegalArgumentException if it does not understand the | |
| 39 | + * <code>Policy.Parameters</code> input. | |
| 40 | + * | |
| 41 | + * | |
| 42 | + * @since 1.6 | |
| 43 | + */ | |
| 44 | + | |
| 45 | +public abstract class PolicySpi { | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * Check whether the policy has granted a Permission to a ProtectionDomain. | |
| 49 | + * | |
| 50 | + * @param domain the ProtectionDomain to check. | |
| 51 | + * | |
| 52 | + * @param permission check whether this permission is granted to the | |
| 53 | + * specified domain. | |
| 54 | + * | |
| 55 | + * @return boolean true if the permission is granted to the domain. | |
| 56 | + */ | |
| 57 | + protected abstract boolean engineImplies | |
| 58 | + (ProtectionDomain domain, Permission permission); | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * Refreshes/reloads the policy configuration. The behavior of this method | |
| 62 | + * depends on the implementation. For example, calling <code>refresh</code> | |
| 63 | + * on a file-based policy will cause the file to be re-read. | |
| 64 | + * | |
| 65 | + * <p> The default implementation of this method does nothing. | |
| 66 | + * This method should be overridden if a refresh operation is supported | |
| 67 | + * by the policy implementation. | |
| 68 | + */ | |
| 69 | + protected void engineRefresh() { } | |
| 70 | + | |
| 71 | + /** | |
| 72 | + * Return a PermissionCollection object containing the set of | |
| 73 | + * permissions granted to the specified CodeSource. | |
| 74 | + * | |
| 75 | + * <p> The default implementation of this method returns | |
| 76 | + * Policy.UNSUPPORTED_EMPTY_COLLECTION object. This method can be | |
| 77 | + * overridden if the policy implementation can return a set of | |
| 78 | + * permissions granted to a CodeSource. | |
| 79 | + * | |
| 80 | + * @param codesource the CodeSource to which the returned | |
| 81 | + * PermissionCollection has been granted. | |
| 82 | + * | |
| 83 | + * @return a set of permissions granted to the specified CodeSource. | |
| 84 | + * If this operation is supported, the returned | |
| 85 | + * set of permissions must be a new mutable instance | |
| 86 | + * and it must support heterogeneous Permission types. | |
| 87 | + * If this operation is not supported, | |
| 88 | + * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned. | |
| 89 | + */ | |
| 90 | + protected PermissionCollection engineGetPermissions | |
| 91 | + (CodeSource codesource) { | |
| 92 | + return Policy.UNSUPPORTED_EMPTY_COLLECTION; | |
| 93 | + } | |
| 94 | + | |
| 95 | + /** | |
| 96 | + * Return a PermissionCollection object containing the set of | |
| 97 | + * permissions granted to the specified ProtectionDomain. | |
| 98 | + * | |
| 99 | + * <p> The default implementation of this method returns | |
| 100 | + * Policy.UNSUPPORTED_EMPTY_COLLECTION object. This method can be | |
| 101 | + * overridden if the policy implementation can return a set of | |
| 102 | + * permissions granted to a ProtectionDomain. | |
| 103 | + * | |
| 104 | + * @param domain the ProtectionDomain to which the returned | |
| 105 | + * PermissionCollection has been granted. | |
| 106 | + * | |
| 107 | + * @return a set of permissions granted to the specified ProtectionDomain. | |
| 108 | + * If this operation is supported, the returned | |
| 109 | + * set of permissions must be a new mutable instance | |
| 110 | + * and it must support heterogeneous Permission types. | |
| 111 | + * If this operation is not supported, | |
| 112 | + * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned. | |
| 113 | + */ | |
| 114 | + protected PermissionCollection engineGetPermissions | |
| 115 | + (ProtectionDomain domain) { | |
| 116 | + return Policy.UNSUPPORTED_EMPTY_COLLECTION; | |
| 117 | + } | |
| 118 | +} | |
Binary file not shown.
| @@ -0,0 +1,72 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This interface represents the abstract notion of a principal, which | |
| 30 | + * can be used to represent any entity, such as an individual, a | |
| 31 | + * corporation, and a login id. | |
| 32 | + * | |
| 33 | + * @see java.security.cert.X509Certificate | |
| 34 | + * | |
| 35 | + * @author Li Gong | |
| 36 | + */ | |
| 37 | +public interface Principal { | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * Compares this principal to the specified object. Returns true | |
| 41 | + * if the object passed in matches the principal represented by | |
| 42 | + * the implementation of this interface. | |
| 43 | + * | |
| 44 | + * @param another principal to compare with. | |
| 45 | + * | |
| 46 | + * @return true if the principal passed in is the same as that | |
| 47 | + * encapsulated by this principal, and false otherwise. | |
| 48 | + | |
| 49 | + */ | |
| 50 | + public boolean equals(Object another); | |
| 51 | + | |
| 52 | + /** | |
| 53 | + * Returns a string representation of this principal. | |
| 54 | + * | |
| 55 | + * @return a string representation of this principal. | |
| 56 | + */ | |
| 57 | + public String toString(); | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * Returns a hashcode for this principal. | |
| 61 | + * | |
| 62 | + * @return a hashcode for this principal. | |
| 63 | + */ | |
| 64 | + public int hashCode(); | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * Returns the name of this principal. | |
| 68 | + * | |
| 69 | + * @return the name of this principal. | |
| 70 | + */ | |
| 71 | + public String getName(); | |
| 72 | +} | |
Binary file not shown.
| @@ -0,0 +1,56 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2001, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * <p>A private key. This interface contains no methods or constants. | |
| 30 | + * It merely serves to group (and provide type safety for) all private key | |
| 31 | + * interfaces. | |
| 32 | + * | |
| 33 | + * Note: The specialized private key interfaces extend this interface. | |
| 34 | + * See, for example, the DSAPrivateKey interface in | |
| 35 | + * <code>java.security.interfaces</code>. | |
| 36 | + * | |
| 37 | + * @see Key | |
| 38 | + * @see PublicKey | |
| 39 | + * @see Certificate | |
| 40 | + * @see Signature#initVerify | |
| 41 | + * @see java.security.interfaces.DSAPrivateKey | |
| 42 | + * @see java.security.interfaces.RSAPrivateKey | |
| 43 | + * @see java.security.interfaces.RSAPrivateCrtKey | |
| 44 | + * | |
| 45 | + * @author Benjamin Renaud | |
| 46 | + * @author Josh Bloch | |
| 47 | + */ | |
| 48 | + | |
| 49 | +public interface PrivateKey extends Key { | |
| 50 | + // Declare serialVersionUID to be compatible with JDK1.1 | |
| 51 | + /** | |
| 52 | + * The class fingerprint that is set to indicate serialization | |
| 53 | + * compatibility with a previous version of the class. | |
| 54 | + */ | |
| 55 | + static final long serialVersionUID = 6034044314589513430L; | |
| 56 | +} | |
Binary file not shown.
| @@ -0,0 +1,56 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | + | |
| 29 | +/** | |
| 30 | + * A computation to be performed with privileges enabled. The computation is | |
| 31 | + * performed by invoking <code>AccessController.doPrivileged</code> on the | |
| 32 | + * <code>PrivilegedAction</code> object. This interface is used only for | |
| 33 | + * computations that do not throw checked exceptions; computations that | |
| 34 | + * throw checked exceptions must use <code>PrivilegedExceptionAction</code> | |
| 35 | + * instead. | |
| 36 | + * | |
| 37 | + * @see AccessController | |
| 38 | + * @see AccessController#doPrivileged(PrivilegedAction) | |
| 39 | + * @see PrivilegedExceptionAction | |
| 40 | + */ | |
| 41 | + | |
| 42 | +public interface PrivilegedAction<T> { | |
| 43 | + /** | |
| 44 | + * Performs the computation. This method will be called by | |
| 45 | + * <code>AccessController.doPrivileged</code> after enabling privileges. | |
| 46 | + * | |
| 47 | + * @return a class-dependent value that may represent the results of the | |
| 48 | + * computation. Each class that implements | |
| 49 | + * <code>PrivilegedAction</code> | |
| 50 | + * should document what (if anything) this value represents. | |
| 51 | + * @see AccessController#doPrivileged(PrivilegedAction) | |
| 52 | + * @see AccessController#doPrivileged(PrivilegedAction, | |
| 53 | + * AccessControlContext) | |
| 54 | + */ | |
| 55 | + T run(); | |
| 56 | +} | |
Binary file not shown.
| @@ -0,0 +1,105 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This exception is thrown by | |
| 30 | + * <code>doPrivileged(PrivilegedExceptionAction)</code> and | |
| 31 | + * <code>doPrivileged(PrivilegedExceptionAction, | |
| 32 | + * AccessControlContext context)</code> to indicate | |
| 33 | + * that the action being performed threw a checked exception. The exception | |
| 34 | + * thrown by the action can be obtained by calling the | |
| 35 | + * <code>getException</code> method. In effect, an | |
| 36 | + * <code>PrivilegedActionException</code> is a "wrapper" | |
| 37 | + * for an exception thrown by a privileged action. | |
| 38 | + * | |
| 39 | + * <p>As of release 1.4, this exception has been retrofitted to conform to | |
| 40 | + * the general purpose exception-chaining mechanism. The "exception thrown | |
| 41 | + * by the privileged computation" that is provided at construction time and | |
| 42 | + * accessed via the {@link #getException()} method is now known as the | |
| 43 | + * <i>cause</i>, and may be accessed via the {@link Throwable#getCause()} | |
| 44 | + * method, as well as the aforementioned "legacy method." | |
| 45 | + * | |
| 46 | + * @see PrivilegedExceptionAction | |
| 47 | + * @see AccessController#doPrivileged(PrivilegedExceptionAction) | |
| 48 | + * @see AccessController#doPrivileged(PrivilegedExceptionAction,AccessControlContext) | |
| 49 | + */ | |
| 50 | +public class PrivilegedActionException extends Exception { | |
| 51 | + // use serialVersionUID from JDK 1.2.2 for interoperability | |
| 52 | + private static final long serialVersionUID = 4724086851538908602L; | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * @serial | |
| 56 | + */ | |
| 57 | + private Exception exception; | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * Constructs a new PrivilegedActionException "wrapping" | |
| 61 | + * the specific Exception. | |
| 62 | + * | |
| 63 | + * @param exception The exception thrown | |
| 64 | + */ | |
| 65 | + public PrivilegedActionException(Exception exception) { | |
| 66 | + super((Throwable)null); // Disallow initCause | |
| 67 | + this.exception = exception; | |
| 68 | + } | |
| 69 | + | |
| 70 | + /** | |
| 71 | + * Returns the exception thrown by the privileged computation that | |
| 72 | + * resulted in this <code>PrivilegedActionException</code>. | |
| 73 | + * | |
| 74 | + * <p>This method predates the general-purpose exception chaining facility. | |
| 75 | + * The {@link Throwable#getCause()} method is now the preferred means of | |
| 76 | + * obtaining this information. | |
| 77 | + * | |
| 78 | + * @return the exception thrown by the privileged computation that | |
| 79 | + * resulted in this <code>PrivilegedActionException</code>. | |
| 80 | + * @see PrivilegedExceptionAction | |
| 81 | + * @see AccessController#doPrivileged(PrivilegedExceptionAction) | |
| 82 | + * @see AccessController#doPrivileged(PrivilegedExceptionAction, | |
| 83 | + * AccessControlContext) | |
| 84 | + */ | |
| 85 | + public Exception getException() { | |
| 86 | + return exception; | |
| 87 | + } | |
| 88 | + | |
| 89 | + /** | |
| 90 | + * Returns the cause of this exception (the exception thrown by | |
| 91 | + * the privileged computation that resulted in this | |
| 92 | + * <code>PrivilegedActionException</code>). | |
| 93 | + * | |
| 94 | + * @return the cause of this exception. | |
| 95 | + * @since 1.4 | |
| 96 | + */ | |
| 97 | + public Throwable getCause() { | |
| 98 | + return exception; | |
| 99 | + } | |
| 100 | + | |
| 101 | + public String toString() { | |
| 102 | + String s = getClass().getName(); | |
| 103 | + return (exception != null) ? (s + ": " + exception.toString()) : s; | |
| 104 | + } | |
| 105 | +} | |
Binary file not shown.
| @@ -0,0 +1,62 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | + | |
| 29 | +/** | |
| 30 | + * A computation to be performed with privileges enabled, that throws one or | |
| 31 | + * more checked exceptions. The computation is performed by invoking | |
| 32 | + * <code>AccessController.doPrivileged</code> on the | |
| 33 | + * <code>PrivilegedExceptionAction</code> object. This interface is | |
| 34 | + * used only for computations that throw checked exceptions; | |
| 35 | + * computations that do not throw | |
| 36 | + * checked exceptions should use <code>PrivilegedAction</code> instead. | |
| 37 | + * | |
| 38 | + * @see AccessController | |
| 39 | + * @see AccessController#doPrivileged(PrivilegedExceptionAction) | |
| 40 | + * @see AccessController#doPrivileged(PrivilegedExceptionAction, | |
| 41 | + * AccessControlContext) | |
| 42 | + * @see PrivilegedAction | |
| 43 | + */ | |
| 44 | + | |
| 45 | +public interface PrivilegedExceptionAction<T> { | |
| 46 | + /** | |
| 47 | + * Performs the computation. This method will be called by | |
| 48 | + * <code>AccessController.doPrivileged</code> after enabling privileges. | |
| 49 | + * | |
| 50 | + * @return a class-dependent value that may represent the results of the | |
| 51 | + * computation. Each class that implements | |
| 52 | + * <code>PrivilegedExceptionAction</code> should document what | |
| 53 | + * (if anything) this value represents. | |
| 54 | + * @throws Exception an exceptional condition has occurred. Each class | |
| 55 | + * that implements <code>PrivilegedExceptionAction</code> should | |
| 56 | + * document the exceptions that its run method can throw. | |
| 57 | + * @see AccessController#doPrivileged(PrivilegedExceptionAction) | |
| 58 | + * @see AccessController#doPrivileged(PrivilegedExceptionAction,AccessControlContext) | |
| 59 | + */ | |
| 60 | + | |
| 61 | + T run() throws Exception; | |
| 62 | +} | |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,467 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.util.ArrayList; | |
| 29 | +import java.util.Collections; | |
| 30 | +import java.util.Enumeration; | |
| 31 | +import java.util.List; | |
| 32 | +import java.util.Map; | |
| 33 | +import java.util.WeakHashMap; | |
| 34 | +import sun.misc.JavaSecurityProtectionDomainAccess; | |
| 35 | +import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache; | |
| 36 | +import sun.misc.SharedSecrets; | |
| 37 | +import sun.security.util.Debug; | |
| 38 | +import sun.security.util.SecurityConstants; | |
| 39 | +import sun.misc.JavaSecurityAccess; | |
| 40 | +import sun.misc.SharedSecrets; | |
| 41 | + | |
| 42 | +/** | |
| 43 | + * | |
| 44 | + *<p> | |
| 45 | + * This ProtectionDomain class encapsulates the characteristics of a domain, | |
| 46 | + * which encloses a set of classes whose instances are granted a set | |
| 47 | + * of permissions when being executed on behalf of a given set of Principals. | |
| 48 | + * <p> | |
| 49 | + * A static set of permissions can be bound to a ProtectionDomain when it is | |
| 50 | + * constructed; such permissions are granted to the domain regardless of the | |
| 51 | + * Policy in force. However, to support dynamic security policies, a | |
| 52 | + * ProtectionDomain can also be constructed such that it is dynamically | |
| 53 | + * mapped to a set of permissions by the current Policy whenever a permission | |
| 54 | + * is checked. | |
| 55 | + * <p> | |
| 56 | + * | |
| 57 | + * @author Li Gong | |
| 58 | + * @author Roland Schemers | |
| 59 | + * @author Gary Ellison | |
| 60 | + */ | |
| 61 | + | |
| 62 | +public class ProtectionDomain { | |
| 63 | + | |
| 64 | + static { | |
| 65 | + // Set up JavaSecurityAccess in SharedSecrets | |
| 66 | + SharedSecrets.setJavaSecurityAccess( | |
| 67 | + new JavaSecurityAccess() { | |
| 68 | + public <T> T doIntersectionPrivilege( | |
| 69 | + PrivilegedAction<T> action, | |
| 70 | + final AccessControlContext stack, | |
| 71 | + final AccessControlContext context) | |
| 72 | + { | |
| 73 | + if (action == null) { | |
| 74 | + throw new NullPointerException(); | |
| 75 | + } | |
| 76 | + return AccessController.doPrivileged( | |
| 77 | + action, | |
| 78 | + new AccessControlContext( | |
| 79 | + stack.getContext(), context).optimize() | |
| 80 | + ); | |
| 81 | + } | |
| 82 | + | |
| 83 | + public <T> T doIntersectionPrivilege( | |
| 84 | + PrivilegedAction<T> action, | |
| 85 | + AccessControlContext context) | |
| 86 | + { | |
| 87 | + return doIntersectionPrivilege(action, | |
| 88 | + AccessController.getContext(), context); | |
| 89 | + } | |
| 90 | + } | |
| 91 | + ); | |
| 92 | + } | |
| 93 | + | |
| 94 | + /* CodeSource */ | |
| 95 | + private CodeSource codesource ; | |
| 96 | + | |
| 97 | + /* ClassLoader the protection domain was consed from */ | |
| 98 | + private ClassLoader classloader; | |
| 99 | + | |
| 100 | + /* Principals running-as within this protection domain */ | |
| 101 | + private Principal[] principals; | |
| 102 | + | |
| 103 | + /* the rights this protection domain is granted */ | |
| 104 | + private PermissionCollection permissions; | |
| 105 | + | |
| 106 | + /* if the permissions object has AllPermission */ | |
| 107 | + private boolean hasAllPerm = false; | |
| 108 | + | |
| 109 | + /* the PermissionCollection is static (pre 1.4 constructor) | |
| 110 | + or dynamic (via a policy refresh) */ | |
| 111 | + private boolean staticPermissions; | |
| 112 | + | |
| 113 | + /* | |
| 114 | + * An object used as a key when the ProtectionDomain is stored in a Map. | |
| 115 | + */ | |
| 116 | + final Key key = new Key(); | |
| 117 | + | |
| 118 | + private static final Debug debug = Debug.getInstance("domain"); | |
| 119 | + | |
| 120 | + /** | |
| 121 | + * Creates a new ProtectionDomain with the given CodeSource and | |
| 122 | + * Permissions. If the permissions object is not null, then | |
| 123 | + * <code>setReadOnly())</code> will be called on the passed in | |
| 124 | + * Permissions object. The only permissions granted to this domain | |
| 125 | + * are the ones specified; the current Policy will not be consulted. | |
| 126 | + * | |
| 127 | + * @param codesource the codesource associated with this domain | |
| 128 | + * @param permissions the permissions granted to this domain | |
| 129 | + */ | |
| 130 | + public ProtectionDomain(CodeSource codesource, | |
| 131 | + PermissionCollection permissions) { | |
| 132 | + this.codesource = codesource; | |
| 133 | + if (permissions != null) { | |
| 134 | + this.permissions = permissions; | |
| 135 | + this.permissions.setReadOnly(); | |
| 136 | + if (permissions instanceof Permissions && | |
| 137 | + ((Permissions)permissions).allPermission != null) { | |
| 138 | + hasAllPerm = true; | |
| 139 | + } | |
| 140 | + } | |
| 141 | + this.classloader = null; | |
| 142 | + this.principals = new Principal[0]; | |
| 143 | + staticPermissions = true; | |
| 144 | + } | |
| 145 | + | |
| 146 | + /** | |
| 147 | + * Creates a new ProtectionDomain qualified by the given CodeSource, | |
| 148 | + * Permissions, ClassLoader and array of Principals. If the | |
| 149 | + * permissions object is not null, then <code>setReadOnly()</code> | |
| 150 | + * will be called on the passed in Permissions object. | |
| 151 | + * The permissions granted to this domain are dynamic; they include | |
| 152 | + * both the static permissions passed to this constructor, and any | |
| 153 | + * permissions granted to this domain by the current Policy at the | |
| 154 | + * time a permission is checked. | |
| 155 | + * <p> | |
| 156 | + * This constructor is typically used by | |
| 157 | + * {@link SecureClassLoader ClassLoaders} | |
| 158 | + * and {@link DomainCombiner DomainCombiners} which delegate to | |
| 159 | + * <code>Policy</code> to actively associate the permissions granted to | |
| 160 | + * this domain. This constructor affords the | |
| 161 | + * Policy provider the opportunity to augment the supplied | |
| 162 | + * PermissionCollection to reflect policy changes. | |
| 163 | + * <p> | |
| 164 | + * | |
| 165 | + * @param codesource the CodeSource associated with this domain | |
| 166 | + * @param permissions the permissions granted to this domain | |
| 167 | + * @param classloader the ClassLoader associated with this domain | |
| 168 | + * @param principals the array of Principals associated with this | |
| 169 | + * domain. The contents of the array are copied to protect against | |
| 170 | + * subsequent modification. | |
| 171 | + * @see Policy#refresh | |
| 172 | + * @see Policy#getPermissions(ProtectionDomain) | |
| 173 | + * @since 1.4 | |
| 174 | + */ | |
| 175 | + public ProtectionDomain(CodeSource codesource, | |
| 176 | + PermissionCollection permissions, | |
| 177 | + ClassLoader classloader, | |
| 178 | + Principal[] principals) { | |
| 179 | + this.codesource = codesource; | |
| 180 | + if (permissions != null) { | |
| 181 | + this.permissions = permissions; | |
| 182 | + this.permissions.setReadOnly(); | |
| 183 | + if (permissions instanceof Permissions && | |
| 184 | + ((Permissions)permissions).allPermission != null) { | |
| 185 | + hasAllPerm = true; | |
| 186 | + } | |
| 187 | + } | |
| 188 | + this.classloader = classloader; | |
| 189 | + this.principals = (principals != null ? principals.clone(): | |
| 190 | + new Principal[0]); | |
| 191 | + staticPermissions = false; | |
| 192 | + } | |
| 193 | + | |
| 194 | + /** | |
| 195 | + * Returns the CodeSource of this domain. | |
| 196 | + * @return the CodeSource of this domain which may be null. | |
| 197 | + * @since 1.2 | |
| 198 | + */ | |
| 199 | + public final CodeSource getCodeSource() { | |
| 200 | + return this.codesource; | |
| 201 | + } | |
| 202 | + | |
| 203 | + | |
| 204 | + /** | |
| 205 | + * Returns the ClassLoader of this domain. | |
| 206 | + * @return the ClassLoader of this domain which may be null. | |
| 207 | + * | |
| 208 | + * @since 1.4 | |
| 209 | + */ | |
| 210 | + public final ClassLoader getClassLoader() { | |
| 211 | + return this.classloader; | |
| 212 | + } | |
| 213 | + | |
| 214 | + | |
| 215 | + /** | |
| 216 | + * Returns an array of principals for this domain. | |
| 217 | + * @return a non-null array of principals for this domain. | |
| 218 | + * Returns a new array each time this method is called. | |
| 219 | + * | |
| 220 | + * @since 1.4 | |
| 221 | + */ | |
| 222 | + public final Principal[] getPrincipals() { | |
| 223 | + return this.principals.clone(); | |
| 224 | + } | |
| 225 | + | |
| 226 | + /** | |
| 227 | + * Returns the static permissions granted to this domain. | |
| 228 | + * | |
| 229 | + * @return the static set of permissions for this domain which may be null. | |
| 230 | + * @see Policy#refresh | |
| 231 | + * @see Policy#getPermissions(ProtectionDomain) | |
| 232 | + */ | |
| 233 | + public final PermissionCollection getPermissions() { | |
| 234 | + return permissions; | |
| 235 | + } | |
| 236 | + | |
| 237 | + /** | |
| 238 | + * Check and see if this ProtectionDomain implies the permissions | |
| 239 | + * expressed in the Permission object. | |
| 240 | + * <p> | |
| 241 | + * The set of permissions evaluated is a function of whether the | |
| 242 | + * ProtectionDomain was constructed with a static set of permissions | |
| 243 | + * or it was bound to a dynamically mapped set of permissions. | |
| 244 | + * <p> | |
| 245 | + * If the ProtectionDomain was constructed to a | |
| 246 | + * {@link #ProtectionDomain(CodeSource, PermissionCollection) | |
| 247 | + * statically bound} PermissionCollection then the permission will | |
| 248 | + * only be checked against the PermissionCollection supplied at | |
| 249 | + * construction. | |
| 250 | + * <p> | |
| 251 | + * However, if the ProtectionDomain was constructed with | |
| 252 | + * the constructor variant which supports | |
| 253 | + * {@link #ProtectionDomain(CodeSource, PermissionCollection, | |
| 254 | + * ClassLoader, java.security.Principal[]) dynamically binding} | |
| 255 | + * permissions, then the permission will be checked against the | |
| 256 | + * combination of the PermissionCollection supplied at construction and | |
| 257 | + * the current Policy binding. | |
| 258 | + * <p> | |
| 259 | + * | |
| 260 | + * @param permission the Permission object to check. | |
| 261 | + * | |
| 262 | + * @return true if "permission" is implicit to this ProtectionDomain. | |
| 263 | + */ | |
| 264 | + public boolean implies(Permission permission) { | |
| 265 | + | |
| 266 | + if (hasAllPerm) { | |
| 267 | + // internal permission collection already has AllPermission - | |
| 268 | + // no need to go to policy | |
| 269 | + return true; | |
| 270 | + } | |
| 271 | + | |
| 272 | + if (!staticPermissions && | |
| 273 | + Policy.getPolicyNoCheck().implies(this, permission)) | |
| 274 | + return true; | |
| 275 | + if (permissions != null) | |
| 276 | + return permissions.implies(permission); | |
| 277 | + | |
| 278 | + return false; | |
| 279 | + } | |
| 280 | + | |
| 281 | + /** | |
| 282 | + * Convert a ProtectionDomain to a String. | |
| 283 | + */ | |
| 284 | + @Override public String toString() { | |
| 285 | + String pals = "<no principals>"; | |
| 286 | + if (principals != null && principals.length > 0) { | |
| 287 | + StringBuilder palBuf = new StringBuilder("(principals "); | |
| 288 | + | |
| 289 | + for (int i = 0; i < principals.length; i++) { | |
| 290 | + palBuf.append(principals[i].getClass().getName() + | |
| 291 | + " \"" + principals[i].getName() + | |
| 292 | + "\""); | |
| 293 | + if (i < principals.length-1) | |
| 294 | + palBuf.append(",\n"); | |
| 295 | + else | |
| 296 | + palBuf.append(")\n"); | |
| 297 | + } | |
| 298 | + pals = palBuf.toString(); | |
| 299 | + } | |
| 300 | + | |
| 301 | + // Check if policy is set; we don't want to load | |
| 302 | + // the policy prematurely here | |
| 303 | + PermissionCollection pc = Policy.isSet() && seeAllp() ? | |
| 304 | + mergePermissions(): | |
| 305 | + getPermissions(); | |
| 306 | + | |
| 307 | + return "ProtectionDomain "+ | |
| 308 | + " "+codesource+"\n"+ | |
| 309 | + " "+classloader+"\n"+ | |
| 310 | + " "+pals+"\n"+ | |
| 311 | + " "+pc+"\n"; | |
| 312 | + } | |
| 313 | + | |
| 314 | + /** | |
| 315 | + * Return true (merge policy permissions) in the following cases: | |
| 316 | + * | |
| 317 | + * . SecurityManager is null | |
| 318 | + * | |
| 319 | + * . SecurityManager is not null, | |
| 320 | + * debug is not null, | |
| 321 | + * SecurityManager impelmentation is in bootclasspath, | |
| 322 | + * Policy implementation is in bootclasspath | |
| 323 | + * (the bootclasspath restrictions avoid recursion) | |
| 324 | + * | |
| 325 | + * . SecurityManager is not null, | |
| 326 | + * debug is null, | |
| 327 | + * caller has Policy.getPolicy permission | |
| 328 | + */ | |
| 329 | + private static boolean seeAllp() { | |
| 330 | + SecurityManager sm = System.getSecurityManager(); | |
| 331 | + | |
| 332 | + if (sm == null) { | |
| 333 | + return true; | |
| 334 | + } else { | |
| 335 | + if (debug != null) { | |
| 336 | + if (sm.getClass().getClassLoader() == null && | |
| 337 | + Policy.getPolicyNoCheck().getClass().getClassLoader() | |
| 338 | + == null) { | |
| 339 | + return true; | |
| 340 | + } | |
| 341 | + } else { | |
| 342 | + try { | |
| 343 | + sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION); | |
| 344 | + return true; | |
| 345 | + } catch (SecurityException se) { | |
| 346 | + // fall thru and return false | |
| 347 | + } | |
| 348 | + } | |
| 349 | + } | |
| 350 | + | |
| 351 | + return false; | |
| 352 | + } | |
| 353 | + | |
| 354 | + private PermissionCollection mergePermissions() { | |
| 355 | + if (staticPermissions) | |
| 356 | + return permissions; | |
| 357 | + | |
| 358 | + PermissionCollection perms = | |
| 359 | + java.security.AccessController.doPrivileged | |
| 360 | + (new java.security.PrivilegedAction<PermissionCollection>() { | |
| 361 | + public PermissionCollection run() { | |
| 362 | + Policy p = Policy.getPolicyNoCheck(); | |
| 363 | + return p.getPermissions(ProtectionDomain.this); | |
| 364 | + } | |
| 365 | + }); | |
| 366 | + | |
| 367 | + Permissions mergedPerms = new Permissions(); | |
| 368 | + int swag = 32; | |
| 369 | + int vcap = 8; | |
| 370 | + Enumeration<Permission> e; | |
| 371 | + List<Permission> pdVector = new ArrayList<>(vcap); | |
| 372 | + List<Permission> plVector = new ArrayList<>(swag); | |
| 373 | + | |
| 374 | + // | |
| 375 | + // Build a vector of domain permissions for subsequent merge | |
| 376 | + if (permissions != null) { | |
| 377 | + synchronized (permissions) { | |
| 378 | + e = permissions.elements(); | |
| 379 | + while (e.hasMoreElements()) { | |
| 380 | + pdVector.add(e.nextElement()); | |
| 381 | + } | |
| 382 | + } | |
| 383 | + } | |
| 384 | + | |
| 385 | + // | |
| 386 | + // Build a vector of Policy permissions for subsequent merge | |
| 387 | + if (perms != null) { | |
| 388 | + synchronized (perms) { | |
| 389 | + e = perms.elements(); | |
| 390 | + while (e.hasMoreElements()) { | |
| 391 | + plVector.add(e.nextElement()); | |
| 392 | + vcap++; | |
| 393 | + } | |
| 394 | + } | |
| 395 | + } | |
| 396 | + | |
| 397 | + if (perms != null && permissions != null) { | |
| 398 | + // | |
| 399 | + // Weed out the duplicates from the policy. Unless a refresh | |
| 400 | + // has occured since the pd was consed this should result in | |
| 401 | + // an empty vector. | |
| 402 | + synchronized (permissions) { | |
| 403 | + e = permissions.elements(); // domain vs policy | |
| 404 | + while (e.hasMoreElements()) { | |
| 405 | + Permission pdp = e.nextElement(); | |
| 406 | + Class pdpClass = pdp.getClass(); | |
| 407 | + String pdpActions = pdp.getActions(); | |
| 408 | + String pdpName = pdp.getName(); | |
| 409 | + for (int i = 0; i < plVector.size(); i++) { | |
| 410 | + Permission pp = plVector.get(i); | |
| 411 | + if (pdpClass.isInstance(pp)) { | |
| 412 | + // The equals() method on some permissions | |
| 413 | + // have some side effects so this manual | |
| 414 | + // comparison is sufficient. | |
| 415 | + if (pdpName.equals(pp.getName()) && | |
| 416 | + pdpActions.equals(pp.getActions())) { | |
| 417 | + plVector.remove(i); | |
| 418 | + break; | |
| 419 | + } | |
| 420 | + } | |
| 421 | + } | |
| 422 | + } | |
| 423 | + } | |
| 424 | + } | |
| 425 | + | |
| 426 | + if (perms !=null) { | |
| 427 | + // the order of adding to merged perms and permissions | |
| 428 | + // needs to preserve the bugfix 4301064 | |
| 429 | + | |
| 430 | + for (int i = plVector.size()-1; i >= 0; i--) { | |
| 431 | + mergedPerms.add(plVector.get(i)); | |
| 432 | + } | |
| 433 | + } | |
| 434 | + if (permissions != null) { | |
| 435 | + for (int i = pdVector.size()-1; i >= 0; i--) { | |
| 436 | + mergedPerms.add(pdVector.get(i)); | |
| 437 | + } | |
| 438 | + } | |
| 439 | + | |
| 440 | + return mergedPerms; | |
| 441 | + } | |
| 442 | + | |
| 443 | + /** | |
| 444 | + * Used for storing ProtectionDomains as keys in a Map. | |
| 445 | + */ | |
| 446 | + final class Key {} | |
| 447 | + | |
| 448 | + static { | |
| 449 | + SharedSecrets.setJavaSecurityProtectionDomainAccess( | |
| 450 | + new JavaSecurityProtectionDomainAccess() { | |
| 451 | + public ProtectionDomainCache getProtectionDomainCache() { | |
| 452 | + return new ProtectionDomainCache() { | |
| 453 | + private final Map<Key, PermissionCollection> map = | |
| 454 | + Collections.synchronizedMap | |
| 455 | + (new WeakHashMap<Key, PermissionCollection>()); | |
| 456 | + public void put(ProtectionDomain pd, | |
| 457 | + PermissionCollection pc) { | |
| 458 | + map.put((pd == null ? null : pd.key), pc); | |
| 459 | + } | |
| 460 | + public PermissionCollection get(ProtectionDomain pd) { | |
| 461 | + return pd == null ? map.get(null) : map.get(pd.key); | |
| 462 | + } | |
| 463 | + }; | |
| 464 | + } | |
| 465 | + }); | |
| 466 | + } | |
| 467 | +} | |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,1479 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.io.*; | |
| 29 | +import java.util.*; | |
| 30 | +import static java.util.Locale.ENGLISH; | |
| 31 | +import java.lang.ref.*; | |
| 32 | +import java.lang.reflect.*; | |
| 33 | + | |
| 34 | +import java.security.cert.CertStoreParameters; | |
| 35 | +import javax.security.auth.login.Configuration; | |
| 36 | + | |
| 37 | +/** | |
| 38 | + * This class represents a "provider" for the | |
| 39 | + * Java Security API, where a provider implements some or all parts of | |
| 40 | + * Java Security. Services that a provider may implement include: | |
| 41 | + * | |
| 42 | + * <ul> | |
| 43 | + * | |
| 44 | + * <li>Algorithms (such as DSA, RSA, MD5 or SHA-1). | |
| 45 | + * | |
| 46 | + * <li>Key generation, conversion, and management facilities (such as for | |
| 47 | + * algorithm-specific keys). | |
| 48 | + * | |
| 49 | + *</ul> | |
| 50 | + * | |
| 51 | + * <p>Each provider has a name and a version number, and is configured | |
| 52 | + * in each runtime it is installed in. | |
| 53 | + * | |
| 54 | + * <p>See <a href = | |
| 55 | + * "../../../technotes/guides/security/crypto/CryptoSpec.html#Provider">The Provider Class</a> | |
| 56 | + * in the "Java Cryptography Architecture API Specification & Reference" | |
| 57 | + * for information about how a particular type of provider, the | |
| 58 | + * cryptographic service provider, works and is installed. However, | |
| 59 | + * please note that a provider can be used to implement any security | |
| 60 | + * service in Java that uses a pluggable architecture with a choice | |
| 61 | + * of implementations that fit underneath. | |
| 62 | + * | |
| 63 | + * <p>Some provider implementations may encounter unrecoverable internal | |
| 64 | + * errors during their operation, for example a failure to communicate with a | |
| 65 | + * security token. A {@link ProviderException} should be used to indicate | |
| 66 | + * such errors. | |
| 67 | + * | |
| 68 | + * <p>The service type <code>Provider</code> is reserved for use by the | |
| 69 | + * security framework. Services of this type cannot be added, removed, | |
| 70 | + * or modified by applications. | |
| 71 | + * The following attributes are automatically placed in each Provider object: | |
| 72 | + * <table cellspacing=4> | |
| 73 | + * <tr><th>Name</th><th>Value</th> | |
| 74 | + * <tr><td><code>Provider.id name</code></td> | |
| 75 | + * <td><code>String.valueOf(provider.getName())</code></td> | |
| 76 | + * <tr><td><code>Provider.id version</code></td> | |
| 77 | + * <td><code>String.valueOf(provider.getVersion())</code></td> | |
| 78 | + * <tr><td><code>Provider.id info</code></td> | |
| 79 | + <td><code>String.valueOf(provider.getInfo())</code></td> | |
| 80 | + * <tr><td><code>Provider.id className</code></td> | |
| 81 | + * <td><code>provider.getClass().getName()</code></td> | |
| 82 | + * </table> | |
| 83 | + * | |
| 84 | + * @author Benjamin Renaud | |
| 85 | + * @author Andreas Sterbenz | |
| 86 | + */ | |
| 87 | +public abstract class Provider extends Properties { | |
| 88 | + | |
| 89 | + // Declare serialVersionUID to be compatible with JDK1.1 | |
| 90 | + static final long serialVersionUID = -4298000515446427739L; | |
| 91 | + | |
| 92 | + private static final sun.security.util.Debug debug = | |
| 93 | + sun.security.util.Debug.getInstance | |
| 94 | + ("provider", "Provider"); | |
| 95 | + | |
| 96 | + /** | |
| 97 | + * The provider name. | |
| 98 | + * | |
| 99 | + * @serial | |
| 100 | + */ | |
| 101 | + private String name; | |
| 102 | + | |
| 103 | + /** | |
| 104 | + * A description of the provider and its services. | |
| 105 | + * | |
| 106 | + * @serial | |
| 107 | + */ | |
| 108 | + private String info; | |
| 109 | + | |
| 110 | + /** | |
| 111 | + * The provider version number. | |
| 112 | + * | |
| 113 | + * @serial | |
| 114 | + */ | |
| 115 | + private double version; | |
| 116 | + | |
| 117 | + | |
| 118 | + private transient Set<Map.Entry<Object,Object>> entrySet = null; | |
| 119 | + private transient int entrySetCallCount = 0; | |
| 120 | + | |
| 121 | + private transient boolean initialized; | |
| 122 | + | |
| 123 | + /** | |
| 124 | + * Constructs a provider with the specified name, version number, | |
| 125 | + * and information. | |
| 126 | + * | |
| 127 | + * @param name the provider name. | |
| 128 | + * | |
| 129 | + * @param version the provider version number. | |
| 130 | + * | |
| 131 | + * @param info a description of the provider and its services. | |
| 132 | + */ | |
| 133 | + protected Provider(String name, double version, String info) { | |
| 134 | + this.name = name; | |
| 135 | + this.version = version; | |
| 136 | + this.info = info; | |
| 137 | + putId(); | |
| 138 | + initialized = true; | |
| 139 | + } | |
| 140 | + | |
| 141 | + /** | |
| 142 | + * Returns the name of this provider. | |
| 143 | + * | |
| 144 | + * @return the name of this provider. | |
| 145 | + */ | |
| 146 | + public String getName() { | |
| 147 | + return name; | |
| 148 | + } | |
| 149 | + | |
| 150 | + /** | |
| 151 | + * Returns the version number for this provider. | |
| 152 | + * | |
| 153 | + * @return the version number for this provider. | |
| 154 | + */ | |
| 155 | + public double getVersion() { | |
| 156 | + return version; | |
| 157 | + } | |
| 158 | + | |
| 159 | + /** | |
| 160 | + * Returns a human-readable description of the provider and its | |
| 161 | + * services. This may return an HTML page, with relevant links. | |
| 162 | + * | |
| 163 | + * @return a description of the provider and its services. | |
| 164 | + */ | |
| 165 | + public String getInfo() { | |
| 166 | + return info; | |
| 167 | + } | |
| 168 | + | |
| 169 | + /** | |
| 170 | + * Returns a string with the name and the version number | |
| 171 | + * of this provider. | |
| 172 | + * | |
| 173 | + * @return the string with the name and the version number | |
| 174 | + * for this provider. | |
| 175 | + */ | |
| 176 | + public String toString() { | |
| 177 | + return name + " version " + version; | |
| 178 | + } | |
| 179 | + | |
| 180 | + /* | |
| 181 | + * override the following methods to ensure that provider | |
| 182 | + * information can only be changed if the caller has the appropriate | |
| 183 | + * permissions. | |
| 184 | + */ | |
| 185 | + | |
| 186 | + /** | |
| 187 | + * Clears this provider so that it no longer contains the properties | |
| 188 | + * used to look up facilities implemented by the provider. | |
| 189 | + * | |
| 190 | + * <p>First, if there is a security manager, its | |
| 191 | + * <code>checkSecurityAccess</code> method is called with the string | |
| 192 | + * <code>"clearProviderProperties."+name</code> (where <code>name</code> | |
| 193 | + * is the provider name) to see if it's ok to clear this provider. | |
| 194 | + * If the default implementation of <code>checkSecurityAccess</code> | |
| 195 | + * is used (that is, that method is not overriden), then this results in | |
| 196 | + * a call to the security manager's <code>checkPermission</code> method | |
| 197 | + * with a <code>SecurityPermission("clearProviderProperties."+name)</code> | |
| 198 | + * permission. | |
| 199 | + * | |
| 200 | + * @throws SecurityException | |
| 201 | + * if a security manager exists and its <code>{@link | |
| 202 | + * java.lang.SecurityManager#checkSecurityAccess}</code> method | |
| 203 | + * denies access to clear this provider | |
| 204 | + * | |
| 205 | + * @since 1.2 | |
| 206 | + */ | |
| 207 | + public synchronized void clear() { | |
| 208 | + check("clearProviderProperties."+name); | |
| 209 | + if (debug != null) { | |
| 210 | + debug.println("Remove " + name + " provider properties"); | |
| 211 | + } | |
| 212 | + implClear(); | |
| 213 | + } | |
| 214 | + | |
| 215 | + /** | |
| 216 | + * Reads a property list (key and element pairs) from the input stream. | |
| 217 | + * | |
| 218 | + * @param inStream the input stream. | |
| 219 | + * @exception IOException if an error occurred when reading from the | |
| 220 | + * input stream. | |
| 221 | + * @see java.util.Properties#load | |
| 222 | + */ | |
| 223 | + public synchronized void load(InputStream inStream) throws IOException { | |
| 224 | + check("putProviderProperty."+name); | |
| 225 | + if (debug != null) { | |
| 226 | + debug.println("Load " + name + " provider properties"); | |
| 227 | + } | |
| 228 | + Properties tempProperties = new Properties(); | |
| 229 | + tempProperties.load(inStream); | |
| 230 | + implPutAll(tempProperties); | |
| 231 | + } | |
| 232 | + | |
| 233 | + /** | |
| 234 | + * Copies all of the mappings from the specified Map to this provider. | |
| 235 | + * These mappings will replace any properties that this provider had | |
| 236 | + * for any of the keys currently in the specified Map. | |
| 237 | + * | |
| 238 | + * @since 1.2 | |
| 239 | + */ | |
| 240 | + public synchronized void putAll(Map<?,?> t) { | |
| 241 | + check("putProviderProperty."+name); | |
| 242 | + if (debug != null) { | |
| 243 | + debug.println("Put all " + name + " provider properties"); | |
| 244 | + } | |
| 245 | + implPutAll(t); | |
| 246 | + } | |
| 247 | + | |
| 248 | + /** | |
| 249 | + * Returns an unmodifiable Set view of the property entries contained | |
| 250 | + * in this Provider. | |
| 251 | + * | |
| 252 | + * @see java.util.Map.Entry | |
| 253 | + * @since 1.2 | |
| 254 | + */ | |
| 255 | + public synchronized Set<Map.Entry<Object,Object>> entrySet() { | |
| 256 | + checkInitialized(); | |
| 257 | + if (entrySet == null) { | |
| 258 | + if (entrySetCallCount++ == 0) // Initial call | |
| 259 | + entrySet = Collections.unmodifiableMap(this).entrySet(); | |
| 260 | + else | |
| 261 | + return super.entrySet(); // Recursive call | |
| 262 | + } | |
| 263 | + | |
| 264 | + // This exception will be thrown if the implementation of | |
| 265 | + // Collections.unmodifiableMap.entrySet() is changed such that it | |
| 266 | + // no longer calls entrySet() on the backing Map. (Provider's | |
| 267 | + // entrySet implementation depends on this "implementation detail", | |
| 268 | + // which is unlikely to change. | |
| 269 | + if (entrySetCallCount != 2) | |
| 270 | + throw new RuntimeException("Internal error."); | |
| 271 | + | |
| 272 | + return entrySet; | |
| 273 | + } | |
| 274 | + | |
| 275 | + /** | |
| 276 | + * Returns an unmodifiable Set view of the property keys contained in | |
| 277 | + * this provider. | |
| 278 | + * | |
| 279 | + * @since 1.2 | |
| 280 | + */ | |
| 281 | + public Set<Object> keySet() { | |
| 282 | + checkInitialized(); | |
| 283 | + return Collections.unmodifiableSet(super.keySet()); | |
| 284 | + } | |
| 285 | + | |
| 286 | + /** | |
| 287 | + * Returns an unmodifiable Collection view of the property values | |
| 288 | + * contained in this provider. | |
| 289 | + * | |
| 290 | + * @since 1.2 | |
| 291 | + */ | |
| 292 | + public Collection<Object> values() { | |
| 293 | + checkInitialized(); | |
| 294 | + return Collections.unmodifiableCollection(super.values()); | |
| 295 | + } | |
| 296 | + | |
| 297 | + /** | |
| 298 | + * Sets the <code>key</code> property to have the specified | |
| 299 | + * <code>value</code>. | |
| 300 | + * | |
| 301 | + * <p>First, if there is a security manager, its | |
| 302 | + * <code>checkSecurityAccess</code> method is called with the string | |
| 303 | + * <code>"putProviderProperty."+name</code>, where <code>name</code> is the | |
| 304 | + * provider name, to see if it's ok to set this provider's property values. | |
| 305 | + * If the default implementation of <code>checkSecurityAccess</code> | |
| 306 | + * is used (that is, that method is not overriden), then this results in | |
| 307 | + * a call to the security manager's <code>checkPermission</code> method | |
| 308 | + * with a <code>SecurityPermission("putProviderProperty."+name)</code> | |
| 309 | + * permission. | |
| 310 | + * | |
| 311 | + * @param key the property key. | |
| 312 | + * | |
| 313 | + * @param value the property value. | |
| 314 | + * | |
| 315 | + * @return the previous value of the specified property | |
| 316 | + * (<code>key</code>), or null if it did not have one. | |
| 317 | + * | |
| 318 | + * @throws SecurityException | |
| 319 | + * if a security manager exists and its <code>{@link | |
| 320 | + * java.lang.SecurityManager#checkSecurityAccess}</code> method | |
| 321 | + * denies access to set property values. | |
| 322 | + * | |
| 323 | + * @since 1.2 | |
| 324 | + */ | |
| 325 | + public synchronized Object put(Object key, Object value) { | |
| 326 | + check("putProviderProperty."+name); | |
| 327 | + if (debug != null) { | |
| 328 | + debug.println("Set " + name + " provider property [" + | |
| 329 | + key + "/" + value +"]"); | |
| 330 | + } | |
| 331 | + return implPut(key, value); | |
| 332 | + } | |
| 333 | + | |
| 334 | + /** | |
| 335 | + * Removes the <code>key</code> property (and its corresponding | |
| 336 | + * <code>value</code>). | |
| 337 | + * | |
| 338 | + * <p>First, if there is a security manager, its | |
| 339 | + * <code>checkSecurityAccess</code> method is called with the string | |
| 340 | + * <code>"removeProviderProperty."+name</code>, where <code>name</code> is | |
| 341 | + * the provider name, to see if it's ok to remove this provider's | |
| 342 | + * properties. If the default implementation of | |
| 343 | + * <code>checkSecurityAccess</code> is used (that is, that method is not | |
| 344 | + * overriden), then this results in a call to the security manager's | |
| 345 | + * <code>checkPermission</code> method with a | |
| 346 | + * <code>SecurityPermission("removeProviderProperty."+name)</code> | |
| 347 | + * permission. | |
| 348 | + * | |
| 349 | + * @param key the key for the property to be removed. | |
| 350 | + * | |
| 351 | + * @return the value to which the key had been mapped, | |
| 352 | + * or null if the key did not have a mapping. | |
| 353 | + * | |
| 354 | + * @throws SecurityException | |
| 355 | + * if a security manager exists and its <code>{@link | |
| 356 | + * java.lang.SecurityManager#checkSecurityAccess}</code> method | |
| 357 | + * denies access to remove this provider's properties. | |
| 358 | + * | |
| 359 | + * @since 1.2 | |
| 360 | + */ | |
| 361 | + public synchronized Object remove(Object key) { | |
| 362 | + check("removeProviderProperty."+name); | |
| 363 | + if (debug != null) { | |
| 364 | + debug.println("Remove " + name + " provider property " + key); | |
| 365 | + } | |
| 366 | + return implRemove(key); | |
| 367 | + } | |
| 368 | + | |
| 369 | + // let javadoc show doc from superclass | |
| 370 | + public Object get(Object key) { | |
| 371 | + checkInitialized(); | |
| 372 | + return super.get(key); | |
| 373 | + } | |
| 374 | + | |
| 375 | + // let javadoc show doc from superclass | |
| 376 | + public Enumeration<Object> keys() { | |
| 377 | + checkInitialized(); | |
| 378 | + return super.keys(); | |
| 379 | + } | |
| 380 | + | |
| 381 | + // let javadoc show doc from superclass | |
| 382 | + public Enumeration<Object> elements() { | |
| 383 | + checkInitialized(); | |
| 384 | + return super.elements(); | |
| 385 | + } | |
| 386 | + | |
| 387 | + // let javadoc show doc from superclass | |
| 388 | + public String getProperty(String key) { | |
| 389 | + checkInitialized(); | |
| 390 | + return super.getProperty(key); | |
| 391 | + } | |
| 392 | + | |
| 393 | + private void checkInitialized() { | |
| 394 | + if (!initialized) { | |
| 395 | + throw new IllegalStateException(); | |
| 396 | + } | |
| 397 | + } | |
| 398 | + | |
| 399 | + private void check(String directive) { | |
| 400 | + checkInitialized(); | |
| 401 | + SecurityManager security = System.getSecurityManager(); | |
| 402 | + if (security != null) { | |
| 403 | + security.checkSecurityAccess(directive); | |
| 404 | + } | |
| 405 | + } | |
| 406 | + | |
| 407 | + // legacy properties changed since last call to any services method? | |
| 408 | + private transient boolean legacyChanged; | |
| 409 | + // serviceMap changed since last call to getServices() | |
| 410 | + private transient boolean servicesChanged; | |
| 411 | + | |
| 412 | + // Map<String,String> | |
| 413 | + private transient Map<String,String> legacyStrings; | |
| 414 | + | |
| 415 | + // Map<ServiceKey,Service> | |
| 416 | + // used for services added via putService(), initialized on demand | |
| 417 | + private transient Map<ServiceKey,Service> serviceMap; | |
| 418 | + | |
| 419 | + // Map<ServiceKey,Service> | |
| 420 | + // used for services added via legacy methods, init on demand | |
| 421 | + private transient Map<ServiceKey,Service> legacyMap; | |
| 422 | + | |
| 423 | + // Set<Service> | |
| 424 | + // Unmodifiable set of all services. Initialized on demand. | |
| 425 | + private transient Set<Service> serviceSet; | |
| 426 | + | |
| 427 | + // register the id attributes for this provider | |
| 428 | + // this is to ensure that equals() and hashCode() do not incorrectly | |
| 429 | + // report to different provider objects as the same | |
| 430 | + private void putId() { | |
| 431 | + // note: name and info may be null | |
| 432 | + super.put("Provider.id name", String.valueOf(name)); | |
| 433 | + super.put("Provider.id version", String.valueOf(version)); | |
| 434 | + super.put("Provider.id info", String.valueOf(info)); | |
| 435 | + super.put("Provider.id className", this.getClass().getName()); | |
| 436 | + } | |
| 437 | + | |
| 438 | + private void readObject(ObjectInputStream in) | |
| 439 | + throws IOException, ClassNotFoundException { | |
| 440 | + Map<Object,Object> copy = new HashMap<>(); | |
| 441 | + for (Map.Entry<Object,Object> entry : super.entrySet()) { | |
| 442 | + copy.put(entry.getKey(), entry.getValue()); | |
| 443 | + } | |
| 444 | + defaults = null; | |
| 445 | + in.defaultReadObject(); | |
| 446 | + implClear(); | |
| 447 | + initialized = true; | |
| 448 | + putAll(copy); | |
| 449 | + } | |
| 450 | + | |
| 451 | + /** | |
| 452 | + * Copies all of the mappings from the specified Map to this provider. | |
| 453 | + * Internal method to be called AFTER the security check has been | |
| 454 | + * performed. | |
| 455 | + */ | |
| 456 | + private void implPutAll(Map t) { | |
| 457 | + for (Map.Entry e : ((Map<?,?>)t).entrySet()) { | |
| 458 | + implPut(e.getKey(), e.getValue()); | |
| 459 | + } | |
| 460 | + } | |
| 461 | + | |
| 462 | + private Object implRemove(Object key) { | |
| 463 | + if (key instanceof String) { | |
| 464 | + String keyString = (String)key; | |
| 465 | + if (keyString.startsWith("Provider.")) { | |
| 466 | + return null; | |
| 467 | + } | |
| 468 | + legacyChanged = true; | |
| 469 | + if (legacyStrings == null) { | |
| 470 | + legacyStrings = new LinkedHashMap<String,String>(); | |
| 471 | + } | |
| 472 | + legacyStrings.remove(keyString); | |
| 473 | + } | |
| 474 | + return super.remove(key); | |
| 475 | + } | |
| 476 | + | |
| 477 | + private Object implPut(Object key, Object value) { | |
| 478 | + if ((key instanceof String) && (value instanceof String)) { | |
| 479 | + String keyString = (String)key; | |
| 480 | + if (keyString.startsWith("Provider.")) { | |
| 481 | + return null; | |
| 482 | + } | |
| 483 | + legacyChanged = true; | |
| 484 | + if (legacyStrings == null) { | |
| 485 | + legacyStrings = new LinkedHashMap<String,String>(); | |
| 486 | + } | |
| 487 | + legacyStrings.put(keyString, (String)value); | |
| 488 | + } | |
| 489 | + return super.put(key, value); | |
| 490 | + } | |
| 491 | + | |
| 492 | + private void implClear() { | |
| 493 | + if (legacyStrings != null) { | |
| 494 | + legacyStrings.clear(); | |
| 495 | + } | |
| 496 | + if (legacyMap != null) { | |
| 497 | + legacyMap.clear(); | |
| 498 | + } | |
| 499 | + if (serviceMap != null) { | |
| 500 | + serviceMap.clear(); | |
| 501 | + } | |
| 502 | + legacyChanged = false; | |
| 503 | + servicesChanged = false; | |
| 504 | + serviceSet = null; | |
| 505 | + super.clear(); | |
| 506 | + putId(); | |
| 507 | + } | |
| 508 | + | |
| 509 | + // used as key in the serviceMap and legacyMap HashMaps | |
| 510 | + private static class ServiceKey { | |
| 511 | + private final String type; | |
| 512 | + private final String algorithm; | |
| 513 | + private final String originalAlgorithm; | |
| 514 | + private ServiceKey(String type, String algorithm, boolean intern) { | |
| 515 | + this.type = type; | |
| 516 | + this.originalAlgorithm = algorithm; | |
| 517 | + algorithm = algorithm.toUpperCase(ENGLISH); | |
| 518 | + this.algorithm = intern ? algorithm.intern() : algorithm; | |
| 519 | + } | |
| 520 | + public int hashCode() { | |
| 521 | + return type.hashCode() + algorithm.hashCode(); | |
| 522 | + } | |
| 523 | + public boolean equals(Object obj) { | |
| 524 | + if (this == obj) { | |
| 525 | + return true; | |
| 526 | + } | |
| 527 | + if (obj instanceof ServiceKey == false) { | |
| 528 | + return false; | |
| 529 | + } | |
| 530 | + ServiceKey other = (ServiceKey)obj; | |
| 531 | + return this.type.equals(other.type) | |
| 532 | + && this.algorithm.equals(other.algorithm); | |
| 533 | + } | |
| 534 | + boolean matches(String type, String algorithm) { | |
| 535 | + return (this.type == type) && (this.originalAlgorithm == algorithm); | |
| 536 | + } | |
| 537 | + } | |
| 538 | + | |
| 539 | + /** | |
| 540 | + * Ensure all the legacy String properties are fully parsed into | |
| 541 | + * service objects. | |
| 542 | + */ | |
| 543 | + private void ensureLegacyParsed() { | |
| 544 | + if ((legacyChanged == false) || (legacyStrings == null)) { | |
| 545 | + return; | |
| 546 | + } | |
| 547 | + serviceSet = null; | |
| 548 | + if (legacyMap == null) { | |
| 549 | + legacyMap = new LinkedHashMap<ServiceKey,Service>(); | |
| 550 | + } else { | |
| 551 | + legacyMap.clear(); | |
| 552 | + } | |
| 553 | + for (Map.Entry<String,String> entry : legacyStrings.entrySet()) { | |
| 554 | + parseLegacyPut(entry.getKey(), entry.getValue()); | |
| 555 | + } | |
| 556 | + removeInvalidServices(legacyMap); | |
| 557 | + legacyChanged = false; | |
| 558 | + } | |
| 559 | + | |
| 560 | + /** | |
| 561 | + * Remove all invalid services from the Map. Invalid services can only | |
| 562 | + * occur if the legacy properties are inconsistent or incomplete. | |
| 563 | + */ | |
| 564 | + private void removeInvalidServices(Map<ServiceKey,Service> map) { | |
| 565 | + for (Iterator t = map.entrySet().iterator(); t.hasNext(); ) { | |
| 566 | + Map.Entry entry = (Map.Entry)t.next(); | |
| 567 | + Service s = (Service)entry.getValue(); | |
| 568 | + if (s.isValid() == false) { | |
| 569 | + t.remove(); | |
| 570 | + } | |
| 571 | + } | |
| 572 | + } | |
| 573 | + | |
| 574 | + private String[] getTypeAndAlgorithm(String key) { | |
| 575 | + int i = key.indexOf("."); | |
| 576 | + if (i < 1) { | |
| 577 | + if (debug != null) { | |
| 578 | + debug.println("Ignoring invalid entry in provider " | |
| 579 | + + name + ":" + key); | |
| 580 | + } | |
| 581 | + return null; | |
| 582 | + } | |
| 583 | + String type = key.substring(0, i); | |
| 584 | + String alg = key.substring(i + 1); | |
| 585 | + return new String[] {type, alg}; | |
| 586 | + } | |
| 587 | + | |
| 588 | + private final static String ALIAS_PREFIX = "Alg.Alias."; | |
| 589 | + private final static String ALIAS_PREFIX_LOWER = "alg.alias."; | |
| 590 | + private final static int ALIAS_LENGTH = ALIAS_PREFIX.length(); | |
| 591 | + | |
| 592 | + private void parseLegacyPut(String name, String value) { | |
| 593 | + if (name.toLowerCase(ENGLISH).startsWith(ALIAS_PREFIX_LOWER)) { | |
| 594 | + // e.g. put("Alg.Alias.MessageDigest.SHA", "SHA-1"); | |
| 595 | + // aliasKey ~ MessageDigest.SHA | |
| 596 | + String stdAlg = value; | |
| 597 | + String aliasKey = name.substring(ALIAS_LENGTH); | |
| 598 | + String[] typeAndAlg = getTypeAndAlgorithm(aliasKey); | |
| 599 | + if (typeAndAlg == null) { | |
| 600 | + return; | |
| 601 | + } | |
| 602 | + String type = getEngineName(typeAndAlg[0]); | |
| 603 | + String aliasAlg = typeAndAlg[1].intern(); | |
| 604 | + ServiceKey key = new ServiceKey(type, stdAlg, true); | |
| 605 | + Service s = legacyMap.get(key); | |
| 606 | + if (s == null) { | |
| 607 | + s = new Service(this); | |
| 608 | + s.type = type; | |
| 609 | + s.algorithm = stdAlg; | |
| 610 | + legacyMap.put(key, s); | |
| 611 | + } | |
| 612 | + legacyMap.put(new ServiceKey(type, aliasAlg, true), s); | |
| 613 | + s.addAlias(aliasAlg); | |
| 614 | + } else { | |
| 615 | + String[] typeAndAlg = getTypeAndAlgorithm(name); | |
| 616 | + if (typeAndAlg == null) { | |
| 617 | + return; | |
| 618 | + } | |
| 619 | + int i = typeAndAlg[1].indexOf(' '); | |
| 620 | + if (i == -1) { | |
| 621 | + // e.g. put("MessageDigest.SHA-1", "sun.security.provider.SHA"); | |
| 622 | + String type = getEngineName(typeAndAlg[0]); | |
| 623 | + String stdAlg = typeAndAlg[1].intern(); | |
| 624 | + String className = value; | |
| 625 | + ServiceKey key = new ServiceKey(type, stdAlg, true); | |
| 626 | + Service s = legacyMap.get(key); | |
| 627 | + if (s == null) { | |
| 628 | + s = new Service(this); | |
| 629 | + s.type = type; | |
| 630 | + s.algorithm = stdAlg; | |
| 631 | + legacyMap.put(key, s); | |
| 632 | + } | |
| 633 | + s.className = className; | |
| 634 | + } else { // attribute | |
| 635 | + // e.g. put("MessageDigest.SHA-1 ImplementedIn", "Software"); | |
| 636 | + String attributeValue = value; | |
| 637 | + String type = getEngineName(typeAndAlg[0]); | |
| 638 | + String attributeString = typeAndAlg[1]; | |
| 639 | + String stdAlg = attributeString.substring(0, i).intern(); | |
| 640 | + String attributeName = attributeString.substring(i + 1); | |
| 641 | + // kill additional spaces | |
| 642 | + while (attributeName.startsWith(" ")) { | |
| 643 | + attributeName = attributeName.substring(1); | |
| 644 | + } | |
| 645 | + attributeName = attributeName.intern(); | |
| 646 | + ServiceKey key = new ServiceKey(type, stdAlg, true); | |
| 647 | + Service s = legacyMap.get(key); | |
| 648 | + if (s == null) { | |
| 649 | + s = new Service(this); | |
| 650 | + s.type = type; | |
| 651 | + s.algorithm = stdAlg; | |
| 652 | + legacyMap.put(key, s); | |
| 653 | + } | |
| 654 | + s.addAttribute(attributeName, attributeValue); | |
| 655 | + } | |
| 656 | + } | |
| 657 | + } | |
| 658 | + | |
| 659 | + /** | |
| 660 | + * Get the service describing this Provider's implementation of the | |
| 661 | + * specified type of this algorithm or alias. If no such | |
| 662 | + * implementation exists, this method returns null. If there are two | |
| 663 | + * matching services, one added to this provider using | |
| 664 | + * {@link #putService putService()} and one added via {@link #put put()}, | |
| 665 | + * the service added via {@link #putService putService()} is returned. | |
| 666 | + * | |
| 667 | + * @param type the type of {@link Service service} requested | |
| 668 | + * (for example, <code>MessageDigest</code>) | |
| 669 | + * @param algorithm the case insensitive algorithm name (or alternate | |
| 670 | + * alias) of the service requested (for example, <code>SHA-1</code>) | |
| 671 | + * | |
| 672 | + * @return the service describing this Provider's matching service | |
| 673 | + * or null if no such service exists | |
| 674 | + * | |
| 675 | + * @throws NullPointerException if type or algorithm is null | |
| 676 | + * | |
| 677 | + * @since 1.5 | |
| 678 | + */ | |
| 679 | + public synchronized Service getService(String type, String algorithm) { | |
| 680 | + checkInitialized(); | |
| 681 | + // avoid allocating a new key object if possible | |
| 682 | + ServiceKey key = previousKey; | |
| 683 | + if (key.matches(type, algorithm) == false) { | |
| 684 | + key = new ServiceKey(type, algorithm, false); | |
| 685 | + previousKey = key; | |
| 686 | + } | |
| 687 | + if (serviceMap != null) { | |
| 688 | + Service service = serviceMap.get(key); | |
| 689 | + if (service != null) { | |
| 690 | + return service; | |
| 691 | + } | |
| 692 | + } | |
| 693 | + ensureLegacyParsed(); | |
| 694 | + return (legacyMap != null) ? legacyMap.get(key) : null; | |
| 695 | + } | |
| 696 | + | |
| 697 | + // ServiceKey from previous getService() call | |
| 698 | + // by re-using it if possible we avoid allocating a new object | |
| 699 | + // and the toUpperCase() call. | |
| 700 | + // re-use will occur e.g. as the framework traverses the provider | |
| 701 | + // list and queries each provider with the same values until it finds | |
| 702 | + // a matching service | |
| 703 | + private static volatile ServiceKey previousKey = | |
| 704 | + new ServiceKey("", "", false); | |
| 705 | + | |
| 706 | + /** | |
| 707 | + * Get an unmodifiable Set of all services supported by | |
| 708 | + * this Provider. | |
| 709 | + * | |
| 710 | + * @return an unmodifiable Set of all services supported by | |
| 711 | + * this Provider | |
| 712 | + * | |
| 713 | + * @since 1.5 | |
| 714 | + */ | |
| 715 | + public synchronized Set<Service> getServices() { | |
| 716 | + checkInitialized(); | |
| 717 | + if (legacyChanged || servicesChanged) { | |
| 718 | + serviceSet = null; | |
| 719 | + } | |
| 720 | + if (serviceSet == null) { | |
| 721 | + ensureLegacyParsed(); | |
| 722 | + Set<Service> set = new LinkedHashSet<>(); | |
| 723 | + if (serviceMap != null) { | |
| 724 | + set.addAll(serviceMap.values()); | |
| 725 | + } | |
| 726 | + if (legacyMap != null) { | |
| 727 | + set.addAll(legacyMap.values()); | |
| 728 | + } | |
| 729 | + serviceSet = Collections.unmodifiableSet(set); | |
| 730 | + servicesChanged = false; | |
| 731 | + } | |
| 732 | + return serviceSet; | |
| 733 | + } | |
| 734 | + | |
| 735 | + /** | |
| 736 | + * Add a service. If a service of the same type with the same algorithm | |
| 737 | + * name exists and it was added using {@link #putService putService()}, | |
| 738 | + * it is replaced by the new service. | |
| 739 | + * This method also places information about this service | |
| 740 | + * in the provider's Hashtable values in the format described in the | |
| 741 | + * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html"> | |
| 742 | + * Java Cryptography Architecture API Specification & Reference </a>. | |
| 743 | + * | |
| 744 | + * <p>Also, if there is a security manager, its | |
| 745 | + * <code>checkSecurityAccess</code> method is called with the string | |
| 746 | + * <code>"putProviderProperty."+name</code>, where <code>name</code> is | |
| 747 | + * the provider name, to see if it's ok to set this provider's property | |
| 748 | + * values. If the default implementation of <code>checkSecurityAccess</code> | |
| 749 | + * is used (that is, that method is not overriden), then this results in | |
| 750 | + * a call to the security manager's <code>checkPermission</code> method with | |
| 751 | + * a <code>SecurityPermission("putProviderProperty."+name)</code> | |
| 752 | + * permission. | |
| 753 | + * | |
| 754 | + * @param s the Service to add | |
| 755 | + * | |
| 756 | + * @throws SecurityException | |
| 757 | + * if a security manager exists and its <code>{@link | |
| 758 | + * java.lang.SecurityManager#checkSecurityAccess}</code> method denies | |
| 759 | + * access to set property values. | |
| 760 | + * @throws NullPointerException if s is null | |
| 761 | + * | |
| 762 | + * @since 1.5 | |
| 763 | + */ | |
| 764 | + protected synchronized void putService(Service s) { | |
| 765 | + check("putProviderProperty." + name); | |
| 766 | + if (debug != null) { | |
| 767 | + debug.println(name + ".putService(): " + s); | |
| 768 | + } | |
| 769 | + if (s == null) { | |
| 770 | + throw new NullPointerException(); | |
| 771 | + } | |
| 772 | + if (s.getProvider() != this) { | |
| 773 | + throw new IllegalArgumentException | |
| 774 | + ("service.getProvider() must match this Provider object"); | |
| 775 | + } | |
| 776 | + if (serviceMap == null) { | |
| 777 | + serviceMap = new LinkedHashMap<ServiceKey,Service>(); | |
| 778 | + } | |
| 779 | + servicesChanged = true; | |
| 780 | + String type = s.getType(); | |
| 781 | + String algorithm = s.getAlgorithm(); | |
| 782 | + ServiceKey key = new ServiceKey(type, algorithm, true); | |
| 783 | + // remove existing service | |
| 784 | + implRemoveService(serviceMap.get(key)); | |
| 785 | + serviceMap.put(key, s); | |
| 786 | + for (String alias : s.getAliases()) { | |
| 787 | + serviceMap.put(new ServiceKey(type, alias, true), s); | |
| 788 | + } | |
| 789 | + putPropertyStrings(s); | |
| 790 | + } | |
| 791 | + | |
| 792 | + /** | |
| 793 | + * Put the string properties for this Service in this Provider's | |
| 794 | + * Hashtable. | |
| 795 | + */ | |
| 796 | + private void putPropertyStrings(Service s) { | |
| 797 | + String type = s.getType(); | |
| 798 | + String algorithm = s.getAlgorithm(); | |
| 799 | + // use super() to avoid permission check and other processing | |
| 800 | + super.put(type + "." + algorithm, s.getClassName()); | |
| 801 | + for (String alias : s.getAliases()) { | |
| 802 | + super.put(ALIAS_PREFIX + type + "." + alias, algorithm); | |
| 803 | + } | |
| 804 | + for (Map.Entry<UString,String> entry : s.attributes.entrySet()) { | |
| 805 | + String key = type + "." + algorithm + " " + entry.getKey(); | |
| 806 | + super.put(key, entry.getValue()); | |
| 807 | + } | |
| 808 | + } | |
| 809 | + | |
| 810 | + /** | |
| 811 | + * Remove the string properties for this Service from this Provider's | |
| 812 | + * Hashtable. | |
| 813 | + */ | |
| 814 | + private void removePropertyStrings(Service s) { | |
| 815 | + String type = s.getType(); | |
| 816 | + String algorithm = s.getAlgorithm(); | |
| 817 | + // use super() to avoid permission check and other processing | |
| 818 | + super.remove(type + "." + algorithm); | |
| 819 | + for (String alias : s.getAliases()) { | |
| 820 | + super.remove(ALIAS_PREFIX + type + "." + alias); | |
| 821 | + } | |
| 822 | + for (Map.Entry<UString,String> entry : s.attributes.entrySet()) { | |
| 823 | + String key = type + "." + algorithm + " " + entry.getKey(); | |
| 824 | + super.remove(key); | |
| 825 | + } | |
| 826 | + } | |
| 827 | + | |
| 828 | + /** | |
| 829 | + * Remove a service previously added using | |
| 830 | + * {@link #putService putService()}. The specified service is removed from | |
| 831 | + * this provider. It will no longer be returned by | |
| 832 | + * {@link #getService getService()} and its information will be removed | |
| 833 | + * from this provider's Hashtable. | |
| 834 | + * | |
| 835 | + * <p>Also, if there is a security manager, its | |
| 836 | + * <code>checkSecurityAccess</code> method is called with the string | |
| 837 | + * <code>"removeProviderProperty."+name</code>, where <code>name</code> is | |
| 838 | + * the provider name, to see if it's ok to remove this provider's | |
| 839 | + * properties. If the default implementation of | |
| 840 | + * <code>checkSecurityAccess</code> is used (that is, that method is not | |
| 841 | + * overriden), then this results in a call to the security manager's | |
| 842 | + * <code>checkPermission</code> method with a | |
| 843 | + * <code>SecurityPermission("removeProviderProperty."+name)</code> | |
| 844 | + * permission. | |
| 845 | + * | |
| 846 | + * @param s the Service to be removed | |
| 847 | + * | |
| 848 | + * @throws SecurityException | |
| 849 | + * if a security manager exists and its <code>{@link | |
| 850 | + * java.lang.SecurityManager#checkSecurityAccess}</code> method denies | |
| 851 | + * access to remove this provider's properties. | |
| 852 | + * @throws NullPointerException if s is null | |
| 853 | + * | |
| 854 | + * @since 1.5 | |
| 855 | + */ | |
| 856 | + protected synchronized void removeService(Service s) { | |
| 857 | + check("removeProviderProperty." + name); | |
| 858 | + if (debug != null) { | |
| 859 | + debug.println(name + ".removeService(): " + s); | |
| 860 | + } | |
| 861 | + if (s == null) { | |
| 862 | + throw new NullPointerException(); | |
| 863 | + } | |
| 864 | + implRemoveService(s); | |
| 865 | + } | |
| 866 | + | |
| 867 | + private void implRemoveService(Service s) { | |
| 868 | + if ((s == null) || (serviceMap == null)) { | |
| 869 | + return; | |
| 870 | + } | |
| 871 | + String type = s.getType(); | |
| 872 | + String algorithm = s.getAlgorithm(); | |
| 873 | + ServiceKey key = new ServiceKey(type, algorithm, false); | |
| 874 | + Service oldService = serviceMap.get(key); | |
| 875 | + if (s != oldService) { | |
| 876 | + return; | |
| 877 | + } | |
| 878 | + servicesChanged = true; | |
| 879 | + serviceMap.remove(key); | |
| 880 | + for (String alias : s.getAliases()) { | |
| 881 | + serviceMap.remove(new ServiceKey(type, alias, false)); | |
| 882 | + } | |
| 883 | + removePropertyStrings(s); | |
| 884 | + } | |
| 885 | + | |
| 886 | + // Wrapped String that behaves in a case insensitive way for equals/hashCode | |
| 887 | + private static class UString { | |
| 888 | + final String string; | |
| 889 | + final String lowerString; | |
| 890 | + | |
| 891 | + UString(String s) { | |
| 892 | + this.string = s; | |
| 893 | + this.lowerString = s.toLowerCase(ENGLISH); | |
| 894 | + } | |
| 895 | + | |
| 896 | + public int hashCode() { | |
| 897 | + return lowerString.hashCode(); | |
| 898 | + } | |
| 899 | + | |
| 900 | + public boolean equals(Object obj) { | |
| 901 | + if (this == obj) { | |
| 902 | + return true; | |
| 903 | + } | |
| 904 | + if (obj instanceof UString == false) { | |
| 905 | + return false; | |
| 906 | + } | |
| 907 | + UString other = (UString)obj; | |
| 908 | + return lowerString.equals(other.lowerString); | |
| 909 | + } | |
| 910 | + | |
| 911 | + public String toString() { | |
| 912 | + return string; | |
| 913 | + } | |
| 914 | + } | |
| 915 | + | |
| 916 | + // describe relevant properties of a type of engine | |
| 917 | + private static class EngineDescription { | |
| 918 | + final String name; | |
| 919 | + final boolean supportsParameter; | |
| 920 | + final String constructorParameterClassName; | |
| 921 | + private volatile Class constructorParameterClass; | |
| 922 | + | |
| 923 | + EngineDescription(String name, boolean sp, String paramName) { | |
| 924 | + this.name = name; | |
| 925 | + this.supportsParameter = sp; | |
| 926 | + this.constructorParameterClassName = paramName; | |
| 927 | + } | |
| 928 | + Class getConstructorParameterClass() throws ClassNotFoundException { | |
| 929 | + Class clazz = constructorParameterClass; | |
| 930 | + if (clazz == null) { | |
| 931 | + clazz = Class.forName(constructorParameterClassName); | |
| 932 | + constructorParameterClass = clazz; | |
| 933 | + } | |
| 934 | + return clazz; | |
| 935 | + } | |
| 936 | + } | |
| 937 | + | |
| 938 | + // built in knowledge of the engine types shipped as part of the JDK | |
| 939 | + private static final Map<String,EngineDescription> knownEngines; | |
| 940 | + | |
| 941 | + private static void addEngine(String name, boolean sp, String paramName) { | |
| 942 | + EngineDescription ed = new EngineDescription(name, sp, paramName); | |
| 943 | + // also index by canonical name to avoid toLowerCase() for some lookups | |
| 944 | + knownEngines.put(name.toLowerCase(ENGLISH), ed); | |
| 945 | + knownEngines.put(name, ed); | |
| 946 | + } | |
| 947 | + | |
| 948 | + static { | |
| 949 | + knownEngines = new HashMap<String,EngineDescription>(); | |
| 950 | + // JCA | |
| 951 | + addEngine("AlgorithmParameterGenerator", false, null); | |
| 952 | + addEngine("AlgorithmParameters", false, null); | |
| 953 | + addEngine("KeyFactory", false, null); | |
| 954 | + addEngine("KeyPairGenerator", false, null); | |
| 955 | + addEngine("KeyStore", false, null); | |
| 956 | + addEngine("MessageDigest", false, null); | |
| 957 | + addEngine("SecureRandom", false, null); | |
| 958 | + addEngine("Signature", true, null); | |
| 959 | + addEngine("CertificateFactory", false, null); | |
| 960 | + addEngine("CertPathBuilder", false, null); | |
| 961 | + addEngine("CertPathValidator", false, null); | |
| 962 | + addEngine("CertStore", false, | |
| 963 | + "java.security.cert.CertStoreParameters"); | |
| 964 | + // JCE | |
| 965 | + addEngine("Cipher", true, null); | |
| 966 | + addEngine("ExemptionMechanism", false, null); | |
| 967 | + addEngine("Mac", true, null); | |
| 968 | + addEngine("KeyAgreement", true, null); | |
| 969 | + addEngine("KeyGenerator", false, null); | |
| 970 | + addEngine("SecretKeyFactory", false, null); | |
| 971 | + // JSSE | |
| 972 | + addEngine("KeyManagerFactory", false, null); | |
| 973 | + addEngine("SSLContext", false, null); | |
| 974 | + addEngine("TrustManagerFactory", false, null); | |
| 975 | + // JGSS | |
| 976 | + addEngine("GssApiMechanism", false, null); | |
| 977 | + // SASL | |
| 978 | + addEngine("SaslClientFactory", false, null); | |
| 979 | + addEngine("SaslServerFactory", false, null); | |
| 980 | + // POLICY | |
| 981 | + addEngine("Policy", false, | |
| 982 | + "java.security.Policy$Parameters"); | |
| 983 | + // CONFIGURATION | |
| 984 | + addEngine("Configuration", false, | |
| 985 | + "javax.security.auth.login.Configuration$Parameters"); | |
| 986 | + // XML DSig | |
| 987 | + addEngine("XMLSignatureFactory", false, null); | |
| 988 | + addEngine("KeyInfoFactory", false, null); | |
| 989 | + addEngine("TransformService", false, null); | |
| 990 | + // Smart Card I/O | |
| 991 | + addEngine("TerminalFactory", false, | |
| 992 | + "java.lang.Object"); | |
| 993 | + } | |
| 994 | + | |
| 995 | + // get the "standard" (mixed-case) engine name for arbitary case engine name | |
| 996 | + // if there is no known engine by that name, return s | |
| 997 | + private static String getEngineName(String s) { | |
| 998 | + // try original case first, usually correct | |
| 999 | + EngineDescription e = knownEngines.get(s); | |
| 1000 | + if (e == null) { | |
| 1001 | + e = knownEngines.get(s.toLowerCase(ENGLISH)); | |
| 1002 | + } | |
| 1003 | + return (e == null) ? s : e.name; | |
| 1004 | + } | |
| 1005 | + | |
| 1006 | + /** | |
| 1007 | + * The description of a security service. It encapsulates the properties | |
| 1008 | + * of a service and contains a factory method to obtain new implementation | |
| 1009 | + * instances of this service. | |
| 1010 | + * | |
| 1011 | + * <p>Each service has a provider that offers the service, a type, | |
| 1012 | + * an algorithm name, and the name of the class that implements the | |
| 1013 | + * service. Optionally, it also includes a list of alternate algorithm | |
| 1014 | + * names for this service (aliases) and attributes, which are a map of | |
| 1015 | + * (name, value) String pairs. | |
| 1016 | + * | |
| 1017 | + * <p>This class defines the methods {@link #supportsParameter | |
| 1018 | + * supportsParameter()} and {@link #newInstance newInstance()} | |
| 1019 | + * which are used by the Java security framework when it searches for | |
| 1020 | + * suitable services and instantes them. The valid arguments to those | |
| 1021 | + * methods depend on the type of service. For the service types defined | |
| 1022 | + * within Java SE, see the | |
| 1023 | + * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html"> | |
| 1024 | + * Java Cryptography Architecture API Specification & Reference </a> | |
| 1025 | + * for the valid values. | |
| 1026 | + * Note that components outside of Java SE can define additional types of | |
| 1027 | + * services and their behavior. | |
| 1028 | + * | |
| 1029 | + * <p>Instances of this class are immutable. | |
| 1030 | + * | |
| 1031 | + * @since 1.5 | |
| 1032 | + */ | |
| 1033 | + public static class Service { | |
| 1034 | + | |
| 1035 | + private String type, algorithm, className; | |
| 1036 | + private final Provider provider; | |
| 1037 | + private List<String> aliases; | |
| 1038 | + private Map<UString,String> attributes; | |
| 1039 | + | |
| 1040 | + // Reference to the cached implementation Class object | |
| 1041 | + private volatile Reference<Class> classRef; | |
| 1042 | + | |
| 1043 | + // flag indicating whether this service has its attributes for | |
| 1044 | + // supportedKeyFormats or supportedKeyClasses set | |
| 1045 | + // if null, the values have not been initialized | |
| 1046 | + // if TRUE, at least one of supportedFormats/Classes is non null | |
| 1047 | + private volatile Boolean hasKeyAttributes; | |
| 1048 | + | |
| 1049 | + // supported encoding formats | |
| 1050 | + private String[] supportedFormats; | |
| 1051 | + | |
| 1052 | + // names of the supported key (super) classes | |
| 1053 | + private Class[] supportedClasses; | |
| 1054 | + | |
| 1055 | + // whether this service has been registered with the Provider | |
| 1056 | + private boolean registered; | |
| 1057 | + | |
| 1058 | + private static final Class[] CLASS0 = new Class[0]; | |
| 1059 | + | |
| 1060 | + // this constructor and these methods are used for parsing | |
| 1061 | + // the legacy string properties. | |
| 1062 | + | |
| 1063 | + private Service(Provider provider) { | |
| 1064 | + this.provider = provider; | |
| 1065 | + aliases = Collections.<String>emptyList(); | |
| 1066 | + attributes = Collections.<UString,String>emptyMap(); | |
| 1067 | + } | |
| 1068 | + | |
| 1069 | + private boolean isValid() { | |
| 1070 | + return (type != null) && (algorithm != null) && (className != null); | |
| 1071 | + } | |
| 1072 | + | |
| 1073 | + private void addAlias(String alias) { | |
| 1074 | + if (aliases.isEmpty()) { | |
| 1075 | + aliases = new ArrayList<String>(2); | |
| 1076 | + } | |
| 1077 | + aliases.add(alias); | |
| 1078 | + } | |
| 1079 | + | |
| 1080 | + void addAttribute(String type, String value) { | |
| 1081 | + if (attributes.isEmpty()) { | |
| 1082 | + attributes = new HashMap<UString,String>(8); | |
| 1083 | + } | |
| 1084 | + attributes.put(new UString(type), value); | |
| 1085 | + } | |
| 1086 | + | |
| 1087 | + /** | |
| 1088 | + * Construct a new service. | |
| 1089 | + * | |
| 1090 | + * @param provider the provider that offers this service | |
| 1091 | + * @param type the type of this service | |
| 1092 | + * @param algorithm the algorithm name | |
| 1093 | + * @param className the name of the class implementing this service | |
| 1094 | + * @param aliases List of aliases or null if algorithm has no aliases | |
| 1095 | + * @param attributes Map of attributes or null if this implementation | |
| 1096 | + * has no attributes | |
| 1097 | + * | |
| 1098 | + * @throws NullPointerException if provider, type, algorithm, or | |
| 1099 | + * className is null | |
| 1100 | + */ | |
| 1101 | + public Service(Provider provider, String type, String algorithm, | |
| 1102 | + String className, List<String> aliases, | |
| 1103 | + Map<String,String> attributes) { | |
| 1104 | + if ((provider == null) || (type == null) || | |
| 1105 | + (algorithm == null) || (className == null)) { | |
| 1106 | + throw new NullPointerException(); | |
| 1107 | + } | |
| 1108 | + this.provider = provider; | |
| 1109 | + this.type = getEngineName(type); | |
| 1110 | + this.algorithm = algorithm; | |
| 1111 | + this.className = className; | |
| 1112 | + if (aliases == null) { | |
| 1113 | + this.aliases = Collections.<String>emptyList(); | |
| 1114 | + } else { | |
| 1115 | + this.aliases = new ArrayList<String>(aliases); | |
| 1116 | + } | |
| 1117 | + if (attributes == null) { | |
| 1118 | + this.attributes = Collections.<UString,String>emptyMap(); | |
| 1119 | + } else { | |
| 1120 | + this.attributes = new HashMap<UString,String>(); | |
| 1121 | + for (Map.Entry<String,String> entry : attributes.entrySet()) { | |
| 1122 | + this.attributes.put(new UString(entry.getKey()), entry.getValue()); | |
| 1123 | + } | |
| 1124 | + } | |
| 1125 | + } | |
| 1126 | + | |
| 1127 | + /** | |
| 1128 | + * Get the type of this service. For example, <code>MessageDigest</code>. | |
| 1129 | + * | |
| 1130 | + * @return the type of this service | |
| 1131 | + */ | |
| 1132 | + public final String getType() { | |
| 1133 | + return type; | |
| 1134 | + } | |
| 1135 | + | |
| 1136 | + /** | |
| 1137 | + * Return the name of the algorithm of this service. For example, | |
| 1138 | + * <code>SHA-1</code>. | |
| 1139 | + * | |
| 1140 | + * @return the algorithm of this service | |
| 1141 | + */ | |
| 1142 | + public final String getAlgorithm() { | |
| 1143 | + return algorithm; | |
| 1144 | + } | |
| 1145 | + | |
| 1146 | + /** | |
| 1147 | + * Return the Provider of this service. | |
| 1148 | + * | |
| 1149 | + * @return the Provider of this service | |
| 1150 | + */ | |
| 1151 | + public final Provider getProvider() { | |
| 1152 | + return provider; | |
| 1153 | + } | |
| 1154 | + | |
| 1155 | + /** | |
| 1156 | + * Return the name of the class implementing this service. | |
| 1157 | + * | |
| 1158 | + * @return the name of the class implementing this service | |
| 1159 | + */ | |
| 1160 | + public final String getClassName() { | |
| 1161 | + return className; | |
| 1162 | + } | |
| 1163 | + | |
| 1164 | + // internal only | |
| 1165 | + private final List<String> getAliases() { | |
| 1166 | + return aliases; | |
| 1167 | + } | |
| 1168 | + | |
| 1169 | + /** | |
| 1170 | + * Return the value of the specified attribute or null if this | |
| 1171 | + * attribute is not set for this Service. | |
| 1172 | + * | |
| 1173 | + * @param name the name of the requested attribute | |
| 1174 | + * | |
| 1175 | + * @return the value of the specified attribute or null if the | |
| 1176 | + * attribute is not present | |
| 1177 | + * | |
| 1178 | + * @throws NullPointerException if name is null | |
| 1179 | + */ | |
| 1180 | + public final String getAttribute(String name) { | |
| 1181 | + if (name == null) { | |
| 1182 | + throw new NullPointerException(); | |
| 1183 | + } | |
| 1184 | + return attributes.get(new UString(name)); | |
| 1185 | + } | |
| 1186 | + | |
| 1187 | + /** | |
| 1188 | + * Return a new instance of the implementation described by this | |
| 1189 | + * service. The security provider framework uses this method to | |
| 1190 | + * construct implementations. Applications will typically not need | |
| 1191 | + * to call it. | |
| 1192 | + * | |
| 1193 | + * <p>The default implementation uses reflection to invoke the | |
| 1194 | + * standard constructor for this type of service. | |
| 1195 | + * Security providers can override this method to implement | |
| 1196 | + * instantiation in a different way. | |
| 1197 | + * For details and the values of constructorParameter that are | |
| 1198 | + * valid for the various types of services see the | |
| 1199 | + * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html"> | |
| 1200 | + * Java Cryptography Architecture API Specification & | |
| 1201 | + * Reference</a>. | |
| 1202 | + * | |
| 1203 | + * @param constructorParameter the value to pass to the constructor, | |
| 1204 | + * or null if this type of service does not use a constructorParameter. | |
| 1205 | + * | |
| 1206 | + * @return a new implementation of this service | |
| 1207 | + * | |
| 1208 | + * @throws InvalidParameterException if the value of | |
| 1209 | + * constructorParameter is invalid for this type of service. | |
| 1210 | + * @throws NoSuchAlgorithmException if instantation failed for | |
| 1211 | + * any other reason. | |
| 1212 | + */ | |
| 1213 | + public Object newInstance(Object constructorParameter) | |
| 1214 | + throws NoSuchAlgorithmException { | |
| 1215 | + if (registered == false) { | |
| 1216 | + if (provider.getService(type, algorithm) != this) { | |
| 1217 | + throw new NoSuchAlgorithmException | |
| 1218 | + ("Service not registered with Provider " | |
| 1219 | + + provider.getName() + ": " + this); | |
| 1220 | + } | |
| 1221 | + registered = true; | |
| 1222 | + } | |
| 1223 | + try { | |
| 1224 | + EngineDescription cap = knownEngines.get(type); | |
| 1225 | + if (cap == null) { | |
| 1226 | + // unknown engine type, use generic code | |
| 1227 | + // this is the code path future for non-core | |
| 1228 | + // optional packages | |
| 1229 | + return newInstanceGeneric(constructorParameter); | |
| 1230 | + } | |
| 1231 | + if (cap.constructorParameterClassName == null) { | |
| 1232 | + if (constructorParameter != null) { | |
| 1233 | + throw new InvalidParameterException | |
| 1234 | + ("constructorParameter not used with " + type | |
| 1235 | + + " engines"); | |
| 1236 | + } | |
| 1237 | + Class clazz = getImplClass(); | |
| 1238 | + return clazz.newInstance(); | |
| 1239 | + } else { | |
| 1240 | + Class paramClass = cap.getConstructorParameterClass(); | |
| 1241 | + if (constructorParameter != null) { | |
| 1242 | + Class argClass = constructorParameter.getClass(); | |
| 1243 | + if (paramClass.isAssignableFrom(argClass) == false) { | |
| 1244 | + throw new InvalidParameterException | |
| 1245 | + ("constructorParameter must be instanceof " | |
| 1246 | + + cap.constructorParameterClassName.replace('$', '.') | |
| 1247 | + + " for engine type " + type); | |
| 1248 | + } | |
| 1249 | + } | |
| 1250 | + Class clazz = getImplClass(); | |
| 1251 | + Constructor cons = clazz.getConstructor(paramClass); | |
| 1252 | + return cons.newInstance(constructorParameter); | |
| 1253 | + } | |
| 1254 | + } catch (NoSuchAlgorithmException e) { | |
| 1255 | + throw e; | |
| 1256 | + } catch (InvocationTargetException e) { | |
| 1257 | + throw new NoSuchAlgorithmException | |
| 1258 | + ("Error constructing implementation (algorithm: " | |
| 1259 | + + algorithm + ", provider: " + provider.getName() | |
| 1260 | + + ", class: " + className + ")", e.getCause()); | |
| 1261 | + } catch (Exception e) { | |
| 1262 | + throw new NoSuchAlgorithmException | |
| 1263 | + ("Error constructing implementation (algorithm: " | |
| 1264 | + + algorithm + ", provider: " + provider.getName() | |
| 1265 | + + ", class: " + className + ")", e); | |
| 1266 | + } | |
| 1267 | + } | |
| 1268 | + | |
| 1269 | + // return the implementation Class object for this service | |
| 1270 | + private Class getImplClass() throws NoSuchAlgorithmException { | |
| 1271 | + try { | |
| 1272 | + Reference<Class> ref = classRef; | |
| 1273 | + Class clazz = (ref == null) ? null : ref.get(); | |
| 1274 | + if (clazz == null) { | |
| 1275 | + ClassLoader cl = provider.getClass().getClassLoader(); | |
| 1276 | + if (cl == null) { | |
| 1277 | + clazz = Class.forName(className); | |
| 1278 | + } else { | |
| 1279 | + clazz = cl.loadClass(className); | |
| 1280 | + } | |
| 1281 | + classRef = new WeakReference<Class>(clazz); | |
| 1282 | + } | |
| 1283 | + return clazz; | |
| 1284 | + } catch (ClassNotFoundException e) { | |
| 1285 | + throw new NoSuchAlgorithmException | |
| 1286 | + ("class configured for " + type + "(provider: " + | |
| 1287 | + provider.getName() + ")" + "cannot be found.", e); | |
| 1288 | + } | |
| 1289 | + } | |
| 1290 | + | |
| 1291 | + /** | |
| 1292 | + * Generic code path for unknown engine types. Call the | |
| 1293 | + * no-args constructor if constructorParameter is null, otherwise | |
| 1294 | + * use the first matching constructor. | |
| 1295 | + */ | |
| 1296 | + private Object newInstanceGeneric(Object constructorParameter) | |
| 1297 | + throws Exception { | |
| 1298 | + Class clazz = getImplClass(); | |
| 1299 | + if (constructorParameter == null) { | |
| 1300 | + Object o = clazz.newInstance(); | |
| 1301 | + return o; | |
| 1302 | + } | |
| 1303 | + Class argClass = constructorParameter.getClass(); | |
| 1304 | + Constructor[] cons = clazz.getConstructors(); | |
| 1305 | + // find first public constructor that can take the | |
| 1306 | + // argument as parameter | |
| 1307 | + for (int i = 0; i < cons.length; i++) { | |
| 1308 | + Constructor con = cons[i]; | |
| 1309 | + Class[] paramTypes = con.getParameterTypes(); | |
| 1310 | + if (paramTypes.length != 1) { | |
| 1311 | + continue; | |
| 1312 | + } | |
| 1313 | + if (paramTypes[0].isAssignableFrom(argClass) == false) { | |
| 1314 | + continue; | |
| 1315 | + } | |
| 1316 | + Object o = con.newInstance(new Object[] {constructorParameter}); | |
| 1317 | + return o; | |
| 1318 | + } | |
| 1319 | + throw new NoSuchAlgorithmException("No constructor matching " | |
| 1320 | + + argClass.getName() + " found in class " + className); | |
| 1321 | + } | |
| 1322 | + | |
| 1323 | + /** | |
| 1324 | + * Test whether this Service can use the specified parameter. | |
| 1325 | + * Returns false if this service cannot use the parameter. Returns | |
| 1326 | + * true if this service can use the parameter, if a fast test is | |
| 1327 | + * infeasible, or if the status is unknown. | |
| 1328 | + * | |
| 1329 | + * <p>The security provider framework uses this method with | |
| 1330 | + * some types of services to quickly exclude non-matching | |
| 1331 | + * implementations for consideration. | |
| 1332 | + * Applications will typically not need to call it. | |
| 1333 | + * | |
| 1334 | + * <p>For details and the values of parameter that are valid for the | |
| 1335 | + * various types of services see the top of this class and the | |
| 1336 | + * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html"> | |
| 1337 | + * Java Cryptography Architecture API Specification & | |
| 1338 | + * Reference</a>. | |
| 1339 | + * Security providers can override it to implement their own test. | |
| 1340 | + * | |
| 1341 | + * @param parameter the parameter to test | |
| 1342 | + * | |
| 1343 | + * @return false if this this service cannot use the specified | |
| 1344 | + * parameter; true if it can possibly use the parameter | |
| 1345 | + * | |
| 1346 | + * @throws InvalidParameterException if the value of parameter is | |
| 1347 | + * invalid for this type of service or if this method cannot be | |
| 1348 | + * used with this type of service | |
| 1349 | + */ | |
| 1350 | + public boolean supportsParameter(Object parameter) { | |
| 1351 | + EngineDescription cap = knownEngines.get(type); | |
| 1352 | + if (cap == null) { | |
| 1353 | + // unknown engine type, return true by default | |
| 1354 | + return true; | |
| 1355 | + } | |
| 1356 | + if (cap.supportsParameter == false) { | |
| 1357 | + throw new InvalidParameterException("supportsParameter() not " | |
| 1358 | + + "used with " + type + " engines"); | |
| 1359 | + } | |
| 1360 | + // allow null for keys without attributes for compatibility | |
| 1361 | + if ((parameter != null) && (parameter instanceof Key == false)) { | |
| 1362 | + throw new InvalidParameterException | |
| 1363 | + ("Parameter must be instanceof Key for engine " + type); | |
| 1364 | + } | |
| 1365 | + if (hasKeyAttributes() == false) { | |
| 1366 | + return true; | |
| 1367 | + } | |
| 1368 | + if (parameter == null) { | |
| 1369 | + return false; | |
| 1370 | + } | |
| 1371 | + Key key = (Key)parameter; | |
| 1372 | + if (supportsKeyFormat(key)) { | |
| 1373 | + return true; | |
| 1374 | + } | |
| 1375 | + if (supportsKeyClass(key)) { | |
| 1376 | + return true; | |
| 1377 | + } | |
| 1378 | + return false; | |
| 1379 | + } | |
| 1380 | + | |
| 1381 | + /** | |
| 1382 | + * Return whether this service has its Supported* properties for | |
| 1383 | + * keys defined. Parses the attributes if not yet initialized. | |
| 1384 | + */ | |
| 1385 | + private boolean hasKeyAttributes() { | |
| 1386 | + Boolean b = hasKeyAttributes; | |
| 1387 | + if (b == null) { | |
| 1388 | + synchronized (this) { | |
| 1389 | + String s; | |
| 1390 | + s = getAttribute("SupportedKeyFormats"); | |
| 1391 | + if (s != null) { | |
| 1392 | + supportedFormats = s.split("\\|"); | |
| 1393 | + } | |
| 1394 | + s = getAttribute("SupportedKeyClasses"); | |
| 1395 | + if (s != null) { | |
| 1396 | + String[] classNames = s.split("\\|"); | |
| 1397 | + List<Class> classList = | |
| 1398 | + new ArrayList<>(classNames.length); | |
| 1399 | + for (String className : classNames) { | |
| 1400 | + Class clazz = getKeyClass(className); | |
| 1401 | + if (clazz != null) { | |
| 1402 | + classList.add(clazz); | |
| 1403 | + } | |
| 1404 | + } | |
| 1405 | + supportedClasses = classList.toArray(CLASS0); | |
| 1406 | + } | |
| 1407 | + boolean bool = (supportedFormats != null) | |
| 1408 | + || (supportedClasses != null); | |
| 1409 | + b = Boolean.valueOf(bool); | |
| 1410 | + hasKeyAttributes = b; | |
| 1411 | + } | |
| 1412 | + } | |
| 1413 | + return b.booleanValue(); | |
| 1414 | + } | |
| 1415 | + | |
| 1416 | + // get the key class object of the specified name | |
| 1417 | + private Class getKeyClass(String name) { | |
| 1418 | + try { | |
| 1419 | + return Class.forName(name); | |
| 1420 | + } catch (ClassNotFoundException e) { | |
| 1421 | + // ignore | |
| 1422 | + } | |
| 1423 | + try { | |
| 1424 | + ClassLoader cl = provider.getClass().getClassLoader(); | |
| 1425 | + if (cl != null) { | |
| 1426 | + return cl.loadClass(name); | |
| 1427 | + } | |
| 1428 | + } catch (ClassNotFoundException e) { | |
| 1429 | + // ignore | |
| 1430 | + } | |
| 1431 | + return null; | |
| 1432 | + } | |
| 1433 | + | |
| 1434 | + private boolean supportsKeyFormat(Key key) { | |
| 1435 | + if (supportedFormats == null) { | |
| 1436 | + return false; | |
| 1437 | + } | |
| 1438 | + String format = key.getFormat(); | |
| 1439 | + if (format == null) { | |
| 1440 | + return false; | |
| 1441 | + } | |
| 1442 | + for (String supportedFormat : supportedFormats) { | |
| 1443 | + if (supportedFormat.equals(format)) { | |
| 1444 | + return true; | |
| 1445 | + } | |
| 1446 | + } | |
| 1447 | + return false; | |
| 1448 | + } | |
| 1449 | + | |
| 1450 | + private boolean supportsKeyClass(Key key) { | |
| 1451 | + if (supportedClasses == null) { | |
| 1452 | + return false; | |
| 1453 | + } | |
| 1454 | + Class keyClass = key.getClass(); | |
| 1455 | + for (Class clazz : supportedClasses) { | |
| 1456 | + if (clazz.isAssignableFrom(keyClass)) { | |
| 1457 | + return true; | |
| 1458 | + } | |
| 1459 | + } | |
| 1460 | + return false; | |
| 1461 | + } | |
| 1462 | + | |
| 1463 | + /** | |
| 1464 | + * Return a String representation of this service. | |
| 1465 | + * | |
| 1466 | + * @return a String representation of this service. | |
| 1467 | + */ | |
| 1468 | + public String toString() { | |
| 1469 | + String aString = aliases.isEmpty() | |
| 1470 | + ? "" : "\r\n aliases: " + aliases.toString(); | |
| 1471 | + String attrs = attributes.isEmpty() | |
| 1472 | + ? "" : "\r\n attributes: " + attributes.toString(); | |
| 1473 | + return provider.getName() + ": " + type + "." + algorithm | |
| 1474 | + + " -> " + className + aString + attrs + "\r\n"; | |
| 1475 | + } | |
| 1476 | + | |
| 1477 | + } | |
| 1478 | + | |
| 1479 | +} | |
Binary file not shown.
| @@ -0,0 +1,89 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * A runtime exception for Provider exceptions (such as | |
| 30 | + * misconfiguration errors or unrecoverable internal errors), | |
| 31 | + * which may be subclassed by Providers to | |
| 32 | + * throw specialized, provider-specific runtime errors. | |
| 33 | + * | |
| 34 | + * @author Benjamin Renaud | |
| 35 | + */ | |
| 36 | +public class ProviderException extends RuntimeException { | |
| 37 | + | |
| 38 | + private static final long serialVersionUID = 5256023526693665674L; | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * Constructs a ProviderException with no detail message. A | |
| 42 | + * detail message is a String that describes this particular | |
| 43 | + * exception. | |
| 44 | + */ | |
| 45 | + public ProviderException() { | |
| 46 | + super(); | |
| 47 | + } | |
| 48 | + | |
| 49 | + /** | |
| 50 | + * Constructs a ProviderException with the specified detail | |
| 51 | + * message. A detail message is a String that describes this | |
| 52 | + * particular exception. | |
| 53 | + * | |
| 54 | + * @param s the detail message. | |
| 55 | + */ | |
| 56 | + public ProviderException(String s) { | |
| 57 | + super(s); | |
| 58 | + } | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * Creates a <code>ProviderException</code> with the specified | |
| 62 | + * detail message and cause. | |
| 63 | + * | |
| 64 | + * @param message the detail message (which is saved for later retrieval | |
| 65 | + * by the {@link #getMessage()} method). | |
| 66 | + * @param cause the cause (which is saved for later retrieval by the | |
| 67 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 68 | + * and indicates that the cause is nonexistent or unknown.) | |
| 69 | + * @since 1.5 | |
| 70 | + */ | |
| 71 | + public ProviderException(String message, Throwable cause) { | |
| 72 | + super(message, cause); | |
| 73 | + } | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * Creates a <code>ProviderException</code> with the specified cause | |
| 77 | + * and a detail message of <tt>(cause==null ? null : cause.toString())</tt> | |
| 78 | + * (which typically contains the class and detail message of | |
| 79 | + * <tt>cause</tt>). | |
| 80 | + * | |
| 81 | + * @param cause the cause (which is saved for later retrieval by the | |
| 82 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 83 | + * and indicates that the cause is nonexistent or unknown.) | |
| 84 | + * @since 1.5 | |
| 85 | + */ | |
| 86 | + public ProviderException(Throwable cause) { | |
| 87 | + super(cause); | |
| 88 | + } | |
| 89 | +} | |
Binary file not shown.
| @@ -0,0 +1,53 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2001, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * <p>A public key. This interface contains no methods or constants. | |
| 30 | + * It merely serves to group (and provide type safety for) all public key | |
| 31 | + * interfaces. | |
| 32 | + * | |
| 33 | + * Note: The specialized public key interfaces extend this interface. | |
| 34 | + * See, for example, the DSAPublicKey interface in | |
| 35 | + * <code>java.security.interfaces</code>. | |
| 36 | + * | |
| 37 | + * @see Key | |
| 38 | + * @see PrivateKey | |
| 39 | + * @see Certificate | |
| 40 | + * @see Signature#initVerify | |
| 41 | + * @see java.security.interfaces.DSAPublicKey | |
| 42 | + * @see java.security.interfaces.RSAPublicKey | |
| 43 | + * | |
| 44 | + */ | |
| 45 | + | |
| 46 | +public interface PublicKey extends Key { | |
| 47 | + // Declare serialVersionUID to be compatible with JDK1.1 | |
| 48 | + /** | |
| 49 | + * The class fingerprint that is set to indicate serialization | |
| 50 | + * compatibility with a previous version of the class. | |
| 51 | + */ | |
| 52 | + static final long serialVersionUID = 7187392471159151072L; | |
| 53 | +} | |
Binary file not shown.
| @@ -0,0 +1,227 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.util.HashMap; | |
| 29 | +import java.util.ArrayList; | |
| 30 | +import java.net.URL; | |
| 31 | + | |
| 32 | +import sun.security.util.Debug; | |
| 33 | + | |
| 34 | +/** | |
| 35 | + * This class extends ClassLoader with additional support for defining | |
| 36 | + * classes with an associated code source and permissions which are | |
| 37 | + * retrieved by the system policy by default. | |
| 38 | + * | |
| 39 | + * @author Li Gong | |
| 40 | + * @author Roland Schemers | |
| 41 | + */ | |
| 42 | +public class SecureClassLoader extends ClassLoader { | |
| 43 | + /* | |
| 44 | + * If initialization succeed this is set to true and security checks will | |
| 45 | + * succeed. Otherwise the object is not initialized and the object is | |
| 46 | + * useless. | |
| 47 | + */ | |
| 48 | + private final boolean initialized; | |
| 49 | + | |
| 50 | + // HashMap that maps CodeSource to ProtectionDomain | |
| 51 | + // @GuardedBy("pdcache") | |
| 52 | + private final HashMap<CodeSource, ProtectionDomain> pdcache = | |
| 53 | + new HashMap<>(11); | |
| 54 | + | |
| 55 | + private static final Debug debug = Debug.getInstance("scl"); | |
| 56 | + | |
| 57 | + static { | |
| 58 | + ClassLoader.registerAsParallelCapable(); | |
| 59 | + } | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * Creates a new SecureClassLoader using the specified parent | |
| 63 | + * class loader for delegation. | |
| 64 | + * | |
| 65 | + * <p>If there is a security manager, this method first | |
| 66 | + * calls the security manager's <code>checkCreateClassLoader</code> | |
| 67 | + * method to ensure creation of a class loader is allowed. | |
| 68 | + * <p> | |
| 69 | + * @param parent the parent ClassLoader | |
| 70 | + * @exception SecurityException if a security manager exists and its | |
| 71 | + * <code>checkCreateClassLoader</code> method doesn't allow | |
| 72 | + * creation of a class loader. | |
| 73 | + * @see SecurityManager#checkCreateClassLoader | |
| 74 | + */ | |
| 75 | + protected SecureClassLoader(ClassLoader parent) { | |
| 76 | + super(parent); | |
| 77 | + // this is to make the stack depth consistent with 1.1 | |
| 78 | + SecurityManager security = System.getSecurityManager(); | |
| 79 | + if (security != null) { | |
| 80 | + security.checkCreateClassLoader(); | |
| 81 | + } | |
| 82 | + initialized = true; | |
| 83 | + } | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * Creates a new SecureClassLoader using the default parent class | |
| 87 | + * loader for delegation. | |
| 88 | + * | |
| 89 | + * <p>If there is a security manager, this method first | |
| 90 | + * calls the security manager's <code>checkCreateClassLoader</code> | |
| 91 | + * method to ensure creation of a class loader is allowed. | |
| 92 | + * | |
| 93 | + * @exception SecurityException if a security manager exists and its | |
| 94 | + * <code>checkCreateClassLoader</code> method doesn't allow | |
| 95 | + * creation of a class loader. | |
| 96 | + * @see SecurityManager#checkCreateClassLoader | |
| 97 | + */ | |
| 98 | + protected SecureClassLoader() { | |
| 99 | + super(); | |
| 100 | + // this is to make the stack depth consistent with 1.1 | |
| 101 | + SecurityManager security = System.getSecurityManager(); | |
| 102 | + if (security != null) { | |
| 103 | + security.checkCreateClassLoader(); | |
| 104 | + } | |
| 105 | + initialized = true; | |
| 106 | + } | |
| 107 | + | |
| 108 | + /** | |
| 109 | + * Converts an array of bytes into an instance of class Class, | |
| 110 | + * with an optional CodeSource. Before the | |
| 111 | + * class can be used it must be resolved. | |
| 112 | + * <p> | |
| 113 | + * If a non-null CodeSource is supplied a ProtectionDomain is | |
| 114 | + * constructed and associated with the class being defined. | |
| 115 | + * <p> | |
| 116 | + * @param name the expected name of the class, or <code>null</code> | |
| 117 | + * if not known, using '.' and not '/' as the separator | |
| 118 | + * and without a trailing ".class" suffix. | |
| 119 | + * @param b the bytes that make up the class data. The bytes in | |
| 120 | + * positions <code>off</code> through <code>off+len-1</code> | |
| 121 | + * should have the format of a valid class file as defined by | |
| 122 | + * <cite>The Java™ Virtual Machine Specification</cite>. | |
| 123 | + * @param off the start offset in <code>b</code> of the class data | |
| 124 | + * @param len the length of the class data | |
| 125 | + * @param cs the associated CodeSource, or <code>null</code> if none | |
| 126 | + * @return the <code>Class</code> object created from the data, | |
| 127 | + * and optional CodeSource. | |
| 128 | + * @exception ClassFormatError if the data did not contain a valid class | |
| 129 | + * @exception IndexOutOfBoundsException if either <code>off</code> or | |
| 130 | + * <code>len</code> is negative, or if | |
| 131 | + * <code>off+len</code> is greater than <code>b.length</code>. | |
| 132 | + * | |
| 133 | + * @exception SecurityException if an attempt is made to add this class | |
| 134 | + * to a package that contains classes that were signed by | |
| 135 | + * a different set of certificates than this class, or if | |
| 136 | + * the class name begins with "java.". | |
| 137 | + */ | |
| 138 | + protected final Class<?> defineClass(String name, | |
| 139 | + byte[] b, int off, int len, | |
| 140 | + CodeSource cs) | |
| 141 | + { | |
| 142 | + return defineClass(name, b, off, len, getProtectionDomain(cs)); | |
| 143 | + } | |
| 144 | + | |
| 145 | + /** | |
| 146 | + * Converts a {@link java.nio.ByteBuffer <tt>ByteBuffer</tt>} | |
| 147 | + * into an instance of class <tt>Class</tt>, with an optional CodeSource. | |
| 148 | + * Before the class can be used it must be resolved. | |
| 149 | + * <p> | |
| 150 | + * If a non-null CodeSource is supplied a ProtectionDomain is | |
| 151 | + * constructed and associated with the class being defined. | |
| 152 | + * <p> | |
| 153 | + * @param name the expected name of the class, or <code>null</code> | |
| 154 | + * if not known, using '.' and not '/' as the separator | |
| 155 | + * and without a trailing ".class" suffix. | |
| 156 | + * @param b the bytes that make up the class data. The bytes from positions | |
| 157 | + * <tt>b.position()</tt> through <tt>b.position() + b.limit() -1</tt> | |
| 158 | + * should have the format of a valid class file as defined by | |
| 159 | + * <cite>The Java™ Virtual Machine Specification</cite>. | |
| 160 | + * @param cs the associated CodeSource, or <code>null</code> if none | |
| 161 | + * @return the <code>Class</code> object created from the data, | |
| 162 | + * and optional CodeSource. | |
| 163 | + * @exception ClassFormatError if the data did not contain a valid class | |
| 164 | + * @exception SecurityException if an attempt is made to add this class | |
| 165 | + * to a package that contains classes that were signed by | |
| 166 | + * a different set of certificates than this class, or if | |
| 167 | + * the class name begins with "java.". | |
| 168 | + * | |
| 169 | + * @since 1.5 | |
| 170 | + */ | |
| 171 | + protected final Class<?> defineClass(String name, java.nio.ByteBuffer b, | |
| 172 | + CodeSource cs) | |
| 173 | + { | |
| 174 | + return defineClass(name, b, getProtectionDomain(cs)); | |
| 175 | + } | |
| 176 | + | |
| 177 | + /** | |
| 178 | + * Returns the permissions for the given CodeSource object. | |
| 179 | + * <p> | |
| 180 | + * This method is invoked by the defineClass method which takes | |
| 181 | + * a CodeSource as an argument when it is constructing the | |
| 182 | + * ProtectionDomain for the class being defined. | |
| 183 | + * <p> | |
| 184 | + * @param codesource the codesource. | |
| 185 | + * | |
| 186 | + * @return the permissions granted to the codesource. | |
| 187 | + * | |
| 188 | + */ | |
| 189 | + protected PermissionCollection getPermissions(CodeSource codesource) | |
| 190 | + { | |
| 191 | + check(); | |
| 192 | + return new Permissions(); // ProtectionDomain defers the binding | |
| 193 | + } | |
| 194 | + | |
| 195 | + /* | |
| 196 | + * Returned cached ProtectionDomain for the specified CodeSource. | |
| 197 | + */ | |
| 198 | + private ProtectionDomain getProtectionDomain(CodeSource cs) { | |
| 199 | + if (cs == null) | |
| 200 | + return null; | |
| 201 | + | |
| 202 | + ProtectionDomain pd = null; | |
| 203 | + synchronized (pdcache) { | |
| 204 | + pd = pdcache.get(cs); | |
| 205 | + if (pd == null) { | |
| 206 | + PermissionCollection perms = getPermissions(cs); | |
| 207 | + pd = new ProtectionDomain(cs, perms, this, null); | |
| 208 | + pdcache.put(cs, pd); | |
| 209 | + if (debug != null) { | |
| 210 | + debug.println(" getPermissions "+ pd); | |
| 211 | + debug.println(""); | |
| 212 | + } | |
| 213 | + } | |
| 214 | + } | |
| 215 | + return pd; | |
| 216 | + } | |
| 217 | + | |
| 218 | + /* | |
| 219 | + * Check to make sure the class loader has been initialized. | |
| 220 | + */ | |
| 221 | + private void check() { | |
| 222 | + if (!initialized) { | |
| 223 | + throw new SecurityException("ClassLoader object not initialized"); | |
| 224 | + } | |
| 225 | + } | |
| 226 | + | |
| 227 | +} | |
Binary file not shown.
| @@ -0,0 +1,581 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.util.*; | |
| 29 | + | |
| 30 | +import java.security.Provider.Service; | |
| 31 | + | |
| 32 | +import sun.security.jca.*; | |
| 33 | +import sun.security.jca.GetInstance.Instance; | |
| 34 | + | |
| 35 | +/** | |
| 36 | + * This class provides a cryptographically strong random number | |
| 37 | + * generator (RNG). | |
| 38 | + * | |
| 39 | + * <p>A cryptographically strong random number | |
| 40 | + * minimally complies with the statistical random number generator tests | |
| 41 | + * specified in <a href="http://csrc.nist.gov/cryptval/140-2.htm"> | |
| 42 | + * <i>FIPS 140-2, Security Requirements for Cryptographic Modules</i></a>, | |
| 43 | + * section 4.9.1. | |
| 44 | + * Additionally, SecureRandom must produce non-deterministic output. | |
| 45 | + * Therefore any seed material passed to a SecureRandom object must be | |
| 46 | + * unpredictable, and all SecureRandom output sequences must be | |
| 47 | + * cryptographically strong, as described in | |
| 48 | + * <a href="http://www.ietf.org/rfc/rfc1750.txt"> | |
| 49 | + * <i>RFC 1750: Randomness Recommendations for Security</i></a>. | |
| 50 | + * | |
| 51 | + * <p>A caller obtains a SecureRandom instance via the | |
| 52 | + * no-argument constructor or one of the <code>getInstance</code> methods: | |
| 53 | + * | |
| 54 | + * <pre> | |
| 55 | + * SecureRandom random = new SecureRandom(); | |
| 56 | + * </pre> | |
| 57 | + * | |
| 58 | + * <p> Many SecureRandom implementations are in the form of a pseudo-random | |
| 59 | + * number generator (PRNG), which means they use a deterministic algorithm | |
| 60 | + * to produce a pseudo-random sequence from a true random seed. | |
| 61 | + * Other implementations may produce true random numbers, | |
| 62 | + * and yet others may use a combination of both techniques. | |
| 63 | + * | |
| 64 | + * <p> Typical callers of SecureRandom invoke the following methods | |
| 65 | + * to retrieve random bytes: | |
| 66 | + * | |
| 67 | + * <pre> | |
| 68 | + * SecureRandom random = new SecureRandom(); | |
| 69 | + * byte bytes[] = new byte[20]; | |
| 70 | + * random.nextBytes(bytes); | |
| 71 | + * </pre> | |
| 72 | + * | |
| 73 | + * <p> Callers may also invoke the <code>generateSeed</code> method | |
| 74 | + * to generate a given number of seed bytes (to seed other random number | |
| 75 | + * generators, for example): | |
| 76 | + * <pre> | |
| 77 | + * byte seed[] = random.generateSeed(20); | |
| 78 | + * </pre> | |
| 79 | + * | |
| 80 | + * Note: Depending on the implementation, the <code>generateSeed</code> and | |
| 81 | + * <code>nextBytes</code> methods may block as entropy is being gathered, | |
| 82 | + * for example, if they need to read from /dev/random on various unix-like | |
| 83 | + * operating systems. | |
| 84 | + * | |
| 85 | + * @see java.security.SecureRandomSpi | |
| 86 | + * @see java.util.Random | |
| 87 | + * | |
| 88 | + * @author Benjamin Renaud | |
| 89 | + * @author Josh Bloch | |
| 90 | + */ | |
| 91 | + | |
| 92 | +public class SecureRandom extends java.util.Random { | |
| 93 | + | |
| 94 | + /** | |
| 95 | + * The provider. | |
| 96 | + * | |
| 97 | + * @serial | |
| 98 | + * @since 1.2 | |
| 99 | + */ | |
| 100 | + private Provider provider = null; | |
| 101 | + | |
| 102 | + /** | |
| 103 | + * The provider implementation. | |
| 104 | + * | |
| 105 | + * @serial | |
| 106 | + * @since 1.2 | |
| 107 | + */ | |
| 108 | + private SecureRandomSpi secureRandomSpi = null; | |
| 109 | + | |
| 110 | + /* | |
| 111 | + * The algorithm name of null if unknown. | |
| 112 | + * | |
| 113 | + * @serial | |
| 114 | + * @since 1.5 | |
| 115 | + */ | |
| 116 | + private String algorithm; | |
| 117 | + | |
| 118 | + // Seed Generator | |
| 119 | + private static volatile SecureRandom seedGenerator = null; | |
| 120 | + | |
| 121 | + /** | |
| 122 | + * Constructs a secure random number generator (RNG) implementing the | |
| 123 | + * default random number algorithm. | |
| 124 | + * | |
| 125 | + * <p> This constructor traverses the list of registered security Providers, | |
| 126 | + * starting with the most preferred Provider. | |
| 127 | + * A new SecureRandom object encapsulating the | |
| 128 | + * SecureRandomSpi implementation from the first | |
| 129 | + * Provider that supports a SecureRandom (RNG) algorithm is returned. | |
| 130 | + * If none of the Providers support a RNG algorithm, | |
| 131 | + * then an implementation-specific default is returned. | |
| 132 | + * | |
| 133 | + * <p> Note that the list of registered providers may be retrieved via | |
| 134 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 135 | + * | |
| 136 | + * <p> See the SecureRandom section in the <a href= | |
| 137 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom"> | |
| 138 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 139 | + * for information about standard RNG algorithm names. | |
| 140 | + * | |
| 141 | + * <p> The returned SecureRandom object has not been seeded. To seed the | |
| 142 | + * returned object, call the <code>setSeed</code> method. | |
| 143 | + * If <code>setSeed</code> is not called, the first call to | |
| 144 | + * <code>nextBytes</code> will force the SecureRandom object to seed itself. | |
| 145 | + * This self-seeding will not occur if <code>setSeed</code> was | |
| 146 | + * previously called. | |
| 147 | + */ | |
| 148 | + public SecureRandom() { | |
| 149 | + /* | |
| 150 | + * This call to our superclass constructor will result in a call | |
| 151 | + * to our own <code>setSeed</code> method, which will return | |
| 152 | + * immediately when it is passed zero. | |
| 153 | + */ | |
| 154 | + super(0); | |
| 155 | + getDefaultPRNG(false, null); | |
| 156 | + } | |
| 157 | + | |
| 158 | + /** | |
| 159 | + * Constructs a secure random number generator (RNG) implementing the | |
| 160 | + * default random number algorithm. | |
| 161 | + * The SecureRandom instance is seeded with the specified seed bytes. | |
| 162 | + * | |
| 163 | + * <p> This constructor traverses the list of registered security Providers, | |
| 164 | + * starting with the most preferred Provider. | |
| 165 | + * A new SecureRandom object encapsulating the | |
| 166 | + * SecureRandomSpi implementation from the first | |
| 167 | + * Provider that supports a SecureRandom (RNG) algorithm is returned. | |
| 168 | + * If none of the Providers support a RNG algorithm, | |
| 169 | + * then an implementation-specific default is returned. | |
| 170 | + * | |
| 171 | + * <p> Note that the list of registered providers may be retrieved via | |
| 172 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 173 | + * | |
| 174 | + * <p> See the SecureRandom section in the <a href= | |
| 175 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom"> | |
| 176 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 177 | + * for information about standard RNG algorithm names. | |
| 178 | + * | |
| 179 | + * @param seed the seed. | |
| 180 | + */ | |
| 181 | + public SecureRandom(byte seed[]) { | |
| 182 | + super(0); | |
| 183 | + getDefaultPRNG(true, seed); | |
| 184 | + } | |
| 185 | + | |
| 186 | + private void getDefaultPRNG(boolean setSeed, byte[] seed) { | |
| 187 | + String prng = getPrngAlgorithm(); | |
| 188 | + if (prng == null) { | |
| 189 | + // bummer, get the SUN implementation | |
| 190 | + prng = "SHA1PRNG"; | |
| 191 | + this.secureRandomSpi = new sun.security.provider.SecureRandom(); | |
| 192 | + this.provider = Providers.getSunProvider(); | |
| 193 | + if (setSeed) { | |
| 194 | + this.secureRandomSpi.engineSetSeed(seed); | |
| 195 | + } | |
| 196 | + } else { | |
| 197 | + try { | |
| 198 | + SecureRandom random = SecureRandom.getInstance(prng); | |
| 199 | + this.secureRandomSpi = random.getSecureRandomSpi(); | |
| 200 | + this.provider = random.getProvider(); | |
| 201 | + if (setSeed) { | |
| 202 | + this.secureRandomSpi.engineSetSeed(seed); | |
| 203 | + } | |
| 204 | + } catch (NoSuchAlgorithmException nsae) { | |
| 205 | + // never happens, because we made sure the algorithm exists | |
| 206 | + throw new RuntimeException(nsae); | |
| 207 | + } | |
| 208 | + } | |
| 209 | + // JDK 1.1 based implementations subclass SecureRandom instead of | |
| 210 | + // SecureRandomSpi. They will also go through this code path because | |
| 211 | + // they must call a SecureRandom constructor as it is their superclass. | |
| 212 | + // If we are dealing with such an implementation, do not set the | |
| 213 | + // algorithm value as it would be inaccurate. | |
| 214 | + if (getClass() == SecureRandom.class) { | |
| 215 | + this.algorithm = prng; | |
| 216 | + } | |
| 217 | + } | |
| 218 | + | |
| 219 | + /** | |
| 220 | + * Creates a SecureRandom object. | |
| 221 | + * | |
| 222 | + * @param secureRandomSpi the SecureRandom implementation. | |
| 223 | + * @param provider the provider. | |
| 224 | + */ | |
| 225 | + protected SecureRandom(SecureRandomSpi secureRandomSpi, | |
| 226 | + Provider provider) { | |
| 227 | + this(secureRandomSpi, provider, null); | |
| 228 | + } | |
| 229 | + | |
| 230 | + private SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider, | |
| 231 | + String algorithm) { | |
| 232 | + super(0); | |
| 233 | + this.secureRandomSpi = secureRandomSpi; | |
| 234 | + this.provider = provider; | |
| 235 | + this.algorithm = algorithm; | |
| 236 | + } | |
| 237 | + | |
| 238 | + /** | |
| 239 | + * Returns a SecureRandom object that implements the specified | |
| 240 | + * Random Number Generator (RNG) algorithm. | |
| 241 | + * | |
| 242 | + * <p> This method traverses the list of registered security Providers, | |
| 243 | + * starting with the most preferred Provider. | |
| 244 | + * A new SecureRandom object encapsulating the | |
| 245 | + * SecureRandomSpi implementation from the first | |
| 246 | + * Provider that supports the specified algorithm is returned. | |
| 247 | + * | |
| 248 | + * <p> Note that the list of registered providers may be retrieved via | |
| 249 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 250 | + * | |
| 251 | + * <p> The returned SecureRandom object has not been seeded. To seed the | |
| 252 | + * returned object, call the <code>setSeed</code> method. | |
| 253 | + * If <code>setSeed</code> is not called, the first call to | |
| 254 | + * <code>nextBytes</code> will force the SecureRandom object to seed itself. | |
| 255 | + * This self-seeding will not occur if <code>setSeed</code> was | |
| 256 | + * previously called. | |
| 257 | + * | |
| 258 | + * @param algorithm the name of the RNG algorithm. | |
| 259 | + * See the SecureRandom section in the <a href= | |
| 260 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom"> | |
| 261 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 262 | + * for information about standard RNG algorithm names. | |
| 263 | + * | |
| 264 | + * @return the new SecureRandom object. | |
| 265 | + * | |
| 266 | + * @exception NoSuchAlgorithmException if no Provider supports a | |
| 267 | + * SecureRandomSpi implementation for the | |
| 268 | + * specified algorithm. | |
| 269 | + * | |
| 270 | + * @see Provider | |
| 271 | + * | |
| 272 | + * @since 1.2 | |
| 273 | + */ | |
| 274 | + public static SecureRandom getInstance(String algorithm) | |
| 275 | + throws NoSuchAlgorithmException { | |
| 276 | + Instance instance = GetInstance.getInstance("SecureRandom", | |
| 277 | + SecureRandomSpi.class, algorithm); | |
| 278 | + return new SecureRandom((SecureRandomSpi)instance.impl, | |
| 279 | + instance.provider, algorithm); | |
| 280 | + } | |
| 281 | + | |
| 282 | + /** | |
| 283 | + * Returns a SecureRandom object that implements the specified | |
| 284 | + * Random Number Generator (RNG) algorithm. | |
| 285 | + * | |
| 286 | + * <p> A new SecureRandom object encapsulating the | |
| 287 | + * SecureRandomSpi implementation from the specified provider | |
| 288 | + * is returned. The specified provider must be registered | |
| 289 | + * in the security provider list. | |
| 290 | + * | |
| 291 | + * <p> Note that the list of registered providers may be retrieved via | |
| 292 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 293 | + * | |
| 294 | + * <p> The returned SecureRandom object has not been seeded. To seed the | |
| 295 | + * returned object, call the <code>setSeed</code> method. | |
| 296 | + * If <code>setSeed</code> is not called, the first call to | |
| 297 | + * <code>nextBytes</code> will force the SecureRandom object to seed itself. | |
| 298 | + * This self-seeding will not occur if <code>setSeed</code> was | |
| 299 | + * previously called. | |
| 300 | + * | |
| 301 | + * @param algorithm the name of the RNG algorithm. | |
| 302 | + * See the SecureRandom section in the <a href= | |
| 303 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom"> | |
| 304 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 305 | + * for information about standard RNG algorithm names. | |
| 306 | + * | |
| 307 | + * @param provider the name of the provider. | |
| 308 | + * | |
| 309 | + * @return the new SecureRandom object. | |
| 310 | + * | |
| 311 | + * @exception NoSuchAlgorithmException if a SecureRandomSpi | |
| 312 | + * implementation for the specified algorithm is not | |
| 313 | + * available from the specified provider. | |
| 314 | + * | |
| 315 | + * @exception NoSuchProviderException if the specified provider is not | |
| 316 | + * registered in the security provider list. | |
| 317 | + * | |
| 318 | + * @exception IllegalArgumentException if the provider name is null | |
| 319 | + * or empty. | |
| 320 | + * | |
| 321 | + * @see Provider | |
| 322 | + * | |
| 323 | + * @since 1.2 | |
| 324 | + */ | |
| 325 | + public static SecureRandom getInstance(String algorithm, String provider) | |
| 326 | + throws NoSuchAlgorithmException, NoSuchProviderException { | |
| 327 | + Instance instance = GetInstance.getInstance("SecureRandom", | |
| 328 | + SecureRandomSpi.class, algorithm, provider); | |
| 329 | + return new SecureRandom((SecureRandomSpi)instance.impl, | |
| 330 | + instance.provider, algorithm); | |
| 331 | + } | |
| 332 | + | |
| 333 | + /** | |
| 334 | + * Returns a SecureRandom object that implements the specified | |
| 335 | + * Random Number Generator (RNG) algorithm. | |
| 336 | + * | |
| 337 | + * <p> A new SecureRandom object encapsulating the | |
| 338 | + * SecureRandomSpi implementation from the specified Provider | |
| 339 | + * object is returned. Note that the specified Provider object | |
| 340 | + * does not have to be registered in the provider list. | |
| 341 | + * | |
| 342 | + * <p> The returned SecureRandom object has not been seeded. To seed the | |
| 343 | + * returned object, call the <code>setSeed</code> method. | |
| 344 | + * If <code>setSeed</code> is not called, the first call to | |
| 345 | + * <code>nextBytes</code> will force the SecureRandom object to seed itself. | |
| 346 | + * This self-seeding will not occur if <code>setSeed</code> was | |
| 347 | + * previously called. | |
| 348 | + * | |
| 349 | + * @param algorithm the name of the RNG algorithm. | |
| 350 | + * See the SecureRandom section in the <a href= | |
| 351 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom"> | |
| 352 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 353 | + * for information about standard RNG algorithm names. | |
| 354 | + * | |
| 355 | + * @param provider the provider. | |
| 356 | + * | |
| 357 | + * @return the new SecureRandom object. | |
| 358 | + * | |
| 359 | + * @exception NoSuchAlgorithmException if a SecureRandomSpi | |
| 360 | + * implementation for the specified algorithm is not available | |
| 361 | + * from the specified Provider object. | |
| 362 | + * | |
| 363 | + * @exception IllegalArgumentException if the specified provider is null. | |
| 364 | + * | |
| 365 | + * @see Provider | |
| 366 | + * | |
| 367 | + * @since 1.4 | |
| 368 | + */ | |
| 369 | + public static SecureRandom getInstance(String algorithm, | |
| 370 | + Provider provider) throws NoSuchAlgorithmException { | |
| 371 | + Instance instance = GetInstance.getInstance("SecureRandom", | |
| 372 | + SecureRandomSpi.class, algorithm, provider); | |
| 373 | + return new SecureRandom((SecureRandomSpi)instance.impl, | |
| 374 | + instance.provider, algorithm); | |
| 375 | + } | |
| 376 | + | |
| 377 | + /** | |
| 378 | + * Returns the SecureRandomSpi of this SecureRandom object. | |
| 379 | + */ | |
| 380 | + SecureRandomSpi getSecureRandomSpi() { | |
| 381 | + return secureRandomSpi; | |
| 382 | + } | |
| 383 | + | |
| 384 | + /** | |
| 385 | + * Returns the provider of this SecureRandom object. | |
| 386 | + * | |
| 387 | + * @return the provider of this SecureRandom object. | |
| 388 | + */ | |
| 389 | + public final Provider getProvider() { | |
| 390 | + return provider; | |
| 391 | + } | |
| 392 | + | |
| 393 | + /** | |
| 394 | + * Returns the name of the algorithm implemented by this SecureRandom | |
| 395 | + * object. | |
| 396 | + * | |
| 397 | + * @return the name of the algorithm or <code>unknown</code> | |
| 398 | + * if the algorithm name cannot be determined. | |
| 399 | + * @since 1.5 | |
| 400 | + */ | |
| 401 | + public String getAlgorithm() { | |
| 402 | + return (algorithm != null) ? algorithm : "unknown"; | |
| 403 | + } | |
| 404 | + | |
| 405 | + /** | |
| 406 | + * Reseeds this random object. The given seed supplements, rather than | |
| 407 | + * replaces, the existing seed. Thus, repeated calls are guaranteed | |
| 408 | + * never to reduce randomness. | |
| 409 | + * | |
| 410 | + * @param seed the seed. | |
| 411 | + * | |
| 412 | + * @see #getSeed | |
| 413 | + */ | |
| 414 | + synchronized public void setSeed(byte[] seed) { | |
| 415 | + secureRandomSpi.engineSetSeed(seed); | |
| 416 | + } | |
| 417 | + | |
| 418 | + /** | |
| 419 | + * Reseeds this random object, using the eight bytes contained | |
| 420 | + * in the given <code>long seed</code>. The given seed supplements, | |
| 421 | + * rather than replaces, the existing seed. Thus, repeated calls | |
| 422 | + * are guaranteed never to reduce randomness. | |
| 423 | + * | |
| 424 | + * <p>This method is defined for compatibility with | |
| 425 | + * <code>java.util.Random</code>. | |
| 426 | + * | |
| 427 | + * @param seed the seed. | |
| 428 | + * | |
| 429 | + * @see #getSeed | |
| 430 | + */ | |
| 431 | + public void setSeed(long seed) { | |
| 432 | + /* | |
| 433 | + * Ignore call from super constructor (as well as any other calls | |
| 434 | + * unfortunate enough to be passing 0). It's critical that we | |
| 435 | + * ignore call from superclass constructor, as digest has not | |
| 436 | + * yet been initialized at that point. | |
| 437 | + */ | |
| 438 | + if (seed != 0) { | |
| 439 | + secureRandomSpi.engineSetSeed(longToByteArray(seed)); | |
| 440 | + } | |
| 441 | + } | |
| 442 | + | |
| 443 | + /** | |
| 444 | + * Generates a user-specified number of random bytes. | |
| 445 | + * | |
| 446 | + * <p> If a call to <code>setSeed</code> had not occurred previously, | |
| 447 | + * the first call to this method forces this SecureRandom object | |
| 448 | + * to seed itself. This self-seeding will not occur if | |
| 449 | + * <code>setSeed</code> was previously called. | |
| 450 | + * | |
| 451 | + * @param bytes the array to be filled in with random bytes. | |
| 452 | + */ | |
| 453 | + | |
| 454 | + synchronized public void nextBytes(byte[] bytes) { | |
| 455 | + secureRandomSpi.engineNextBytes(bytes); | |
| 456 | + } | |
| 457 | + | |
| 458 | + /** | |
| 459 | + * Generates an integer containing the user-specified number of | |
| 460 | + * pseudo-random bits (right justified, with leading zeros). This | |
| 461 | + * method overrides a <code>java.util.Random</code> method, and serves | |
| 462 | + * to provide a source of random bits to all of the methods inherited | |
| 463 | + * from that class (for example, <code>nextInt</code>, | |
| 464 | + * <code>nextLong</code>, and <code>nextFloat</code>). | |
| 465 | + * | |
| 466 | + * @param numBits number of pseudo-random bits to be generated, where | |
| 467 | + * 0 <= <code>numBits</code> <= 32. | |
| 468 | + * | |
| 469 | + * @return an <code>int</code> containing the user-specified number | |
| 470 | + * of pseudo-random bits (right justified, with leading zeros). | |
| 471 | + */ | |
| 472 | + final protected int next(int numBits) { | |
| 473 | + int numBytes = (numBits+7)/8; | |
| 474 | + byte b[] = new byte[numBytes]; | |
| 475 | + int next = 0; | |
| 476 | + | |
| 477 | + nextBytes(b); | |
| 478 | + for (int i = 0; i < numBytes; i++) | |
| 479 | + next = (next << 8) + (b[i] & 0xFF); | |
| 480 | + | |
| 481 | + return next >>> (numBytes*8 - numBits); | |
| 482 | + } | |
| 483 | + | |
| 484 | + /** | |
| 485 | + * Returns the given number of seed bytes, computed using the seed | |
| 486 | + * generation algorithm that this class uses to seed itself. This | |
| 487 | + * call may be used to seed other random number generators. | |
| 488 | + * | |
| 489 | + * <p>This method is only included for backwards compatibility. | |
| 490 | + * The caller is encouraged to use one of the alternative | |
| 491 | + * <code>getInstance</code> methods to obtain a SecureRandom object, and | |
| 492 | + * then call the <code>generateSeed</code> method to obtain seed bytes | |
| 493 | + * from that object. | |
| 494 | + * | |
| 495 | + * @param numBytes the number of seed bytes to generate. | |
| 496 | + * | |
| 497 | + * @return the seed bytes. | |
| 498 | + * | |
| 499 | + * @see #setSeed | |
| 500 | + */ | |
| 501 | + public static byte[] getSeed(int numBytes) { | |
| 502 | + if (seedGenerator == null) | |
| 503 | + seedGenerator = new SecureRandom(); | |
| 504 | + return seedGenerator.generateSeed(numBytes); | |
| 505 | + } | |
| 506 | + | |
| 507 | + /** | |
| 508 | + * Returns the given number of seed bytes, computed using the seed | |
| 509 | + * generation algorithm that this class uses to seed itself. This | |
| 510 | + * call may be used to seed other random number generators. | |
| 511 | + * | |
| 512 | + * @param numBytes the number of seed bytes to generate. | |
| 513 | + * | |
| 514 | + * @return the seed bytes. | |
| 515 | + */ | |
| 516 | + public byte[] generateSeed(int numBytes) { | |
| 517 | + return secureRandomSpi.engineGenerateSeed(numBytes); | |
| 518 | + } | |
| 519 | + | |
| 520 | + /** | |
| 521 | + * Helper function to convert a long into a byte array (least significant | |
| 522 | + * byte first). | |
| 523 | + */ | |
| 524 | + private static byte[] longToByteArray(long l) { | |
| 525 | + byte[] retVal = new byte[8]; | |
| 526 | + | |
| 527 | + for (int i = 0; i < 8; i++) { | |
| 528 | + retVal[i] = (byte) l; | |
| 529 | + l >>= 8; | |
| 530 | + } | |
| 531 | + | |
| 532 | + return retVal; | |
| 533 | + } | |
| 534 | + | |
| 535 | + /** | |
| 536 | + * Gets a default PRNG algorithm by looking through all registered | |
| 537 | + * providers. Returns the first PRNG algorithm of the first provider that | |
| 538 | + * has registered a SecureRandom implementation, or null if none of the | |
| 539 | + * registered providers supplies a SecureRandom implementation. | |
| 540 | + */ | |
| 541 | + private static String getPrngAlgorithm() { | |
| 542 | + for (Provider p : Providers.getProviderList().providers()) { | |
| 543 | + for (Service s : p.getServices()) { | |
| 544 | + if (s.getType().equals("SecureRandom")) { | |
| 545 | + return s.getAlgorithm(); | |
| 546 | + } | |
| 547 | + } | |
| 548 | + } | |
| 549 | + return null; | |
| 550 | + } | |
| 551 | + | |
| 552 | + // Declare serialVersionUID to be compatible with JDK1.1 | |
| 553 | + static final long serialVersionUID = 4940670005562187L; | |
| 554 | + | |
| 555 | + // Retain unused values serialized from JDK1.1 | |
| 556 | + /** | |
| 557 | + * @serial | |
| 558 | + */ | |
| 559 | + private byte[] state; | |
| 560 | + /** | |
| 561 | + * @serial | |
| 562 | + */ | |
| 563 | + private MessageDigest digest = null; | |
| 564 | + /** | |
| 565 | + * @serial | |
| 566 | + * | |
| 567 | + * We know that the MessageDigest class does not implement | |
| 568 | + * java.io.Serializable. However, since this field is no longer | |
| 569 | + * used, it will always be NULL and won't affect the serialization | |
| 570 | + * of the SecureRandom class itself. | |
| 571 | + */ | |
| 572 | + private byte[] randomBytes; | |
| 573 | + /** | |
| 574 | + * @serial | |
| 575 | + */ | |
| 576 | + private int randomBytesUsed; | |
| 577 | + /** | |
| 578 | + * @serial | |
| 579 | + */ | |
| 580 | + private long counter; | |
| 581 | +} | |
Binary file not shown.
| @@ -0,0 +1,74 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) | |
| 30 | + * for the <code>SecureRandom</code> class. | |
| 31 | + * All the abstract methods in this class must be implemented by each | |
| 32 | + * service provider who wishes to supply the implementation | |
| 33 | + * of a cryptographically strong pseudo-random number generator. | |
| 34 | + * | |
| 35 | + * | |
| 36 | + * @see SecureRandom | |
| 37 | + * @since 1.2 | |
| 38 | + */ | |
| 39 | + | |
| 40 | +public abstract class SecureRandomSpi implements java.io.Serializable { | |
| 41 | + | |
| 42 | + private static final long serialVersionUID = -2991854161009191830L; | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * Reseeds this random object. The given seed supplements, rather than | |
| 46 | + * replaces, the existing seed. Thus, repeated calls are guaranteed | |
| 47 | + * never to reduce randomness. | |
| 48 | + * | |
| 49 | + * @param seed the seed. | |
| 50 | + */ | |
| 51 | + protected abstract void engineSetSeed(byte[] seed); | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * Generates a user-specified number of random bytes. | |
| 55 | + * | |
| 56 | + * <p> If a call to <code>engineSetSeed</code> had not occurred previously, | |
| 57 | + * the first call to this method forces this SecureRandom implementation | |
| 58 | + * to seed itself. This self-seeding will not occur if | |
| 59 | + * <code>engineSetSeed</code> was previously called. | |
| 60 | + * | |
| 61 | + * @param bytes the array to be filled in with random bytes. | |
| 62 | + */ | |
| 63 | + protected abstract void engineNextBytes(byte[] bytes); | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * Returns the given number of seed bytes. This call may be used to | |
| 67 | + * seed other random number generators. | |
| 68 | + * | |
| 69 | + * @param numBytes the number of seed bytes to generate. | |
| 70 | + * | |
| 71 | + * @return the seed bytes. | |
| 72 | + */ | |
| 73 | + protected abstract byte[] engineGenerateSeed(int numBytes); | |
| 74 | +} | |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,1107 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.lang.reflect.*; | |
| 29 | +import java.util.*; | |
| 30 | +import java.util.concurrent.ConcurrentHashMap; | |
| 31 | +import java.io.*; | |
| 32 | +import java.net.URL; | |
| 33 | +import sun.security.util.Debug; | |
| 34 | +import sun.security.util.PropertyExpander; | |
| 35 | + | |
| 36 | +import java.security.Provider.Service; | |
| 37 | + | |
| 38 | +import sun.security.jca.*; | |
| 39 | + | |
| 40 | +/** | |
| 41 | + * <p>This class centralizes all security properties and common security | |
| 42 | + * methods. One of its primary uses is to manage providers. | |
| 43 | + * | |
| 44 | + * @author Benjamin Renaud | |
| 45 | + */ | |
| 46 | + | |
| 47 | +public final class Security { | |
| 48 | + | |
| 49 | + /* Are we debugging? -- for developers */ | |
| 50 | + private static final Debug sdebug = | |
| 51 | + Debug.getInstance("properties"); | |
| 52 | + | |
| 53 | + /* The java.security properties */ | |
| 54 | + private static Properties props; | |
| 55 | + | |
| 56 | + // An element in the cache | |
| 57 | + private static class ProviderProperty { | |
| 58 | + String className; | |
| 59 | + Provider provider; | |
| 60 | + } | |
| 61 | + | |
| 62 | + static { | |
| 63 | + // doPrivileged here because there are multiple | |
| 64 | + // things in initialize that might require privs. | |
| 65 | + // (the FileInputStream call and the File.exists call, | |
| 66 | + // the securityPropFile call, etc) | |
| 67 | + AccessController.doPrivileged(new PrivilegedAction<Void>() { | |
| 68 | + public Void run() { | |
| 69 | + initialize(); | |
| 70 | + return null; | |
| 71 | + } | |
| 72 | + }); | |
| 73 | + } | |
| 74 | + | |
| 75 | + private static void initialize() { | |
| 76 | + props = new Properties(); | |
| 77 | + boolean loadedProps = false; | |
| 78 | + boolean overrideAll = false; | |
| 79 | + | |
| 80 | + // first load the system properties file | |
| 81 | + // to determine the value of security.overridePropertiesFile | |
| 82 | + File propFile = securityPropFile("java.security"); | |
| 83 | + if (propFile.exists()) { | |
| 84 | + InputStream is = null; | |
| 85 | + try { | |
| 86 | + FileInputStream fis = new FileInputStream(propFile); | |
| 87 | + is = new BufferedInputStream(fis); | |
| 88 | + props.load(is); | |
| 89 | + loadedProps = true; | |
| 90 | + | |
| 91 | + if (sdebug != null) { | |
| 92 | + sdebug.println("reading security properties file: " + | |
| 93 | + propFile); | |
| 94 | + } | |
| 95 | + } catch (IOException e) { | |
| 96 | + if (sdebug != null) { | |
| 97 | + sdebug.println("unable to load security properties from " + | |
| 98 | + propFile); | |
| 99 | + e.printStackTrace(); | |
| 100 | + } | |
| 101 | + } finally { | |
| 102 | + if (is != null) { | |
| 103 | + try { | |
| 104 | + is.close(); | |
| 105 | + } catch (IOException ioe) { | |
| 106 | + if (sdebug != null) { | |
| 107 | + sdebug.println("unable to close input stream"); | |
| 108 | + } | |
| 109 | + } | |
| 110 | + } | |
| 111 | + } | |
| 112 | + } | |
| 113 | + | |
| 114 | + if ("true".equalsIgnoreCase(props.getProperty | |
| 115 | + ("security.overridePropertiesFile"))) { | |
| 116 | + | |
| 117 | + String extraPropFile = System.getProperty | |
| 118 | + ("java.security.properties"); | |
| 119 | + if (extraPropFile != null && extraPropFile.startsWith("=")) { | |
| 120 | + overrideAll = true; | |
| 121 | + extraPropFile = extraPropFile.substring(1); | |
| 122 | + } | |
| 123 | + | |
| 124 | + if (overrideAll) { | |
| 125 | + props = new Properties(); | |
| 126 | + if (sdebug != null) { | |
| 127 | + sdebug.println | |
| 128 | + ("overriding other security properties files!"); | |
| 129 | + } | |
| 130 | + } | |
| 131 | + | |
| 132 | + // now load the user-specified file so its values | |
| 133 | + // will win if they conflict with the earlier values | |
| 134 | + if (extraPropFile != null) { | |
| 135 | + BufferedInputStream bis = null; | |
| 136 | + try { | |
| 137 | + URL propURL; | |
| 138 | + | |
| 139 | + extraPropFile = PropertyExpander.expand(extraPropFile); | |
| 140 | + propFile = new File(extraPropFile); | |
| 141 | + if (propFile.exists()) { | |
| 142 | + propURL = new URL | |
| 143 | + ("file:" + propFile.getCanonicalPath()); | |
| 144 | + } else { | |
| 145 | + propURL = new URL(extraPropFile); | |
| 146 | + } | |
| 147 | + bis = new BufferedInputStream(propURL.openStream()); | |
| 148 | + props.load(bis); | |
| 149 | + loadedProps = true; | |
| 150 | + | |
| 151 | + if (sdebug != null) { | |
| 152 | + sdebug.println("reading security properties file: " + | |
| 153 | + propURL); | |
| 154 | + if (overrideAll) { | |
| 155 | + sdebug.println | |
| 156 | + ("overriding other security properties files!"); | |
| 157 | + } | |
| 158 | + } | |
| 159 | + } catch (Exception e) { | |
| 160 | + if (sdebug != null) { | |
| 161 | + sdebug.println | |
| 162 | + ("unable to load security properties from " + | |
| 163 | + extraPropFile); | |
| 164 | + e.printStackTrace(); | |
| 165 | + } | |
| 166 | + } finally { | |
| 167 | + if (bis != null) { | |
| 168 | + try { | |
| 169 | + bis.close(); | |
| 170 | + } catch (IOException ioe) { | |
| 171 | + if (sdebug != null) { | |
| 172 | + sdebug.println("unable to close input stream"); | |
| 173 | + } | |
| 174 | + } | |
| 175 | + } | |
| 176 | + } | |
| 177 | + } | |
| 178 | + } | |
| 179 | + | |
| 180 | + if (!loadedProps) { | |
| 181 | + initializeStatic(); | |
| 182 | + if (sdebug != null) { | |
| 183 | + sdebug.println("unable to load security properties " + | |
| 184 | + "-- using defaults"); | |
| 185 | + } | |
| 186 | + } | |
| 187 | + | |
| 188 | + } | |
| 189 | + | |
| 190 | + /* | |
| 191 | + * Initialize to default values, if <java.home>/lib/java.security | |
| 192 | + * is not found. | |
| 193 | + */ | |
| 194 | + private static void initializeStatic() { | |
| 195 | + props.put("security.provider.1", "sun.security.provider.Sun"); | |
| 196 | + props.put("security.provider.2", "sun.security.rsa.SunRsaSign"); | |
| 197 | + props.put("security.provider.3", "com.sun.net.ssl.internal.ssl.Provider"); | |
| 198 | + props.put("security.provider.4", "com.sun.crypto.provider.SunJCE"); | |
| 199 | + props.put("security.provider.5", "sun.security.jgss.SunProvider"); | |
| 200 | + props.put("security.provider.6", "com.sun.security.sasl.Provider"); | |
| 201 | + } | |
| 202 | + | |
| 203 | + /** | |
| 204 | + * Don't let anyone instantiate this. | |
| 205 | + */ | |
| 206 | + private Security() { | |
| 207 | + } | |
| 208 | + | |
| 209 | + private static File securityPropFile(String filename) { | |
| 210 | + // maybe check for a system property which will specify where to | |
| 211 | + // look. Someday. | |
| 212 | + String sep = File.separator; | |
| 213 | + return new File(System.getProperty("java.home") + sep + "lib" + sep + | |
| 214 | + "security" + sep + filename); | |
| 215 | + } | |
| 216 | + | |
| 217 | + /** | |
| 218 | + * Looks up providers, and returns the property (and its associated | |
| 219 | + * provider) mapping the key, if any. | |
| 220 | + * The order in which the providers are looked up is the | |
| 221 | + * provider-preference order, as specificed in the security | |
| 222 | + * properties file. | |
| 223 | + */ | |
| 224 | + private static ProviderProperty getProviderProperty(String key) { | |
| 225 | + ProviderProperty entry = null; | |
| 226 | + | |
| 227 | + List<Provider> providers = Providers.getProviderList().providers(); | |
| 228 | + for (int i = 0; i < providers.size(); i++) { | |
| 229 | + | |
| 230 | + String matchKey = null; | |
| 231 | + Provider prov = providers.get(i); | |
| 232 | + String prop = prov.getProperty(key); | |
| 233 | + | |
| 234 | + if (prop == null) { | |
| 235 | + // Is there a match if we do a case-insensitive property name | |
| 236 | + // comparison? Let's try ... | |
| 237 | + for (Enumeration<Object> e = prov.keys(); | |
| 238 | + e.hasMoreElements() && prop == null; ) { | |
| 239 | + matchKey = (String)e.nextElement(); | |
| 240 | + if (key.equalsIgnoreCase(matchKey)) { | |
| 241 | + prop = prov.getProperty(matchKey); | |
| 242 | + break; | |
| 243 | + } | |
| 244 | + } | |
| 245 | + } | |
| 246 | + | |
| 247 | + if (prop != null) { | |
| 248 | + ProviderProperty newEntry = new ProviderProperty(); | |
| 249 | + newEntry.className = prop; | |
| 250 | + newEntry.provider = prov; | |
| 251 | + return newEntry; | |
| 252 | + } | |
| 253 | + } | |
| 254 | + | |
| 255 | + return entry; | |
| 256 | + } | |
| 257 | + | |
| 258 | + /** | |
| 259 | + * Returns the property (if any) mapping the key for the given provider. | |
| 260 | + */ | |
| 261 | + private static String getProviderProperty(String key, Provider provider) { | |
| 262 | + String prop = provider.getProperty(key); | |
| 263 | + if (prop == null) { | |
| 264 | + // Is there a match if we do a case-insensitive property name | |
| 265 | + // comparison? Let's try ... | |
| 266 | + for (Enumeration<Object> e = provider.keys(); | |
| 267 | + e.hasMoreElements() && prop == null; ) { | |
| 268 | + String matchKey = (String)e.nextElement(); | |
| 269 | + if (key.equalsIgnoreCase(matchKey)) { | |
| 270 | + prop = provider.getProperty(matchKey); | |
| 271 | + break; | |
| 272 | + } | |
| 273 | + } | |
| 274 | + } | |
| 275 | + return prop; | |
| 276 | + } | |
| 277 | + | |
| 278 | + /** | |
| 279 | + * Gets a specified property for an algorithm. The algorithm name | |
| 280 | + * should be a standard name. See the <a href= | |
| 281 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html"> | |
| 282 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 283 | + * for information about standard algorithm names. | |
| 284 | + * | |
| 285 | + * One possible use is by specialized algorithm parsers, which may map | |
| 286 | + * classes to algorithms which they understand (much like Key parsers | |
| 287 | + * do). | |
| 288 | + * | |
| 289 | + * @param algName the algorithm name. | |
| 290 | + * | |
| 291 | + * @param propName the name of the property to get. | |
| 292 | + * | |
| 293 | + * @return the value of the specified property. | |
| 294 | + * | |
| 295 | + * @deprecated This method used to return the value of a proprietary | |
| 296 | + * property in the master file of the "SUN" Cryptographic Service | |
| 297 | + * Provider in order to determine how to parse algorithm-specific | |
| 298 | + * parameters. Use the new provider-based and algorithm-independent | |
| 299 | + * <code>AlgorithmParameters</code> and <code>KeyFactory</code> engine | |
| 300 | + * classes (introduced in the J2SE version 1.2 platform) instead. | |
| 301 | + */ | |
| 302 | + @Deprecated | |
| 303 | + public static String getAlgorithmProperty(String algName, | |
| 304 | + String propName) { | |
| 305 | + ProviderProperty entry = getProviderProperty("Alg." + propName | |
| 306 | + + "." + algName); | |
| 307 | + if (entry != null) { | |
| 308 | + return entry.className; | |
| 309 | + } else { | |
| 310 | + return null; | |
| 311 | + } | |
| 312 | + } | |
| 313 | + | |
| 314 | + /** | |
| 315 | + * Adds a new provider, at a specified position. The position is | |
| 316 | + * the preference order in which providers are searched for | |
| 317 | + * requested algorithms. The position is 1-based, that is, | |
| 318 | + * 1 is most preferred, followed by 2, and so on. | |
| 319 | + * | |
| 320 | + * <p>If the given provider is installed at the requested position, | |
| 321 | + * the provider that used to be at that position, and all providers | |
| 322 | + * with a position greater than <code>position</code>, are shifted up | |
| 323 | + * one position (towards the end of the list of installed providers). | |
| 324 | + * | |
| 325 | + * <p>A provider cannot be added if it is already installed. | |
| 326 | + * | |
| 327 | + * <p>First, if there is a security manager, its | |
| 328 | + * <code>checkSecurityAccess</code> | |
| 329 | + * method is called with the string | |
| 330 | + * <code>"insertProvider."+provider.getName()</code> | |
| 331 | + * to see if it's ok to add a new provider. | |
| 332 | + * If the default implementation of <code>checkSecurityAccess</code> | |
| 333 | + * is used (i.e., that method is not overriden), then this will result in | |
| 334 | + * a call to the security manager's <code>checkPermission</code> method | |
| 335 | + * with a | |
| 336 | + * <code>SecurityPermission("insertProvider."+provider.getName())</code> | |
| 337 | + * permission. | |
| 338 | + * | |
| 339 | + * @param provider the provider to be added. | |
| 340 | + * | |
| 341 | + * @param position the preference position that the caller would | |
| 342 | + * like for this provider. | |
| 343 | + * | |
| 344 | + * @return the actual preference position in which the provider was | |
| 345 | + * added, or -1 if the provider was not added because it is | |
| 346 | + * already installed. | |
| 347 | + * | |
| 348 | + * @throws NullPointerException if provider is null | |
| 349 | + * @throws SecurityException | |
| 350 | + * if a security manager exists and its <code>{@link | |
| 351 | + * java.lang.SecurityManager#checkSecurityAccess}</code> method | |
| 352 | + * denies access to add a new provider | |
| 353 | + * | |
| 354 | + * @see #getProvider | |
| 355 | + * @see #removeProvider | |
| 356 | + * @see java.security.SecurityPermission | |
| 357 | + */ | |
| 358 | + public static synchronized int insertProviderAt(Provider provider, | |
| 359 | + int position) { | |
| 360 | + String providerName = provider.getName(); | |
| 361 | + check("insertProvider." + providerName); | |
| 362 | + ProviderList list = Providers.getFullProviderList(); | |
| 363 | + ProviderList newList = ProviderList.insertAt(list, provider, position - 1); | |
| 364 | + if (list == newList) { | |
| 365 | + return -1; | |
| 366 | + } | |
| 367 | + Providers.setProviderList(newList); | |
| 368 | + return newList.getIndex(providerName) + 1; | |
| 369 | + } | |
| 370 | + | |
| 371 | + /** | |
| 372 | + * Adds a provider to the next position available. | |
| 373 | + * | |
| 374 | + * <p>First, if there is a security manager, its | |
| 375 | + * <code>checkSecurityAccess</code> | |
| 376 | + * method is called with the string | |
| 377 | + * <code>"insertProvider."+provider.getName()</code> | |
| 378 | + * to see if it's ok to add a new provider. | |
| 379 | + * If the default implementation of <code>checkSecurityAccess</code> | |
| 380 | + * is used (i.e., that method is not overriden), then this will result in | |
| 381 | + * a call to the security manager's <code>checkPermission</code> method | |
| 382 | + * with a | |
| 383 | + * <code>SecurityPermission("insertProvider."+provider.getName())</code> | |
| 384 | + * permission. | |
| 385 | + * | |
| 386 | + * @param provider the provider to be added. | |
| 387 | + * | |
| 388 | + * @return the preference position in which the provider was | |
| 389 | + * added, or -1 if the provider was not added because it is | |
| 390 | + * already installed. | |
| 391 | + * | |
| 392 | + * @throws NullPointerException if provider is null | |
| 393 | + * @throws SecurityException | |
| 394 | + * if a security manager exists and its <code>{@link | |
| 395 | + * java.lang.SecurityManager#checkSecurityAccess}</code> method | |
| 396 | + * denies access to add a new provider | |
| 397 | + * | |
| 398 | + * @see #getProvider | |
| 399 | + * @see #removeProvider | |
| 400 | + * @see java.security.SecurityPermission | |
| 401 | + */ | |
| 402 | + public static int addProvider(Provider provider) { | |
| 403 | + /* | |
| 404 | + * We can't assign a position here because the statically | |
| 405 | + * registered providers may not have been installed yet. | |
| 406 | + * insertProviderAt() will fix that value after it has | |
| 407 | + * loaded the static providers. | |
| 408 | + */ | |
| 409 | + return insertProviderAt(provider, 0); | |
| 410 | + } | |
| 411 | + | |
| 412 | + /** | |
| 413 | + * Removes the provider with the specified name. | |
| 414 | + * | |
| 415 | + * <p>When the specified provider is removed, all providers located | |
| 416 | + * at a position greater than where the specified provider was are shifted | |
| 417 | + * down one position (towards the head of the list of installed | |
| 418 | + * providers). | |
| 419 | + * | |
| 420 | + * <p>This method returns silently if the provider is not installed or | |
| 421 | + * if name is null. | |
| 422 | + * | |
| 423 | + * <p>First, if there is a security manager, its | |
| 424 | + * <code>checkSecurityAccess</code> | |
| 425 | + * method is called with the string <code>"removeProvider."+name</code> | |
| 426 | + * to see if it's ok to remove the provider. | |
| 427 | + * If the default implementation of <code>checkSecurityAccess</code> | |
| 428 | + * is used (i.e., that method is not overriden), then this will result in | |
| 429 | + * a call to the security manager's <code>checkPermission</code> method | |
| 430 | + * with a <code>SecurityPermission("removeProvider."+name)</code> | |
| 431 | + * permission. | |
| 432 | + * | |
| 433 | + * @param name the name of the provider to remove. | |
| 434 | + * | |
| 435 | + * @throws SecurityException | |
| 436 | + * if a security manager exists and its <code>{@link | |
| 437 | + * java.lang.SecurityManager#checkSecurityAccess}</code> method | |
| 438 | + * denies | |
| 439 | + * access to remove the provider | |
| 440 | + * | |
| 441 | + * @see #getProvider | |
| 442 | + * @see #addProvider | |
| 443 | + */ | |
| 444 | + public static synchronized void removeProvider(String name) { | |
| 445 | + check("removeProvider." + name); | |
| 446 | + ProviderList list = Providers.getFullProviderList(); | |
| 447 | + ProviderList newList = ProviderList.remove(list, name); | |
| 448 | + Providers.setProviderList(newList); | |
| 449 | + } | |
| 450 | + | |
| 451 | + /** | |
| 452 | + * Returns an array containing all the installed providers. The order of | |
| 453 | + * the providers in the array is their preference order. | |
| 454 | + * | |
| 455 | + * @return an array of all the installed providers. | |
| 456 | + */ | |
| 457 | + public static Provider[] getProviders() { | |
| 458 | + return Providers.getFullProviderList().toArray(); | |
| 459 | + } | |
| 460 | + | |
| 461 | + /** | |
| 462 | + * Returns the provider installed with the specified name, if | |
| 463 | + * any. Returns null if no provider with the specified name is | |
| 464 | + * installed or if name is null. | |
| 465 | + * | |
| 466 | + * @param name the name of the provider to get. | |
| 467 | + * | |
| 468 | + * @return the provider of the specified name. | |
| 469 | + * | |
| 470 | + * @see #removeProvider | |
| 471 | + * @see #addProvider | |
| 472 | + */ | |
| 473 | + public static Provider getProvider(String name) { | |
| 474 | + return Providers.getProviderList().getProvider(name); | |
| 475 | + } | |
| 476 | + | |
| 477 | + /** | |
| 478 | + * Returns an array containing all installed providers that satisfy the | |
| 479 | + * specified selection criterion, or null if no such providers have been | |
| 480 | + * installed. The returned providers are ordered | |
| 481 | + * according to their <a href= | |
| 482 | + * "#insertProviderAt(java.security.Provider, int)">preference order</a>. | |
| 483 | + * | |
| 484 | + * <p> A cryptographic service is always associated with a particular | |
| 485 | + * algorithm or type. For example, a digital signature service is | |
| 486 | + * always associated with a particular algorithm (e.g., DSA), | |
| 487 | + * and a CertificateFactory service is always associated with | |
| 488 | + * a particular certificate type (e.g., X.509). | |
| 489 | + * | |
| 490 | + * <p>The selection criterion must be specified in one of the following two | |
| 491 | + * formats: | |
| 492 | + * <ul> | |
| 493 | + * <li> <i><crypto_service>.<algorithm_or_type></i> <p> The | |
| 494 | + * cryptographic service name must not contain any dots. | |
| 495 | + * <p> A | |
| 496 | + * provider satisfies the specified selection criterion iff the provider | |
| 497 | + * implements the | |
| 498 | + * specified algorithm or type for the specified cryptographic service. | |
| 499 | + * <p> For example, "CertificateFactory.X.509" | |
| 500 | + * would be satisfied by any provider that supplied | |
| 501 | + * a CertificateFactory implementation for X.509 certificates. | |
| 502 | + * <li> <i><crypto_service>.<algorithm_or_type> | |
| 503 | + * <attribute_name>:< attribute_value></i> | |
| 504 | + * <p> The cryptographic service name must not contain any dots. There | |
| 505 | + * must be one or more space charaters between the | |
| 506 | + * <i><algorithm_or_type></i> and the <i><attribute_name></i>. | |
| 507 | + * <p> A provider satisfies this selection criterion iff the | |
| 508 | + * provider implements the specified algorithm or type for the specified | |
| 509 | + * cryptographic service and its implementation meets the | |
| 510 | + * constraint expressed by the specified attribute name/value pair. | |
| 511 | + * <p> For example, "Signature.SHA1withDSA KeySize:1024" would be | |
| 512 | + * satisfied by any provider that implemented | |
| 513 | + * the SHA1withDSA signature algorithm with a keysize of 1024 (or larger). | |
| 514 | + * | |
| 515 | + * </ul> | |
| 516 | + * | |
| 517 | + * <p> See the <a href= | |
| 518 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html"> | |
| 519 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 520 | + * for information about standard cryptographic service names, standard | |
| 521 | + * algorithm names and standard attribute names. | |
| 522 | + * | |
| 523 | + * @param filter the criterion for selecting | |
| 524 | + * providers. The filter is case-insensitive. | |
| 525 | + * | |
| 526 | + * @return all the installed providers that satisfy the selection | |
| 527 | + * criterion, or null if no such providers have been installed. | |
| 528 | + * | |
| 529 | + * @throws InvalidParameterException | |
| 530 | + * if the filter is not in the required format | |
| 531 | + * @throws NullPointerException if filter is null | |
| 532 | + * | |
| 533 | + * @see #getProviders(java.util.Map) | |
| 534 | + * @since 1.3 | |
| 535 | + */ | |
| 536 | + public static Provider[] getProviders(String filter) { | |
| 537 | + String key = null; | |
| 538 | + String value = null; | |
| 539 | + int index = filter.indexOf(':'); | |
| 540 | + | |
| 541 | + if (index == -1) { | |
| 542 | + key = filter; | |
| 543 | + value = ""; | |
| 544 | + } else { | |
| 545 | + key = filter.substring(0, index); | |
| 546 | + value = filter.substring(index + 1); | |
| 547 | + } | |
| 548 | + | |
| 549 | + Hashtable<String, String> hashtableFilter = new Hashtable<>(1); | |
| 550 | + hashtableFilter.put(key, value); | |
| 551 | + | |
| 552 | + return (getProviders(hashtableFilter)); | |
| 553 | + } | |
| 554 | + | |
| 555 | + /** | |
| 556 | + * Returns an array containing all installed providers that satisfy the | |
| 557 | + * specified* selection criteria, or null if no such providers have been | |
| 558 | + * installed. The returned providers are ordered | |
| 559 | + * according to their <a href= | |
| 560 | + * "#insertProviderAt(java.security.Provider, int)">preference order</a>. | |
| 561 | + * | |
| 562 | + * <p>The selection criteria are represented by a map. | |
| 563 | + * Each map entry represents a selection criterion. | |
| 564 | + * A provider is selected iff it satisfies all selection | |
| 565 | + * criteria. The key for any entry in such a map must be in one of the | |
| 566 | + * following two formats: | |
| 567 | + * <ul> | |
| 568 | + * <li> <i><crypto_service>.<algorithm_or_type></i> | |
| 569 | + * <p> The cryptographic service name must not contain any dots. | |
| 570 | + * <p> The value associated with the key must be an empty string. | |
| 571 | + * <p> A provider | |
| 572 | + * satisfies this selection criterion iff the provider implements the | |
| 573 | + * specified algorithm or type for the specified cryptographic service. | |
| 574 | + * <li> <i><crypto_service>.<algorithm_or_type> <attribute_name></i> | |
| 575 | + * <p> The cryptographic service name must not contain any dots. There | |
| 576 | + * must be one or more space charaters between the <i><algorithm_or_type></i> | |
| 577 | + * and the <i><attribute_name></i>. | |
| 578 | + * <p> The value associated with the key must be a non-empty string. | |
| 579 | + * A provider satisfies this selection criterion iff the | |
| 580 | + * provider implements the specified algorithm or type for the specified | |
| 581 | + * cryptographic service and its implementation meets the | |
| 582 | + * constraint expressed by the specified attribute name/value pair. | |
| 583 | + * </ul> | |
| 584 | + * | |
| 585 | + * <p> See the <a href= | |
| 586 | + * "../../../technotes/guides/security/StandardNames.html"> | |
| 587 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 588 | + * for information about standard cryptographic service names, standard | |
| 589 | + * algorithm names and standard attribute names. | |
| 590 | + * | |
| 591 | + * @param filter the criteria for selecting | |
| 592 | + * providers. The filter is case-insensitive. | |
| 593 | + * | |
| 594 | + * @return all the installed providers that satisfy the selection | |
| 595 | + * criteria, or null if no such providers have been installed. | |
| 596 | + * | |
| 597 | + * @throws InvalidParameterException | |
| 598 | + * if the filter is not in the required format | |
| 599 | + * @throws NullPointerException if filter is null | |
| 600 | + * | |
| 601 | + * @see #getProviders(java.lang.String) | |
| 602 | + * @since 1.3 | |
| 603 | + */ | |
| 604 | + public static Provider[] getProviders(Map<String,String> filter) { | |
| 605 | + // Get all installed providers first. | |
| 606 | + // Then only return those providers who satisfy the selection criteria. | |
| 607 | + Provider[] allProviders = Security.getProviders(); | |
| 608 | + Set<String> keySet = filter.keySet(); | |
| 609 | + LinkedHashSet<Provider> candidates = new LinkedHashSet<>(5); | |
| 610 | + | |
| 611 | + // Returns all installed providers | |
| 612 | + // if the selection criteria is null. | |
| 613 | + if ((keySet == null) || (allProviders == null)) { | |
| 614 | + return allProviders; | |
| 615 | + } | |
| 616 | + | |
| 617 | + boolean firstSearch = true; | |
| 618 | + | |
| 619 | + // For each selection criterion, remove providers | |
| 620 | + // which don't satisfy the criterion from the candidate set. | |
| 621 | + for (Iterator<String> ite = keySet.iterator(); ite.hasNext(); ) { | |
| 622 | + String key = ite.next(); | |
| 623 | + String value = filter.get(key); | |
| 624 | + | |
| 625 | + LinkedHashSet<Provider> newCandidates = getAllQualifyingCandidates(key, value, | |
| 626 | + allProviders); | |
| 627 | + if (firstSearch) { | |
| 628 | + candidates = newCandidates; | |
| 629 | + firstSearch = false; | |
| 630 | + } | |
| 631 | + | |
| 632 | + if ((newCandidates != null) && !newCandidates.isEmpty()) { | |
| 633 | + // For each provider in the candidates set, if it | |
| 634 | + // isn't in the newCandidate set, we should remove | |
| 635 | + // it from the candidate set. | |
| 636 | + for (Iterator<Provider> cansIte = candidates.iterator(); | |
| 637 | + cansIte.hasNext(); ) { | |
| 638 | + Provider prov = cansIte.next(); | |
| 639 | + if (!newCandidates.contains(prov)) { | |
| 640 | + cansIte.remove(); | |
| 641 | + } | |
| 642 | + } | |
| 643 | + } else { | |
| 644 | + candidates = null; | |
| 645 | + break; | |
| 646 | + } | |
| 647 | + } | |
| 648 | + | |
| 649 | + if ((candidates == null) || (candidates.isEmpty())) | |
| 650 | + return null; | |
| 651 | + | |
| 652 | + Object[] candidatesArray = candidates.toArray(); | |
| 653 | + Provider[] result = new Provider[candidatesArray.length]; | |
| 654 | + | |
| 655 | + for (int i = 0; i < result.length; i++) { | |
| 656 | + result[i] = (Provider)candidatesArray[i]; | |
| 657 | + } | |
| 658 | + | |
| 659 | + return result; | |
| 660 | + } | |
| 661 | + | |
| 662 | + // Map containing cached Spi Class objects of the specified type | |
| 663 | + private static final Map<String, Class> spiMap = new ConcurrentHashMap<>(); | |
| 664 | + | |
| 665 | + /** | |
| 666 | + * Return the Class object for the given engine type | |
| 667 | + * (e.g. "MessageDigest"). Works for Spis in the java.security package | |
| 668 | + * only. | |
| 669 | + */ | |
| 670 | + private static Class getSpiClass(String type) { | |
| 671 | + Class clazz = spiMap.get(type); | |
| 672 | + if (clazz != null) { | |
| 673 | + return clazz; | |
| 674 | + } | |
| 675 | + try { | |
| 676 | + clazz = Class.forName("java.security." + type + "Spi"); | |
| 677 | + spiMap.put(type, clazz); | |
| 678 | + return clazz; | |
| 679 | + } catch (ClassNotFoundException e) { | |
| 680 | + throw new AssertionError("Spi class not found", e); | |
| 681 | + } | |
| 682 | + } | |
| 683 | + | |
| 684 | + /* | |
| 685 | + * Returns an array of objects: the first object in the array is | |
| 686 | + * an instance of an implementation of the requested algorithm | |
| 687 | + * and type, and the second object in the array identifies the provider | |
| 688 | + * of that implementation. | |
| 689 | + * The <code>provider</code> argument can be null, in which case all | |
| 690 | + * configured providers will be searched in order of preference. | |
| 691 | + */ | |
| 692 | + static Object[] getImpl(String algorithm, String type, String provider) | |
| 693 | + throws NoSuchAlgorithmException, NoSuchProviderException { | |
| 694 | + if (provider == null) { | |
| 695 | + return GetInstance.getInstance | |
| 696 | + (type, getSpiClass(type), algorithm).toArray(); | |
| 697 | + } else { | |
| 698 | + return GetInstance.getInstance | |
| 699 | + (type, getSpiClass(type), algorithm, provider).toArray(); | |
| 700 | + } | |
| 701 | + } | |
| 702 | + | |
| 703 | + static Object[] getImpl(String algorithm, String type, String provider, | |
| 704 | + Object params) throws NoSuchAlgorithmException, | |
| 705 | + NoSuchProviderException, InvalidAlgorithmParameterException { | |
| 706 | + if (provider == null) { | |
| 707 | + return GetInstance.getInstance | |
| 708 | + (type, getSpiClass(type), algorithm, params).toArray(); | |
| 709 | + } else { | |
| 710 | + return GetInstance.getInstance | |
| 711 | + (type, getSpiClass(type), algorithm, params, provider).toArray(); | |
| 712 | + } | |
| 713 | + } | |
| 714 | + | |
| 715 | + /* | |
| 716 | + * Returns an array of objects: the first object in the array is | |
| 717 | + * an instance of an implementation of the requested algorithm | |
| 718 | + * and type, and the second object in the array identifies the provider | |
| 719 | + * of that implementation. | |
| 720 | + * The <code>provider</code> argument cannot be null. | |
| 721 | + */ | |
| 722 | + static Object[] getImpl(String algorithm, String type, Provider provider) | |
| 723 | + throws NoSuchAlgorithmException { | |
| 724 | + return GetInstance.getInstance | |
| 725 | + (type, getSpiClass(type), algorithm, provider).toArray(); | |
| 726 | + } | |
| 727 | + | |
| 728 | + static Object[] getImpl(String algorithm, String type, Provider provider, | |
| 729 | + Object params) throws NoSuchAlgorithmException, | |
| 730 | + InvalidAlgorithmParameterException { | |
| 731 | + return GetInstance.getInstance | |
| 732 | + (type, getSpiClass(type), algorithm, params, provider).toArray(); | |
| 733 | + } | |
| 734 | + | |
| 735 | + /** | |
| 736 | + * Gets a security property value. | |
| 737 | + * | |
| 738 | + * <p>First, if there is a security manager, its | |
| 739 | + * <code>checkPermission</code> method is called with a | |
| 740 | + * <code>java.security.SecurityPermission("getProperty."+key)</code> | |
| 741 | + * permission to see if it's ok to retrieve the specified | |
| 742 | + * security property value.. | |
| 743 | + * | |
| 744 | + * @param key the key of the property being retrieved. | |
| 745 | + * | |
| 746 | + * @return the value of the security property corresponding to key. | |
| 747 | + * | |
| 748 | + * @throws SecurityException | |
| 749 | + * if a security manager exists and its <code>{@link | |
| 750 | + * java.lang.SecurityManager#checkPermission}</code> method | |
| 751 | + * denies | |
| 752 | + * access to retrieve the specified security property value | |
| 753 | + * @throws NullPointerException is key is null | |
| 754 | + * | |
| 755 | + * @see #setProperty | |
| 756 | + * @see java.security.SecurityPermission | |
| 757 | + */ | |
| 758 | + public static String getProperty(String key) { | |
| 759 | + SecurityManager sm = System.getSecurityManager(); | |
| 760 | + if (sm != null) { | |
| 761 | + sm.checkPermission(new SecurityPermission("getProperty."+ | |
| 762 | + key)); | |
| 763 | + } | |
| 764 | + String name = props.getProperty(key); | |
| 765 | + if (name != null) | |
| 766 | + name = name.trim(); // could be a class name with trailing ws | |
| 767 | + return name; | |
| 768 | + } | |
| 769 | + | |
| 770 | + /** | |
| 771 | + * Sets a security property value. | |
| 772 | + * | |
| 773 | + * <p>First, if there is a security manager, its | |
| 774 | + * <code>checkPermission</code> method is called with a | |
| 775 | + * <code>java.security.SecurityPermission("setProperty."+key)</code> | |
| 776 | + * permission to see if it's ok to set the specified | |
| 777 | + * security property value. | |
| 778 | + * | |
| 779 | + * @param key the name of the property to be set. | |
| 780 | + * | |
| 781 | + * @param datum the value of the property to be set. | |
| 782 | + * | |
| 783 | + * @throws SecurityException | |
| 784 | + * if a security manager exists and its <code>{@link | |
| 785 | + * java.lang.SecurityManager#checkPermission}</code> method | |
| 786 | + * denies access to set the specified security property value | |
| 787 | + * @throws NullPointerException if key or datum is null | |
| 788 | + * | |
| 789 | + * @see #getProperty | |
| 790 | + * @see java.security.SecurityPermission | |
| 791 | + */ | |
| 792 | + public static void setProperty(String key, String datum) { | |
| 793 | + check("setProperty."+key); | |
| 794 | + props.put(key, datum); | |
| 795 | + invalidateSMCache(key); /* See below. */ | |
| 796 | + } | |
| 797 | + | |
| 798 | + /* | |
| 799 | + * Implementation detail: If the property we just set in | |
| 800 | + * setProperty() was either "package.access" or | |
| 801 | + * "package.definition", we need to signal to the SecurityManager | |
| 802 | + * class that the value has just changed, and that it should | |
| 803 | + * invalidate it's local cache values. | |
| 804 | + * | |
| 805 | + * Rather than create a new API entry for this function, | |
| 806 | + * we use reflection to set a private variable. | |
| 807 | + */ | |
| 808 | + private static void invalidateSMCache(String key) { | |
| 809 | + | |
| 810 | + final boolean pa = key.equals("package.access"); | |
| 811 | + final boolean pd = key.equals("package.definition"); | |
| 812 | + | |
| 813 | + if (pa || pd) { | |
| 814 | + AccessController.doPrivileged(new PrivilegedAction<Void>() { | |
| 815 | + public Void run() { | |
| 816 | + try { | |
| 817 | + /* Get the class via the bootstrap class loader. */ | |
| 818 | + Class cl = Class.forName( | |
| 819 | + "java.lang.SecurityManager", false, null); | |
| 820 | + Field f = null; | |
| 821 | + boolean accessible = false; | |
| 822 | + | |
| 823 | + if (pa) { | |
| 824 | + f = cl.getDeclaredField("packageAccessValid"); | |
| 825 | + accessible = f.isAccessible(); | |
| 826 | + f.setAccessible(true); | |
| 827 | + } else { | |
| 828 | + f = cl.getDeclaredField("packageDefinitionValid"); | |
| 829 | + accessible = f.isAccessible(); | |
| 830 | + f.setAccessible(true); | |
| 831 | + } | |
| 832 | + f.setBoolean(f, false); | |
| 833 | + f.setAccessible(accessible); | |
| 834 | + } | |
| 835 | + catch (Exception e1) { | |
| 836 | + /* If we couldn't get the class, it hasn't | |
| 837 | + * been loaded yet. If there is no such | |
| 838 | + * field, we shouldn't try to set it. There | |
| 839 | + * shouldn't be a security execption, as we | |
| 840 | + * are loaded by boot class loader, and we | |
| 841 | + * are inside a doPrivileged() here. | |
| 842 | + * | |
| 843 | + * NOOP: don't do anything... | |
| 844 | + */ | |
| 845 | + } | |
| 846 | + return null; | |
| 847 | + } /* run */ | |
| 848 | + }); /* PrivilegedAction */ | |
| 849 | + } /* if */ | |
| 850 | + } | |
| 851 | + | |
| 852 | + private static void check(String directive) { | |
| 853 | + SecurityManager security = System.getSecurityManager(); | |
| 854 | + if (security != null) { | |
| 855 | + security.checkSecurityAccess(directive); | |
| 856 | + } | |
| 857 | + } | |
| 858 | + | |
| 859 | + /* | |
| 860 | + * Returns all providers who satisfy the specified | |
| 861 | + * criterion. | |
| 862 | + */ | |
| 863 | + private static LinkedHashSet<Provider> getAllQualifyingCandidates( | |
| 864 | + String filterKey, | |
| 865 | + String filterValue, | |
| 866 | + Provider[] allProviders) { | |
| 867 | + String[] filterComponents = getFilterComponents(filterKey, | |
| 868 | + filterValue); | |
| 869 | + | |
| 870 | + // The first component is the service name. | |
| 871 | + // The second is the algorithm name. | |
| 872 | + // If the third isn't null, that is the attrinute name. | |
| 873 | + String serviceName = filterComponents[0]; | |
| 874 | + String algName = filterComponents[1]; | |
| 875 | + String attrName = filterComponents[2]; | |
| 876 | + | |
| 877 | + return getProvidersNotUsingCache(serviceName, algName, attrName, | |
| 878 | + filterValue, allProviders); | |
| 879 | + } | |
| 880 | + | |
| 881 | + private static LinkedHashSet<Provider> getProvidersNotUsingCache( | |
| 882 | + String serviceName, | |
| 883 | + String algName, | |
| 884 | + String attrName, | |
| 885 | + String filterValue, | |
| 886 | + Provider[] allProviders) { | |
| 887 | + LinkedHashSet<Provider> candidates = new LinkedHashSet<>(5); | |
| 888 | + for (int i = 0; i < allProviders.length; i++) { | |
| 889 | + if (isCriterionSatisfied(allProviders[i], serviceName, | |
| 890 | + algName, | |
| 891 | + attrName, filterValue)) { | |
| 892 | + candidates.add(allProviders[i]); | |
| 893 | + } | |
| 894 | + } | |
| 895 | + return candidates; | |
| 896 | + } | |
| 897 | + | |
| 898 | + /* | |
| 899 | + * Returns true if the given provider satisfies | |
| 900 | + * the selection criterion key:value. | |
| 901 | + */ | |
| 902 | + private static boolean isCriterionSatisfied(Provider prov, | |
| 903 | + String serviceName, | |
| 904 | + String algName, | |
| 905 | + String attrName, | |
| 906 | + String filterValue) { | |
| 907 | + String key = serviceName + '.' + algName; | |
| 908 | + | |
| 909 | + if (attrName != null) { | |
| 910 | + key += ' ' + attrName; | |
| 911 | + } | |
| 912 | + // Check whether the provider has a property | |
| 913 | + // whose key is the same as the given key. | |
| 914 | + String propValue = getProviderProperty(key, prov); | |
| 915 | + | |
| 916 | + if (propValue == null) { | |
| 917 | + // Check whether we have an alias instead | |
| 918 | + // of a standard name in the key. | |
| 919 | + String standardName = getProviderProperty("Alg.Alias." + | |
| 920 | + serviceName + "." + | |
| 921 | + algName, | |
| 922 | + prov); | |
| 923 | + if (standardName != null) { | |
| 924 | + key = serviceName + "." + standardName; | |
| 925 | + | |
| 926 | + if (attrName != null) { | |
| 927 | + key += ' ' + attrName; | |
| 928 | + } | |
| 929 | + | |
| 930 | + propValue = getProviderProperty(key, prov); | |
| 931 | + } | |
| 932 | + | |
| 933 | + if (propValue == null) { | |
| 934 | + // The provider doesn't have the given | |
| 935 | + // key in its property list. | |
| 936 | + return false; | |
| 937 | + } | |
| 938 | + } | |
| 939 | + | |
| 940 | + // If the key is in the format of: | |
| 941 | + // <crypto_service>.<algorithm_or_type>, | |
| 942 | + // there is no need to check the value. | |
| 943 | + | |
| 944 | + if (attrName == null) { | |
| 945 | + return true; | |
| 946 | + } | |
| 947 | + | |
| 948 | + // If we get here, the key must be in the | |
| 949 | + // format of <crypto_service>.<algorithm_or_provider> <attribute_name>. | |
| 950 | + if (isStandardAttr(attrName)) { | |
| 951 | + return isConstraintSatisfied(attrName, filterValue, propValue); | |
| 952 | + } else { | |
| 953 | + return filterValue.equalsIgnoreCase(propValue); | |
| 954 | + } | |
| 955 | + } | |
| 956 | + | |
| 957 | + /* | |
| 958 | + * Returns true if the attribute is a standard attribute; | |
| 959 | + * otherwise, returns false. | |
| 960 | + */ | |
| 961 | + private static boolean isStandardAttr(String attribute) { | |
| 962 | + // For now, we just have two standard attributes: | |
| 963 | + // KeySize and ImplementedIn. | |
| 964 | + if (attribute.equalsIgnoreCase("KeySize")) | |
| 965 | + return true; | |
| 966 | + | |
| 967 | + if (attribute.equalsIgnoreCase("ImplementedIn")) | |
| 968 | + return true; | |
| 969 | + | |
| 970 | + return false; | |
| 971 | + } | |
| 972 | + | |
| 973 | + /* | |
| 974 | + * Returns true if the requested attribute value is supported; | |
| 975 | + * otherwise, returns false. | |
| 976 | + */ | |
| 977 | + private static boolean isConstraintSatisfied(String attribute, | |
| 978 | + String value, | |
| 979 | + String prop) { | |
| 980 | + // For KeySize, prop is the max key size the | |
| 981 | + // provider supports for a specific <crypto_service>.<algorithm>. | |
| 982 | + if (attribute.equalsIgnoreCase("KeySize")) { | |
| 983 | + int requestedSize = Integer.parseInt(value); | |
| 984 | + int maxSize = Integer.parseInt(prop); | |
| 985 | + if (requestedSize <= maxSize) { | |
| 986 | + return true; | |
| 987 | + } else { | |
| 988 | + return false; | |
| 989 | + } | |
| 990 | + } | |
| 991 | + | |
| 992 | + // For Type, prop is the type of the implementation | |
| 993 | + // for a specific <crypto service>.<algorithm>. | |
| 994 | + if (attribute.equalsIgnoreCase("ImplementedIn")) { | |
| 995 | + return value.equalsIgnoreCase(prop); | |
| 996 | + } | |
| 997 | + | |
| 998 | + return false; | |
| 999 | + } | |
| 1000 | + | |
| 1001 | + static String[] getFilterComponents(String filterKey, String filterValue) { | |
| 1002 | + int algIndex = filterKey.indexOf('.'); | |
| 1003 | + | |
| 1004 | + if (algIndex < 0) { | |
| 1005 | + // There must be a dot in the filter, and the dot | |
| 1006 | + // shouldn't be at the beginning of this string. | |
| 1007 | + throw new InvalidParameterException("Invalid filter"); | |
| 1008 | + } | |
| 1009 | + | |
| 1010 | + String serviceName = filterKey.substring(0, algIndex); | |
| 1011 | + String algName = null; | |
| 1012 | + String attrName = null; | |
| 1013 | + | |
| 1014 | + if (filterValue.length() == 0) { | |
| 1015 | + // The filterValue is an empty string. So the filterKey | |
| 1016 | + // should be in the format of <crypto_service>.<algorithm_or_type>. | |
| 1017 | + algName = filterKey.substring(algIndex + 1).trim(); | |
| 1018 | + if (algName.length() == 0) { | |
| 1019 | + // There must be a algorithm or type name. | |
| 1020 | + throw new InvalidParameterException("Invalid filter"); | |
| 1021 | + } | |
| 1022 | + } else { | |
| 1023 | + // The filterValue is a non-empty string. So the filterKey must be | |
| 1024 | + // in the format of | |
| 1025 | + // <crypto_service>.<algorithm_or_type> <attribute_name> | |
| 1026 | + int attrIndex = filterKey.indexOf(' '); | |
| 1027 | + | |
| 1028 | + if (attrIndex == -1) { | |
| 1029 | + // There is no attribute name in the filter. | |
| 1030 | + throw new InvalidParameterException("Invalid filter"); | |
| 1031 | + } else { | |
| 1032 | + attrName = filterKey.substring(attrIndex + 1).trim(); | |
| 1033 | + if (attrName.length() == 0) { | |
| 1034 | + // There is no attribute name in the filter. | |
| 1035 | + throw new InvalidParameterException("Invalid filter"); | |
| 1036 | + } | |
| 1037 | + } | |
| 1038 | + | |
| 1039 | + // There must be an algorithm name in the filter. | |
| 1040 | + if ((attrIndex < algIndex) || | |
| 1041 | + (algIndex == attrIndex - 1)) { | |
| 1042 | + throw new InvalidParameterException("Invalid filter"); | |
| 1043 | + } else { | |
| 1044 | + algName = filterKey.substring(algIndex + 1, attrIndex); | |
| 1045 | + } | |
| 1046 | + } | |
| 1047 | + | |
| 1048 | + String[] result = new String[3]; | |
| 1049 | + result[0] = serviceName; | |
| 1050 | + result[1] = algName; | |
| 1051 | + result[2] = attrName; | |
| 1052 | + | |
| 1053 | + return result; | |
| 1054 | + } | |
| 1055 | + | |
| 1056 | + /** | |
| 1057 | + * Returns a Set of Strings containing the names of all available | |
| 1058 | + * algorithms or types for the specified Java cryptographic service | |
| 1059 | + * (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore). Returns | |
| 1060 | + * an empty Set if there is no provider that supports the | |
| 1061 | + * specified service or if serviceName is null. For a complete list | |
| 1062 | + * of Java cryptographic services, please see the | |
| 1063 | + * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html">Java | |
| 1064 | + * Cryptography Architecture API Specification & Reference</a>. | |
| 1065 | + * Note: the returned set is immutable. | |
| 1066 | + * | |
| 1067 | + * @param serviceName the name of the Java cryptographic | |
| 1068 | + * service (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore). | |
| 1069 | + * Note: this parameter is case-insensitive. | |
| 1070 | + * | |
| 1071 | + * @return a Set of Strings containing the names of all available | |
| 1072 | + * algorithms or types for the specified Java cryptographic service | |
| 1073 | + * or an empty set if no provider supports the specified service. | |
| 1074 | + * | |
| 1075 | + * @since 1.4 | |
| 1076 | + **/ | |
| 1077 | + public static Set<String> getAlgorithms(String serviceName) { | |
| 1078 | + | |
| 1079 | + if ((serviceName == null) || (serviceName.length() == 0) || | |
| 1080 | + (serviceName.endsWith("."))) { | |
| 1081 | + return Collections.EMPTY_SET; | |
| 1082 | + } | |
| 1083 | + | |
| 1084 | + HashSet<String> result = new HashSet<>(); | |
| 1085 | + Provider[] providers = Security.getProviders(); | |
| 1086 | + | |
| 1087 | + for (int i = 0; i < providers.length; i++) { | |
| 1088 | + // Check the keys for each provider. | |
| 1089 | + for (Enumeration<Object> e = providers[i].keys(); | |
| 1090 | + e.hasMoreElements(); ) { | |
| 1091 | + String currentKey = ((String)e.nextElement()).toUpperCase(); | |
| 1092 | + if (currentKey.startsWith(serviceName.toUpperCase())) { | |
| 1093 | + // We should skip the currentKey if it contains a | |
| 1094 | + // whitespace. The reason is: such an entry in the | |
| 1095 | + // provider property contains attributes for the | |
| 1096 | + // implementation of an algorithm. We are only interested | |
| 1097 | + // in entries which lead to the implementation | |
| 1098 | + // classes. | |
| 1099 | + if (currentKey.indexOf(" ") < 0) { | |
| 1100 | + result.add(currentKey.substring(serviceName.length() + 1)); | |
| 1101 | + } | |
| 1102 | + } | |
| 1103 | + } | |
| 1104 | + } | |
| 1105 | + return Collections.unmodifiableSet(result); | |
| 1106 | + } | |
| 1107 | +} | |
Binary file not shown.
| @@ -0,0 +1,331 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.security.*; | |
| 29 | +import java.util.Enumeration; | |
| 30 | +import java.util.Hashtable; | |
| 31 | +import java.util.StringTokenizer; | |
| 32 | + | |
| 33 | +/** | |
| 34 | + * This class is for security permissions. | |
| 35 | + * A SecurityPermission contains a name (also referred to as a "target name") | |
| 36 | + * but no actions list; you either have the named permission | |
| 37 | + * or you don't. | |
| 38 | + * <P> | |
| 39 | + * The target name is the name of a security configuration parameter (see below). | |
| 40 | + * Currently the SecurityPermission object is used to guard access | |
| 41 | + * to the Policy, Security, Provider, Signer, and Identity | |
| 42 | + * objects. | |
| 43 | + * <P> | |
| 44 | + * The following table lists all the possible SecurityPermission target names, | |
| 45 | + * and for each provides a description of what the permission allows | |
| 46 | + * and a discussion of the risks of granting code the permission. | |
| 47 | + * <P> | |
| 48 | + * | |
| 49 | + * <table border=1 cellpadding=5 summary="target name,what the permission allows, and associated risks"> | |
| 50 | + * <tr> | |
| 51 | + * <th>Permission Target Name</th> | |
| 52 | + * <th>What the Permission Allows</th> | |
| 53 | + * <th>Risks of Allowing this Permission</th> | |
| 54 | + * </tr> | |
| 55 | + * | |
| 56 | + * <tr> | |
| 57 | + * <td>createAccessControlContext</td> | |
| 58 | + * <td>Creation of an AccessControlContext</td> | |
| 59 | + * <td>This allows someone to instantiate an AccessControlContext | |
| 60 | + * with a <code>DomainCombiner</code>. Extreme care must be taken when | |
| 61 | + * granting this permission. Malicious code could create a DomainCombiner | |
| 62 | + * that augments the set of permissions granted to code, and even grant the | |
| 63 | + * code {@link java.security.AllPermission}.</td> | |
| 64 | + * </tr> | |
| 65 | + * | |
| 66 | + * <tr> | |
| 67 | + * <td>getDomainCombiner</td> | |
| 68 | + * <td>Retrieval of an AccessControlContext's DomainCombiner</td> | |
| 69 | + * <td>This allows someone to retrieve an AccessControlContext's | |
| 70 | + * <code>DomainCombiner</code>. Since DomainCombiners may contain | |
| 71 | + * sensitive information, this could potentially lead to a privacy leak.</td> | |
| 72 | + * </tr> | |
| 73 | + * | |
| 74 | + * <tr> | |
| 75 | + * <td>getPolicy</td> | |
| 76 | + * <td>Retrieval of the system-wide security policy (specifically, of the | |
| 77 | + * currently-installed Policy object)</td> | |
| 78 | + * <td>This allows someone to query the policy via the | |
| 79 | + * <code>getPermissions</code> call, | |
| 80 | + * which discloses which permissions would be granted to a given CodeSource. | |
| 81 | + * While revealing the policy does not compromise the security of | |
| 82 | + * the system, it does provide malicious code with additional information | |
| 83 | + * which it may use to better aim an attack. It is wise | |
| 84 | + * not to divulge more information than necessary.</td> | |
| 85 | + * </tr> | |
| 86 | + * | |
| 87 | + * <tr> | |
| 88 | + * <td>setPolicy</td> | |
| 89 | + * <td>Setting of the system-wide security policy (specifically, | |
| 90 | + * the Policy object)</td> | |
| 91 | + * <td>Granting this permission is extremely dangerous, as malicious | |
| 92 | + * code may grant itself all the necessary permissions it needs | |
| 93 | + * to successfully mount an attack on the system.</td> | |
| 94 | + * </tr> | |
| 95 | + * | |
| 96 | + * <tr> | |
| 97 | + * <td>createPolicy.{policy type}</td> | |
| 98 | + * <td>Getting an instance of a Policy implementation from a provider</td> | |
| 99 | + * <td>Granting this permission enables code to obtain a Policy object. | |
| 100 | + * Malicious code may query the Policy object to determine what permissions | |
| 101 | + * have been granted to code other than itself. </td> | |
| 102 | + * </tr> | |
| 103 | + * | |
| 104 | + * <tr> | |
| 105 | + * <td>getProperty.{key}</td> | |
| 106 | + * <td>Retrieval of the security property with the specified key</td> | |
| 107 | + * <td>Depending on the particular key for which access has | |
| 108 | + * been granted, the code may have access to the list of security | |
| 109 | + * providers, as well as the location of the system-wide and user | |
| 110 | + * security policies. while revealing this information does not | |
| 111 | + * compromise the security of the system, it does provide malicious | |
| 112 | + * code with additional information which it may use to better aim | |
| 113 | + * an attack. | |
| 114 | +</td> | |
| 115 | + * </tr> | |
| 116 | + * | |
| 117 | + * <tr> | |
| 118 | + * <td>setProperty.{key}</td> | |
| 119 | + * <td>Setting of the security property with the specified key</td> | |
| 120 | + * <td>This could include setting a security provider or defining | |
| 121 | + * the location of the system-wide security policy. Malicious | |
| 122 | + * code that has permission to set a new security provider may | |
| 123 | + * set a rogue provider that steals confidential information such | |
| 124 | + * as cryptographic private keys. In addition, malicious code with | |
| 125 | + * permission to set the location of the system-wide security policy | |
| 126 | + * may point it to a security policy that grants the attacker | |
| 127 | + * all the necessary permissions it requires to successfully mount | |
| 128 | + * an attack on the system. | |
| 129 | +</td> | |
| 130 | + * </tr> | |
| 131 | + * | |
| 132 | + * <tr> | |
| 133 | + * <td>insertProvider.{provider name}</td> | |
| 134 | + * <td>Addition of a new provider, with the specified name</td> | |
| 135 | + * <td>This would allow somebody to introduce a possibly | |
| 136 | + * malicious provider (e.g., one that discloses the private keys passed | |
| 137 | + * to it) as the highest-priority provider. This would be possible | |
| 138 | + * because the Security object (which manages the installed providers) | |
| 139 | + * currently does not check the integrity or authenticity of a provider | |
| 140 | + * before attaching it.</td> | |
| 141 | + * </tr> | |
| 142 | + * | |
| 143 | + * <tr> | |
| 144 | + * <td>removeProvider.{provider name}</td> | |
| 145 | + * <td>Removal of the specified provider</td> | |
| 146 | + * <td>This may change the behavior or disable execution of other | |
| 147 | + * parts of the program. If a provider subsequently requested by the | |
| 148 | + * program has been removed, execution may fail. Also, if the removed | |
| 149 | + * provider is not explicitly requested by the rest of the program, but | |
| 150 | + * it would normally be the provider chosen when a cryptography service | |
| 151 | + * is requested (due to its previous order in the list of providers), | |
| 152 | + * a different provider will be chosen instead, or no suitable provider | |
| 153 | + * will be found, thereby resulting in program failure.</td> | |
| 154 | + * </tr> | |
| 155 | + * | |
| 156 | + * <tr> | |
| 157 | + * <td>clearProviderProperties.{provider name}</td> | |
| 158 | + * <td>"Clearing" of a Provider so that it no longer contains the properties | |
| 159 | + * used to look up services implemented by the provider</td> | |
| 160 | + * <td>This disables the lookup of services implemented by the provider. | |
| 161 | + * This may thus change the behavior or disable execution of other | |
| 162 | + * parts of the program that would normally utilize the Provider, as | |
| 163 | + * described under the "removeProvider.{provider name}" permission.</td> | |
| 164 | + * </tr> | |
| 165 | + * | |
| 166 | + * <tr> | |
| 167 | + * <td>putProviderProperty.{provider name}</td> | |
| 168 | + * <td>Setting of properties for the specified Provider</td> | |
| 169 | + * <td>The provider properties each specify the name and location | |
| 170 | + * of a particular service implemented by the provider. By granting | |
| 171 | + * this permission, you let code replace the service specification | |
| 172 | + * with another one, thereby specifying a different implementation.</td> | |
| 173 | + * </tr> | |
| 174 | + * | |
| 175 | + * <tr> | |
| 176 | + * <td>removeProviderProperty.{provider name}</td> | |
| 177 | + * <td>Removal of properties from the specified Provider</td> | |
| 178 | + * <td>This disables the lookup of services implemented by the | |
| 179 | + * provider. They are no longer accessible due to removal of the properties | |
| 180 | + * specifying their names and locations. This | |
| 181 | + * may change the behavior or disable execution of other | |
| 182 | + * parts of the program that would normally utilize the Provider, as | |
| 183 | + * described under the "removeProvider.{provider name}" permission.</td> | |
| 184 | + * </tr> | |
| 185 | + * | |
| 186 | + * </table> | |
| 187 | + * | |
| 188 | + * <P> | |
| 189 | + * The following permissions are associated with classes that have been | |
| 190 | + * deprecated: {@link Identity}, {@link IdentityScope}, {@link Signer}. Use of | |
| 191 | + * them is discouraged. See the applicable classes for more information. | |
| 192 | + * <P> | |
| 193 | + * | |
| 194 | + * <table border=1 cellpadding=5 summary="target name,what the permission allows, and associated risks"> | |
| 195 | + * <tr> | |
| 196 | + * <th>Permission Target Name</th> | |
| 197 | + * <th>What the Permission Allows</th> | |
| 198 | + * <th>Risks of Allowing this Permission</th> | |
| 199 | + * </tr> | |
| 200 | + * | |
| 201 | + * <tr> | |
| 202 | + * <td>setSystemScope</td> | |
| 203 | + * <td>Setting of the system identity scope</td> | |
| 204 | + * <td>This would allow an attacker to configure the system identity scope with | |
| 205 | + * certificates that should not be trusted, thereby granting applet or | |
| 206 | + * application code signed with those certificates privileges that | |
| 207 | + * would have been denied by the system's original identity scope.</td> | |
| 208 | + * </tr> | |
| 209 | + * | |
| 210 | + * <tr> | |
| 211 | + * <td>setIdentityPublicKey</td> | |
| 212 | + * <td>Setting of the public key for an Identity</td> | |
| 213 | + * <td>If the identity is marked as "trusted", this allows an attacker to | |
| 214 | + * introduce a different public key (e.g., its own) that is not trusted | |
| 215 | + * by the system's identity scope, thereby granting applet or | |
| 216 | + * application code signed with that public key privileges that | |
| 217 | + * would have been denied otherwise.</td> | |
| 218 | + * </tr> | |
| 219 | + * | |
| 220 | + * <tr> | |
| 221 | + * <td>setIdentityInfo</td> | |
| 222 | + * <td>Setting of a general information string for an Identity</td> | |
| 223 | + * <td>This allows attackers to set the general description for | |
| 224 | + * an identity. This may trick applications into using a different | |
| 225 | + * identity than intended or may prevent applications from finding a | |
| 226 | + * particular identity.</td> | |
| 227 | + * </tr> | |
| 228 | + * | |
| 229 | + * <tr> | |
| 230 | + * <td>addIdentityCertificate</td> | |
| 231 | + * <td>Addition of a certificate for an Identity</td> | |
| 232 | + * <td>This allows attackers to set a certificate for | |
| 233 | + * an identity's public key. This is dangerous because it affects | |
| 234 | + * the trust relationship across the system. This public key suddenly | |
| 235 | + * becomes trusted to a wider audience than it otherwise would be.</td> | |
| 236 | + * </tr> | |
| 237 | + * | |
| 238 | + * <tr> | |
| 239 | + * <td>removeIdentityCertificate</td> | |
| 240 | + * <td>Removal of a certificate for an Identity</td> | |
| 241 | + * <td>This allows attackers to remove a certificate for | |
| 242 | + * an identity's public key. This is dangerous because it affects | |
| 243 | + * the trust relationship across the system. This public key suddenly | |
| 244 | + * becomes considered less trustworthy than it otherwise would be.</td> | |
| 245 | + * </tr> | |
| 246 | + * | |
| 247 | + * <tr> | |
| 248 | + * <td>printIdentity</td> | |
| 249 | + * <td>Viewing the name of a principal | |
| 250 | + * and optionally the scope in which it is used, and whether | |
| 251 | + * or not it is considered "trusted" in that scope</td> | |
| 252 | + * <td>The scope that is printed out may be a filename, in which case | |
| 253 | + * it may convey local system information. For example, here's a sample | |
| 254 | + * printout of an identity named "carol", who is | |
| 255 | + * marked not trusted in the user's identity database:<br> | |
| 256 | + * carol[/home/luehe/identitydb.obj][not trusted]</td> | |
| 257 | + *</tr> | |
| 258 | + * | |
| 259 | + * <tr> | |
| 260 | + * <td>getSignerPrivateKey</td> | |
| 261 | + * <td>Retrieval of a Signer's private key</td> | |
| 262 | + * <td>It is very dangerous to allow access to a private key; private | |
| 263 | + * keys are supposed to be kept secret. Otherwise, code can use the | |
| 264 | + * private key to sign various files and claim the signature came from | |
| 265 | + * the Signer.</td> | |
| 266 | + * </tr> | |
| 267 | + * | |
| 268 | + * <tr> | |
| 269 | + * <td>setSignerKeyPair</td> | |
| 270 | + * <td>Setting of the key pair (public key and private key) for a Signer</td> | |
| 271 | + * <td>This would allow an attacker to replace somebody else's (the "target's") | |
| 272 | + * keypair with a possibly weaker keypair (e.g., a keypair of a smaller | |
| 273 | + * keysize). This also would allow the attacker to listen in on encrypted | |
| 274 | + * communication between the target and its peers. The target's peers | |
| 275 | + * might wrap an encryption session key under the target's "new" public | |
| 276 | + * key, which would allow the attacker (who possesses the corresponding | |
| 277 | + * private key) to unwrap the session key and decipher the communication | |
| 278 | + * data encrypted under that session key.</td> | |
| 279 | + * </tr> | |
| 280 | + * | |
| 281 | + * </table> | |
| 282 | + * | |
| 283 | + * @see java.security.BasicPermission | |
| 284 | + * @see java.security.Permission | |
| 285 | + * @see java.security.Permissions | |
| 286 | + * @see java.security.PermissionCollection | |
| 287 | + * @see java.lang.SecurityManager | |
| 288 | + * | |
| 289 | + * | |
| 290 | + * @author Marianne Mueller | |
| 291 | + * @author Roland Schemers | |
| 292 | + */ | |
| 293 | + | |
| 294 | +public final class SecurityPermission extends BasicPermission { | |
| 295 | + | |
| 296 | + private static final long serialVersionUID = 5236109936224050470L; | |
| 297 | + | |
| 298 | + /** | |
| 299 | + * Creates a new SecurityPermission with the specified name. | |
| 300 | + * The name is the symbolic name of the SecurityPermission. An asterisk | |
| 301 | + * may appear at the end of the name, following a ".", or by itself, to | |
| 302 | + * signify a wildcard match. | |
| 303 | + * | |
| 304 | + * @param name the name of the SecurityPermission | |
| 305 | + * | |
| 306 | + * @throws NullPointerException if <code>name</code> is <code>null</code>. | |
| 307 | + * @throws IllegalArgumentException if <code>name</code> is empty. | |
| 308 | + */ | |
| 309 | + | |
| 310 | + public SecurityPermission(String name) | |
| 311 | + { | |
| 312 | + super(name); | |
| 313 | + } | |
| 314 | + | |
| 315 | + /** | |
| 316 | + * Creates a new SecurityPermission object with the specified name. | |
| 317 | + * The name is the symbolic name of the SecurityPermission, and the | |
| 318 | + * actions String is currently unused and should be null. | |
| 319 | + * | |
| 320 | + * @param name the name of the SecurityPermission | |
| 321 | + * @param actions should be null. | |
| 322 | + * | |
| 323 | + * @throws NullPointerException if <code>name</code> is <code>null</code>. | |
| 324 | + * @throws IllegalArgumentException if <code>name</code> is empty. | |
| 325 | + */ | |
| 326 | + | |
| 327 | + public SecurityPermission(String name, String actions) | |
| 328 | + { | |
| 329 | + super(name, actions); | |
| 330 | + } | |
| 331 | +} | |
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,1293 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.security.spec.AlgorithmParameterSpec; | |
| 29 | +import java.util.*; | |
| 30 | +import java.util.concurrent.ConcurrentHashMap; | |
| 31 | +import java.io.*; | |
| 32 | +import java.security.cert.Certificate; | |
| 33 | +import java.security.cert.X509Certificate; | |
| 34 | + | |
| 35 | +import java.nio.ByteBuffer; | |
| 36 | + | |
| 37 | +import java.security.Provider.Service; | |
| 38 | + | |
| 39 | +import javax.crypto.Cipher; | |
| 40 | +import javax.crypto.CipherSpi; | |
| 41 | +import javax.crypto.IllegalBlockSizeException; | |
| 42 | +import javax.crypto.BadPaddingException; | |
| 43 | +import javax.crypto.NoSuchPaddingException; | |
| 44 | + | |
| 45 | +import sun.security.util.Debug; | |
| 46 | +import sun.security.jca.*; | |
| 47 | +import sun.security.jca.GetInstance.Instance; | |
| 48 | + | |
| 49 | +/** | |
| 50 | + * The Signature class is used to provide applications the functionality | |
| 51 | + * of a digital signature algorithm. Digital signatures are used for | |
| 52 | + * authentication and integrity assurance of digital data. | |
| 53 | + * | |
| 54 | + * <p> The signature algorithm can be, among others, the NIST standard | |
| 55 | + * DSA, using DSA and SHA-1. The DSA algorithm using the | |
| 56 | + * SHA-1 message digest algorithm can be specified as <tt>SHA1withDSA</tt>. | |
| 57 | + * In the case of RSA, there are multiple choices for the message digest | |
| 58 | + * algorithm, so the signing algorithm could be specified as, for example, | |
| 59 | + * <tt>MD2withRSA</tt>, <tt>MD5withRSA</tt>, or <tt>SHA1withRSA</tt>. | |
| 60 | + * The algorithm name must be specified, as there is no default. | |
| 61 | + * | |
| 62 | + * <p> A Signature object can be used to generate and verify digital | |
| 63 | + * signatures. | |
| 64 | + * | |
| 65 | + * <p> There are three phases to the use of a Signature object for | |
| 66 | + * either signing data or verifying a signature:<ol> | |
| 67 | + * | |
| 68 | + * <li>Initialization, with either | |
| 69 | + * | |
| 70 | + * <ul> | |
| 71 | + * | |
| 72 | + * <li>a public key, which initializes the signature for | |
| 73 | + * verification (see {@link #initVerify(PublicKey) initVerify}), or | |
| 74 | + * | |
| 75 | + * <li>a private key (and optionally a Secure Random Number Generator), | |
| 76 | + * which initializes the signature for signing | |
| 77 | + * (see {@link #initSign(PrivateKey)} | |
| 78 | + * and {@link #initSign(PrivateKey, SecureRandom)}). | |
| 79 | + * | |
| 80 | + * </ul><p> | |
| 81 | + * | |
| 82 | + * <li>Updating<p> | |
| 83 | + * | |
| 84 | + * <p>Depending on the type of initialization, this will update the | |
| 85 | + * bytes to be signed or verified. See the | |
| 86 | + * {@link #update(byte) update} methods.<p> | |
| 87 | + * | |
| 88 | + * <li>Signing or Verifying a signature on all updated bytes. See the | |
| 89 | + * {@link #sign() sign} methods and the {@link #verify(byte[]) verify} | |
| 90 | + * method. | |
| 91 | + * | |
| 92 | + * </ol> | |
| 93 | + * | |
| 94 | + * <p>Note that this class is abstract and extends from | |
| 95 | + * <code>SignatureSpi</code> for historical reasons. | |
| 96 | + * Application developers should only take notice of the methods defined in | |
| 97 | + * this <code>Signature</code> class; all the methods in | |
| 98 | + * the superclass are intended for cryptographic service providers who wish to | |
| 99 | + * supply their own implementations of digital signature algorithms. | |
| 100 | + * | |
| 101 | + * <p> Every implementation of the Java platform is required to support the | |
| 102 | + * following standard <code>Signature</code> algorithms: | |
| 103 | + * <ul> | |
| 104 | + * <li><tt>SHA1withDSA</tt></li> | |
| 105 | + * <li><tt>SHA1withRSA</tt></li> | |
| 106 | + * <li><tt>SHA256withRSA</tt></li> | |
| 107 | + * </ul> | |
| 108 | + * These algorithms are described in the <a href= | |
| 109 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> | |
| 110 | + * Signature section</a> of the | |
| 111 | + * Java Cryptography Architecture Standard Algorithm Name Documentation. | |
| 112 | + * Consult the release documentation for your implementation to see if any | |
| 113 | + * other algorithms are supported. | |
| 114 | + * | |
| 115 | + * @author Benjamin Renaud | |
| 116 | + * | |
| 117 | + */ | |
| 118 | + | |
| 119 | +public abstract class Signature extends SignatureSpi { | |
| 120 | + | |
| 121 | + private static final Debug debug = | |
| 122 | + Debug.getInstance("jca", "Signature"); | |
| 123 | + | |
| 124 | + /* | |
| 125 | + * The algorithm for this signature object. | |
| 126 | + * This value is used to map an OID to the particular algorithm. | |
| 127 | + * The mapping is done in AlgorithmObject.algOID(String algorithm) | |
| 128 | + */ | |
| 129 | + private String algorithm; | |
| 130 | + | |
| 131 | + // The provider | |
| 132 | + Provider provider; | |
| 133 | + | |
| 134 | + /** | |
| 135 | + * Possible {@link #state} value, signifying that | |
| 136 | + * this signature object has not yet been initialized. | |
| 137 | + */ | |
| 138 | + protected final static int UNINITIALIZED = 0; | |
| 139 | + | |
| 140 | + /** | |
| 141 | + * Possible {@link #state} value, signifying that | |
| 142 | + * this signature object has been initialized for signing. | |
| 143 | + */ | |
| 144 | + protected final static int SIGN = 2; | |
| 145 | + | |
| 146 | + /** | |
| 147 | + * Possible {@link #state} value, signifying that | |
| 148 | + * this signature object has been initialized for verification. | |
| 149 | + */ | |
| 150 | + protected final static int VERIFY = 3; | |
| 151 | + | |
| 152 | + /** | |
| 153 | + * Current state of this signature object. | |
| 154 | + */ | |
| 155 | + protected int state = UNINITIALIZED; | |
| 156 | + | |
| 157 | + /** | |
| 158 | + * Creates a Signature object for the specified algorithm. | |
| 159 | + * | |
| 160 | + * @param algorithm the standard string name of the algorithm. | |
| 161 | + * See the Signature section in the <a href= | |
| 162 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> | |
| 163 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 164 | + * for information about standard algorithm names. | |
| 165 | + */ | |
| 166 | + protected Signature(String algorithm) { | |
| 167 | + this.algorithm = algorithm; | |
| 168 | + } | |
| 169 | + | |
| 170 | + // name of the special signature alg | |
| 171 | + private final static String RSA_SIGNATURE = "NONEwithRSA"; | |
| 172 | + | |
| 173 | + // name of the equivalent cipher alg | |
| 174 | + private final static String RSA_CIPHER = "RSA/ECB/PKCS1Padding"; | |
| 175 | + | |
| 176 | + // all the services we need to lookup for compatibility with Cipher | |
| 177 | + private final static List<ServiceId> rsaIds = Arrays.asList( | |
| 178 | + new ServiceId[] { | |
| 179 | + new ServiceId("Signature", "NONEwithRSA"), | |
| 180 | + new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"), | |
| 181 | + new ServiceId("Cipher", "RSA/ECB"), | |
| 182 | + new ServiceId("Cipher", "RSA//PKCS1Padding"), | |
| 183 | + new ServiceId("Cipher", "RSA"), | |
| 184 | + } | |
| 185 | + ); | |
| 186 | + | |
| 187 | + /** | |
| 188 | + * Returns a Signature object that implements the specified signature | |
| 189 | + * algorithm. | |
| 190 | + * | |
| 191 | + * <p> This method traverses the list of registered security Providers, | |
| 192 | + * starting with the most preferred Provider. | |
| 193 | + * A new Signature object encapsulating the | |
| 194 | + * SignatureSpi implementation from the first | |
| 195 | + * Provider that supports the specified algorithm is returned. | |
| 196 | + * | |
| 197 | + * <p> Note that the list of registered providers may be retrieved via | |
| 198 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 199 | + * | |
| 200 | + * @param algorithm the standard name of the algorithm requested. | |
| 201 | + * See the Signature section in the <a href= | |
| 202 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> | |
| 203 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 204 | + * for information about standard algorithm names. | |
| 205 | + * | |
| 206 | + * @return the new Signature object. | |
| 207 | + * | |
| 208 | + * @exception NoSuchAlgorithmException if no Provider supports a | |
| 209 | + * Signature implementation for the | |
| 210 | + * specified algorithm. | |
| 211 | + * | |
| 212 | + * @see Provider | |
| 213 | + */ | |
| 214 | + public static Signature getInstance(String algorithm) | |
| 215 | + throws NoSuchAlgorithmException { | |
| 216 | + List<Service> list; | |
| 217 | + if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { | |
| 218 | + list = GetInstance.getServices(rsaIds); | |
| 219 | + } else { | |
| 220 | + list = GetInstance.getServices("Signature", algorithm); | |
| 221 | + } | |
| 222 | + Iterator<Service> t = list.iterator(); | |
| 223 | + if (t.hasNext() == false) { | |
| 224 | + throw new NoSuchAlgorithmException | |
| 225 | + (algorithm + " Signature not available"); | |
| 226 | + } | |
| 227 | + // try services until we find an Spi or a working Signature subclass | |
| 228 | + NoSuchAlgorithmException failure; | |
| 229 | + do { | |
| 230 | + Service s = t.next(); | |
| 231 | + if (isSpi(s)) { | |
| 232 | + return new Delegate(s, t, algorithm); | |
| 233 | + } else { | |
| 234 | + // must be a subclass of Signature, disable dynamic selection | |
| 235 | + try { | |
| 236 | + Instance instance = | |
| 237 | + GetInstance.getInstance(s, SignatureSpi.class); | |
| 238 | + return getInstance(instance, algorithm); | |
| 239 | + } catch (NoSuchAlgorithmException e) { | |
| 240 | + failure = e; | |
| 241 | + } | |
| 242 | + } | |
| 243 | + } while (t.hasNext()); | |
| 244 | + throw failure; | |
| 245 | + } | |
| 246 | + | |
| 247 | + private static Signature getInstance(Instance instance, String algorithm) { | |
| 248 | + Signature sig; | |
| 249 | + if (instance.impl instanceof Signature) { | |
| 250 | + sig = (Signature)instance.impl; | |
| 251 | + } else { | |
| 252 | + SignatureSpi spi = (SignatureSpi)instance.impl; | |
| 253 | + sig = new Delegate(spi, algorithm); | |
| 254 | + } | |
| 255 | + sig.provider = instance.provider; | |
| 256 | + return sig; | |
| 257 | + } | |
| 258 | + | |
| 259 | + private final static Map<String,Boolean> signatureInfo; | |
| 260 | + | |
| 261 | + static { | |
| 262 | + signatureInfo = new ConcurrentHashMap<String,Boolean>(); | |
| 263 | + Boolean TRUE = Boolean.TRUE; | |
| 264 | + // pre-initialize with values for our SignatureSpi implementations | |
| 265 | + signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE); | |
| 266 | + signatureInfo.put("sun.security.provider.DSA$SHA1withDSA", TRUE); | |
| 267 | + signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA", TRUE); | |
| 268 | + signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA", TRUE); | |
| 269 | + signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA", TRUE); | |
| 270 | + signatureInfo.put("sun.security.rsa.RSASignature$SHA256withRSA", TRUE); | |
| 271 | + signatureInfo.put("sun.security.rsa.RSASignature$SHA384withRSA", TRUE); | |
| 272 | + signatureInfo.put("sun.security.rsa.RSASignature$SHA512withRSA", TRUE); | |
| 273 | + signatureInfo.put("com.sun.net.ssl.internal.ssl.RSASignature", TRUE); | |
| 274 | + signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE); | |
| 275 | + } | |
| 276 | + | |
| 277 | + private static boolean isSpi(Service s) { | |
| 278 | + if (s.getType().equals("Cipher")) { | |
| 279 | + // must be a CipherSpi, which we can wrap with the CipherAdapter | |
| 280 | + return true; | |
| 281 | + } | |
| 282 | + String className = s.getClassName(); | |
| 283 | + Boolean result = signatureInfo.get(className); | |
| 284 | + if (result == null) { | |
| 285 | + try { | |
| 286 | + Object instance = s.newInstance(null); | |
| 287 | + // Signature extends SignatureSpi | |
| 288 | + // so it is a "real" Spi if it is an | |
| 289 | + // instance of SignatureSpi but not Signature | |
| 290 | + boolean r = (instance instanceof SignatureSpi) | |
| 291 | + && (instance instanceof Signature == false); | |
| 292 | + if ((debug != null) && (r == false)) { | |
| 293 | + debug.println("Not a SignatureSpi " + className); | |
| 294 | + debug.println("Delayed provider selection may not be " | |
| 295 | + + "available for algorithm " + s.getAlgorithm()); | |
| 296 | + } | |
| 297 | + result = Boolean.valueOf(r); | |
| 298 | + signatureInfo.put(className, result); | |
| 299 | + } catch (Exception e) { | |
| 300 | + // something is wrong, assume not an SPI | |
| 301 | + return false; | |
| 302 | + } | |
| 303 | + } | |
| 304 | + return result.booleanValue(); | |
| 305 | + } | |
| 306 | + | |
| 307 | + /** | |
| 308 | + * Returns a Signature object that implements the specified signature | |
| 309 | + * algorithm. | |
| 310 | + * | |
| 311 | + * <p> A new Signature object encapsulating the | |
| 312 | + * SignatureSpi implementation from the specified provider | |
| 313 | + * is returned. The specified provider must be registered | |
| 314 | + * in the security provider list. | |
| 315 | + * | |
| 316 | + * <p> Note that the list of registered providers may be retrieved via | |
| 317 | + * the {@link Security#getProviders() Security.getProviders()} method. | |
| 318 | + * | |
| 319 | + * @param algorithm the name of the algorithm requested. | |
| 320 | + * See the Signature section in the <a href= | |
| 321 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> | |
| 322 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 323 | + * for information about standard algorithm names. | |
| 324 | + * | |
| 325 | + * @param provider the name of the provider. | |
| 326 | + * | |
| 327 | + * @return the new Signature object. | |
| 328 | + * | |
| 329 | + * @exception NoSuchAlgorithmException if a SignatureSpi | |
| 330 | + * implementation for the specified algorithm is not | |
| 331 | + * available from the specified provider. | |
| 332 | + * | |
| 333 | + * @exception NoSuchProviderException if the specified provider is not | |
| 334 | + * registered in the security provider list. | |
| 335 | + * | |
| 336 | + * @exception IllegalArgumentException if the provider name is null | |
| 337 | + * or empty. | |
| 338 | + * | |
| 339 | + * @see Provider | |
| 340 | + */ | |
| 341 | + public static Signature getInstance(String algorithm, String provider) | |
| 342 | + throws NoSuchAlgorithmException, NoSuchProviderException { | |
| 343 | + if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { | |
| 344 | + // exception compatibility with existing code | |
| 345 | + if ((provider == null) || (provider.length() == 0)) { | |
| 346 | + throw new IllegalArgumentException("missing provider"); | |
| 347 | + } | |
| 348 | + Provider p = Security.getProvider(provider); | |
| 349 | + if (p == null) { | |
| 350 | + throw new NoSuchProviderException | |
| 351 | + ("no such provider: " + provider); | |
| 352 | + } | |
| 353 | + return getInstanceRSA(p); | |
| 354 | + } | |
| 355 | + Instance instance = GetInstance.getInstance | |
| 356 | + ("Signature", SignatureSpi.class, algorithm, provider); | |
| 357 | + return getInstance(instance, algorithm); | |
| 358 | + } | |
| 359 | + | |
| 360 | + /** | |
| 361 | + * Returns a Signature object that implements the specified | |
| 362 | + * signature algorithm. | |
| 363 | + * | |
| 364 | + * <p> A new Signature object encapsulating the | |
| 365 | + * SignatureSpi implementation from the specified Provider | |
| 366 | + * object is returned. Note that the specified Provider object | |
| 367 | + * does not have to be registered in the provider list. | |
| 368 | + * | |
| 369 | + * @param algorithm the name of the algorithm requested. | |
| 370 | + * See the Signature section in the <a href= | |
| 371 | + * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> | |
| 372 | + * Java Cryptography Architecture Standard Algorithm Name Documentation</a> | |
| 373 | + * for information about standard algorithm names. | |
| 374 | + * | |
| 375 | + * @param provider the provider. | |
| 376 | + * | |
| 377 | + * @return the new Signature object. | |
| 378 | + * | |
| 379 | + * @exception NoSuchAlgorithmException if a SignatureSpi | |
| 380 | + * implementation for the specified algorithm is not available | |
| 381 | + * from the specified Provider object. | |
| 382 | + * | |
| 383 | + * @exception IllegalArgumentException if the provider is null. | |
| 384 | + * | |
| 385 | + * @see Provider | |
| 386 | + * | |
| 387 | + * @since 1.4 | |
| 388 | + */ | |
| 389 | + public static Signature getInstance(String algorithm, Provider provider) | |
| 390 | + throws NoSuchAlgorithmException { | |
| 391 | + if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { | |
| 392 | + // exception compatibility with existing code | |
| 393 | + if (provider == null) { | |
| 394 | + throw new IllegalArgumentException("missing provider"); | |
| 395 | + } | |
| 396 | + return getInstanceRSA(provider); | |
| 397 | + } | |
| 398 | + Instance instance = GetInstance.getInstance | |
| 399 | + ("Signature", SignatureSpi.class, algorithm, provider); | |
| 400 | + return getInstance(instance, algorithm); | |
| 401 | + } | |
| 402 | + | |
| 403 | + // return an implementation for NONEwithRSA, which is a special case | |
| 404 | + // because of the Cipher.RSA/ECB/PKCS1Padding compatibility wrapper | |
| 405 | + private static Signature getInstanceRSA(Provider p) | |
| 406 | + throws NoSuchAlgorithmException { | |
| 407 | + // try Signature first | |
| 408 | + Service s = p.getService("Signature", RSA_SIGNATURE); | |
| 409 | + if (s != null) { | |
| 410 | + Instance instance = GetInstance.getInstance(s, SignatureSpi.class); | |
| 411 | + return getInstance(instance, RSA_SIGNATURE); | |
| 412 | + } | |
| 413 | + // check Cipher | |
| 414 | + try { | |
| 415 | + Cipher c = Cipher.getInstance(RSA_CIPHER, p); | |
| 416 | + return new Delegate(new CipherAdapter(c), RSA_SIGNATURE); | |
| 417 | + } catch (GeneralSecurityException e) { | |
| 418 | + // throw Signature style exception message to avoid confusion, | |
| 419 | + // but append Cipher exception as cause | |
| 420 | + throw new NoSuchAlgorithmException("no such algorithm: " | |
| 421 | + + RSA_SIGNATURE + " for provider " + p.getName(), e); | |
| 422 | + } | |
| 423 | + } | |
| 424 | + | |
| 425 | + /** | |
| 426 | + * Returns the provider of this signature object. | |
| 427 | + * | |
| 428 | + * @return the provider of this signature object | |
| 429 | + */ | |
| 430 | + public final Provider getProvider() { | |
| 431 | + chooseFirstProvider(); | |
| 432 | + return this.provider; | |
| 433 | + } | |
| 434 | + | |
| 435 | + void chooseFirstProvider() { | |
| 436 | + // empty, overridden in Delegate | |
| 437 | + } | |
| 438 | + | |
| 439 | + /** | |
| 440 | + * Initializes this object for verification. If this method is called | |
| 441 | + * again with a different argument, it negates the effect | |
| 442 | + * of this call. | |
| 443 | + * | |
| 444 | + * @param publicKey the public key of the identity whose signature is | |
| 445 | + * going to be verified. | |
| 446 | + * | |
| 447 | + * @exception InvalidKeyException if the key is invalid. | |
| 448 | + */ | |
| 449 | + public final void initVerify(PublicKey publicKey) | |
| 450 | + throws InvalidKeyException { | |
| 451 | + engineInitVerify(publicKey); | |
| 452 | + state = VERIFY; | |
| 453 | + } | |
| 454 | + | |
| 455 | + /** | |
| 456 | + * Initializes this object for verification, using the public key from | |
| 457 | + * the given certificate. | |
| 458 | + * <p>If the certificate is of type X.509 and has a <i>key usage</i> | |
| 459 | + * extension field marked as critical, and the value of the <i>key usage</i> | |
| 460 | + * extension field implies that the public key in | |
| 461 | + * the certificate and its corresponding private key are not | |
| 462 | + * supposed to be used for digital signatures, an | |
| 463 | + * <code>InvalidKeyException</code> is thrown. | |
| 464 | + * | |
| 465 | + * @param certificate the certificate of the identity whose signature is | |
| 466 | + * going to be verified. | |
| 467 | + * | |
| 468 | + * @exception InvalidKeyException if the public key in the certificate | |
| 469 | + * is not encoded properly or does not include required parameter | |
| 470 | + * information or cannot be used for digital signature purposes. | |
| 471 | + * @since 1.3 | |
| 472 | + */ | |
| 473 | + public final void initVerify(Certificate certificate) | |
| 474 | + throws InvalidKeyException { | |
| 475 | + // If the certificate is of type X509Certificate, | |
| 476 | + // we should check whether it has a Key Usage | |
| 477 | + // extension marked as critical. | |
| 478 | + if (certificate instanceof java.security.cert.X509Certificate) { | |
| 479 | + // Check whether the cert has a key usage extension | |
| 480 | + // marked as a critical extension. | |
| 481 | + // The OID for KeyUsage extension is 2.5.29.15. | |
| 482 | + X509Certificate cert = (X509Certificate)certificate; | |
| 483 | + Set<String> critSet = cert.getCriticalExtensionOIDs(); | |
| 484 | + | |
| 485 | + if (critSet != null && !critSet.isEmpty() | |
| 486 | + && critSet.contains("2.5.29.15")) { | |
| 487 | + boolean[] keyUsageInfo = cert.getKeyUsage(); | |
| 488 | + // keyUsageInfo[0] is for digitalSignature. | |
| 489 | + if ((keyUsageInfo != null) && (keyUsageInfo[0] == false)) | |
| 490 | + throw new InvalidKeyException("Wrong key usage"); | |
| 491 | + } | |
| 492 | + } | |
| 493 | + | |
| 494 | + PublicKey publicKey = certificate.getPublicKey(); | |
| 495 | + engineInitVerify(publicKey); | |
| 496 | + state = VERIFY; | |
| 497 | + } | |
| 498 | + | |
| 499 | + /** | |
| 500 | + * Initialize this object for signing. If this method is called | |
| 501 | + * again with a different argument, it negates the effect | |
| 502 | + * of this call. | |
| 503 | + * | |
| 504 | + * @param privateKey the private key of the identity whose signature | |
| 505 | + * is going to be generated. | |
| 506 | + * | |
| 507 | + * @exception InvalidKeyException if the key is invalid. | |
| 508 | + */ | |
| 509 | + public final void initSign(PrivateKey privateKey) | |
| 510 | + throws InvalidKeyException { | |
| 511 | + engineInitSign(privateKey); | |
| 512 | + state = SIGN; | |
| 513 | + } | |
| 514 | + | |
| 515 | + /** | |
| 516 | + * Initialize this object for signing. If this method is called | |
| 517 | + * again with a different argument, it negates the effect | |
| 518 | + * of this call. | |
| 519 | + * | |
| 520 | + * @param privateKey the private key of the identity whose signature | |
| 521 | + * is going to be generated. | |
| 522 | + * | |
| 523 | + * @param random the source of randomness for this signature. | |
| 524 | + * | |
| 525 | + * @exception InvalidKeyException if the key is invalid. | |
| 526 | + */ | |
| 527 | + public final void initSign(PrivateKey privateKey, SecureRandom random) | |
| 528 | + throws InvalidKeyException { | |
| 529 | + engineInitSign(privateKey, random); | |
| 530 | + state = SIGN; | |
| 531 | + } | |
| 532 | + | |
| 533 | + /** | |
| 534 | + * Returns the signature bytes of all the data updated. | |
| 535 | + * The format of the signature depends on the underlying | |
| 536 | + * signature scheme. | |
| 537 | + * | |
| 538 | + * <p>A call to this method resets this signature object to the state | |
| 539 | + * it was in when previously initialized for signing via a | |
| 540 | + * call to <code>initSign(PrivateKey)</code>. That is, the object is | |
| 541 | + * reset and available to generate another signature from the same | |
| 542 | + * signer, if desired, via new calls to <code>update</code> and | |
| 543 | + * <code>sign</code>. | |
| 544 | + * | |
| 545 | + * @return the signature bytes of the signing operation's result. | |
| 546 | + * | |
| 547 | + * @exception SignatureException if this signature object is not | |
| 548 | + * initialized properly or if this signature algorithm is unable to | |
| 549 | + * process the input data provided. | |
| 550 | + */ | |
| 551 | + public final byte[] sign() throws SignatureException { | |
| 552 | + if (state == SIGN) { | |
| 553 | + return engineSign(); | |
| 554 | + } | |
| 555 | + throw new SignatureException("object not initialized for " + | |
| 556 | + "signing"); | |
| 557 | + } | |
| 558 | + | |
| 559 | + /** | |
| 560 | + * Finishes the signature operation and stores the resulting signature | |
| 561 | + * bytes in the provided buffer <code>outbuf</code>, starting at | |
| 562 | + * <code>offset</code>. | |
| 563 | + * The format of the signature depends on the underlying | |
| 564 | + * signature scheme. | |
| 565 | + * | |
| 566 | + * <p>This signature object is reset to its initial state (the state it | |
| 567 | + * was in after a call to one of the <code>initSign</code> methods) and | |
| 568 | + * can be reused to generate further signatures with the same private key. | |
| 569 | + * | |
| 570 | + * @param outbuf buffer for the signature result. | |
| 571 | + * | |
| 572 | + * @param offset offset into <code>outbuf</code> where the signature is | |
| 573 | + * stored. | |
| 574 | + * | |
| 575 | + * @param len number of bytes within <code>outbuf</code> allotted for the | |
| 576 | + * signature. | |
| 577 | + * | |
| 578 | + * @return the number of bytes placed into <code>outbuf</code>. | |
| 579 | + * | |
| 580 | + * @exception SignatureException if this signature object is not | |
| 581 | + * initialized properly, if this signature algorithm is unable to | |
| 582 | + * process the input data provided, or if <code>len</code> is less | |
| 583 | + * than the actual signature length. | |
| 584 | + * | |
| 585 | + * @since 1.2 | |
| 586 | + */ | |
| 587 | + public final int sign(byte[] outbuf, int offset, int len) | |
| 588 | + throws SignatureException { | |
| 589 | + if (outbuf == null) { | |
| 590 | + throw new IllegalArgumentException("No output buffer given"); | |
| 591 | + } | |
| 592 | + if (outbuf.length - offset < len) { | |
| 593 | + throw new IllegalArgumentException | |
| 594 | + ("Output buffer too small for specified offset and length"); | |
| 595 | + } | |
| 596 | + if (state != SIGN) { | |
| 597 | + throw new SignatureException("object not initialized for " + | |
| 598 | + "signing"); | |
| 599 | + } | |
| 600 | + return engineSign(outbuf, offset, len); | |
| 601 | + } | |
| 602 | + | |
| 603 | + /** | |
| 604 | + * Verifies the passed-in signature. | |
| 605 | + * | |
| 606 | + * <p>A call to this method resets this signature object to the state | |
| 607 | + * it was in when previously initialized for verification via a | |
| 608 | + * call to <code>initVerify(PublicKey)</code>. That is, the object is | |
| 609 | + * reset and available to verify another signature from the identity | |
| 610 | + * whose public key was specified in the call to <code>initVerify</code>. | |
| 611 | + * | |
| 612 | + * @param signature the signature bytes to be verified. | |
| 613 | + * | |
| 614 | + * @return true if the signature was verified, false if not. | |
| 615 | + * | |
| 616 | + * @exception SignatureException if this signature object is not | |
| 617 | + * initialized properly, the passed-in signature is improperly | |
| 618 | + * encoded or of the wrong type, if this signature algorithm is unable to | |
| 619 | + * process the input data provided, etc. | |
| 620 | + */ | |
| 621 | + public final boolean verify(byte[] signature) throws SignatureException { | |
| 622 | + if (state == VERIFY) { | |
| 623 | + return engineVerify(signature); | |
| 624 | + } | |
| 625 | + throw new SignatureException("object not initialized for " + | |
| 626 | + "verification"); | |
| 627 | + } | |
| 628 | + | |
| 629 | + /** | |
| 630 | + * Verifies the passed-in signature in the specified array | |
| 631 | + * of bytes, starting at the specified offset. | |
| 632 | + * | |
| 633 | + * <p>A call to this method resets this signature object to the state | |
| 634 | + * it was in when previously initialized for verification via a | |
| 635 | + * call to <code>initVerify(PublicKey)</code>. That is, the object is | |
| 636 | + * reset and available to verify another signature from the identity | |
| 637 | + * whose public key was specified in the call to <code>initVerify</code>. | |
| 638 | + * | |
| 639 | + * | |
| 640 | + * @param signature the signature bytes to be verified. | |
| 641 | + * @param offset the offset to start from in the array of bytes. | |
| 642 | + * @param length the number of bytes to use, starting at offset. | |
| 643 | + * | |
| 644 | + * @return true if the signature was verified, false if not. | |
| 645 | + * | |
| 646 | + * @exception SignatureException if this signature object is not | |
| 647 | + * initialized properly, the passed-in signature is improperly | |
| 648 | + * encoded or of the wrong type, if this signature algorithm is unable to | |
| 649 | + * process the input data provided, etc. | |
| 650 | + * @exception IllegalArgumentException if the <code>signature</code> | |
| 651 | + * byte array is null, or the <code>offset</code> or <code>length</code> | |
| 652 | + * is less than 0, or the sum of the <code>offset</code> and | |
| 653 | + * <code>length</code> is greater than the length of the | |
| 654 | + * <code>signature</code> byte array. | |
| 655 | + * @since 1.4 | |
| 656 | + */ | |
| 657 | + public final boolean verify(byte[] signature, int offset, int length) | |
| 658 | + throws SignatureException { | |
| 659 | + if (state == VERIFY) { | |
| 660 | + if ((signature == null) || (offset < 0) || (length < 0) || | |
| 661 | + (offset + length > signature.length)) { | |
| 662 | + throw new IllegalArgumentException("Bad arguments"); | |
| 663 | + } | |
| 664 | + | |
| 665 | + return engineVerify(signature, offset, length); | |
| 666 | + } | |
| 667 | + throw new SignatureException("object not initialized for " + | |
| 668 | + "verification"); | |
| 669 | + } | |
| 670 | + | |
| 671 | + /** | |
| 672 | + * Updates the data to be signed or verified by a byte. | |
| 673 | + * | |
| 674 | + * @param b the byte to use for the update. | |
| 675 | + * | |
| 676 | + * @exception SignatureException if this signature object is not | |
| 677 | + * initialized properly. | |
| 678 | + */ | |
| 679 | + public final void update(byte b) throws SignatureException { | |
| 680 | + if (state == VERIFY || state == SIGN) { | |
| 681 | + engineUpdate(b); | |
| 682 | + } else { | |
| 683 | + throw new SignatureException("object not initialized for " | |
| 684 | + + "signature or verification"); | |
| 685 | + } | |
| 686 | + } | |
| 687 | + | |
| 688 | + /** | |
| 689 | + * Updates the data to be signed or verified, using the specified | |
| 690 | + * array of bytes. | |
| 691 | + * | |
| 692 | + * @param data the byte array to use for the update. | |
| 693 | + * | |
| 694 | + * @exception SignatureException if this signature object is not | |
| 695 | + * initialized properly. | |
| 696 | + */ | |
| 697 | + public final void update(byte[] data) throws SignatureException { | |
| 698 | + update(data, 0, data.length); | |
| 699 | + } | |
| 700 | + | |
| 701 | + /** | |
| 702 | + * Updates the data to be signed or verified, using the specified | |
| 703 | + * array of bytes, starting at the specified offset. | |
| 704 | + * | |
| 705 | + * @param data the array of bytes. | |
| 706 | + * @param off the offset to start from in the array of bytes. | |
| 707 | + * @param len the number of bytes to use, starting at offset. | |
| 708 | + * | |
| 709 | + * @exception SignatureException if this signature object is not | |
| 710 | + * initialized properly. | |
| 711 | + */ | |
| 712 | + public final void update(byte[] data, int off, int len) | |
| 713 | + throws SignatureException { | |
| 714 | + if (state == SIGN || state == VERIFY) { | |
| 715 | + engineUpdate(data, off, len); | |
| 716 | + } else { | |
| 717 | + throw new SignatureException("object not initialized for " | |
| 718 | + + "signature or verification"); | |
| 719 | + } | |
| 720 | + } | |
| 721 | + | |
| 722 | + /** | |
| 723 | + * Updates the data to be signed or verified using the specified | |
| 724 | + * ByteBuffer. Processes the <code>data.remaining()</code> bytes | |
| 725 | + * starting at at <code>data.position()</code>. | |
| 726 | + * Upon return, the buffer's position will be equal to its limit; | |
| 727 | + * its limit will not have changed. | |
| 728 | + * | |
| 729 | + * @param data the ByteBuffer | |
| 730 | + * | |
| 731 | + * @exception SignatureException if this signature object is not | |
| 732 | + * initialized properly. | |
| 733 | + * @since 1.5 | |
| 734 | + */ | |
| 735 | + public final void update(ByteBuffer data) throws SignatureException { | |
| 736 | + if ((state != SIGN) && (state != VERIFY)) { | |
| 737 | + throw new SignatureException("object not initialized for " | |
| 738 | + + "signature or verification"); | |
| 739 | + } | |
| 740 | + if (data == null) { | |
| 741 | + throw new NullPointerException(); | |
| 742 | + } | |
| 743 | + engineUpdate(data); | |
| 744 | + } | |
| 745 | + | |
| 746 | + /** | |
| 747 | + * Returns the name of the algorithm for this signature object. | |
| 748 | + * | |
| 749 | + * @return the name of the algorithm for this signature object. | |
| 750 | + */ | |
| 751 | + public final String getAlgorithm() { | |
| 752 | + return this.algorithm; | |
| 753 | + } | |
| 754 | + | |
| 755 | + /** | |
| 756 | + * Returns a string representation of this signature object, | |
| 757 | + * providing information that includes the state of the object | |
| 758 | + * and the name of the algorithm used. | |
| 759 | + * | |
| 760 | + * @return a string representation of this signature object. | |
| 761 | + */ | |
| 762 | + public String toString() { | |
| 763 | + String initState = ""; | |
| 764 | + switch (state) { | |
| 765 | + case UNINITIALIZED: | |
| 766 | + initState = "<not initialized>"; | |
| 767 | + break; | |
| 768 | + case VERIFY: | |
| 769 | + initState = "<initialized for verifying>"; | |
| 770 | + break; | |
| 771 | + case SIGN: | |
| 772 | + initState = "<initialized for signing>"; | |
| 773 | + break; | |
| 774 | + } | |
| 775 | + return "Signature object: " + getAlgorithm() + initState; | |
| 776 | + } | |
| 777 | + | |
| 778 | + /** | |
| 779 | + * Sets the specified algorithm parameter to the specified value. | |
| 780 | + * This method supplies a general-purpose mechanism through | |
| 781 | + * which it is possible to set the various parameters of this object. | |
| 782 | + * A parameter may be any settable parameter for the algorithm, such as | |
| 783 | + * a parameter size, or a source of random bits for signature generation | |
| 784 | + * (if appropriate), or an indication of whether or not to perform | |
| 785 | + * a specific but optional computation. A uniform algorithm-specific | |
| 786 | + * naming scheme for each parameter is desirable but left unspecified | |
| 787 | + * at this time. | |
| 788 | + * | |
| 789 | + * @param param the string identifier of the parameter. | |
| 790 | + * @param value the parameter value. | |
| 791 | + * | |
| 792 | + * @exception InvalidParameterException if <code>param</code> is an | |
| 793 | + * invalid parameter for this signature algorithm engine, | |
| 794 | + * the parameter is already set | |
| 795 | + * and cannot be set again, a security exception occurs, and so on. | |
| 796 | + * | |
| 797 | + * @see #getParameter | |
| 798 | + * | |
| 799 | + * @deprecated Use | |
| 800 | + * {@link #setParameter(java.security.spec.AlgorithmParameterSpec) | |
| 801 | + * setParameter}. | |
| 802 | + */ | |
| 803 | + @Deprecated | |
| 804 | + public final void setParameter(String param, Object value) | |
| 805 | + throws InvalidParameterException { | |
| 806 | + engineSetParameter(param, value); | |
| 807 | + } | |
| 808 | + | |
| 809 | + /** | |
| 810 | + * Initializes this signature engine with the specified parameter set. | |
| 811 | + * | |
| 812 | + * @param params the parameters | |
| 813 | + * | |
| 814 | + * @exception InvalidAlgorithmParameterException if the given parameters | |
| 815 | + * are inappropriate for this signature engine | |
| 816 | + * | |
| 817 | + * @see #getParameters | |
| 818 | + */ | |
| 819 | + public final void setParameter(AlgorithmParameterSpec params) | |
| 820 | + throws InvalidAlgorithmParameterException { | |
| 821 | + engineSetParameter(params); | |
| 822 | + } | |
| 823 | + | |
| 824 | + /** | |
| 825 | + * Returns the parameters used with this signature object. | |
| 826 | + * | |
| 827 | + * <p>The returned parameters may be the same that were used to initialize | |
| 828 | + * this signature, or may contain a combination of default and randomly | |
| 829 | + * generated parameter values used by the underlying signature | |
| 830 | + * implementation if this signature requires algorithm parameters but | |
| 831 | + * was not initialized with any. | |
| 832 | + * | |
| 833 | + * @return the parameters used with this signature, or null if this | |
| 834 | + * signature does not use any parameters. | |
| 835 | + * | |
| 836 | + * @see #setParameter(AlgorithmParameterSpec) | |
| 837 | + * @since 1.4 | |
| 838 | + */ | |
| 839 | + public final AlgorithmParameters getParameters() { | |
| 840 | + return engineGetParameters(); | |
| 841 | + } | |
| 842 | + | |
| 843 | + /** | |
| 844 | + * Gets the value of the specified algorithm parameter. This method | |
| 845 | + * supplies a general-purpose mechanism through which it is possible to | |
| 846 | + * get the various parameters of this object. A parameter may be any | |
| 847 | + * settable parameter for the algorithm, such as a parameter size, or | |
| 848 | + * a source of random bits for signature generation (if appropriate), | |
| 849 | + * or an indication of whether or not to perform a specific but optional | |
| 850 | + * computation. A uniform algorithm-specific naming scheme for each | |
| 851 | + * parameter is desirable but left unspecified at this time. | |
| 852 | + * | |
| 853 | + * @param param the string name of the parameter. | |
| 854 | + * | |
| 855 | + * @return the object that represents the parameter value, or null if | |
| 856 | + * there is none. | |
| 857 | + * | |
| 858 | + * @exception InvalidParameterException if <code>param</code> is an invalid | |
| 859 | + * parameter for this engine, or another exception occurs while | |
| 860 | + * trying to get this parameter. | |
| 861 | + * | |
| 862 | + * @see #setParameter(String, Object) | |
| 863 | + * | |
| 864 | + * @deprecated | |
| 865 | + */ | |
| 866 | + @Deprecated | |
| 867 | + public final Object getParameter(String param) | |
| 868 | + throws InvalidParameterException { | |
| 869 | + return engineGetParameter(param); | |
| 870 | + } | |
| 871 | + | |
| 872 | + /** | |
| 873 | + * Returns a clone if the implementation is cloneable. | |
| 874 | + * | |
| 875 | + * @return a clone if the implementation is cloneable. | |
| 876 | + * | |
| 877 | + * @exception CloneNotSupportedException if this is called | |
| 878 | + * on an implementation that does not support <code>Cloneable</code>. | |
| 879 | + */ | |
| 880 | + public Object clone() throws CloneNotSupportedException { | |
| 881 | + if (this instanceof Cloneable) { | |
| 882 | + return super.clone(); | |
| 883 | + } else { | |
| 884 | + throw new CloneNotSupportedException(); | |
| 885 | + } | |
| 886 | + } | |
| 887 | + | |
| 888 | + /* | |
| 889 | + * The following class allows providers to extend from SignatureSpi | |
| 890 | + * rather than from Signature. It represents a Signature with an | |
| 891 | + * encapsulated, provider-supplied SPI object (of type SignatureSpi). | |
| 892 | + * If the provider implementation is an instance of SignatureSpi, the | |
| 893 | + * getInstance() methods above return an instance of this class, with | |
| 894 | + * the SPI object encapsulated. | |
| 895 | + * | |
| 896 | + * Note: All SPI methods from the original Signature class have been | |
| 897 | + * moved up the hierarchy into a new class (SignatureSpi), which has | |
| 898 | + * been interposed in the hierarchy between the API (Signature) | |
| 899 | + * and its original parent (Object). | |
| 900 | + */ | |
| 901 | + | |
| 902 | + private static class Delegate extends Signature { | |
| 903 | + | |
| 904 | + // The provider implementation (delegate) | |
| 905 | + // filled in once the provider is selected | |
| 906 | + private SignatureSpi sigSpi; | |
| 907 | + | |
| 908 | + // lock for mutex during provider selection | |
| 909 | + private final Object lock; | |
| 910 | + | |
| 911 | + // next service to try in provider selection | |
| 912 | + // null once provider is selected | |
| 913 | + private Service firstService; | |
| 914 | + | |
| 915 | + // remaining services to try in provider selection | |
| 916 | + // null once provider is selected | |
| 917 | + private Iterator<Service> serviceIterator; | |
| 918 | + | |
| 919 | + // constructor | |
| 920 | + Delegate(SignatureSpi sigSpi, String algorithm) { | |
| 921 | + super(algorithm); | |
| 922 | + this.sigSpi = sigSpi; | |
| 923 | + this.lock = null; // no lock needed | |
| 924 | + } | |
| 925 | + | |
| 926 | + // used with delayed provider selection | |
| 927 | + Delegate(Service service, | |
| 928 | + Iterator<Service> iterator, String algorithm) { | |
| 929 | + super(algorithm); | |
| 930 | + this.firstService = service; | |
| 931 | + this.serviceIterator = iterator; | |
| 932 | + this.lock = new Object(); | |
| 933 | + } | |
| 934 | + | |
| 935 | + /** | |
| 936 | + * Returns a clone if the delegate is cloneable. | |
| 937 | + * | |
| 938 | + * @return a clone if the delegate is cloneable. | |
| 939 | + * | |
| 940 | + * @exception CloneNotSupportedException if this is called on a | |
| 941 | + * delegate that does not support <code>Cloneable</code>. | |
| 942 | + */ | |
| 943 | + public Object clone() throws CloneNotSupportedException { | |
| 944 | + chooseFirstProvider(); | |
| 945 | + if (sigSpi instanceof Cloneable) { | |
| 946 | + SignatureSpi sigSpiClone = (SignatureSpi)sigSpi.clone(); | |
| 947 | + // Because 'algorithm' and 'provider' are private | |
| 948 | + // members of our supertype, we must perform a cast to | |
| 949 | + // access them. | |
| 950 | + Signature that = | |
| 951 | + new Delegate(sigSpiClone, ((Signature)this).algorithm); | |
| 952 | + that.provider = ((Signature)this).provider; | |
| 953 | + return that; | |
| 954 | + } else { | |
| 955 | + throw new CloneNotSupportedException(); | |
| 956 | + } | |
| 957 | + } | |
| 958 | + | |
| 959 | + private static SignatureSpi newInstance(Service s) | |
| 960 | + throws NoSuchAlgorithmException { | |
| 961 | + if (s.getType().equals("Cipher")) { | |
| 962 | + // must be NONEwithRSA | |
| 963 | + try { | |
| 964 | + Cipher c = Cipher.getInstance(RSA_CIPHER, s.getProvider()); | |
| 965 | + return new CipherAdapter(c); | |
| 966 | + } catch (NoSuchPaddingException e) { | |
| 967 | + throw new NoSuchAlgorithmException(e); | |
| 968 | + } | |
| 969 | + } else { | |
| 970 | + Object o = s.newInstance(null); | |
| 971 | + if (o instanceof SignatureSpi == false) { | |
| 972 | + throw new NoSuchAlgorithmException | |
| 973 | + ("Not a SignatureSpi: " + o.getClass().getName()); | |
| 974 | + } | |
| 975 | + return (SignatureSpi)o; | |
| 976 | + } | |
| 977 | + } | |
| 978 | + | |
| 979 | + // max number of debug warnings to print from chooseFirstProvider() | |
| 980 | + private static int warnCount = 10; | |
| 981 | + | |
| 982 | + /** | |
| 983 | + * Choose the Spi from the first provider available. Used if | |
| 984 | + * delayed provider selection is not possible because initSign()/ | |
| 985 | + * initVerify() is not the first method called. | |
| 986 | + */ | |
| 987 | + void chooseFirstProvider() { | |
| 988 | + if (sigSpi != null) { | |
| 989 | + return; | |
| 990 | + } | |
| 991 | + synchronized (lock) { | |
| 992 | + if (sigSpi != null) { | |
| 993 | + return; | |
| 994 | + } | |
| 995 | + if (debug != null) { | |
| 996 | + int w = --warnCount; | |
| 997 | + if (w >= 0) { | |
| 998 | + debug.println("Signature.init() not first method " | |
| 999 | + + "called, disabling delayed provider selection"); | |
| 1000 | + if (w == 0) { | |
| 1001 | + debug.println("Further warnings of this type will " | |
| 1002 | + + "be suppressed"); | |
| 1003 | + } | |
| 1004 | + new Exception("Call trace").printStackTrace(); | |
| 1005 | + } | |
| 1006 | + } | |
| 1007 | + Exception lastException = null; | |
| 1008 | + while ((firstService != null) || serviceIterator.hasNext()) { | |
| 1009 | + Service s; | |
| 1010 | + if (firstService != null) { | |
| 1011 | + s = firstService; | |
| 1012 | + firstService = null; | |
| 1013 | + } else { | |
| 1014 | + s = serviceIterator.next(); | |
| 1015 | + } | |
| 1016 | + if (isSpi(s) == false) { | |
| 1017 | + continue; | |
| 1018 | + } | |
| 1019 | + try { | |
| 1020 | + sigSpi = newInstance(s); | |
| 1021 | + provider = s.getProvider(); | |
| 1022 | + // not needed any more | |
| 1023 | + firstService = null; | |
| 1024 | + serviceIterator = null; | |
| 1025 | + return; | |
| 1026 | + } catch (NoSuchAlgorithmException e) { | |
| 1027 | + lastException = e; | |
| 1028 | + } | |
| 1029 | + } | |
| 1030 | + ProviderException e = new ProviderException | |
| 1031 | + ("Could not construct SignatureSpi instance"); | |
| 1032 | + if (lastException != null) { | |
| 1033 | + e.initCause(lastException); | |
| 1034 | + } | |
| 1035 | + throw e; | |
| 1036 | + } | |
| 1037 | + } | |
| 1038 | + | |
| 1039 | + private void chooseProvider(int type, Key key, SecureRandom random) | |
| 1040 | + throws InvalidKeyException { | |
| 1041 | + synchronized (lock) { | |
| 1042 | + if (sigSpi != null) { | |
| 1043 | + init(sigSpi, type, key, random); | |
| 1044 | + return; | |
| 1045 | + } | |
| 1046 | + Exception lastException = null; | |
| 1047 | + while ((firstService != null) || serviceIterator.hasNext()) { | |
| 1048 | + Service s; | |
| 1049 | + if (firstService != null) { | |
| 1050 | + s = firstService; | |
| 1051 | + firstService = null; | |
| 1052 | + } else { | |
| 1053 | + s = serviceIterator.next(); | |
| 1054 | + } | |
| 1055 | + // if provider says it does not support this key, ignore it | |
| 1056 | + if (s.supportsParameter(key) == false) { | |
| 1057 | + continue; | |
| 1058 | + } | |
| 1059 | + // if instance is not a SignatureSpi, ignore it | |
| 1060 | + if (isSpi(s) == false) { | |
| 1061 | + continue; | |
| 1062 | + } | |
| 1063 | + try { | |
| 1064 | + SignatureSpi spi = newInstance(s); | |
| 1065 | + init(spi, type, key, random); | |
| 1066 | + provider = s.getProvider(); | |
| 1067 | + sigSpi = spi; | |
| 1068 | + firstService = null; | |
| 1069 | + serviceIterator = null; | |
| 1070 | + return; | |
| 1071 | + } catch (Exception e) { | |
| 1072 | + // NoSuchAlgorithmException from newInstance() | |
| 1073 | + // InvalidKeyException from init() | |
| 1074 | + // RuntimeException (ProviderException) from init() | |
| 1075 | + if (lastException == null) { | |
| 1076 | + lastException = e; | |
| 1077 | + } | |
| 1078 | + } | |
| 1079 | + } | |
| 1080 | + // no working provider found, fail | |
| 1081 | + if (lastException instanceof InvalidKeyException) { | |
| 1082 | + throw (InvalidKeyException)lastException; | |
| 1083 | + } | |
| 1084 | + if (lastException instanceof RuntimeException) { | |
| 1085 | + throw (RuntimeException)lastException; | |
| 1086 | + } | |
| 1087 | + String k = (key != null) ? key.getClass().getName() : "(null)"; | |
| 1088 | + throw new InvalidKeyException | |
| 1089 | + ("No installed provider supports this key: " | |
| 1090 | + + k, lastException); | |
| 1091 | + } | |
| 1092 | + } | |
| 1093 | + | |
| 1094 | + private final static int I_PUB = 1; | |
| 1095 | + private final static int I_PRIV = 2; | |
| 1096 | + private final static int I_PRIV_SR = 3; | |
| 1097 | + | |
| 1098 | + private void init(SignatureSpi spi, int type, Key key, | |
| 1099 | + SecureRandom random) throws InvalidKeyException { | |
| 1100 | + switch (type) { | |
| 1101 | + case I_PUB: | |
| 1102 | + spi.engineInitVerify((PublicKey)key); | |
| 1103 | + break; | |
| 1104 | + case I_PRIV: | |
| 1105 | + spi.engineInitSign((PrivateKey)key); | |
| 1106 | + break; | |
| 1107 | + case I_PRIV_SR: | |
| 1108 | + spi.engineInitSign((PrivateKey)key, random); | |
| 1109 | + break; | |
| 1110 | + default: | |
| 1111 | + throw new AssertionError("Internal error: " + type); | |
| 1112 | + } | |
| 1113 | + } | |
| 1114 | + | |
| 1115 | + protected void engineInitVerify(PublicKey publicKey) | |
| 1116 | + throws InvalidKeyException { | |
| 1117 | + if (sigSpi != null) { | |
| 1118 | + sigSpi.engineInitVerify(publicKey); | |
| 1119 | + } else { | |
| 1120 | + chooseProvider(I_PUB, publicKey, null); | |
| 1121 | + } | |
| 1122 | + } | |
| 1123 | + | |
| 1124 | + protected void engineInitSign(PrivateKey privateKey) | |
| 1125 | + throws InvalidKeyException { | |
| 1126 | + if (sigSpi != null) { | |
| 1127 | + sigSpi.engineInitSign(privateKey); | |
| 1128 | + } else { | |
| 1129 | + chooseProvider(I_PRIV, privateKey, null); | |
| 1130 | + } | |
| 1131 | + } | |
| 1132 | + | |
| 1133 | + protected void engineInitSign(PrivateKey privateKey, SecureRandom sr) | |
| 1134 | + throws InvalidKeyException { | |
| 1135 | + if (sigSpi != null) { | |
| 1136 | + sigSpi.engineInitSign(privateKey, sr); | |
| 1137 | + } else { | |
| 1138 | + chooseProvider(I_PRIV_SR, privateKey, sr); | |
| 1139 | + } | |
| 1140 | + } | |
| 1141 | + | |
| 1142 | + protected void engineUpdate(byte b) throws SignatureException { | |
| 1143 | + chooseFirstProvider(); | |
| 1144 | + sigSpi.engineUpdate(b); | |
| 1145 | + } | |
| 1146 | + | |
| 1147 | + protected void engineUpdate(byte[] b, int off, int len) | |
| 1148 | + throws SignatureException { | |
| 1149 | + chooseFirstProvider(); | |
| 1150 | + sigSpi.engineUpdate(b, off, len); | |
| 1151 | + } | |
| 1152 | + | |
| 1153 | + protected void engineUpdate(ByteBuffer data) { | |
| 1154 | + chooseFirstProvider(); | |
| 1155 | + sigSpi.engineUpdate(data); | |
| 1156 | + } | |
| 1157 | + | |
| 1158 | + protected byte[] engineSign() throws SignatureException { | |
| 1159 | + chooseFirstProvider(); | |
| 1160 | + return sigSpi.engineSign(); | |
| 1161 | + } | |
| 1162 | + | |
| 1163 | + protected int engineSign(byte[] outbuf, int offset, int len) | |
| 1164 | + throws SignatureException { | |
| 1165 | + chooseFirstProvider(); | |
| 1166 | + return sigSpi.engineSign(outbuf, offset, len); | |
| 1167 | + } | |
| 1168 | + | |
| 1169 | + protected boolean engineVerify(byte[] sigBytes) | |
| 1170 | + throws SignatureException { | |
| 1171 | + chooseFirstProvider(); | |
| 1172 | + return sigSpi.engineVerify(sigBytes); | |
| 1173 | + } | |
| 1174 | + | |
| 1175 | + protected boolean engineVerify(byte[] sigBytes, int offset, int length) | |
| 1176 | + throws SignatureException { | |
| 1177 | + chooseFirstProvider(); | |
| 1178 | + return sigSpi.engineVerify(sigBytes, offset, length); | |
| 1179 | + } | |
| 1180 | + | |
| 1181 | + protected void engineSetParameter(String param, Object value) | |
| 1182 | + throws InvalidParameterException { | |
| 1183 | + chooseFirstProvider(); | |
| 1184 | + sigSpi.engineSetParameter(param, value); | |
| 1185 | + } | |
| 1186 | + | |
| 1187 | + protected void engineSetParameter(AlgorithmParameterSpec params) | |
| 1188 | + throws InvalidAlgorithmParameterException { | |
| 1189 | + chooseFirstProvider(); | |
| 1190 | + sigSpi.engineSetParameter(params); | |
| 1191 | + } | |
| 1192 | + | |
| 1193 | + protected Object engineGetParameter(String param) | |
| 1194 | + throws InvalidParameterException { | |
| 1195 | + chooseFirstProvider(); | |
| 1196 | + return sigSpi.engineGetParameter(param); | |
| 1197 | + } | |
| 1198 | + | |
| 1199 | + protected AlgorithmParameters engineGetParameters() { | |
| 1200 | + chooseFirstProvider(); | |
| 1201 | + return sigSpi.engineGetParameters(); | |
| 1202 | + } | |
| 1203 | + } | |
| 1204 | + | |
| 1205 | + // adapter for RSA/ECB/PKCS1Padding ciphers | |
| 1206 | + private static class CipherAdapter extends SignatureSpi { | |
| 1207 | + | |
| 1208 | + private final Cipher cipher; | |
| 1209 | + | |
| 1210 | + private ByteArrayOutputStream data; | |
| 1211 | + | |
| 1212 | + CipherAdapter(Cipher cipher) { | |
| 1213 | + this.cipher = cipher; | |
| 1214 | + } | |
| 1215 | + | |
| 1216 | + protected void engineInitVerify(PublicKey publicKey) | |
| 1217 | + throws InvalidKeyException { | |
| 1218 | + cipher.init(Cipher.DECRYPT_MODE, publicKey); | |
| 1219 | + if (data == null) { | |
| 1220 | + data = new ByteArrayOutputStream(128); | |
| 1221 | + } else { | |
| 1222 | + data.reset(); | |
| 1223 | + } | |
| 1224 | + } | |
| 1225 | + | |
| 1226 | + protected void engineInitSign(PrivateKey privateKey) | |
| 1227 | + throws InvalidKeyException { | |
| 1228 | + cipher.init(Cipher.ENCRYPT_MODE, privateKey); | |
| 1229 | + data = null; | |
| 1230 | + } | |
| 1231 | + | |
| 1232 | + protected void engineInitSign(PrivateKey privateKey, | |
| 1233 | + SecureRandom random) throws InvalidKeyException { | |
| 1234 | + cipher.init(Cipher.ENCRYPT_MODE, privateKey, random); | |
| 1235 | + data = null; | |
| 1236 | + } | |
| 1237 | + | |
| 1238 | + protected void engineUpdate(byte b) throws SignatureException { | |
| 1239 | + engineUpdate(new byte[] {b}, 0, 1); | |
| 1240 | + } | |
| 1241 | + | |
| 1242 | + protected void engineUpdate(byte[] b, int off, int len) | |
| 1243 | + throws SignatureException { | |
| 1244 | + if (data != null) { | |
| 1245 | + data.write(b, off, len); | |
| 1246 | + return; | |
| 1247 | + } | |
| 1248 | + byte[] out = cipher.update(b, off, len); | |
| 1249 | + if ((out != null) && (out.length != 0)) { | |
| 1250 | + throw new SignatureException | |
| 1251 | + ("Cipher unexpectedly returned data"); | |
| 1252 | + } | |
| 1253 | + } | |
| 1254 | + | |
| 1255 | + protected byte[] engineSign() throws SignatureException { | |
| 1256 | + try { | |
| 1257 | + return cipher.doFinal(); | |
| 1258 | + } catch (IllegalBlockSizeException e) { | |
| 1259 | + throw new SignatureException("doFinal() failed", e); | |
| 1260 | + } catch (BadPaddingException e) { | |
| 1261 | + throw new SignatureException("doFinal() failed", e); | |
| 1262 | + } | |
| 1263 | + } | |
| 1264 | + | |
| 1265 | + protected boolean engineVerify(byte[] sigBytes) | |
| 1266 | + throws SignatureException { | |
| 1267 | + try { | |
| 1268 | + byte[] out = cipher.doFinal(sigBytes); | |
| 1269 | + byte[] dataBytes = data.toByteArray(); | |
| 1270 | + data.reset(); | |
| 1271 | + return Arrays.equals(out, dataBytes); | |
| 1272 | + } catch (BadPaddingException e) { | |
| 1273 | + // e.g. wrong public key used | |
| 1274 | + // return false rather than throwing exception | |
| 1275 | + return false; | |
| 1276 | + } catch (IllegalBlockSizeException e) { | |
| 1277 | + throw new SignatureException("doFinal() failed", e); | |
| 1278 | + } | |
| 1279 | + } | |
| 1280 | + | |
| 1281 | + protected void engineSetParameter(String param, Object value) | |
| 1282 | + throws InvalidParameterException { | |
| 1283 | + throw new InvalidParameterException("Parameters not supported"); | |
| 1284 | + } | |
| 1285 | + | |
| 1286 | + protected Object engineGetParameter(String param) | |
| 1287 | + throws InvalidParameterException { | |
| 1288 | + throw new InvalidParameterException("Parameters not supported"); | |
| 1289 | + } | |
| 1290 | + | |
| 1291 | + } | |
| 1292 | + | |
| 1293 | +} | |
Binary file not shown.
| @@ -0,0 +1,87 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This is the generic Signature exception. | |
| 30 | + * | |
| 31 | + * @author Benjamin Renaud | |
| 32 | + */ | |
| 33 | + | |
| 34 | +public class SignatureException extends GeneralSecurityException { | |
| 35 | + | |
| 36 | + private static final long serialVersionUID = 7509989324975124438L; | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * Constructs a SignatureException with no detail message. A | |
| 40 | + * detail message is a String that describes this particular | |
| 41 | + * exception. | |
| 42 | + */ | |
| 43 | + public SignatureException() { | |
| 44 | + super(); | |
| 45 | + } | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * Constructs a SignatureException with the specified detail | |
| 49 | + * message. A detail message is a String that describes this | |
| 50 | + * particular exception. | |
| 51 | + * | |
| 52 | + * @param msg the detail message. | |
| 53 | + */ | |
| 54 | + public SignatureException(String msg) { | |
| 55 | + super(msg); | |
| 56 | + } | |
| 57 | + | |
| 58 | + /** | |
| 59 | + * Creates a <code>SignatureException</code> with the specified | |
| 60 | + * detail message and cause. | |
| 61 | + * | |
| 62 | + * @param message the detail message (which is saved for later retrieval | |
| 63 | + * by the {@link #getMessage()} method). | |
| 64 | + * @param cause the cause (which is saved for later retrieval by the | |
| 65 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 66 | + * and indicates that the cause is nonexistent or unknown.) | |
| 67 | + * @since 1.5 | |
| 68 | + */ | |
| 69 | + public SignatureException(String message, Throwable cause) { | |
| 70 | + super(message, cause); | |
| 71 | + } | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * Creates a <code>SignatureException</code> with the specified cause | |
| 75 | + * and a detail message of <tt>(cause==null ? null : cause.toString())</tt> | |
| 76 | + * (which typically contains the class and detail message of | |
| 77 | + * <tt>cause</tt>). | |
| 78 | + * | |
| 79 | + * @param cause the cause (which is saved for later retrieval by the | |
| 80 | + * {@link #getCause()} method). (A <tt>null</tt> value is permitted, | |
| 81 | + * and indicates that the cause is nonexistent or unknown.) | |
| 82 | + * @since 1.5 | |
| 83 | + */ | |
| 84 | + public SignatureException(Throwable cause) { | |
| 85 | + super(cause); | |
| 86 | + } | |
| 87 | +} | |
Binary file not shown.
| @@ -0,0 +1,390 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package java.security; | |
| 27 | + | |
| 28 | +import java.security.spec.AlgorithmParameterSpec; | |
| 29 | +import java.util.*; | |
| 30 | +import java.io.*; | |
| 31 | + | |
| 32 | +import java.nio.ByteBuffer; | |
| 33 | + | |
| 34 | +import sun.security.jca.JCAUtil; | |
| 35 | + | |
| 36 | +/** | |
| 37 | + * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) | |
| 38 | + * for the <code>Signature</code> class, which is used to provide the | |
| 39 | + * functionality of a digital signature algorithm. Digital signatures are used | |
| 40 | + * for authentication and integrity assurance of digital data. | |
| 41 | + *. | |
| 42 | + * <p> All the abstract methods in this class must be implemented by each | |
| 43 | + * cryptographic service provider who wishes to supply the implementation | |
| 44 | + * of a particular signature algorithm. | |
| 45 | + * | |
| 46 | + * @author Benjamin Renaud | |
| 47 | + * | |
| 48 | + * | |
| 49 | + * @see Signature | |
| 50 | + */ | |
| 51 | + | |
| 52 | +public abstract class SignatureSpi { | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * Application-specified source of randomness. | |
| 56 | + */ | |
| 57 | + protected SecureRandom appRandom = null; | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * Initializes this signature object with the specified | |
| 61 | + * public key for verification operations. | |
| 62 | + * | |
| 63 | + * @param publicKey the public key of the identity whose signature is | |
| 64 | + * going to be verified. | |
| 65 | + * | |
| 66 | + * @exception InvalidKeyException if the key is improperly | |
| 67 | + * encoded, parameters are missing, and so on. | |
| 68 | + */ | |
| 69 | + protected abstract void engineInitVerify(PublicKey publicKey) | |
| 70 | + throws InvalidKeyException; | |
| 71 | + | |
| 72 | + /** | |
| 73 | + * Initializes this signature object with the specified | |
| 74 | + * private key for signing operations. | |
| 75 | + * | |
| 76 | + * @param privateKey the private key of the identity whose signature | |
| 77 | + * will be generated. | |
| 78 | + * | |
| 79 | + * @exception InvalidKeyException if the key is improperly | |
| 80 | + * encoded, parameters are missing, and so on. | |
| 81 | + */ | |
| 82 | + protected abstract void engineInitSign(PrivateKey privateKey) | |
| 83 | + throws InvalidKeyException; | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * Initializes this signature object with the specified | |
| 87 | + * private key and source of randomness for signing operations. | |
| 88 | + * | |
| 89 | + * <p>This concrete method has been added to this previously-defined | |
| 90 | + * abstract class. (For backwards compatibility, it cannot be abstract.) | |
| 91 | + * | |
| 92 | + * @param privateKey the private key of the identity whose signature | |
| 93 | + * will be generated. | |
| 94 | + * @param random the source of randomness | |
| 95 | + * | |
| 96 | + * @exception InvalidKeyException if the key is improperly | |
| 97 | + * encoded, parameters are missing, and so on. | |
| 98 | + */ | |
| 99 | + protected void engineInitSign(PrivateKey privateKey, | |
| 100 | + SecureRandom random) | |
| 101 | + throws InvalidKeyException { | |
| 102 | + this.appRandom = random; | |
| 103 | + engineInitSign(privateKey); | |
| 104 | + } | |
| 105 | + | |
| 106 | + /** | |
| 107 | + * Updates the data to be signed or verified | |
| 108 | + * using the specified byte. | |
| 109 | + * | |
| 110 | + * @param b the byte to use for the update. | |
| 111 | + * | |
| 112 | + * @exception SignatureException if the engine is not initialized | |
| 113 | + * properly. | |
| 114 | + */ | |
| 115 | + protected abstract void engineUpdate(byte b) throws SignatureException; | |
| 116 | + | |
| 117 | + /** | |
| 118 | + * Updates the data to be signed or verified, using the | |
| 119 | + * specified array of bytes, starting at the specified offset. | |
| 120 | + * | |
| 121 | + * @param b the array of bytes | |
| 122 | + * @param off the offset to start from in the array of bytes | |
| 123 | + * @param len the number of bytes to use, starting at offset | |
| 124 | + * | |
| 125 | + * @exception SignatureException if the engine is not initialized | |
| 126 | + * properly | |
| 127 | + */ | |
| 128 | + protected abstract void engineUpdate(byte[] b, int off, int len) | |
| 129 | + throws SignatureException; | |
| 130 | + | |
| 131 | + /** | |
| 132 | + * Updates the data to be signed or verified using the specified | |
| 133 | + * ByteBuffer. Processes the <code>data.remaining()</code> bytes | |
| 134 | + * starting at at <code>data.position()</code>. | |
| 135 | + * Upon return, the buffer's position will be equal to its limit; | |
| 136 | + * its limit will not have changed. | |
| 137 | + * | |
| 138 | + * @param input the ByteBuffer | |
| 139 | + * @since 1.5 | |
| 140 | + */ | |
| 141 | + protected void engineUpdate(ByteBuffer input) { | |
| 142 | + if (input.hasRemaining() == false) { | |
| 143 | + return; | |
| 144 | + } | |
| 145 | + try { | |
| 146 | + if (input.hasArray()) { | |
| 147 | + byte[] b = input.array(); | |
| 148 | + int ofs = input.arrayOffset(); | |
| 149 | + int pos = input.position(); | |
| 150 | + int lim = input.limit(); | |
| 151 | + engineUpdate(b, ofs + pos, lim - pos); | |
| 152 | + input.position(lim); | |
| 153 | + } else { | |
| 154 | + int len = input.remaining(); | |
| 155 | + byte[] b = new byte[JCAUtil.getTempArraySize(len)]; | |
| 156 | + while (len > 0) { | |
| 157 | + int chunk = Math.min(len, b.length); | |
| 158 | + input.get(b, 0, chunk); | |
| 159 | + engineUpdate(b, 0, chunk); | |
| 160 | + len -= chunk; | |
| 161 | + } | |
| 162 | + } | |
| 163 | + } catch (SignatureException e) { | |
| 164 | + // is specified to only occur when the engine is not initialized | |
| 165 | + // this case should never occur as it is caught in Signature.java | |
| 166 | + throw new ProviderException("update() failed", e); | |
| 167 | + } | |
| 168 | + } | |
| 169 | + | |
| 170 | + /** | |
| 171 | + * Returns the signature bytes of all the data | |
| 172 | + * updated so far. | |
| 173 | + * The format of the signature depends on the underlying | |
| 174 | + * signature scheme. | |
| 175 | + * | |
| 176 | + * @return the signature bytes of the signing operation's result. | |
| 177 | + * | |
| 178 | + * @exception SignatureException if the engine is not | |
| 179 | + * initialized properly or if this signature algorithm is unable to | |
| 180 | + * process the input data provided. | |
| 181 | + */ | |
| 182 | + protected abstract byte[] engineSign() throws SignatureException; | |
| 183 | + | |
| 184 | + /** | |
| 185 | + * Finishes this signature operation and stores the resulting signature | |
| 186 | + * bytes in the provided buffer <code>outbuf</code>, starting at | |
| 187 | + * <code>offset</code>. | |
| 188 | + * The format of the signature depends on the underlying | |
| 189 | + * signature scheme. | |
| 190 | + * | |
| 191 | + * <p>The signature implementation is reset to its initial state | |
| 192 | + * (the state it was in after a call to one of the | |
| 193 | + * <code>engineInitSign</code> methods) | |
| 194 | + * and can be reused to generate further signatures with the same private | |
| 195 | + * key. | |
| 196 | + * | |
| 197 | + * This method should be abstract, but we leave it concrete for | |
| 198 | + * binary compatibility. Knowledgeable providers should override this | |
| 199 | + * method. | |
| 200 | + * | |
| 201 | + * @param outbuf buffer for the signature result. | |
| 202 | + * | |
| 203 | + * @param offset offset into <code>outbuf</code> where the signature is | |
| 204 | + * stored. | |
| 205 | + * | |
| 206 | + * @param len number of bytes within <code>outbuf</code> allotted for the | |
| 207 | + * signature. | |
| 208 | + * Both this default implementation and the SUN provider do not | |
| 209 | + * return partial digests. If the value of this parameter is less | |
| 210 | + * than the actual signature length, this method will throw a | |
| 211 | + * SignatureException. | |
| 212 | + * This parameter is ignored if its value is greater than or equal to | |
| 213 | + * the actual signature length. | |
| 214 | + * | |
| 215 | + * @return the number of bytes placed into <code>outbuf</code> | |
| 216 | + * | |
| 217 | + * @exception SignatureException if the engine is not | |
| 218 | + * initialized properly, if this signature algorithm is unable to | |
| 219 | + * process the input data provided, or if <code>len</code> is less | |
| 220 | + * than the actual signature length. | |
| 221 | + * | |
| 222 | + * @since 1.2 | |
| 223 | + */ | |
| 224 | + protected int engineSign(byte[] outbuf, int offset, int len) | |
| 225 | + throws SignatureException { | |
| 226 | + byte[] sig = engineSign(); | |
| 227 | + if (len < sig.length) { | |
| 228 | + throw new SignatureException | |
| 229 | + ("partial signatures not returned"); | |
| 230 | + } | |
| 231 | + if (outbuf.length - offset < sig.length) { | |
| 232 | + throw new SignatureException | |
| 233 | + ("insufficient space in the output buffer to store the " | |
| 234 | + + "signature"); | |
| 235 | + } | |
| 236 | + System.arraycopy(sig, 0, outbuf, offset, sig.length); | |
| 237 | + return sig.length; | |
| 238 | + } | |
| 239 | + | |
| 240 | + /** | |
| 241 | + * Verifies the passed-in signature. | |
| 242 | + * | |
| 243 | + * @param sigBytes the signature bytes to be verified. | |
| 244 | + * | |
| 245 | + * @return true if the signature was verified, false if not. | |
| 246 | + * | |
| 247 | + * @exception SignatureException if the engine is not | |
| 248 | + * initialized properly, the passed-in signature is improperly | |
| 249 | + * encoded or of the wrong type, if this signature algorithm is unable to | |
| 250 | + * process the input data provided, etc. | |
| 251 | + */ | |
| 252 | + protected abstract boolean engineVerify(byte[] sigBytes) | |
| 253 | + throws SignatureException; | |
| 254 | + | |
| 255 | + /** | |
| 256 | + * Verifies the passed-in signature in the specified array | |
| 257 | + * of bytes, starting at the specified offset. | |
| 258 | + * | |
| 259 | + * <p> Note: Subclasses should overwrite the default implementation. | |
| 260 | + * | |
| 261 | + * | |
| 262 | + * @param sigBytes the signature bytes to be verified. | |
| 263 | + * @param offset the offset to start from in the array of bytes. | |
| 264 | + * @param length the number of bytes to use, starting at offset. | |
| 265 | + * | |
| 266 | + * @return true if the signature was verified, false if not. | |
| 267 | + * | |
| 268 | + * @exception SignatureException if the engine is not | |
| 269 | + * initialized properly, the passed-in signature is improperly | |
| 270 | + * encoded or of the wrong type, if this signature algorithm is unable to | |
| 271 | + * process the input data provided, etc. | |
| 272 | + * @since 1.4 | |
| 273 | + */ | |
| 274 | + protected boolean engineVerify(byte[] sigBytes, int offset, int length) | |
| 275 | + throws SignatureException { | |
| 276 | + byte[] sigBytesCopy = new byte[length]; | |
| 277 | + System.arraycopy(sigBytes, offset, sigBytesCopy, 0, length); | |
| 278 | + return engineVerify(sigBytesCopy); | |
| 279 | + } | |
| 280 | + | |
| 281 | + /** | |
| 282 | + * Sets the specified algorithm parameter to the specified | |
| 283 | + * value. This method supplies a general-purpose mechanism through | |
| 284 | + * which it is possible to set the various parameters of this object. | |
| 285 | + * A parameter may be any settable parameter for the algorithm, such as | |
| 286 | + * a parameter size, or a source of random bits for signature generation | |
104 more lines aren’t shown here.
Binary file not shown.
This diff is large: its 259 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 184 lines aren’t shown here.
Binary file not shown.
This diff is large: its 165 lines aren’t shown here.
Binary file not shown.
This diff is large: its 64 lines aren’t shown here.
Binary file not shown.
This diff is large: its 57 lines aren’t shown here.
Binary file not shown.
This diff is large: its 57 lines aren’t shown here.
Binary file not shown.
This diff is large: its 605 lines aren’t shown here.
Binary file not shown.
This diff is large: its 217 lines aren’t shown here.
Binary file not shown.
This diff is large: its 242 lines aren’t shown here.
Binary file not shown.
This diff is large: its 155 lines aren’t shown here.
Binary file not shown.
This diff is large: its 45 lines aren’t shown here.
Binary file not shown.
This diff is large: its 88 lines aren’t shown here.
Binary file not shown.
This diff is large: its 46 lines aren’t shown here.
Binary file not shown.
This diff is large: its 45 lines aren’t shown here.
Binary file not shown.
This diff is large: its 96 lines aren’t shown here.
Binary file not shown.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
Binary file not shown.
This diff is large: its 89 lines aren’t shown here.
Binary file not shown.
This diff is large: its 89 lines aren’t shown here.
Binary file not shown.
This diff is large: its 105 lines aren’t shown here.
Binary file not shown.
This diff is large: its 67 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 344 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 305 lines aren’t shown here.
Binary file not shown.
This diff is large: its 105 lines aren’t shown here.
Binary file not shown.
This diff is large: its 69 lines aren’t shown here.
Binary file not shown.
This diff is large: its 76 lines aren’t shown here.
Binary file not shown.
This diff is large: its 67 lines aren’t shown here.
Binary file not shown.
This diff is large: its 50 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 316 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 297 lines aren’t shown here.
Binary file not shown.
This diff is large: its 51 lines aren’t shown here.
Binary file not shown.
This diff is large: its 86 lines aren’t shown here.
Binary file not shown.
This diff is large: its 68 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 425 lines aren’t shown here.
Binary file not shown.
This diff is large: its 104 lines aren’t shown here.
Binary file not shown.
This diff is large: its 81 lines aren’t shown here.
Binary file not shown.
This diff is large: its 126 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 275 lines aren’t shown here.
Binary file not shown.
This diff is large: its 89 lines aren’t shown here.
Binary file not shown.
This diff is large: its 89 lines aren’t shown here.
Binary file not shown.
This diff is large: its 60 lines aren’t shown here.
Binary file not shown.
This diff is large: its 538 lines aren’t shown here.
Binary file not shown.
This diff is large: its 316 lines aren’t shown here.
Binary file not shown.
This diff is large: its 60 lines aren’t shown here.
Binary file not shown.
This diff is large: its 90 lines aren’t shown here.
Binary file not shown.
This diff is large: its 246 lines aren’t shown here.
Binary file not shown.
This diff is large: its 142 lines aren’t shown here.
Binary file not shown.
This diff is large: its 102 lines aren’t shown here.
Binary file not shown.
This diff is large: its 150 lines aren’t shown here.
Binary file not shown.
This diff is large: its 200 lines aren’t shown here.
Binary file not shown.
This diff is large: its 120 lines aren’t shown here.
Binary file not shown.
This diff is large: its 182 lines aren’t shown here.
Binary file not shown.
This diff is large: its 160 lines aren’t shown here.
Binary file not shown.
This diff is large: its 737 lines aren’t shown here.
Binary file not shown.
This diff is large: its 78 lines aren’t shown here.
Binary file not shown.
This diff is large: its 134 lines aren’t shown here.
Binary file not shown.
This diff is large: its 174 lines aren’t shown here.
Binary file not shown.
This diff is large: its 335 lines aren’t shown here.
Binary file not shown.
This diff is large: its 444 lines aren’t shown here.
Binary file not shown.
This diff is large: its 192 lines aren’t shown here.
Binary file not shown.
This diff is large: its 715 lines aren’t shown here.
Binary file not shown.
This diff is large: its 2639 lines aren’t shown here.
Binary file not shown.
This diff is large: its 650 lines aren’t shown here.
Binary file not shown.
This diff is large: its 200 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
Binary file not shown.
This diff is large: its 51 lines aren’t shown here.
Binary file not shown.
This diff is large: its 116 lines aren’t shown here.
Binary file not shown.
This diff is large: its 65 lines aren’t shown here.
Binary file not shown.
This diff is large: its 59 lines aren’t shown here.
Binary file not shown.
This diff is large: its 59 lines aren’t shown here.
Binary file not shown.
This diff is large: its 46 lines aren’t shown here.
Binary file not shown.
This diff is large: its 54 lines aren’t shown here.
Binary file not shown.
This diff is large: its 56 lines aren’t shown here.
Binary file not shown.
This diff is large: its 50 lines aren’t shown here.
Binary file not shown.
This diff is large: its 101 lines aren’t shown here.
Binary file not shown.
This diff is large: its 86 lines aren’t shown here.
Binary file not shown.
This diff is large: its 51 lines aren’t shown here.
Binary file not shown.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 118 lines aren’t shown here.
Binary file not shown.
This diff is large: its 45 lines aren’t shown here.
Binary file not shown.
This diff is large: its 90 lines aren’t shown here.
Binary file not shown.
This diff is large: its 107 lines aren’t shown here.
Binary file not shown.
This diff is large: its 107 lines aren’t shown here.
Binary file not shown.
This diff is large: its 50 lines aren’t shown here.
Binary file not shown.
This diff is large: its 242 lines aren’t shown here.
Binary file not shown.
This diff is large: its 99 lines aren’t shown here.
Binary file not shown.
This diff is large: its 69 lines aren’t shown here.
Binary file not shown.
This diff is large: its 114 lines aren’t shown here.
Binary file not shown.
This diff is large: its 115 lines aren’t shown here.
Binary file not shown.
This diff is large: its 82 lines aren’t shown here.
Binary file not shown.
This diff is large: its 86 lines aren’t shown here.
Binary file not shown.
This diff is large: its 197 lines aren’t shown here.
Binary file not shown.
This diff is large: its 86 lines aren’t shown here.
Binary file not shown.
This diff is large: its 95 lines aren’t shown here.
Binary file not shown.
This diff is large: its 67 lines aren’t shown here.
Binary file not shown.
This diff is large: its 63 lines aren’t shown here.
Binary file not shown.
This diff is large: its 108 lines aren’t shown here.
Binary file not shown.
This diff is large: its 97 lines aren’t shown here.
Binary file not shown.
This diff is large: its 212 lines aren’t shown here.
Binary file not shown.
This diff is large: its 87 lines aren’t shown here.
Binary file not shown.
This diff is large: its 213 lines aren’t shown here.
Binary file not shown.
This diff is large: its 121 lines aren’t shown here.
Binary file not shown.
This diff is large: its 144 lines aren’t shown here.
Binary file not shown.
This diff is large: its 78 lines aren’t shown here.
Binary file not shown.
This diff is large: its 78 lines aren’t shown here.
Binary file not shown.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.