feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth;
/**
* This class is for authentication permissions.
* An AuthPermission contains a name
* (also referred to as a "target name")
* but no actions list; you either have the named permission
* or you don't.
*
* <p> The target name is the name of a security configuration parameter
* (see below). Currently the AuthPermission object is used to
* guard access to the Policy, Subject, LoginContext,
* and Configuration objects.
*
* <p> The possible target names for an Authentication Permission are:
*
* <pre>
* doAs - allow the caller to invoke the
* {@code Subject.doAs} methods.
*
* doAsPrivileged - allow the caller to invoke the
* {@code Subject.doAsPrivileged} methods.
*
* getSubject - allow for the retrieval of the
* Subject(s) associated with the
* current Thread.
*
* getSubjectFromDomainCombiner - allow for the retrieval of the
* Subject associated with the
* a {@code SubjectDomainCombiner}.
*
* setReadOnly - allow the caller to set a Subject
* to be read-only.
*
* modifyPrincipals - allow the caller to modify the {@code Set}
* of Principals associated with a
* {@code Subject}
*
* modifyPublicCredentials - allow the caller to modify the
* {@code Set} of public credentials
* associated with a {@code Subject}
*
* modifyPrivateCredentials - allow the caller to modify the
* {@code Set} of private credentials
* associated with a {@code Subject}
*
* refreshCredential - allow code to invoke the {@code refresh}
* method on a credential which implements
* the {@code Refreshable} interface.
*
* destroyCredential - allow code to invoke the {@code destroy}
* method on a credential {@code object}
* which implements the {@code Destroyable}
* interface.
*
* createLoginContext.{name} - allow code to instantiate a
* {@code LoginContext} with the
* specified <i>name</i>. <i>name</i>
* is used as the index into the installed login
* {@code Configuration}
* (that returned by
* {@code Configuration.getConfiguration()}).
* <i>name</i> can be wildcarded (set to '*')
* to allow for any name.
*
* getLoginConfiguration - allow for the retrieval of the system-wide
* login Configuration.
*
* createLoginConfiguration.{type} - allow code to obtain a Configuration
* object via
* {@code Configuration.getInstance}.
*
* setLoginConfiguration - allow for the setting of the system-wide
* login Configuration.
*
* refreshLoginConfiguration - allow for the refreshing of the system-wide
* login Configuration.
* </pre>
*
* <p> The following target name has been deprecated in favor of
* {@code createLoginContext.{name}}.
*
* <pre>
* createLoginContext - allow code to instantiate a
* {@code LoginContext}.
* </pre>
*
* <p> {@code javax.security.auth.Policy} has been
* deprecated in favor of {@code java.security.Policy}.
* Therefore, the following target names have also been deprecated:
*
* <pre>
* getPolicy - allow the caller to retrieve the system-wide
* Subject-based access control policy.
*
* setPolicy - allow the caller to set the system-wide
* Subject-based access control policy.
*
* refreshPolicy - allow the caller to refresh the system-wide
* Subject-based access control policy.
* </pre>
*
*/
public final class AuthPermission extends
java.security.BasicPermission {
private static final long serialVersionUID = 5806031445061587174L;
/**
* Creates a new AuthPermission with the specified name.
* The name is the symbolic name of the AuthPermission.
*
* <p>
*
* @param name the name of the AuthPermission
*
* @throws NullPointerException if {@code name} is {@code null}.
* @throws IllegalArgumentException if {@code name} is empty.
*/
public AuthPermission(String name) {
// for backwards compatibility --
// createLoginContext is deprecated in favor of createLoginContext.*
super("createLoginContext".equals(name) ?
"createLoginContext.*" : name);
}
/**
* Creates a new AuthPermission object with the specified name.
* The name is the symbolic name of the AuthPermission, and the
* actions String is currently unused and should be null.
*
* <p>
*
* @param name the name of the AuthPermission <p>
*
* @param actions should be null.
*
* @throws NullPointerException if {@code name} is {@code null}.
* @throws IllegalArgumentException if {@code name} is empty.
*/
public AuthPermission(String name, String actions) {
// for backwards compatibility --
// createLoginContext is deprecated in favor of createLoginContext.*
super("createLoginContext".equals(name) ?
"createLoginContext.*" : name, actions);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth;
/**
* Signals that a {@code destroy} operation failed.
*
* <p> This exception is thrown by credentials implementing
* the {@code Destroyable} interface when the {@code destroy}
* method fails.
*
*/
public class DestroyFailedException extends Exception {
private static final long serialVersionUID = -7790152857282749162L;
/**
* Constructs a DestroyFailedException with no detail message. A detail
* message is a String that describes this particular exception.
*/
public DestroyFailedException() {
super();
}
/**
* Constructs a DestroyFailedException with the specified detail
* message. A detail message is a String that describes this particular
* exception.
*
* <p>
*
* @param msg the detail message.
*/
public DestroyFailedException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth;
/**
* Objects such as credentials may optionally implement this interface
* to provide the capability to destroy its contents.
*
* @see javax.security.auth.Subject
*/
public interface Destroyable {
/**
* Destroy this {@code Object}.
*
* <p> Sensitive information associated with this {@code Object}
* is destroyed or cleared. Subsequent calls to certain methods
* on this {@code Object} will result in an
* {@code IllegalStateException} being thrown.
*
* <p>
* The default implementation throws {@code DestroyFailedException}.
*
* @exception DestroyFailedException if the destroy operation fails. <p>
*
* @exception SecurityException if the caller does not have permission
* to destroy this {@code Object}.
*/
public default void destroy() throws DestroyFailedException {
throw new DestroyFailedException();
}
/**
* Determine if this {@code Object} has been destroyed.
*
* <p>
* The default implementation returns false.
*
* @return true if this {@code Object} has been destroyed,
* false otherwise.
*/
public default boolean isDestroyed() {
return false;
}
}

View File

@@ -0,0 +1,362 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth;
import java.security.Security;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.util.Objects;
import sun.security.util.Debug;
/**
* <p> This is an abstract class for representing the system policy for
* Subject-based authorization. A subclass implementation
* of this class provides a means to specify a Subject-based
* access control {@code Policy}.
*
* <p> A {@code Policy} object can be queried for the set of
* Permissions granted to code running as a
* {@code Principal} in the following manner:
*
* <pre>
* policy = Policy.getPolicy();
* PermissionCollection perms = policy.getPermissions(subject,
* codeSource);
* </pre>
*
* The {@code Policy} object consults the local policy and returns
* and appropriate {@code Permissions} object with the
* Permissions granted to the Principals associated with the
* provided <i>subject</i>, and granted to the code specified
* by the provided <i>codeSource</i>.
*
* <p> A {@code Policy} contains the following information.
* Note that this example only represents the syntax for the default
* {@code Policy} implementation. Subclass implementations of this class
* may implement alternative syntaxes and may retrieve the
* {@code Policy} from any source such as files, databases,
* or servers.
*
* <p> Each entry in the {@code Policy} is represented as
* a <b><i>grant</i></b> entry. Each <b><i>grant</i></b> entry
* specifies a codebase, code signers, and Principals triplet,
* as well as the Permissions granted to that triplet.
*
* <pre>
* grant CodeBase ["URL"], Signedby ["signers"],
* Principal [Principal_Class] "Principal_Name" {
* Permission Permission_Class ["Target_Name"]
* [, "Permission_Actions"]
* [, signedBy "SignerName"];
* };
* </pre>
*
* The CodeBase and Signedby components of the triplet name/value pairs
* are optional. If they are not present, then any any codebase will match,
* and any signer (including unsigned code) will match.
* For Example,
*
* <pre>
* grant CodeBase "foo.com", Signedby "foo",
* Principal com.sun.security.auth.SolarisPrincipal "duke" {
* permission java.io.FilePermission "/home/duke", "read, write";
* };
* </pre>
*
* This <b><i>grant</i></b> entry specifies that code from "foo.com",
* signed by "foo', and running as a {@code SolarisPrincipal} with the
* name, duke, has one {@code Permission}. This {@code Permission}
* permits the executing code to read and write files in the directory,
* "/home/duke".
*
* <p> To "run" as a particular {@code Principal},
* code invokes the {@code Subject.doAs(subject, ...)} method.
* After invoking that method, the code runs as all the Principals
* associated with the specified {@code Subject}.
* Note that this {@code Policy} (and the Permissions
* granted in this {@code Policy}) only become effective
* after the call to {@code Subject.doAs} has occurred.
*
* <p> Multiple Principals may be listed within one <b><i>grant</i></b> entry.
* All the Principals in the grant entry must be associated with
* the {@code Subject} provided to {@code Subject.doAs}
* for that {@code Subject} to be granted the specified Permissions.
*
* <pre>
* grant Principal com.sun.security.auth.SolarisPrincipal "duke",
* Principal com.sun.security.auth.SolarisNumericUserPrincipal "0" {
* permission java.io.FilePermission "/home/duke", "read, write";
* permission java.net.SocketPermission "duke.com", "connect";
* };
* </pre>
*
* This entry grants any code running as both "duke" and "0"
* permission to read and write files in duke's home directory,
* as well as permission to make socket connections to "duke.com".
*
* <p> Note that non Principal-based grant entries are not permitted
* in this {@code Policy}. Therefore, grant entries such as:
*
* <pre>
* grant CodeBase "foo.com", Signedby "foo" {
* permission java.io.FilePermission "/tmp/scratch", "read, write";
* };
* </pre>
*
* are rejected. Such permission must be listed in the
* {@code java.security.Policy}.
*
* <p> The default {@code Policy} implementation can be changed by
* setting the value of the {@code auth.policy.provider} security property to
* the fully qualified name of the desired {@code Policy} implementation class.
*
* @deprecated as of JDK version 1.4 -- Replaced by java.security.Policy.
* java.security.Policy has a method:
* <pre>
* public PermissionCollection getPermissions
* (java.security.ProtectionDomain pd)
*
* </pre>
* and ProtectionDomain has a constructor:
* <pre>
* public ProtectionDomain
* (CodeSource cs,
* PermissionCollection permissions,
* ClassLoader loader,
* Principal[] principals)
* </pre>
*
* These two APIs provide callers the means to query the
* Policy for Principal-based Permission entries.
*
* @see java.security.Security security properties
*/
@Deprecated
public abstract class Policy {
private static Policy policy;
private final static String AUTH_POLICY =
"sun.security.provider.AuthPolicyFile";
private final java.security.AccessControlContext acc =
java.security.AccessController.getContext();
// true if a custom (not AUTH_POLICY) system-wide policy object is set
private static boolean isCustomPolicy;
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected Policy() { }
/**
* Returns the installed Policy object.
* This method first calls
* {@code SecurityManager.checkPermission} with the
* {@code AuthPermission("getPolicy")} permission
* to ensure the caller has permission to get the Policy object.
*
* <p>
*
* @return the installed Policy. The return value cannot be
* {@code null}.
*
* @exception java.lang.SecurityException if the current thread does not
* have permission to get the Policy object.
*
* @see #setPolicy
*/
public static Policy getPolicy() {
java.lang.SecurityManager sm = System.getSecurityManager();
if (sm != null) sm.checkPermission(new AuthPermission("getPolicy"));
return getPolicyNoCheck();
}
/**
* Returns the installed Policy object, skipping the security check.
*
* @return the installed Policy.
*
*/
static Policy getPolicyNoCheck() {
if (policy == null) {
synchronized(Policy.class) {
if (policy == null) {
String policy_class = null;
policy_class = AccessController.doPrivileged
(new PrivilegedAction<String>() {
public String run() {
return java.security.Security.getProperty
("auth.policy.provider");
}
});
if (policy_class == null) {
policy_class = AUTH_POLICY;
}
try {
final String finalClass = policy_class;
Policy untrustedImpl = AccessController.doPrivileged(
new PrivilegedExceptionAction<Policy>() {
public Policy run() throws ClassNotFoundException,
InstantiationException,
IllegalAccessException {
Class<? extends Policy> implClass = Class.forName(
finalClass, false,
Thread.currentThread().getContextClassLoader()
).asSubclass(Policy.class);
return implClass.newInstance();
}
});
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>() {
public Void run() {
setPolicy(untrustedImpl);
isCustomPolicy = !finalClass.equals(AUTH_POLICY);
return null;
}
}, Objects.requireNonNull(untrustedImpl.acc)
);
} catch (Exception e) {
throw new SecurityException
(sun.security.util.ResourcesMgr.getString
("unable.to.instantiate.Subject.based.policy"));
}
}
}
}
return policy;
}
/**
* Sets the system-wide Policy object. This method first calls
* {@code SecurityManager.checkPermission} with the
* {@code AuthPermission("setPolicy")}
* permission to ensure the caller has permission to set the Policy.
*
* <p>
*
* @param policy the new system Policy object.
*
* @exception java.lang.SecurityException if the current thread does not
* have permission to set the Policy.
*
* @see #getPolicy
*/
public static void setPolicy(Policy policy) {
java.lang.SecurityManager sm = System.getSecurityManager();
if (sm != null) sm.checkPermission(new AuthPermission("setPolicy"));
Policy.policy = policy;
// all non-null policy objects are assumed to be custom
isCustomPolicy = policy != null ? true : false;
}
/**
* Returns true if a custom (not AUTH_POLICY) system-wide policy object
* has been set or installed. This method is called by
* SubjectDomainCombiner to provide backwards compatibility for
* developers that provide their own javax.security.auth.Policy
* implementations.
*
* @return true if a custom (not AUTH_POLICY) system-wide policy object
* has been set; false otherwise
*/
static boolean isCustomPolicySet(Debug debug) {
if (policy != null) {
if (debug != null && isCustomPolicy) {
debug.println("Providing backwards compatibility for " +
"javax.security.auth.policy implementation: " +
policy.toString());
}
return isCustomPolicy;
}
// check if custom policy has been set using auth.policy.provider prop
String policyClass = java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction<String>() {
public String run() {
return Security.getProperty("auth.policy.provider");
}
});
if (policyClass != null && !policyClass.equals(AUTH_POLICY)) {
if (debug != null) {
debug.println("Providing backwards compatibility for " +
"javax.security.auth.policy implementation: " +
policyClass);
}
return true;
}
return false;
}
/**
* Retrieve the Permissions granted to the Principals associated with
* the specified {@code CodeSource}.
*
* <p>
*
* @param subject the {@code Subject}
* whose associated Principals,
* in conjunction with the provided
* {@code CodeSource}, determines the Permissions
* returned by this method. This parameter
* may be {@code null}. <p>
*
* @param cs the code specified by its {@code CodeSource}
* that determines, in conjunction with the provided
* {@code Subject}, the Permissions
* returned by this method. This parameter may be
* {@code null}.
*
* @return the Collection of Permissions granted to all the
* {@code Subject} and code specified in
* the provided <i>subject</i> and <i>cs</i>
* parameters.
*/
public abstract java.security.PermissionCollection getPermissions
(Subject subject,
java.security.CodeSource cs);
/**
* Refresh and reload the Policy.
*
* <p>This method causes this object to refresh/reload its current
* Policy. This is implementation-dependent.
* For example, if the Policy object is stored in
* a file, calling {@code refresh} will cause the file to be re-read.
*
* <p>
*
* @exception SecurityException if the caller does not have permission
* to refresh the Policy.
*/
public abstract void refresh();
}

View File

@@ -0,0 +1,561 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth;
import java.util.*;
import java.text.MessageFormat;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Principal;
import sun.security.util.ResourcesMgr;
/**
* This class is used to protect access to private Credentials
* belonging to a particular {@code Subject}. The {@code Subject}
* is represented by a Set of Principals.
*
* <p> The target name of this {@code Permission} specifies
* a Credential class name, and a Set of Principals.
* The only valid value for this Permission's actions is, "read".
* The target name must abide by the following syntax:
*
* <pre>
* CredentialClass {PrincipalClass "PrincipalName"}*
* </pre>
*
* For example, the following permission grants access to the
* com.sun.PrivateCredential owned by Subjects which have
* a com.sun.Principal with the name, "duke". Note that although
* this example, as well as all the examples below, do not contain
* Codebase, SignedBy, or Principal information in the grant statement
* (for simplicity reasons), actual policy configurations should
* specify that information when appropriate.
*
* <pre>
*
* grant {
* permission javax.security.auth.PrivateCredentialPermission
* "com.sun.PrivateCredential com.sun.Principal \"duke\"",
* "read";
* };
* </pre>
*
* If CredentialClass is "*", then access is granted to
* all private Credentials belonging to the specified
* {@code Subject}.
* If "PrincipalName" is "*", then access is granted to the
* specified Credential owned by any {@code Subject} that has the
* specified {@code Principal} (the actual PrincipalName doesn't matter).
* For example, the following grants access to the
* a.b.Credential owned by any {@code Subject} that has
* an a.b.Principal.
*
* <pre>
* grant {
* permission javax.security.auth.PrivateCredentialPermission
* "a.b.Credential a.b.Principal "*"",
* "read";
* };
* </pre>
*
* If both the PrincipalClass and "PrincipalName" are "*",
* then access is granted to the specified Credential owned by
* any {@code Subject}.
*
* <p> In addition, the PrincipalClass/PrincipalName pairing may be repeated:
*
* <pre>
* grant {
* permission javax.security.auth.PrivateCredentialPermission
* "a.b.Credential a.b.Principal "duke" c.d.Principal "dukette"",
* "read";
* };
* </pre>
*
* The above grants access to the private Credential, "a.b.Credential",
* belonging to a {@code Subject} with at least two associated Principals:
* "a.b.Principal" with the name, "duke", and "c.d.Principal", with the name,
* "dukette".
*
*/
public final class PrivateCredentialPermission extends Permission {
private static final long serialVersionUID = 5284372143517237068L;
private static final CredOwner[] EMPTY_PRINCIPALS = new CredOwner[0];
/**
* @serial
*/
private String credentialClass;
/**
* @serial The Principals associated with this permission.
* The set contains elements of type,
* {@code PrivateCredentialPermission.CredOwner}.
*/
private Set<Principal> principals; // ignored - kept around for compatibility
private transient CredOwner[] credOwners;
/**
* @serial
*/
private boolean testing = false;
/**
* Create a new {@code PrivateCredentialPermission}
* with the specified {@code credentialClass} and Principals.
*/
PrivateCredentialPermission(String credentialClass,
Set<Principal> principals) {
super(credentialClass);
this.credentialClass = credentialClass;
synchronized(principals) {
if (principals.size() == 0) {
this.credOwners = EMPTY_PRINCIPALS;
} else {
this.credOwners = new CredOwner[principals.size()];
int index = 0;
Iterator<Principal> i = principals.iterator();
while (i.hasNext()) {
Principal p = i.next();
this.credOwners[index++] = new CredOwner
(p.getClass().getName(),
p.getName());
}
}
}
}
/**
* Creates a new {@code PrivateCredentialPermission}
* with the specified {@code name}. The {@code name}
* specifies both a Credential class and a {@code Principal} Set.
*
* <p>
*
* @param name the name specifying the Credential class and
* {@code Principal} Set. <p>
*
* @param actions the actions specifying that the Credential can be read.
*
* @throws IllegalArgumentException if {@code name} does not conform
* to the correct syntax or if {@code actions} is not "read".
*/
public PrivateCredentialPermission(String name, String actions) {
super(name);
if (!"read".equalsIgnoreCase(actions))
throw new IllegalArgumentException
(ResourcesMgr.getString("actions.can.only.be.read."));
init(name);
}
/**
* Returns the Class name of the Credential associated with this
* {@code PrivateCredentialPermission}.
*
* <p>
*
* @return the Class name of the Credential associated with this
* {@code PrivateCredentialPermission}.
*/
public String getCredentialClass() {
return credentialClass;
}
/**
* Returns the {@code Principal} classes and names
* associated with this {@code PrivateCredentialPermission}.
* The information is returned as a two-dimensional array (array[x][y]).
* The 'x' value corresponds to the number of {@code Principal}
* class and name pairs. When (y==0), it corresponds to
* the {@code Principal} class value, and when (y==1),
* it corresponds to the {@code Principal} name value.
* For example, array[0][0] corresponds to the class name of
* the first {@code Principal} in the array. array[0][1]
* corresponds to the {@code Principal} name of the
* first {@code Principal} in the array.
*
* <p>
*
* @return the {@code Principal} class and names associated
* with this {@code PrivateCredentialPermission}.
*/
public String[][] getPrincipals() {
if (credOwners == null || credOwners.length == 0) {
return new String[0][0];
}
String[][] pArray = new String[credOwners.length][2];
for (int i = 0; i < credOwners.length; i++) {
pArray[i][0] = credOwners[i].principalClass;
pArray[i][1] = credOwners[i].principalName;
}
return pArray;
}
/**
* Checks if this {@code PrivateCredentialPermission} implies
* the specified {@code Permission}.
*
* <p>
*
* This method returns true if:
* <ul>
* <li> <i>p</i> is an instanceof PrivateCredentialPermission and
* <li> the target name for <i>p</i> is implied by this object's
* target name. For example:
* <pre>
* [* P1 "duke"] implies [a.b.Credential P1 "duke"].
* [C1 P1 "duke"] implies [C1 P1 "duke" P2 "dukette"].
* [C1 P2 "dukette"] implies [C1 P1 "duke" P2 "dukette"].
* </pre>
* </ul>
*
* <p>
*
* @param p the {@code Permission} to check against.
*
* @return true if this {@code PrivateCredentialPermission} implies
* the specified {@code Permission}, false if not.
*/
public boolean implies(Permission p) {
if (p == null || !(p instanceof PrivateCredentialPermission))
return false;
PrivateCredentialPermission that = (PrivateCredentialPermission)p;
if (!impliesCredentialClass(credentialClass, that.credentialClass))
return false;
return impliesPrincipalSet(credOwners, that.credOwners);
}
/**
* Checks two {@code PrivateCredentialPermission} objects for
* equality. Checks that <i>obj</i> is a
* {@code PrivateCredentialPermission},
* and has the same credential class as this object,
* as well as the same Principals as this object.
* The order of the Principals in the respective Permission's
* target names is not relevant.
*
* <p>
*
* @param obj the object we are testing for equality with this object.
*
* @return true if obj is a {@code PrivateCredentialPermission},
* has the same credential class as this object,
* and has the same Principals as this object.
*/
public boolean equals(Object obj) {
if (obj == this)
return true;
if (! (obj instanceof PrivateCredentialPermission))
return false;
PrivateCredentialPermission that = (PrivateCredentialPermission)obj;
return (this.implies(that) && that.implies(this));
}
/**
* Returns the hash code value for this object.
*
* @return a hash code value for this object.
*/
public int hashCode() {
return this.credentialClass.hashCode();
}
/**
* Returns the "canonical string representation" of the actions.
* This method always returns the String, "read".
*
* <p>
*
* @return the actions (always returns "read").
*/
public String getActions() {
return "read";
}
/**
* Return a homogeneous collection of PrivateCredentialPermissions
* in a {@code PermissionCollection}.
* No such {@code PermissionCollection} is defined,
* so this method always returns {@code null}.
*
* <p>
*
* @return null in all cases.
*/
public PermissionCollection newPermissionCollection() {
return null;
}
private void init(String name) {
if (name == null || name.trim().length() == 0) {
throw new IllegalArgumentException("invalid empty name");
}
ArrayList<CredOwner> pList = new ArrayList<>();
StringTokenizer tokenizer = new StringTokenizer(name, " ", true);
String principalClass = null;
String principalName = null;
if (testing)
System.out.println("whole name = " + name);
// get the Credential Class
credentialClass = tokenizer.nextToken();
if (testing)
System.out.println("Credential Class = " + credentialClass);
if (tokenizer.hasMoreTokens() == false) {
MessageFormat form = new MessageFormat(ResourcesMgr.getString
("permission.name.name.syntax.invalid."));
Object[] source = {name};
throw new IllegalArgumentException
(form.format(source) + ResourcesMgr.getString
("Credential.Class.not.followed.by.a.Principal.Class.and.Name"));
}
while (tokenizer.hasMoreTokens()) {
// skip delimiter
tokenizer.nextToken();
// get the Principal Class
principalClass = tokenizer.nextToken();
if (testing)
System.out.println(" Principal Class = " + principalClass);
if (tokenizer.hasMoreTokens() == false) {
MessageFormat form = new MessageFormat(ResourcesMgr.getString
("permission.name.name.syntax.invalid."));
Object[] source = {name};
throw new IllegalArgumentException
(form.format(source) + ResourcesMgr.getString
("Principal.Class.not.followed.by.a.Principal.Name"));
}
// skip delimiter
tokenizer.nextToken();
// get the Principal Name
principalName = tokenizer.nextToken();
if (!principalName.startsWith("\"")) {
MessageFormat form = new MessageFormat(ResourcesMgr.getString
("permission.name.name.syntax.invalid."));
Object[] source = {name};
throw new IllegalArgumentException
(form.format(source) + ResourcesMgr.getString
("Principal.Name.must.be.surrounded.by.quotes"));
}
if (!principalName.endsWith("\"")) {
// we have a name with spaces in it --
// keep parsing until we find the end quote,
// and keep the spaces in the name
while (tokenizer.hasMoreTokens()) {
principalName = principalName + tokenizer.nextToken();
if (principalName.endsWith("\""))
break;
}
if (!principalName.endsWith("\"")) {
MessageFormat form = new MessageFormat
(ResourcesMgr.getString
("permission.name.name.syntax.invalid."));
Object[] source = {name};
throw new IllegalArgumentException
(form.format(source) + ResourcesMgr.getString
("Principal.Name.missing.end.quote"));
}
}
if (testing)
System.out.println("\tprincipalName = '" + principalName + "'");
principalName = principalName.substring
(1, principalName.length() - 1);
if (principalClass.equals("*") &&
!principalName.equals("*")) {
throw new IllegalArgumentException(ResourcesMgr.getString
("PrivateCredentialPermission.Principal.Class.can.not.be.a.wildcard.value.if.Principal.Name.is.not.a.wildcard.value"));
}
if (testing)
System.out.println("\tprincipalName = '" + principalName + "'");
pList.add(new CredOwner(principalClass, principalName));
}
this.credOwners = new CredOwner[pList.size()];
pList.toArray(this.credOwners);
}
private boolean impliesCredentialClass(String thisC, String thatC) {
// this should never happen
if (thisC == null || thatC == null)
return false;
if (testing)
System.out.println("credential class comparison: " +
thisC + "/" + thatC);
if (thisC.equals("*"))
return true;
/**
* XXX let's not enable this for now --
* if people want it, we'll enable it later
*/
/*
if (thisC.endsWith("*")) {
String cClass = thisC.substring(0, thisC.length() - 2);
return thatC.startsWith(cClass);
}
*/
return thisC.equals(thatC);
}
private boolean impliesPrincipalSet(CredOwner[] thisP, CredOwner[] thatP) {
// this should never happen
if (thisP == null || thatP == null)
return false;
if (thatP.length == 0)
return true;
if (thisP.length == 0)
return false;
for (int i = 0; i < thisP.length; i++) {
boolean foundMatch = false;
for (int j = 0; j < thatP.length; j++) {
if (thisP[i].implies(thatP[j])) {
foundMatch = true;
break;
}
}
if (!foundMatch) {
return false;
}
}
return true;
}
/**
* Reads this object from a stream (i.e., deserializes it)
*/
private void readObject(java.io.ObjectInputStream s) throws
java.io.IOException,
ClassNotFoundException {
s.defaultReadObject();
// perform new initialization from the permission name
if (getName().indexOf(" ") == -1 && getName().indexOf("\"") == -1) {
// name only has a credential class specified
credentialClass = getName();
credOwners = EMPTY_PRINCIPALS;
} else {
// perform regular initialization
init(getName());
}
}
/**
* @serial include
*/
static class CredOwner implements java.io.Serializable {
private static final long serialVersionUID = -5607449830436408266L;
/**
* @serial
*/
String principalClass;
/**
* @serial
*/
String principalName;
CredOwner(String principalClass, String principalName) {
this.principalClass = principalClass;
this.principalName = principalName;
}
public boolean implies(Object obj) {
if (obj == null || !(obj instanceof CredOwner))
return false;
CredOwner that = (CredOwner)obj;
if (principalClass.equals("*") ||
principalClass.equals(that.principalClass)) {
if (principalName.equals("*") ||
principalName.equals(that.principalName)) {
return true;
}
}
/**
* XXX no code yet to support a.b.*
*/
return false;
}
public String toString() {
MessageFormat form = new MessageFormat(ResourcesMgr.getString
("CredOwner.Principal.Class.class.Principal.Name.name"));
Object[] source = {principalClass, principalName};
return (form.format(source));
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth;
/**
* Signals that a {@code refresh} operation failed.
*
* <p> This exception is thrown by credentials implementing
* the {@code Refreshable} interface when the {@code refresh}
* method fails.
*
*/
public class RefreshFailedException extends Exception {
private static final long serialVersionUID = 5058444488565265840L;
/**
* Constructs a RefreshFailedException with no detail message. A detail
* message is a String that describes this particular exception.
*/
public RefreshFailedException() {
super();
}
/**
* Constructs a RefreshFailedException with the specified detail
* message. A detail message is a String that describes this particular
* exception.
*
* <p>
*
* @param msg the detail message.
*/
public RefreshFailedException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth;
/**
* Objects such as credentials may optionally implement this
* interface to provide the capability to refresh itself.
* For example, a credential with a particular time-restricted lifespan
* may implement this interface to allow callers to refresh the time period
* for which it is valid.
*
* @see javax.security.auth.Subject
*/
public interface Refreshable {
/**
* Determine if this {@code Object} is current.
*
* <p>
*
* @return true if this {@code Object} is currently current,
* false otherwise.
*/
boolean isCurrent();
/**
* Update or extend the validity period for this
* {@code Object}.
*
* <p>
*
* @exception SecurityException if the caller does not have permission
* to update or extend the validity period for this
* {@code Object}. <p>
*
* @exception RefreshFailedException if the refresh attempt failed.
*/
void refresh() throws RefreshFailedException;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,583 @@
/*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth;
import java.security.AccessController;
import java.security.Permission;
import java.security.Permissions;
import java.security.PermissionCollection;
import java.security.Policy;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.security.Security;
import java.util.Set;
import java.util.WeakHashMap;
import java.lang.ref.WeakReference;
import sun.misc.SharedSecrets;
import sun.misc.JavaSecurityProtectionDomainAccess;
/**
* A {@code SubjectDomainCombiner} updates ProtectionDomains
* with Principals from the {@code Subject} associated with this
* {@code SubjectDomainCombiner}.
*
*/
public class SubjectDomainCombiner implements java.security.DomainCombiner {
private Subject subject;
private WeakKeyValueMap<ProtectionDomain, ProtectionDomain> cachedPDs =
new WeakKeyValueMap<>();
private Set<Principal> principalSet;
private Principal[] principals;
private static final sun.security.util.Debug debug =
sun.security.util.Debug.getInstance("combiner",
"\t[SubjectDomainCombiner]");
@SuppressWarnings("deprecation")
// Note: check only at classloading time, not dynamically during combine()
private static final boolean useJavaxPolicy =
javax.security.auth.Policy.isCustomPolicySet(debug);
// Relevant only when useJavaxPolicy is true
private static final boolean allowCaching =
(useJavaxPolicy && cachePolicy());
private static final JavaSecurityProtectionDomainAccess pdAccess =
SharedSecrets.getJavaSecurityProtectionDomainAccess();
/**
* Associate the provided {@code Subject} with this
* {@code SubjectDomainCombiner}.
*
* <p>
*
* @param subject the {@code Subject} to be associated with
* with this {@code SubjectDomainCombiner}.
*/
public SubjectDomainCombiner(Subject subject) {
this.subject = subject;
if (subject.isReadOnly()) {
principalSet = subject.getPrincipals();
principals = principalSet.toArray
(new Principal[principalSet.size()]);
}
}
/**
* Get the {@code Subject} associated with this
* {@code SubjectDomainCombiner}.
*
* <p>
*
* @return the {@code Subject} associated with this
* {@code SubjectDomainCombiner}, or {@code null}
* if no {@code Subject} is associated with this
* {@code SubjectDomainCombiner}.
*
* @exception SecurityException if the caller does not have permission
* to get the {@code Subject} associated with this
* {@code SubjectDomainCombiner}.
*/
public Subject getSubject() {
java.lang.SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new AuthPermission
("getSubjectFromDomainCombiner"));
}
return subject;
}
/**
* Update the relevant ProtectionDomains with the Principals
* from the {@code Subject} associated with this
* {@code SubjectDomainCombiner}.
*
* <p> A new {@code ProtectionDomain} instance is created
* for each {@code ProtectionDomain} in the
* <i>currentDomains</i> array. Each new {@code ProtectionDomain}
* instance is created using the {@code CodeSource},
* {@code Permission}s and {@code ClassLoader}
* from the corresponding {@code ProtectionDomain} in
* <i>currentDomains</i>, as well as with the Principals from
* the {@code Subject} associated with this
* {@code SubjectDomainCombiner}.
*
* <p> All of the newly instantiated ProtectionDomains are
* combined into a new array. The ProtectionDomains from the
* <i>assignedDomains</i> array are appended to this new array,
* and the result is returned.
*
* <p> Note that optimizations such as the removal of duplicate
* ProtectionDomains may have occurred.
* In addition, caching of ProtectionDomains may be permitted.
*
* <p>
*
* @param currentDomains the ProtectionDomains associated with the
* current execution Thread, up to the most recent
* privileged {@code ProtectionDomain}.
* The ProtectionDomains are are listed in order of execution,
* with the most recently executing {@code ProtectionDomain}
* residing at the beginning of the array. This parameter may
* be {@code null} if the current execution Thread
* has no associated ProtectionDomains.<p>
*
* @param assignedDomains the ProtectionDomains inherited from the
* parent Thread, or the ProtectionDomains from the
* privileged <i>context</i>, if a call to
* AccessController.doPrivileged(..., <i>context</i>)
* had occurred This parameter may be {@code null}
* if there were no ProtectionDomains inherited from the
* parent Thread, or from the privileged <i>context</i>.
*
* @return a new array consisting of the updated ProtectionDomains,
* or {@code null}.
*/
public ProtectionDomain[] combine(ProtectionDomain[] currentDomains,
ProtectionDomain[] assignedDomains) {
if (debug != null) {
if (subject == null) {
debug.println("null subject");
} else {
final Subject s = subject;
AccessController.doPrivileged
(new java.security.PrivilegedAction<Void>() {
public Void run() {
debug.println(s.toString());
return null;
}
});
}
printInputDomains(currentDomains, assignedDomains);
}
if (currentDomains == null || currentDomains.length == 0) {
// No need to optimize assignedDomains because it should
// have been previously optimized (when it was set).
// Note that we are returning a direct reference
// to the input array - since ACC does not clone
// the arrays when it calls combiner.combine,
// multiple ACC instances may share the same
// array instance in this case
return assignedDomains;
}
// optimize currentDomains
//
// No need to optimize assignedDomains because it should
// have been previously optimized (when it was set).
currentDomains = optimize(currentDomains);
if (debug != null) {
debug.println("after optimize");
printInputDomains(currentDomains, assignedDomains);
}
if (currentDomains == null && assignedDomains == null) {
return null;
}
// maintain backwards compatibility for developers who provide
// their own custom javax.security.auth.Policy implementations
if (useJavaxPolicy) {
return combineJavaxPolicy(currentDomains, assignedDomains);
}
int cLen = (currentDomains == null ? 0 : currentDomains.length);
int aLen = (assignedDomains == null ? 0 : assignedDomains.length);
// the ProtectionDomains for the new AccessControlContext
// that we will return
ProtectionDomain[] newDomains = new ProtectionDomain[cLen + aLen];
boolean allNew = true;
synchronized(cachedPDs) {
if (!subject.isReadOnly() &&
!subject.getPrincipals().equals(principalSet)) {
// if the Subject was mutated, clear the PD cache
Set<Principal> newSet = subject.getPrincipals();
synchronized(newSet) {
principalSet = new java.util.HashSet<Principal>(newSet);
}
principals = principalSet.toArray
(new Principal[principalSet.size()]);
cachedPDs.clear();
if (debug != null) {
debug.println("Subject mutated - clearing cache");
}
}
ProtectionDomain subjectPd;
for (int i = 0; i < cLen; i++) {
ProtectionDomain pd = currentDomains[i];
subjectPd = cachedPDs.getValue(pd);
if (subjectPd == null) {
if (pdAccess.getStaticPermissionsField(pd)) {
// Need to keep static ProtectionDomain objects static
subjectPd = new ProtectionDomain(pd.getCodeSource(),
pd.getPermissions());
} else {
subjectPd = new ProtectionDomain(pd.getCodeSource(),
pd.getPermissions(),
pd.getClassLoader(),
principals);
}
cachedPDs.putValue(pd, subjectPd);
} else {
allNew = false;
}
newDomains[i] = subjectPd;
}
}
if (debug != null) {
debug.println("updated current: ");
for (int i = 0; i < cLen; i++) {
debug.println("\tupdated[" + i + "] = " +
printDomain(newDomains[i]));
}
}
// now add on the assigned domains
if (aLen > 0) {
System.arraycopy(assignedDomains, 0, newDomains, cLen, aLen);
// optimize the result (cached PDs might exist in assignedDomains)
if (!allNew) {
newDomains = optimize(newDomains);
}
}
// if aLen == 0 || allNew, no need to further optimize newDomains
if (debug != null) {
if (newDomains == null || newDomains.length == 0) {
debug.println("returning null");
} else {
debug.println("combinedDomains: ");
for (int i = 0; i < newDomains.length; i++) {
debug.println("newDomain " + i + ": " +
printDomain(newDomains[i]));
}
}
}
// return the new ProtectionDomains
if (newDomains == null || newDomains.length == 0) {
return null;
} else {
return newDomains;
}
}
/**
* Use the javax.security.auth.Policy implementation
*/
private ProtectionDomain[] combineJavaxPolicy(
ProtectionDomain[] currentDomains,
ProtectionDomain[] assignedDomains) {
if (!allowCaching) {
java.security.AccessController.doPrivileged
(new PrivilegedAction<Void>() {
@SuppressWarnings("deprecation")
public Void run() {
// Call refresh only caching is disallowed
javax.security.auth.Policy.getPolicy().refresh();
return null;
}
});
}
int cLen = (currentDomains == null ? 0 : currentDomains.length);
int aLen = (assignedDomains == null ? 0 : assignedDomains.length);
// the ProtectionDomains for the new AccessControlContext
// that we will return
ProtectionDomain[] newDomains = new ProtectionDomain[cLen + aLen];
synchronized(cachedPDs) {
if (!subject.isReadOnly() &&
!subject.getPrincipals().equals(principalSet)) {
// if the Subject was mutated, clear the PD cache
Set<Principal> newSet = subject.getPrincipals();
synchronized(newSet) {
principalSet = new java.util.HashSet<Principal>(newSet);
}
principals = principalSet.toArray
(new Principal[principalSet.size()]);
cachedPDs.clear();
if (debug != null) {
debug.println("Subject mutated - clearing cache");
}
}
for (int i = 0; i < cLen; i++) {
ProtectionDomain pd = currentDomains[i];
ProtectionDomain subjectPd = cachedPDs.getValue(pd);
if (subjectPd == null) {
if (pdAccess.getStaticPermissionsField(pd)) {
// keep static ProtectionDomain objects static
subjectPd = new ProtectionDomain(pd.getCodeSource(),
pd.getPermissions());
} else {
// XXX
// we must first add the original permissions.
// that way when we later add the new JAAS permissions,
// any unresolved JAAS-related permissions will
// automatically get resolved.
// get the original perms
Permissions perms = new Permissions();
PermissionCollection coll = pd.getPermissions();
java.util.Enumeration<Permission> e;
if (coll != null) {
synchronized (coll) {
e = coll.elements();
while (e.hasMoreElements()) {
Permission newPerm =
e.nextElement();
perms.add(newPerm);
}
}
}
// get perms from the policy
final java.security.CodeSource finalCs = pd.getCodeSource();
final Subject finalS = subject;
PermissionCollection newPerms =
java.security.AccessController.doPrivileged
(new PrivilegedAction<PermissionCollection>() {
@SuppressWarnings("deprecation")
public PermissionCollection run() {
return
javax.security.auth.Policy.getPolicy().getPermissions
(finalS, finalCs);
}
});
// add the newly granted perms,
// avoiding duplicates
synchronized (newPerms) {
e = newPerms.elements();
while (e.hasMoreElements()) {
Permission newPerm = e.nextElement();
if (!perms.implies(newPerm)) {
perms.add(newPerm);
if (debug != null)
debug.println (
"Adding perm " + newPerm + "\n");
}
}
}
subjectPd = new ProtectionDomain
(finalCs, perms, pd.getClassLoader(), principals);
}
if (allowCaching)
cachedPDs.putValue(pd, subjectPd);
}
newDomains[i] = subjectPd;
}
}
if (debug != null) {
debug.println("updated current: ");
for (int i = 0; i < cLen; i++) {
debug.println("\tupdated[" + i + "] = " + newDomains[i]);
}
}
// now add on the assigned domains
if (aLen > 0) {
System.arraycopy(assignedDomains, 0, newDomains, cLen, aLen);
}
if (debug != null) {
if (newDomains == null || newDomains.length == 0) {
debug.println("returning null");
} else {
debug.println("combinedDomains: ");
for (int i = 0; i < newDomains.length; i++) {
debug.println("newDomain " + i + ": " +
newDomains[i].toString());
}
}
}
// return the new ProtectionDomains
if (newDomains == null || newDomains.length == 0) {
return null;
} else {
return newDomains;
}
}
private static ProtectionDomain[] optimize(ProtectionDomain[] domains) {
if (domains == null || domains.length == 0)
return null;
ProtectionDomain[] optimized = new ProtectionDomain[domains.length];
ProtectionDomain pd;
int num = 0;
for (int i = 0; i < domains.length; i++) {
// skip domains with AllPermission
// XXX
//
// if (domains[i].implies(ALL_PERMISSION))
// continue;
// skip System Domains
if ((pd = domains[i]) != null) {
// remove duplicates
boolean found = false;
for (int j = 0; j < num && !found; j++) {
found = (optimized[j] == pd);
}
if (!found) {
optimized[num++] = pd;
}
}
}
// resize the array if necessary
if (num > 0 && num < domains.length) {
ProtectionDomain[] downSize = new ProtectionDomain[num];
System.arraycopy(optimized, 0, downSize, 0, downSize.length);
optimized = downSize;
}
return ((num == 0 || optimized.length == 0) ? null : optimized);
}
private static boolean cachePolicy() {
String s = AccessController.doPrivileged
(new PrivilegedAction<String>() {
public String run() {
return Security.getProperty("cache.auth.policy");
}
});
if (s != null) {
return Boolean.parseBoolean(s);
}
// cache by default
return true;
}
private static void printInputDomains(ProtectionDomain[] currentDomains,
ProtectionDomain[] assignedDomains) {
if (currentDomains == null || currentDomains.length == 0) {
debug.println("currentDomains null or 0 length");
} else {
for (int i = 0; currentDomains != null &&
i < currentDomains.length; i++) {
if (currentDomains[i] == null) {
debug.println("currentDomain " + i + ": SystemDomain");
} else {
debug.println("currentDomain " + i + ": " +
printDomain(currentDomains[i]));
}
}
}
if (assignedDomains == null || assignedDomains.length == 0) {
debug.println("assignedDomains null or 0 length");
} else {
debug.println("assignedDomains = ");
for (int i = 0; assignedDomains != null &&
i < assignedDomains.length; i++) {
if (assignedDomains[i] == null) {
debug.println("assignedDomain " + i + ": SystemDomain");
} else {
debug.println("assignedDomain " + i + ": " +
printDomain(assignedDomains[i]));
}
}
}
}
private static String printDomain(final ProtectionDomain pd) {
if (pd == null) {
return "null";
}
return AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return pd.toString();
}
});
}
/**
* A HashMap that has weak keys and values.
*
* Key objects in this map are the "current" ProtectionDomain instances
* received via the combine method. Each "current" PD is mapped to a
* new PD instance that holds both the contents of the "current" PD,
* as well as the principals from the Subject associated with this combiner.
*
* The newly created "principal-based" PD values must be stored as
* WeakReferences since they contain strong references to the
* corresponding key object (the "current" non-principal-based PD),
* which will prevent the key from being GC'd. Specifically,
* a "principal-based" PD contains strong references to the CodeSource,
* signer certs, PermissionCollection and ClassLoader objects
* in the "current PD".
*/
private static class WeakKeyValueMap<K,V> extends
WeakHashMap<K,WeakReference<V>> {
public V getValue(K key) {
WeakReference<V> wr = super.get(key);
if (wr != null) {
return wr.get();
}
return null;
}
public V putValue(K key, V value) {
WeakReference<V> wr = super.put(key, new WeakReference<V>(value));
if (wr != null) {
return wr.get();
}
return null;
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.callback;
/**
* <p> Implementations of this interface are passed to a
* {@code CallbackHandler}, allowing underlying security services
* the ability to interact with a calling application to retrieve specific
* authentication data such as usernames and passwords, or to display
* certain information, such as error and warning messages.
*
* <p> {@code Callback} implementations do not retrieve or
* display the information requested by underlying security services.
* {@code Callback} implementations simply provide the means
* to pass such requests to applications, and for applications,
* if appropriate, to return requested information back to the
* underlying security services.
*
* @see javax.security.auth.callback.CallbackHandler
* @see javax.security.auth.callback.ChoiceCallback
* @see javax.security.auth.callback.ConfirmationCallback
* @see javax.security.auth.callback.LanguageCallback
* @see javax.security.auth.callback.NameCallback
* @see javax.security.auth.callback.PasswordCallback
* @see javax.security.auth.callback.TextInputCallback
* @see javax.security.auth.callback.TextOutputCallback
*/
public interface Callback { }

View File

@@ -0,0 +1,150 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.callback;
/**
* <p> An application implements a {@code CallbackHandler} and passes
* it to underlying security services so that they may interact with
* the application to retrieve specific authentication data,
* such as usernames and passwords, or to display certain information,
* such as error and warning messages.
*
* <p> CallbackHandlers are implemented in an application-dependent fashion.
* For example, implementations for an application with a graphical user
* interface (GUI) may pop up windows to prompt for requested information
* or to display error messages. An implementation may also choose to obtain
* requested information from an alternate source without asking the end user.
*
* <p> Underlying security services make requests for different types
* of information by passing individual Callbacks to the
* {@code CallbackHandler}. The {@code CallbackHandler}
* implementation decides how to retrieve and display information
* depending on the Callbacks passed to it. For example,
* if the underlying service needs a username and password to
* authenticate a user, it uses a {@code NameCallback} and
* {@code PasswordCallback}. The {@code CallbackHandler}
* can then choose to prompt for a username and password serially,
* or to prompt for both in a single window.
*
* <p> A default {@code CallbackHandler} class implementation
* may be specified by setting the value of the
* {@code auth.login.defaultCallbackHandler} security property.
*
* <p> If the security property is set to the fully qualified name of a
* {@code CallbackHandler} implementation class,
* then a {@code LoginContext} will load the specified
* {@code CallbackHandler} and pass it to the underlying LoginModules.
* The {@code LoginContext} only loads the default handler
* if it was not provided one.
*
* <p> All default handler implementations must provide a public
* zero-argument constructor.
*
* @see java.security.Security security properties
*/
public interface CallbackHandler {
/**
* <p> Retrieve or display the information requested in the
* provided Callbacks.
*
* <p> The {@code handle} method implementation checks the
* instance(s) of the {@code Callback} object(s) passed in
* to retrieve or display the requested information.
* The following example is provided to help demonstrate what an
* {@code handle} method implementation might look like.
* This example code is for guidance only. Many details,
* including proper error handling, are left out for simplicity.
*
* <pre>{@code
* public void handle(Callback[] callbacks)
* throws IOException, UnsupportedCallbackException {
*
* for (int i = 0; i < callbacks.length; i++) {
* if (callbacks[i] instanceof TextOutputCallback) {
*
* // display the message according to the specified type
* TextOutputCallback toc = (TextOutputCallback)callbacks[i];
* switch (toc.getMessageType()) {
* case TextOutputCallback.INFORMATION:
* System.out.println(toc.getMessage());
* break;
* case TextOutputCallback.ERROR:
* System.out.println("ERROR: " + toc.getMessage());
* break;
* case TextOutputCallback.WARNING:
* System.out.println("WARNING: " + toc.getMessage());
* break;
* default:
* throw new IOException("Unsupported message type: " +
* toc.getMessageType());
* }
*
* } else if (callbacks[i] instanceof NameCallback) {
*
* // prompt the user for a username
* NameCallback nc = (NameCallback)callbacks[i];
*
* // ignore the provided defaultName
* System.err.print(nc.getPrompt());
* System.err.flush();
* nc.setName((new BufferedReader
* (new InputStreamReader(System.in))).readLine());
*
* } else if (callbacks[i] instanceof PasswordCallback) {
*
* // prompt the user for sensitive information
* PasswordCallback pc = (PasswordCallback)callbacks[i];
* System.err.print(pc.getPrompt());
* System.err.flush();
* pc.setPassword(readPassword(System.in));
*
* } else {
* throw new UnsupportedCallbackException
* (callbacks[i], "Unrecognized Callback");
* }
* }
* }
*
* // Reads user password from given input stream.
* private char[] readPassword(InputStream in) throws IOException {
* // insert code to read a user password from the input stream
* }
* }</pre>
*
* @param callbacks an array of {@code Callback} objects provided
* by an underlying security service which contains
* the information requested to be retrieved or displayed.
*
* @exception java.io.IOException if an input or output error occurs. <p>
*
* @exception UnsupportedCallbackException if the implementation of this
* method does not support one or more of the Callbacks
* specified in the {@code callbacks} parameter.
*/
void handle(Callback[] callbacks)
throws java.io.IOException, UnsupportedCallbackException;
}

View File

@@ -0,0 +1,248 @@
/*
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.callback;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
/**
* <p> Underlying security services instantiate and pass a
* {@code ChoiceCallback} to the {@code handle}
* method of a {@code CallbackHandler} to display a list of choices
* and to retrieve the selected choice(s).
*
* @see javax.security.auth.callback.CallbackHandler
*/
public class ChoiceCallback implements Callback, java.io.Serializable {
private static final long serialVersionUID = -3975664071579892167L;
/**
* @serial
* @since 1.4
*/
private final String prompt;
/**
* @serial the list of choices
* @since 1.4
*/
private String[] choices;
/**
* @serial the choice to be used as the default choice
* @since 1.4
*/
private final int defaultChoice;
/**
* @serial whether multiple selections are allowed from the list of
* choices
* @since 1.4
*/
private final boolean multipleSelectionsAllowed;
/**
* @serial the selected choices, represented as indexes into the
* {@code choices} list.
* @since 1.4
*/
private int[] selections;
/**
* Construct a {@code ChoiceCallback} with a prompt,
* a list of choices, a default choice, and a boolean specifying
* whether or not multiple selections from the list of choices are allowed.
*
* <p>
*
* @param prompt the prompt used to describe the list of choices. <p>
*
* @param choices the list of choices. <p>
*
* @param defaultChoice the choice to be used as the default choice
* when the list of choices are displayed. This value
* is represented as an index into the
* {@code choices} array. <p>
*
* @param multipleSelectionsAllowed boolean specifying whether or
* not multiple selections can be made from the
* list of choices.
*
* @exception IllegalArgumentException if {@code prompt} is null,
* if {@code prompt} has a length of 0,
* if {@code choices} is null,
* if {@code choices} has a length of 0,
* if any element from {@code choices} is null,
* if any element from {@code choices}
* has a length of 0 or if {@code defaultChoice}
* does not fall within the array boundaries of
* {@code choices}.
*/
public ChoiceCallback(String prompt, String[] choices,
int defaultChoice, boolean multipleSelectionsAllowed) {
if (prompt == null || prompt.length() == 0 ||
choices == null || choices.length == 0 ||
defaultChoice < 0 || defaultChoice >= choices.length)
throw new IllegalArgumentException();
this.prompt = prompt;
this.defaultChoice = defaultChoice;
this.multipleSelectionsAllowed = multipleSelectionsAllowed;
this.choices = choices.clone();
for (int i = 0; i < choices.length; i++) {
if (choices[i] == null || choices[i].length() == 0)
throw new IllegalArgumentException();
}
}
/**
* Get the prompt.
*
* <p>
*
* @return the prompt.
*/
public String getPrompt() {
return prompt;
}
/**
* Get the list of choices.
*
* <p>
*
* @return the list of choices.
*/
public String[] getChoices() {
return choices.clone();
}
/**
* Get the defaultChoice.
*
* <p>
*
* @return the defaultChoice, represented as an index into
* the {@code choices} list.
*/
public int getDefaultChoice() {
return defaultChoice;
}
/**
* Get the boolean determining whether multiple selections from
* the {@code choices} list are allowed.
*
* <p>
*
* @return whether multiple selections are allowed.
*/
public boolean allowMultipleSelections() {
return multipleSelectionsAllowed;
}
/**
* Set the selected choice.
*
* <p>
*
* @param selection the selection represented as an index into the
* {@code choices} list.
*
* @see #getSelectedIndexes
*/
public void setSelectedIndex(int selection) {
this.selections = new int[1];
this.selections[0] = selection;
}
/**
* Set the selected choices.
*
* <p>
*
* @param selections the selections represented as indexes into the
* {@code choices} list.
*
* @exception UnsupportedOperationException if multiple selections are
* not allowed, as determined by
* {@code allowMultipleSelections}.
*
* @see #getSelectedIndexes
*/
public void setSelectedIndexes(int[] selections) {
if (!multipleSelectionsAllowed)
throw new UnsupportedOperationException();
this.selections = selections == null ? null : selections.clone();
}
/**
* Get the selected choices.
*
* <p>
*
* @return the selected choices, represented as indexes into the
* {@code choices} list.
*
* @see #setSelectedIndexes
*/
public int[] getSelectedIndexes() {
return selections == null ? null : selections.clone();
}
/**
* Restores the state of this object from the stream.
*
* @param stream the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
if ((prompt == null) || prompt.isEmpty() ||
(choices == null) || (choices.length == 0) ||
(defaultChoice < 0) || (defaultChoice >= choices.length)) {
throw new InvalidObjectException(
"Missing/invalid prompt/choices");
}
choices = choices.clone();
for (int i = 0; i < choices.length; i++) {
if ((choices[i] == null) || choices[i].isEmpty())
throw new InvalidObjectException("Null/empty choices");
}
if (selections != null) {
selections = selections.clone();
if (!multipleSelectionsAllowed && (selections.length != 1)) {
throw new InvalidObjectException(
"Multiple selections not allowed");
}
}
}
}

View File

@@ -0,0 +1,526 @@
/*
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.callback;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* <p> Underlying security services instantiate and pass a
* {@code ConfirmationCallback} to the {@code handle}
* method of a {@code CallbackHandler} to ask for YES/NO,
* OK/CANCEL, YES/NO/CANCEL or other similar confirmations.
*
* @see javax.security.auth.callback.CallbackHandler
*/
public class ConfirmationCallback implements Callback, java.io.Serializable {
private static final long serialVersionUID = -9095656433782481624L;
/**
* Unspecified option type.
*
* <p> The {@code getOptionType} method returns this
* value if this {@code ConfirmationCallback} was instantiated
* with {@code options} instead of an {@code optionType}.
*/
public static final int UNSPECIFIED_OPTION = -1;
/**
* YES/NO confirmation option.
*
* <p> An underlying security service specifies this as the
* {@code optionType} to a {@code ConfirmationCallback}
* constructor if it requires a confirmation which can be answered
* with either {@code YES} or {@code NO}.
*/
public static final int YES_NO_OPTION = 0;
/**
* YES/NO/CANCEL confirmation confirmation option.
*
* <p> An underlying security service specifies this as the
* {@code optionType} to a {@code ConfirmationCallback}
* constructor if it requires a confirmation which can be answered
* with either {@code YES}, {@code NO} or {@code CANCEL}.
*/
public static final int YES_NO_CANCEL_OPTION = 1;
/**
* OK/CANCEL confirmation confirmation option.
*
* <p> An underlying security service specifies this as the
* {@code optionType} to a {@code ConfirmationCallback}
* constructor if it requires a confirmation which can be answered
* with either {@code OK} or {@code CANCEL}.
*/
public static final int OK_CANCEL_OPTION = 2;
/**
* YES option.
*
* <p> If an {@code optionType} was specified to this
* {@code ConfirmationCallback}, this option may be specified as a
* {@code defaultOption} or returned as the selected index.
*/
public static final int YES = 0;
/**
* NO option.
*
* <p> If an {@code optionType} was specified to this
* {@code ConfirmationCallback}, this option may be specified as a
* {@code defaultOption} or returned as the selected index.
*/
public static final int NO = 1;
/**
* CANCEL option.
*
* <p> If an {@code optionType} was specified to this
* {@code ConfirmationCallback}, this option may be specified as a
* {@code defaultOption} or returned as the selected index.
*/
public static final int CANCEL = 2;
/**
* OK option.
*
* <p> If an {@code optionType} was specified to this
* {@code ConfirmationCallback}, this option may be specified as a
* {@code defaultOption} or returned as the selected index.
*/
public static final int OK = 3;
/** INFORMATION message type. */
public static final int INFORMATION = 0;
/** WARNING message type. */
public static final int WARNING = 1;
/** ERROR message type. */
public static final int ERROR = 2;
/**
* @serial
* @since 1.4
*/
private final String prompt;
/**
* @serial
* @since 1.4
*/
private final int messageType;
/**
* @serial
* @since 1.4
*/
private final int optionType;
/**
* @serial
* @since 1.4
*/
private final int defaultOption;
/**
* @serial
* @since 1.4
*/
private String[] options;
/**
* @serial
* @since 1.4
*/
private int selection;
/**
* Construct a {@code ConfirmationCallback} with a
* message type, an option type and a default option.
*
* <p> Underlying security services use this constructor if
* they require either a YES/NO, YES/NO/CANCEL or OK/CANCEL
* confirmation.
*
* <p>
*
* @param messageType the message type ({@code INFORMATION},
* {@code WARNING} or {@code ERROR}). <p>
*
* @param optionType the option type ({@code YES_NO_OPTION},
* {@code YES_NO_CANCEL_OPTION} or
* {@code OK_CANCEL_OPTION}). <p>
*
* @param defaultOption the default option
* from the provided optionType ({@code YES},
* {@code NO}, {@code CANCEL} or
* {@code OK}).
*
* @exception IllegalArgumentException if messageType is not either
* {@code INFORMATION}, {@code WARNING},
* or {@code ERROR}, if optionType is not either
* {@code YES_NO_OPTION},
* {@code YES_NO_CANCEL_OPTION}, or
* {@code OK_CANCEL_OPTION},
* or if {@code defaultOption}
* does not correspond to one of the options in
* {@code optionType}.
*/
public ConfirmationCallback(int messageType,
int optionType, int defaultOption) {
if (messageType < INFORMATION || messageType > ERROR ||
optionType < YES_NO_OPTION || optionType > OK_CANCEL_OPTION)
throw new IllegalArgumentException();
switch (optionType) {
case YES_NO_OPTION:
if (defaultOption != YES && defaultOption != NO)
throw new IllegalArgumentException();
break;
case YES_NO_CANCEL_OPTION:
if (defaultOption != YES && defaultOption != NO &&
defaultOption != CANCEL)
throw new IllegalArgumentException();
break;
case OK_CANCEL_OPTION:
if (defaultOption != OK && defaultOption != CANCEL)
throw new IllegalArgumentException();
break;
}
this.prompt = null;
this.messageType = messageType;
this.optionType = optionType;
this.options = null;
this.defaultOption = defaultOption;
}
/**
* Construct a {@code ConfirmationCallback} with a
* message type, a list of options and a default option.
*
* <p> Underlying security services use this constructor if
* they require a confirmation different from the available preset
* confirmations provided (for example, CONTINUE/ABORT or STOP/GO).
* The confirmation options are listed in the {@code options} array,
* and are displayed by the {@code CallbackHandler} implementation
* in a manner consistent with the way preset options are displayed.
*
* <p>
*
* @param messageType the message type ({@code INFORMATION},
* {@code WARNING} or {@code ERROR}). <p>
*
* @param options the list of confirmation options. <p>
*
* @param defaultOption the default option, represented as an index
* into the {@code options} array.
*
* @exception IllegalArgumentException if messageType is not either
* {@code INFORMATION}, {@code WARNING},
* or {@code ERROR}, if {@code options} is null,
* if {@code options} has a length of 0,
* if any element from {@code options} is null,
* if any element from {@code options}
* has a length of 0, or if {@code defaultOption}
* does not lie within the array boundaries of
* {@code options}.
*/
public ConfirmationCallback(int messageType,
String[] options, int defaultOption) {
if (messageType < INFORMATION || messageType > ERROR ||
options == null || options.length == 0 ||
defaultOption < 0 || defaultOption >= options.length)
throw new IllegalArgumentException();
this.prompt = null;
this.messageType = messageType;
this.optionType = UNSPECIFIED_OPTION;
this.defaultOption = defaultOption;
this.options = options.clone();
for (int i = 0; i < options.length; i++) {
if (options[i] == null || options[i].length() == 0)
throw new IllegalArgumentException();
}
}
/**
* Construct a {@code ConfirmationCallback} with a prompt,
* message type, an option type and a default option.
*
* <p> Underlying security services use this constructor if
* they require either a YES/NO, YES/NO/CANCEL or OK/CANCEL
* confirmation.
*
* <p>
*
* @param prompt the prompt used to describe the list of options. <p>
*
* @param messageType the message type ({@code INFORMATION},
* {@code WARNING} or {@code ERROR}). <p>
*
* @param optionType the option type ({@code YES_NO_OPTION},
* {@code YES_NO_CANCEL_OPTION} or
* {@code OK_CANCEL_OPTION}). <p>
*
* @param defaultOption the default option
* from the provided optionType ({@code YES},
* {@code NO}, {@code CANCEL} or
* {@code OK}).
*
* @exception IllegalArgumentException if {@code prompt} is null,
* if {@code prompt} has a length of 0,
* if messageType is not either
* {@code INFORMATION}, {@code WARNING},
* or {@code ERROR}, if optionType is not either
* {@code YES_NO_OPTION},
* {@code YES_NO_CANCEL_OPTION}, or
* {@code OK_CANCEL_OPTION},
* or if {@code defaultOption}
* does not correspond to one of the options in
* {@code optionType}.
*/
public ConfirmationCallback(String prompt, int messageType,
int optionType, int defaultOption) {
if (prompt == null || prompt.length() == 0 ||
messageType < INFORMATION || messageType > ERROR ||
optionType < YES_NO_OPTION || optionType > OK_CANCEL_OPTION)
throw new IllegalArgumentException();
switch (optionType) {
case YES_NO_OPTION:
if (defaultOption != YES && defaultOption != NO)
throw new IllegalArgumentException();
break;
case YES_NO_CANCEL_OPTION:
if (defaultOption != YES && defaultOption != NO &&
defaultOption != CANCEL)
throw new IllegalArgumentException();
break;
case OK_CANCEL_OPTION:
if (defaultOption != OK && defaultOption != CANCEL)
throw new IllegalArgumentException();
break;
}
this.prompt = prompt;
this.messageType = messageType;
this.optionType = optionType;
this.options = null;
this.defaultOption = defaultOption;
}
/**
* Construct a {@code ConfirmationCallback} with a prompt,
* message type, a list of options and a default option.
*
* <p> Underlying security services use this constructor if
* they require a confirmation different from the available preset
* confirmations provided (for example, CONTINUE/ABORT or STOP/GO).
* The confirmation options are listed in the {@code options} array,
* and are displayed by the {@code CallbackHandler} implementation
* in a manner consistent with the way preset options are displayed.
*
* <p>
*
* @param prompt the prompt used to describe the list of options. <p>
*
* @param messageType the message type ({@code INFORMATION},
* {@code WARNING} or {@code ERROR}). <p>
*
* @param options the list of confirmation options. <p>
*
* @param defaultOption the default option, represented as an index
* into the {@code options} array.
*
* @exception IllegalArgumentException if {@code prompt} is null,
* if {@code prompt} has a length of 0,
* if messageType is not either
* {@code INFORMATION}, {@code WARNING},
* or {@code ERROR}, if {@code options} is null,
* if {@code options} has a length of 0,
* if any element from {@code options} is null,
* if any element from {@code options}
* has a length of 0, or if {@code defaultOption}
* does not lie within the array boundaries of
* {@code options}.
*/
public ConfirmationCallback(String prompt, int messageType,
String[] options, int defaultOption) {
if (prompt == null || prompt.length() == 0 ||
messageType < INFORMATION || messageType > ERROR ||
options == null || options.length == 0 ||
defaultOption < 0 || defaultOption >= options.length)
throw new IllegalArgumentException();
this.prompt = prompt;
this.messageType = messageType;
this.optionType = UNSPECIFIED_OPTION;
this.defaultOption = defaultOption;
this.options = options.clone();
for (int i = 0; i < options.length; i++) {
if (options[i] == null || options[i].length() == 0)
throw new IllegalArgumentException();
}
}
/**
* Get the prompt.
*
* <p>
*
* @return the prompt, or null if this {@code ConfirmationCallback}
* was instantiated without a {@code prompt}.
*/
public String getPrompt() {
return prompt;
}
/**
* Get the message type.
*
* <p>
*
* @return the message type ({@code INFORMATION},
* {@code WARNING} or {@code ERROR}).
*/
public int getMessageType() {
return messageType;
}
/**
* Get the option type.
*
* <p> If this method returns {@code UNSPECIFIED_OPTION}, then this
* {@code ConfirmationCallback} was instantiated with
* {@code options} instead of an {@code optionType}.
* In this case, invoke the {@code getOptions} method
* to determine which confirmation options to display.
*
* <p>
*
* @return the option type ({@code YES_NO_OPTION},
* {@code YES_NO_CANCEL_OPTION} or
* {@code OK_CANCEL_OPTION}), or
* {@code UNSPECIFIED_OPTION} if this
* {@code ConfirmationCallback} was instantiated with
* {@code options} instead of an {@code optionType}.
*/
public int getOptionType() {
return optionType;
}
/**
* Get the confirmation options.
*
* <p>
*
* @return the list of confirmation options, or null if this
* {@code ConfirmationCallback} was instantiated with
* an {@code optionType} instead of {@code options}.
*/
public String[] getOptions() {
return options == null ? null : options.clone();
}
/**
* Get the default option.
*
* <p>
*
* @return the default option, represented as
* {@code YES}, {@code NO}, {@code OK} or
* {@code CANCEL} if an {@code optionType}
* was specified to the constructor of this
* {@code ConfirmationCallback}.
* Otherwise, this method returns the default option as
* an index into the
* {@code options} array specified to the constructor
* of this {@code ConfirmationCallback}.
*/
public int getDefaultOption() {
return defaultOption;
}
/**
* Set the selected confirmation option.
*
* <p>
*
* @param selection the selection represented as {@code YES},
* {@code NO}, {@code OK} or {@code CANCEL}
* if an {@code optionType} was specified to the constructor
* of this {@code ConfirmationCallback}.
* Otherwise, the selection represents the index into the
* {@code options} array specified to the constructor
* of this {@code ConfirmationCallback}.
*
* @see #getSelectedIndex
*/
public void setSelectedIndex(int selection) {
this.selection = selection;
}
/**
* Get the selected confirmation option.
*
* <p>
*
* @return the selected confirmation option represented as
* {@code YES}, {@code NO}, {@code OK} or
* {@code CANCEL} if an {@code optionType}
* was specified to the constructor of this
* {@code ConfirmationCallback}.
* Otherwise, this method returns the selected confirmation
* option as an index into the
* {@code options} array specified to the constructor
* of this {@code ConfirmationCallback}.
*
* @see #setSelectedIndex
*/
public int getSelectedIndex() {
return selection;
}
/**
* Restores the state of this object from the stream.
*
* @param stream the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
if (options != null) {
options = options.clone();
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.callback;
import java.util.Locale;
/**
* <p> Underlying security services instantiate and pass a
* {@code LanguageCallback} to the {@code handle}
* method of a {@code CallbackHandler} to retrieve the {@code Locale}
* used for localizing text.
*
* @see javax.security.auth.callback.CallbackHandler
*/
public class LanguageCallback implements Callback, java.io.Serializable {
private static final long serialVersionUID = 2019050433478903213L;
/**
* @serial
* @since 1.4
*/
private Locale locale;
/**
* Construct a {@code LanguageCallback}.
*/
public LanguageCallback() { }
/**
* Set the retrieved {@code Locale}.
*
* <p>
*
* @param locale the retrieved {@code Locale}.
*
* @see #getLocale
*/
public void setLocale(Locale locale) {
this.locale = locale;
}
/**
* Get the retrieved {@code Locale}.
*
* <p>
*
* @return the retrieved {@code Locale}, or null
* if no {@code Locale} could be retrieved.
*
* @see #setLocale
*/
public Locale getLocale() {
return locale;
}
}

View File

@@ -0,0 +1,144 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.callback;
/**
* <p> Underlying security services instantiate and pass a
* {@code NameCallback} to the {@code handle}
* method of a {@code CallbackHandler} to retrieve name information.
*
* @see javax.security.auth.callback.CallbackHandler
*/
public class NameCallback implements Callback, java.io.Serializable {
private static final long serialVersionUID = 3770938795909392253L;
/**
* @serial
* @since 1.4
*/
private String prompt;
/**
* @serial
* @since 1.4
*/
private String defaultName;
/**
* @serial
* @since 1.4
*/
private String inputName;
/**
* Construct a {@code NameCallback} with a prompt.
*
* <p>
*
* @param prompt the prompt used to request the name.
*
* @exception IllegalArgumentException if {@code prompt} is null
* or if {@code prompt} has a length of 0.
*/
public NameCallback(String prompt) {
if (prompt == null || prompt.length() == 0)
throw new IllegalArgumentException();
this.prompt = prompt;
}
/**
* Construct a {@code NameCallback} with a prompt
* and default name.
*
* <p>
*
* @param prompt the prompt used to request the information. <p>
*
* @param defaultName the name to be used as the default name displayed
* with the prompt.
*
* @exception IllegalArgumentException if {@code prompt} is null,
* if {@code prompt} has a length of 0,
* if {@code defaultName} is null,
* or if {@code defaultName} has a length of 0.
*/
public NameCallback(String prompt, String defaultName) {
if (prompt == null || prompt.length() == 0 ||
defaultName == null || defaultName.length() == 0)
throw new IllegalArgumentException();
this.prompt = prompt;
this.defaultName = defaultName;
}
/**
* Get the prompt.
*
* <p>
*
* @return the prompt.
*/
public String getPrompt() {
return prompt;
}
/**
* Get the default name.
*
* <p>
*
* @return the default name, or null if this {@code NameCallback}
* was not instantiated with a {@code defaultName}.
*/
public String getDefaultName() {
return defaultName;
}
/**
* Set the retrieved name.
*
* <p>
*
* @param name the retrieved name (which may be null).
*
* @see #getName
*/
public void setName(String name) {
this.inputName = name;
}
/**
* Get the retrieved name.
*
* <p>
*
* @return the retrieved name (which may be null)
*
* @see #setName
*/
public String getName() {
return inputName;
}
}

View File

@@ -0,0 +1,192 @@
/*
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.callback;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.util.Arrays;
import sun.misc.Cleaner;
/**
* <p> Underlying security services instantiate and pass a
* {@code PasswordCallback} to the {@code handle}
* method of a {@code CallbackHandler} to retrieve password information.
*
* @see javax.security.auth.callback.CallbackHandler
*/
public class PasswordCallback implements Callback, java.io.Serializable {
private static final long serialVersionUID = 2267422647454909926L;
/**
* @serial
* @since 1.4
*/
private final String prompt;
/**
* @serial
* @since 1.4
*/
private final boolean echoOn;
/**
* @serial
* @since 1.4
*/
private char[] inputPassword;
private transient Cleaner cleaner;
/**
* Construct a {@code PasswordCallback} with a prompt
* and a boolean specifying whether the password should be displayed
* as it is being typed.
*
* <p>
*
* @param prompt the prompt used to request the password. <p>
*
* @param echoOn true if the password should be displayed
* as it is being typed.
*
* @exception IllegalArgumentException if {@code prompt} is null or
* if {@code prompt} has a length of 0.
*/
public PasswordCallback(String prompt, boolean echoOn) {
if (prompt == null || prompt.length() == 0)
throw new IllegalArgumentException();
this.prompt = prompt;
this.echoOn = echoOn;
}
/**
* Get the prompt.
*
* <p>
*
* @return the prompt.
*/
public String getPrompt() {
return prompt;
}
/**
* Return whether the password
* should be displayed as it is being typed.
*
* <p>
*
* @return the whether the password
* should be displayed as it is being typed.
*/
public boolean isEchoOn() {
return echoOn;
}
/**
* Set the retrieved password.
*
* <p> This method makes a copy of the input <i>password</i>
* before storing it.
*
* <p>
*
* @param password the retrieved password, which may be null.
*
* @see #getPassword
*/
public void setPassword(char[] password) {
// Cleanup the last buffered password copy.
if (cleaner != null) {
cleaner.clean();
cleaner = null;
}
// Set the retrieved password.
this.inputPassword = (password == null ? null : password.clone());
if (this.inputPassword != null) {
cleaner = Cleaner.create(this, cleanerFor(inputPassword));
}
}
/**
* Get the retrieved password.
*
* <p> This method returns a copy of the retrieved password.
*
* <p>
*
* @return the retrieved password, which may be null.
*
* @see #setPassword
*/
public char[] getPassword() {
return (inputPassword == null ? null : inputPassword.clone());
}
/**
* Clear the retrieved password.
*/
public void clearPassword() {
// Cleanup the last retrieved password copy.
if (cleaner != null) {
cleaner.clean();
cleaner = null;
}
}
private static Runnable cleanerFor(char[] password) {
return () -> {
Arrays.fill(password, ' ');
};
}
/**
* Restores the state of this object from the stream.
*
* @param stream the {@code ObjectInputStream} from which data is read
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if a serialized class cannot be loaded
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
if (prompt == null || prompt.isEmpty()) {
throw new InvalidObjectException("Missing prompt");
}
if (inputPassword != null) {
inputPassword = inputPassword.clone();
cleaner = Cleaner.create(this, cleanerFor(inputPassword));
}
}
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.callback;
/**
* <p> Underlying security services instantiate and pass a
* {@code TextInputCallback} to the {@code handle}
* method of a {@code CallbackHandler} to retrieve generic text
* information.
*
* @see javax.security.auth.callback.CallbackHandler
*/
public class TextInputCallback implements Callback, java.io.Serializable {
private static final long serialVersionUID = -8064222478852811804L;
/**
* @serial
* @since 1.4
*/
private String prompt;
/**
* @serial
* @since 1.4
*/
private String defaultText;
/**
* @serial
* @since 1.4
*/
private String inputText;
/**
* Construct a {@code TextInputCallback} with a prompt.
*
* <p>
*
* @param prompt the prompt used to request the information.
*
* @exception IllegalArgumentException if {@code prompt} is null
* or if {@code prompt} has a length of 0.
*/
public TextInputCallback(String prompt) {
if (prompt == null || prompt.length() == 0)
throw new IllegalArgumentException();
this.prompt = prompt;
}
/**
* Construct a {@code TextInputCallback} with a prompt
* and default input value.
*
* <p>
*
* @param prompt the prompt used to request the information. <p>
*
* @param defaultText the text to be used as the default text displayed
* with the prompt.
*
* @exception IllegalArgumentException if {@code prompt} is null,
* if {@code prompt} has a length of 0,
* if {@code defaultText} is null
* or if {@code defaultText} has a length of 0.
*/
public TextInputCallback(String prompt, String defaultText) {
if (prompt == null || prompt.length() == 0 ||
defaultText == null || defaultText.length() == 0)
throw new IllegalArgumentException();
this.prompt = prompt;
this.defaultText = defaultText;
}
/**
* Get the prompt.
*
* <p>
*
* @return the prompt.
*/
public String getPrompt() {
return prompt;
}
/**
* Get the default text.
*
* <p>
*
* @return the default text, or null if this {@code TextInputCallback}
* was not instantiated with {@code defaultText}.
*/
public String getDefaultText() {
return defaultText;
}
/**
* Set the retrieved text.
*
* <p>
*
* @param text the retrieved text, which may be null.
*
* @see #getText
*/
public void setText(String text) {
this.inputText = text;
}
/**
* Get the retrieved text.
*
* <p>
*
* @return the retrieved text, which may be null.
*
* @see #setText
*/
public String getText() {
return inputText;
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.callback;
/**
* <p> Underlying security services instantiate and pass a
* {@code TextOutputCallback} to the {@code handle}
* method of a {@code CallbackHandler} to display information messages,
* warning messages and error messages.
*
* @see javax.security.auth.callback.CallbackHandler
*/
public class TextOutputCallback implements Callback, java.io.Serializable {
private static final long serialVersionUID = 1689502495511663102L;
/** Information message. */
public static final int INFORMATION = 0;
/** Warning message. */
public static final int WARNING = 1;
/** Error message. */
public static final int ERROR = 2;
/**
* @serial
* @since 1.4
*/
private int messageType;
/**
* @serial
* @since 1.4
*/
private String message;
/**
* Construct a TextOutputCallback with a message type and message
* to be displayed.
*
* <p>
*
* @param messageType the message type ({@code INFORMATION},
* {@code WARNING} or {@code ERROR}). <p>
*
* @param message the message to be displayed. <p>
*
* @exception IllegalArgumentException if {@code messageType}
* is not either {@code INFORMATION},
* {@code WARNING} or {@code ERROR},
* if {@code message} is null,
* or if {@code message} has a length of 0.
*/
public TextOutputCallback(int messageType, String message) {
if ((messageType != INFORMATION &&
messageType != WARNING && messageType != ERROR) ||
message == null || message.length() == 0)
throw new IllegalArgumentException();
this.messageType = messageType;
this.message = message;
}
/**
* Get the message type.
*
* <p>
*
* @return the message type ({@code INFORMATION},
* {@code WARNING} or {@code ERROR}).
*/
public int getMessageType() {
return messageType;
}
/**
* Get the message to be displayed.
*
* <p>
*
* @return the message to be displayed.
*/
public String getMessage() {
return message;
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.callback;
/**
* Signals that a {@code CallbackHandler} does not
* recognize a particular {@code Callback}.
*
*/
public class UnsupportedCallbackException extends Exception {
private static final long serialVersionUID = -6873556327655666839L;
/**
* @serial
*/
private Callback callback;
/**
* Constructs a {@code UnsupportedCallbackException}
* with no detail message.
*
* <p>
*
* @param callback the unrecognized {@code Callback}.
*/
public UnsupportedCallbackException(Callback callback) {
super();
this.callback = callback;
}
/**
* Constructs a UnsupportedCallbackException with the specified detail
* message. A detail message is a String that describes this particular
* exception.
*
* <p>
*
* @param callback the unrecognized {@code Callback}. <p>
*
* @param msg the detail message.
*/
public UnsupportedCallbackException(Callback callback, String msg) {
super(msg);
this.callback = callback;
}
/**
* Get the unrecognized {@code Callback}.
*
* <p>
*
* @return the unrecognized {@code Callback}.
*/
public Callback getCallback() {
return callback;
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This package provides the classes necessary for services
* to interact with applications in order to retrieve
* information (authentication data including usernames
* or passwords, for example) or to display information
* (error and warning messages, for example).
*
* @since JDK1.4
*/
package javax.security.auth.callback;

View File

@@ -0,0 +1,389 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.kerberos;
import java.util.*;
import java.security.Permission;
import java.security.BasicPermission;
import java.security.PermissionCollection;
import java.io.ObjectStreamField;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
/**
* This class is used to restrict the usage of the Kerberos
* delegation model, ie: forwardable and proxiable tickets.
* <p>
* The target name of this {@code Permission} specifies a pair of
* kerberos service principals. The first is the subordinate service principal
* being entrusted to use the TGT. The second service principal designates
* the target service the subordinate service principal is to
* interact with on behalf of the initiating KerberosPrincipal. This
* latter service principal is specified to restrict the use of a
* proxiable ticket.
* <p>
* For example, to specify the "host" service use of a forwardable TGT the
* target permission is specified as follows:
*
* <pre>
* DelegationPermission("\"host/foo.example.com@EXAMPLE.COM\" \"krbtgt/EXAMPLE.COM@EXAMPLE.COM\"");
* </pre>
* <p>
* To give the "backup" service a proxiable nfs service ticket the target permission
* might be specified:
*
* <pre>
* DelegationPermission("\"backup/bar.example.com@EXAMPLE.COM\" \"nfs/home.EXAMPLE.COM@EXAMPLE.COM\"");
* </pre>
*
* @since 1.4
*/
public final class DelegationPermission extends BasicPermission
implements java.io.Serializable {
private static final long serialVersionUID = 883133252142523922L;
private transient String subordinate, service;
/**
* Create a new {@code DelegationPermission}
* with the specified subordinate and target principals.
*
* <p>
*
* @param principals the name of the subordinate and target principals
*
* @throws NullPointerException if {@code principals} is {@code null}.
* @throws IllegalArgumentException if {@code principals} is empty.
*/
public DelegationPermission(String principals) {
super(principals);
init(principals);
}
/**
* Create a new {@code DelegationPermission}
* with the specified subordinate and target principals.
* <p>
*
* @param principals the name of the subordinate and target principals
* <p>
* @param actions should be null.
*
* @throws NullPointerException if {@code principals} is {@code null}.
* @throws IllegalArgumentException if {@code principals} is empty.
*/
public DelegationPermission(String principals, String actions) {
super(principals, actions);
init(principals);
}
/**
* Initialize the DelegationPermission object.
*/
private void init(String target) {
StringTokenizer t = null;
if (!target.startsWith("\"")) {
throw new IllegalArgumentException
("service principal [" + target +
"] syntax invalid: " +
"improperly quoted");
} else {
t = new StringTokenizer(target, "\"", false);
subordinate = t.nextToken();
if (t.countTokens() == 2) {
t.nextToken(); // bypass whitespace
service = t.nextToken();
} else if (t.countTokens() > 0) {
throw new IllegalArgumentException
("service principal [" + t.nextToken() +
"] syntax invalid: " +
"improperly quoted");
}
}
}
/**
* Checks if this Kerberos delegation permission object "implies" the
* specified permission.
* <P>
* If none of the above are true, {@code implies} returns false.
* @param p the permission to check against.
*
* @return true if the specified permission is implied by this object,
* false if not.
*/
public boolean implies(Permission p) {
if (!(p instanceof DelegationPermission))
return false;
DelegationPermission that = (DelegationPermission) p;
if (this.subordinate.equals(that.subordinate) &&
this.service.equals(that.service))
return true;
return false;
}
/**
* Checks two DelegationPermission objects for equality.
* <P>
* @param obj the object to test for equality with this object.
*
* @return true if <i>obj</i> is a DelegationPermission, and
* has the same subordinate and service principal as this.
* DelegationPermission object.
*/
public boolean equals(Object obj) {
if (obj == this)
return true;
if (! (obj instanceof DelegationPermission))
return false;
DelegationPermission that = (DelegationPermission) obj;
return implies(that);
}
/**
* Returns the hash code value for this object.
*
* @return a hash code value for this object.
*/
public int hashCode() {
return getName().hashCode();
}
/**
* Returns a PermissionCollection object for storing
* DelegationPermission objects.
* <br>
* DelegationPermission objects must be stored in a manner that
* allows them to be inserted into the collection in any order, but
* that also enables the PermissionCollection implies method to
* be implemented in an efficient (and consistent) manner.
*
* @return a new PermissionCollection object suitable for storing
* DelegationPermissions.
*/
public PermissionCollection newPermissionCollection() {
return new KrbDelegationPermissionCollection();
}
/**
* WriteObject is called to save the state of the DelegationPermission
* to a stream. The actions are serialized, and the superclass
* takes care of the name.
*/
private synchronized void writeObject(java.io.ObjectOutputStream s)
throws IOException
{
s.defaultWriteObject();
}
/**
* readObject is called to restore the state of the
* DelegationPermission from a stream.
*/
private synchronized void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException
{
// Read in the action, then initialize the rest
s.defaultReadObject();
init(getName());
}
/*
public static void main(String args[]) throws Exception {
DelegationPermission this_ =
new DelegationPermission(args[0]);
DelegationPermission that_ =
new DelegationPermission(args[1]);
System.out.println("-----\n");
System.out.println("this.implies(that) = " + this_.implies(that_));
System.out.println("-----\n");
System.out.println("this = "+this_);
System.out.println("-----\n");
System.out.println("that = "+that_);
System.out.println("-----\n");
KrbDelegationPermissionCollection nps =
new KrbDelegationPermissionCollection();
nps.add(this_);
nps.add(new DelegationPermission("\"host/foo.example.com@EXAMPLE.COM\" \"CN=Gary Ellison/OU=JSN/O=SUNW/L=Palo Alto/ST=CA/C=US\""));
try {
nps.add(new DelegationPermission("host/foo.example.com@EXAMPLE.COM \"CN=Gary Ellison/OU=JSN/O=SUNW/L=Palo Alto/ST=CA/C=US\""));
} catch (Exception e) {
System.err.println(e);
}
System.out.println("nps.implies(that) = " + nps.implies(that_));
System.out.println("-----\n");
Enumeration e = nps.elements();
while (e.hasMoreElements()) {
DelegationPermission x =
(DelegationPermission) e.nextElement();
System.out.println("nps.e = " + x);
}
}
*/
}
final class KrbDelegationPermissionCollection extends PermissionCollection
implements java.io.Serializable {
// Not serialized; see serialization section at end of class.
private transient List<Permission> perms;
public KrbDelegationPermissionCollection() {
perms = new ArrayList<Permission>();
}
/**
* Check and see if this collection of permissions implies the permissions
* expressed in "permission".
*
* @param permission the Permission object to compare
*
* @return true if "permission" is a proper subset of a permission in
* the collection, false if not.
*/
public boolean implies(Permission permission) {
if (! (permission instanceof DelegationPermission))
return false;
synchronized (this) {
for (Permission x : perms) {
if (x.implies(permission))
return true;
}
}
return false;
}
/**
* Adds a permission to the DelegationPermissions. The key for
* the hash is the name.
*
* @param permission the Permission object to add.
*
* @exception IllegalArgumentException - if the permission is not a
* DelegationPermission
*
* @exception SecurityException - if this PermissionCollection object
* has been marked readonly
*/
public void add(Permission permission) {
if (! (permission instanceof DelegationPermission))
throw new IllegalArgumentException("invalid permission: "+
permission);
if (isReadOnly())
throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection");
synchronized (this) {
perms.add(0, permission);
}
}
/**
* Returns an enumeration of all the DelegationPermission objects
* in the container.
*
* @return an enumeration of all the DelegationPermission objects.
*/
public Enumeration<Permission> elements() {
// Convert Iterator into Enumeration
synchronized (this) {
return Collections.enumeration(perms);
}
}
private static final long serialVersionUID = -3383936936589966948L;
// Need to maintain serialization interoperability with earlier releases,
// which had the serializable field:
// private Vector permissions;
/**
* @serialField permissions java.util.Vector
* A list of DelegationPermission objects.
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("permissions", Vector.class),
};
/**
* @serialData "permissions" field (a Vector containing the DelegationPermissions).
*/
/*
* Writes the contents of the perms field out as a Vector for
* serialization compatibility with earlier releases.
*/
private void writeObject(ObjectOutputStream out) throws IOException {
// Don't call out.defaultWriteObject()
// Write out Vector
Vector<Permission> permissions = new Vector<>(perms.size());
synchronized (this) {
permissions.addAll(perms);
}
ObjectOutputStream.PutField pfields = out.putFields();
pfields.put("permissions", permissions);
out.writeFields();
}
/*
* Reads in a Vector of DelegationPermissions and saves them in the perms field.
*/
@SuppressWarnings("unchecked")
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException
{
// Don't call defaultReadObject()
// Read in serialized fields
ObjectInputStream.GetField gfields = in.readFields();
// Get the one we want
Vector<Permission> permissions =
(Vector<Permission>)gfields.get("permissions", null);
perms = new ArrayList<Permission>(permissions.size());
perms.addAll(permissions);
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.kerberos;
import sun.security.krb5.JavaxSecurityAuthKerberosAccess;
class JavaxSecurityAuthKerberosAccessImpl
implements JavaxSecurityAuthKerberosAccess {
public sun.security.krb5.internal.ktab.KeyTab keyTabTakeSnapshot(
KeyTab ktab) {
return ktab.takeSnapshot();
}
public KerberosPrincipal kerberosTicketGetClientAlias(KerberosTicket t) {
return t.clientAlias;
}
public void kerberosTicketSetClientAlias(KerberosTicket t, KerberosPrincipal a) {
t.clientAlias = a;
}
public KerberosPrincipal kerberosTicketGetServerAlias(KerberosTicket t) {
return t.serverAlias;
}
public void kerberosTicketSetServerAlias(KerberosTicket t, KerberosPrincipal a) {
t.serverAlias = a;
}
public KerberosTicket kerberosTicketGetProxy(KerberosTicket t) {
return t.proxy;
}
public void kerberosTicketSetProxy(KerberosTicket t, KerberosTicket p) {
t.proxy = p;
}
}

View File

@@ -0,0 +1,304 @@
/*
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.kerberos;
import java.util.Arrays;
import javax.crypto.SecretKey;
import javax.security.auth.Destroyable;
import javax.security.auth.DestroyFailedException;
/**
* This class encapsulates a long term secret key for a Kerberos
* principal.<p>
*
* All Kerberos JAAS login modules that obtain a principal's password and
* generate the secret key from it should use this class.
* Sometimes, such as when authenticating a server in
* the absence of user-to-user authentication, the login module will store
* an instance of this class in the private credential set of a
* {@link javax.security.auth.Subject Subject} during the commit phase of the
* authentication process.<p>
*
* A Kerberos service using a keytab to read secret keys should use
* the {@link KeyTab} class, where latest keys can be read when needed.<p>
*
* It might be necessary for the application to be granted a
* {@link javax.security.auth.PrivateCredentialPermission
* PrivateCredentialPermission} if it needs to access the KerberosKey
* instance from a Subject. This permission is not needed when the
* application depends on the default JGSS Kerberos mechanism to access the
* KerberosKey. In that case, however, the application will need an
* appropriate
* {@link javax.security.auth.kerberos.ServicePermission ServicePermission}.
*
* @author Mayank Upadhyay
* @since 1.4
*/
public class KerberosKey implements SecretKey, Destroyable {
private static final long serialVersionUID = -4625402278148246993L;
/**
* The principal that this secret key belongs to.
*
* @serial
*/
private KerberosPrincipal principal;
/**
* the version number of this secret key
*
* @serial
*/
private int versionNum;
/**
* {@code KeyImpl} is serialized by writing out the ASN1 Encoded bytes
* of the encryption key.
* The ASN1 encoding is defined in RFC4120 and as follows:
* <pre>
* EncryptionKey ::= SEQUENCE {
* keytype [0] Int32 -- actually encryption type --,
* keyvalue [1] OCTET STRING
* }
* </pre>
*
* @serial
*/
private KeyImpl key;
private transient boolean destroyed = false;
/**
* Constructs a KerberosKey from the given bytes when the key type and
* key version number are known. This can be used when reading the secret
* key information from a Kerberos "keytab".
*
* @param principal the principal that this secret key belongs to
* @param keyBytes the raw bytes for the secret key
* @param keyType the key type for the secret key as defined by the
* Kerberos protocol specification.
* @param versionNum the version number of this secret key
*/
public KerberosKey(KerberosPrincipal principal,
byte[] keyBytes,
int keyType,
int versionNum) {
this.principal = principal;
this.versionNum = versionNum;
key = new KeyImpl(keyBytes, keyType);
}
/**
* Constructs a KerberosKey from a principal's password.
*
* @param principal the principal that this password belongs to
* @param password the password that should be used to compute the key
* @param algorithm the name for the algorithm that this key will be
* used for. This parameter may be null in which case the default
* algorithm "DES" will be assumed.
* @throws IllegalArgumentException if the name of the
* algorithm passed is unsupported.
*/
public KerberosKey(KerberosPrincipal principal,
char[] password,
String algorithm) {
this.principal = principal;
// Pass principal in for salt
key = new KeyImpl(principal, password, algorithm);
}
/**
* Returns the principal that this key belongs to.
*
* @return the principal this key belongs to.
*/
public final KerberosPrincipal getPrincipal() {
if (destroyed)
throw new IllegalStateException("This key is no longer valid");
return principal;
}
/**
* Returns the key version number.
*
* @return the key version number.
*/
public final int getVersionNumber() {
if (destroyed)
throw new IllegalStateException("This key is no longer valid");
return versionNum;
}
/**
* Returns the key type for this long-term key.
*
* @return the key type.
*/
public final int getKeyType() {
if (destroyed)
throw new IllegalStateException("This key is no longer valid");
return key.getKeyType();
}
/*
* Methods from java.security.Key
*/
/**
* Returns the standard algorithm name for this key. For
* example, "DES" would indicate that this key is a DES key.
* See Appendix A in the <a href=
* "../../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture API Specification &amp; Reference
* </a>
* for information about standard algorithm names.
*
* @return the name of the algorithm associated with this key.
*/
public final String getAlgorithm() {
if (destroyed)
throw new IllegalStateException("This key is no longer valid");
return key.getAlgorithm();
}
/**
* Returns the name of the encoding format for this secret key.
*
* @return the String "RAW"
*/
public final String getFormat() {
if (destroyed)
throw new IllegalStateException("This key is no longer valid");
return key.getFormat();
}
/**
* Returns the key material of this secret key.
*
* @return the key material
*/
public final byte[] getEncoded() {
if (destroyed)
throw new IllegalStateException("This key is no longer valid");
return key.getEncoded();
}
/**
* Destroys this key. A call to any of its other methods after this
* will cause an IllegalStateException to be thrown.
*
* @throws DestroyFailedException if some error occurs while destorying
* this key.
*/
public void destroy() throws DestroyFailedException {
if (!destroyed) {
key.destroy();
principal = null;
destroyed = true;
}
}
/** Determines if this key has been destroyed.*/
public boolean isDestroyed() {
return destroyed;
}
public String toString() {
if (destroyed) {
return "Destroyed Principal";
}
return "KerberosKey: principal " + principal +
", version " + versionNum +
", key " + key.toString();
}
/**
* Returns a hashcode for this KerberosKey.
*
* @return a hashCode() for the {@code KerberosKey}
* @since 1.6
*/
public int hashCode() {
int result = 17;
if (isDestroyed()) {
return result;
}
result = 37 * result + Arrays.hashCode(getEncoded());
result = 37 * result + getKeyType();
if (principal != null) {
result = 37 * result + principal.hashCode();
}
return result * 37 + versionNum;
}
/**
* Compares the specified Object with this KerberosKey for equality.
* Returns true if the given object is also a
* {@code KerberosKey} and the two
* {@code KerberosKey} instances are equivalent.
*
* @param other the Object to compare to
* @return true if the specified object is equal to this KerberosKey,
* false otherwise. NOTE: Returns false if either of the KerberosKey
* objects has been destroyed.
* @since 1.6
*/
public boolean equals(Object other) {
if (other == this)
return true;
if (! (other instanceof KerberosKey)) {
return false;
}
KerberosKey otherKey = ((KerberosKey) other);
if (isDestroyed() || otherKey.isDestroyed()) {
return false;
}
if (versionNum != otherKey.getVersionNumber() ||
getKeyType() != otherKey.getKeyType() ||
!Arrays.equals(getEncoded(), otherKey.getEncoded())) {
return false;
}
if (principal == null) {
if (otherKey.getPrincipal() != null) {
return false;
}
} else {
if (!principal.equals(otherKey.getPrincipal())) {
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,293 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.kerberos;
import java.io.*;
import sun.security.krb5.KrbException;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.Realm;
import sun.security.util.*;
/**
* This class encapsulates a Kerberos principal.
*
* @author Mayank Upadhyay
* @since 1.4
*/
public final class KerberosPrincipal
implements java.security.Principal, java.io.Serializable {
private static final long serialVersionUID = -7374788026156829911L;
//name types
/**
* unknown name type.
*/
public static final int KRB_NT_UNKNOWN = 0;
/**
* user principal name type.
*/
public static final int KRB_NT_PRINCIPAL = 1;
/**
* service and other unique instance (krbtgt) name type.
*/
public static final int KRB_NT_SRV_INST = 2;
/**
* service with host name as instance (telnet, rcommands) name type.
*/
public static final int KRB_NT_SRV_HST = 3;
/**
* service with host as remaining components name type.
*/
public static final int KRB_NT_SRV_XHST = 4;
/**
* unique ID name type.
*/
public static final int KRB_NT_UID = 5;
/**
* Enterprise name (alias)
*/
static final int KRB_NT_ENTERPRISE = 10;
private transient String fullName;
private transient String realm;
private transient int nameType;
/**
* Constructs a KerberosPrincipal from the provided string input. The
* name type for this principal defaults to
* {@link #KRB_NT_PRINCIPAL KRB_NT_PRINCIPAL}
* This string is assumed to contain a name in the format
* that is specified in Section 2.1.1. (Kerberos Principal Name Form) of
* <a href=http://www.ietf.org/rfc/rfc1964.txt> RFC 1964 </a>
* (for example, <i>duke@FOO.COM</i>, where <i>duke</i>
* represents a principal, and <i>FOO.COM</i> represents a realm).
*
* <p>If the input name does not contain a realm, the default realm
* is used. The default realm can be specified either in a Kerberos
* configuration file or via the java.security.krb5.realm
* system property. For more information,
* <a href="../../../../../technotes/guides/security/jgss/tutorials/index.html">
* Kerberos Requirements </a>
*
* @param name the principal name
* @throws IllegalArgumentException if name is improperly
* formatted, if name is null, or if name does not contain
* the realm to use and the default realm is not specified
* in either a Kerberos configuration file or via the
* java.security.krb5.realm system property.
*/
public KerberosPrincipal(String name) {
this(name, KRB_NT_PRINCIPAL);
}
/**
* Constructs a KerberosPrincipal from the provided string and
* name type input. The string is assumed to contain a name in the
* format that is specified in Section 2.1 (Mandatory Name Forms) of
* <a href=http://www.ietf.org/rfc/rfc1964.txt>RFC 1964</a>.
* Valid name types are specified in Section 6.2 (Principal Names) of
* <a href=http://www.ietf.org/rfc/rfc4120.txt>RFC 4120</a>.
* The input name must be consistent with the provided name type.
* (for example, <i>duke@FOO.COM</i>, is a valid input string for the
* name type, KRB_NT_PRINCIPAL where <i>duke</i>
* represents a principal, and <i>FOO.COM</i> represents a realm).
* <p> If the input name does not contain a realm, the default realm
* is used. The default realm can be specified either in a Kerberos
* configuration file or via the java.security.krb5.realm
* system property. For more information, see
* <a href="../../../../../technotes/guides/security/jgss/tutorials/index.html">
* Kerberos Requirements</a>.
*
* @param name the principal name
* @param nameType the name type of the principal
* @throws IllegalArgumentException if name is improperly
* formatted, if name is null, if the nameType is not supported,
* or if name does not contain the realm to use and the default
* realm is not specified in either a Kerberos configuration
* file or via the java.security.krb5.realm system property.
*/
public KerberosPrincipal(String name, int nameType) {
PrincipalName krb5Principal = null;
try {
// Appends the default realm if it is missing
krb5Principal = new PrincipalName(name,nameType);
} catch (KrbException e) {
throw new IllegalArgumentException(e.getMessage());
}
// A ServicePermission with a principal in the deduced realm and
// any action must be granted if no realm is provided by caller.
if (krb5Principal.isRealmDeduced() && !Realm.AUTODEDUCEREALM) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {
sm.checkPermission(new ServicePermission(
"@" + krb5Principal.getRealmAsString(), "-"));
} catch (SecurityException se) {
// Swallow the actual exception to hide info
throw new SecurityException("Cannot read realm info");
}
}
}
this.nameType = nameType;
fullName = krb5Principal.toString();
realm = krb5Principal.getRealmString();
}
/**
* Returns the realm component of this Kerberos principal.
*
* @return the realm component of this Kerberos principal.
*/
public String getRealm() {
return realm;
}
/**
* Returns a hashcode for this principal. The hash code is defined to
* be the result of the following calculation:
* <pre>{@code
* hashCode = getName().hashCode();
* }</pre>
*
* @return a hashCode() for the {@code KerberosPrincipal}
*/
public int hashCode() {
return getName().hashCode();
}
/**
* Compares the specified Object with this Principal for equality.
* Returns true if the given object is also a
* {@code KerberosPrincipal} and the two
* {@code KerberosPrincipal} instances are equivalent.
* More formally two {@code KerberosPrincipal} instances are equal
* if the values returned by {@code getName()} are equal.
*
* @param other the Object to compare to
* @return true if the Object passed in represents the same principal
* as this one, false otherwise.
*/
public boolean equals(Object other) {
if (other == this)
return true;
if (! (other instanceof KerberosPrincipal)) {
return false;
}
String myFullName = getName();
String otherFullName = ((KerberosPrincipal) other).getName();
return myFullName.equals(otherFullName);
}
/**
* Save the KerberosPrincipal object to a stream
*
* @serialData this {@code KerberosPrincipal} is serialized
* by writing out the PrincipalName and the
* realm in their DER-encoded form as specified in Section 5.2.2 of
* <a href=http://www.ietf.org/rfc/rfc4120.txt> RFC4120</a>.
*/
private void writeObject(ObjectOutputStream oos)
throws IOException {
PrincipalName krb5Principal;
try {
krb5Principal = new PrincipalName(fullName, nameType);
oos.writeObject(krb5Principal.asn1Encode());
oos.writeObject(krb5Principal.getRealm().asn1Encode());
} catch (Exception e) {
throw new IOException(e);
}
}
/**
* Reads this object from a stream (i.e., deserializes it)
*/
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
byte[] asn1EncPrincipal = (byte [])ois.readObject();
byte[] encRealm = (byte [])ois.readObject();
try {
Realm realmObject = new Realm(new DerValue(encRealm));
PrincipalName krb5Principal = new PrincipalName(
new DerValue(asn1EncPrincipal), realmObject);
realm = realmObject.toString();
fullName = krb5Principal.toString();
nameType = krb5Principal.getNameType();
} catch (Exception e) {
throw new IOException(e);
}
}
/**
* The returned string corresponds to the single-string
* representation of a Kerberos Principal name as specified in
* Section 2.1 of <a href=http://www.ietf.org/rfc/rfc1964.txt>RFC 1964</a>.
*
* @return the principal name.
*/
public String getName() {
return fullName;
}
/**
* Returns the name type of the KerberosPrincipal. Valid name types
* are specified in Section 6.2 of
* <a href=http://www.ietf.org/rfc/rfc4120.txt> RFC4120</a>.
*
* @return the name type.
*/
public int getNameType() {
return nameType;
}
// Inherits javadocs from Object
public String toString() {
return getName();
}
}

View File

@@ -0,0 +1,810 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.kerberos;
import java.io.*;
import java.util.Date;
import java.util.Arrays;
import java.net.InetAddress;
import java.util.Objects;
import javax.crypto.SecretKey;
import javax.security.auth.Refreshable;
import javax.security.auth.Destroyable;
import javax.security.auth.RefreshFailedException;
import javax.security.auth.DestroyFailedException;
import sun.misc.HexDumpEncoder;
import sun.security.krb5.EncryptionKey;
import sun.security.krb5.Asn1Exception;
import sun.security.util.*;
/**
* This class encapsulates a Kerberos ticket and associated
* information as viewed from the client's point of view. It captures all
* information that the Key Distribution Center (KDC) sends to the client
* in the reply message KDC-REP defined in the Kerberos Protocol
* Specification (<a href=http://www.ietf.org/rfc/rfc4120.txt>RFC 4120</a>).
* <p>
* All Kerberos JAAS login modules that authenticate a user to a KDC should
* use this class. Where available, the login module might even read this
* information from a ticket cache in the operating system instead of
* directly communicating with the KDC. During the commit phase of the JAAS
* authentication process, the JAAS login module should instantiate this
* class and store the instance in the private credential set of a
* {@link javax.security.auth.Subject Subject}.<p>
*
* It might be necessary for the application to be granted a
* {@link javax.security.auth.PrivateCredentialPermission
* PrivateCredentialPermission} if it needs to access a KerberosTicket
* instance from a Subject. This permission is not needed when the
* application depends on the default JGSS Kerberos mechanism to access the
* KerberosTicket. In that case, however, the application will need an
* appropriate
* {@link javax.security.auth.kerberos.ServicePermission ServicePermission}.
* <p>
* Note that this class is applicable to both ticket granting tickets and
* other regular service tickets. A ticket granting ticket is just a
* special case of a more generalized service ticket.
*
* @see javax.security.auth.Subject
* @see javax.security.auth.PrivateCredentialPermission
* @see javax.security.auth.login.LoginContext
* @see org.ietf.jgss.GSSCredential
* @see org.ietf.jgss.GSSManager
*
* @author Mayank Upadhyay
* @since 1.4
*/
public class KerberosTicket implements Destroyable, Refreshable,
java.io.Serializable {
private static final long serialVersionUID = 7395334370157380539L;
// XXX Make these flag indices public
private static final int FORWARDABLE_TICKET_FLAG = 1;
private static final int FORWARDED_TICKET_FLAG = 2;
private static final int PROXIABLE_TICKET_FLAG = 3;
private static final int PROXY_TICKET_FLAG = 4;
private static final int POSTDATED_TICKET_FLAG = 6;
private static final int RENEWABLE_TICKET_FLAG = 8;
private static final int INITIAL_TICKET_FLAG = 9;
private static final int NUM_FLAGS = 32;
/**
*
* ASN.1 DER Encoding of the Ticket as defined in the
* Kerberos Protocol Specification RFC4120.
*
* @serial
*/
private byte[] asn1Encoding;
/**
*{@code KeyImpl} is serialized by writing out the ASN1 Encoded bytes
* of the encryption key. The ASN1 encoding is defined in RFC4120 and as
* follows:
* <pre>
* EncryptionKey ::= SEQUENCE {
* keytype [0] Int32 -- actually encryption type --,
* keyvalue [1] OCTET STRING
* }
* </pre>
*
* @serial
*/
private KeyImpl sessionKey;
/**
*
* Ticket Flags as defined in the Kerberos Protocol Specification RFC4120.
*
* @serial
*/
private boolean[] flags;
/**
*
* Time of initial authentication
*
* @serial
*/
private Date authTime;
/**
*
* Time after which the ticket is valid.
* @serial
*/
private Date startTime;
/**
*
* Time after which the ticket will not be honored. (its expiration time).
*
* @serial
*/
private Date endTime;
/**
*
* For renewable Tickets it indicates the maximum endtime that may be
* included in a renewal. It can be thought of as the absolute expiration
* time for the ticket, including all renewals. This field may be null
* for tickets that are not renewable.
*
* @serial
*/
private Date renewTill;
/**
*
* Client that owns the service ticket
*
* @serial
*/
private KerberosPrincipal client;
/**
*
* The service for which the ticket was issued.
*
* @serial
*/
private KerberosPrincipal server;
/**
*
* The addresses from where the ticket may be used by the client.
* This field may be null when the ticket is usable from any address.
*
* @serial
*/
private InetAddress[] clientAddresses;
transient KerberosPrincipal clientAlias = null;
transient KerberosPrincipal serverAlias = null;
/**
* Evidence ticket if proxy_impersonator. This field can be accessed
* by KerberosSecrets. It's serialized.
*/
KerberosTicket proxy = null;
private transient boolean destroyed = false;
/**
* Constructs a KerberosTicket using credentials information that a
* client either receives from a KDC or reads from a cache.
*
* @param asn1Encoding the ASN.1 encoding of the ticket as defined by
* the Kerberos protocol specification.
* @param client the client that owns this service
* ticket
* @param server the service that this ticket is for
* @param sessionKey the raw bytes for the session key that must be
* used to encrypt the authenticator that will be sent to the server
* @param keyType the key type for the session key as defined by the
* Kerberos protocol specification.
* @param flags the ticket flags. Each element in this array indicates
* the value for the corresponding bit in the ASN.1 BitString that
* represents the ticket flags. If the number of elements in this array
* is less than the number of flags used by the Kerberos protocol,
* then the missing flags will be filled in with false.
* @param authTime the time of initial authentication for the client
* @param startTime the time after which the ticket will be valid. This
* may be null in which case the value of authTime is treated as the
* startTime.
* @param endTime the time after which the ticket will no longer be
* valid
* @param renewTill an absolute expiration time for the ticket,
* including all renewal that might be possible. This field may be null
* for tickets that are not renewable.
* @param clientAddresses the addresses from where the ticket may be
* used by the client. This field may be null when the ticket is usable
* from any address.
*/
public KerberosTicket(byte[] asn1Encoding,
KerberosPrincipal client,
KerberosPrincipal server,
byte[] sessionKey,
int keyType,
boolean[] flags,
Date authTime,
Date startTime,
Date endTime,
Date renewTill,
InetAddress[] clientAddresses) {
init(asn1Encoding, client, server, sessionKey, keyType, flags,
authTime, startTime, endTime, renewTill, clientAddresses);
}
private void init(byte[] asn1Encoding,
KerberosPrincipal client,
KerberosPrincipal server,
byte[] sessionKey,
int keyType,
boolean[] flags,
Date authTime,
Date startTime,
Date endTime,
Date renewTill,
InetAddress[] clientAddresses) {
if (sessionKey == null)
throw new IllegalArgumentException("Session key for ticket"
+ " cannot be null");
init(asn1Encoding, client, server,
new KeyImpl(sessionKey, keyType), flags, authTime,
startTime, endTime, renewTill, clientAddresses);
}
private void init(byte[] asn1Encoding,
KerberosPrincipal client,
KerberosPrincipal server,
KeyImpl sessionKey,
boolean[] flags,
Date authTime,
Date startTime,
Date endTime,
Date renewTill,
InetAddress[] clientAddresses) {
if (asn1Encoding == null)
throw new IllegalArgumentException("ASN.1 encoding of ticket"
+ " cannot be null");
this.asn1Encoding = asn1Encoding.clone();
if (client == null)
throw new IllegalArgumentException("Client name in ticket"
+ " cannot be null");
this.client = client;
if (server == null)
throw new IllegalArgumentException("Server name in ticket"
+ " cannot be null");
this.server = server;
// Caller needs to make sure `sessionKey` will not be null
this.sessionKey = sessionKey;
if (flags != null) {
if (flags.length >= NUM_FLAGS)
this.flags = flags.clone();
else {
this.flags = new boolean[NUM_FLAGS];
// Fill in whatever we have
for (int i = 0; i < flags.length; i++)
this.flags[i] = flags[i];
}
} else
this.flags = new boolean[NUM_FLAGS];
if (this.flags[RENEWABLE_TICKET_FLAG] && renewTill != null) {
this.renewTill = new Date(renewTill.getTime());
}
if (authTime != null) {
this.authTime = new Date(authTime.getTime());
}
if (startTime != null) {
this.startTime = new Date(startTime.getTime());
} else {
this.startTime = this.authTime;
}
if (endTime == null)
throw new IllegalArgumentException("End time for ticket validity"
+ " cannot be null");
this.endTime = new Date(endTime.getTime());
if (clientAddresses != null)
this.clientAddresses = clientAddresses.clone();
}
/**
* Returns the client principal associated with this ticket.
*
* @return the client principal.
*/
public final KerberosPrincipal getClient() {
return client;
}
/**
* Returns the service principal associated with this ticket.
*
* @return the service principal.
*/
public final KerberosPrincipal getServer() {
return server;
}
/**
* Returns the session key associated with this ticket.
*
* @return the session key.
*/
public final SecretKey getSessionKey() {
if (destroyed)
throw new IllegalStateException("This ticket is no longer valid");
return sessionKey;
}
/**
* Returns the key type of the session key associated with this
* ticket as defined by the Kerberos Protocol Specification.
*
* @return the key type of the session key associated with this
* ticket.
*
* @see #getSessionKey()
*/
public final int getSessionKeyType() {
if (destroyed)
throw new IllegalStateException("This ticket is no longer valid");
return sessionKey.getKeyType();
}
/**
* Determines if this ticket is forwardable.
*
* @return true if this ticket is forwardable, false if not.
*/
public final boolean isForwardable() {
return flags == null? false: flags[FORWARDABLE_TICKET_FLAG];
}
/**
* Determines if this ticket had been forwarded or was issued based on
* authentication involving a forwarded ticket-granting ticket.
*
* @return true if this ticket had been forwarded or was issued based on
* authentication involving a forwarded ticket-granting ticket,
* false otherwise.
*/
public final boolean isForwarded() {
return flags == null? false: flags[FORWARDED_TICKET_FLAG];
}
/**
* Determines if this ticket is proxiable.
*
* @return true if this ticket is proxiable, false if not.
*/
public final boolean isProxiable() {
return flags == null? false: flags[PROXIABLE_TICKET_FLAG];
}
/**
* Determines is this ticket is a proxy-ticket.
*
* @return true if this ticket is a proxy-ticket, false if not.
*/
public final boolean isProxy() {
return flags == null? false: flags[PROXY_TICKET_FLAG];
}
/**
* Determines is this ticket is post-dated.
*
* @return true if this ticket is post-dated, false if not.
*/
public final boolean isPostdated() {
return flags == null? false: flags[POSTDATED_TICKET_FLAG];
}
/**
* Determines is this ticket is renewable. If so, the {@link #refresh()
* refresh} method can be called, assuming the validity period for
* renewing is not already over.
*
* @return true if this ticket is renewable, false if not.
*/
public final boolean isRenewable() {
return flags == null? false: flags[RENEWABLE_TICKET_FLAG];
}
/**
* Determines if this ticket was issued using the Kerberos AS-Exchange
* protocol, and not issued based on some ticket-granting ticket.
*
* @return true if this ticket was issued using the Kerberos AS-Exchange
* protocol, false if not.
*/
public final boolean isInitial() {
return flags == null? false: flags[INITIAL_TICKET_FLAG];
}
/**
* Returns the flags associated with this ticket. Each element in the
* returned array indicates the value for the corresponding bit in the
* ASN.1 BitString that represents the ticket flags.
*
* @return the flags associated with this ticket.
*/
public final boolean[] getFlags() {
return (flags == null? null: flags.clone());
}
/**
* Returns the time that the client was authenticated.
*
* @return the time that the client was authenticated
* or null if not set.
*/
public final java.util.Date getAuthTime() {
return (authTime == null) ? null : (Date)authTime.clone();
}
/**
* Returns the start time for this ticket's validity period.
*
* @return the start time for this ticket's validity period
* or null if not set.
*/
public final java.util.Date getStartTime() {
return (startTime == null) ? null : (Date)startTime.clone();
}
/**
* Returns the expiration time for this ticket's validity period.
*
* @return the expiration time for this ticket's validity period.
*/
public final java.util.Date getEndTime() {
return (endTime == null) ? null : (Date) endTime.clone();
}
/**
* Returns the latest expiration time for this ticket, including all
* renewals. This will return a null value for non-renewable tickets.
*
* @return the latest expiration time for this ticket.
*/
public final java.util.Date getRenewTill() {
return (renewTill == null) ? null: (Date)renewTill.clone();
}
/**
* Returns a list of addresses from where the ticket can be used.
*
* @return ths list of addresses or null, if the field was not
* provided.
*/
public final java.net.InetAddress[] getClientAddresses() {
return (clientAddresses == null) ? null: clientAddresses.clone();
}
/**
* Returns an ASN.1 encoding of the entire ticket.
*
* @return an ASN.1 encoding of the entire ticket.
*/
public final byte[] getEncoded() {
if (destroyed)
throw new IllegalStateException("This ticket is no longer valid");
return asn1Encoding.clone();
}
/** Determines if this ticket is still current. */
public boolean isCurrent() {
return endTime == null? false: (System.currentTimeMillis() <= endTime.getTime());
}
/**
* Extends the validity period of this ticket. The ticket will contain
* a new session key if the refresh operation succeeds. The refresh
* operation will fail if the ticket is not renewable or the latest
* allowable renew time has passed. Any other error returned by the
* KDC will also cause this method to fail.
*
* Note: This method is not synchronized with the the accessor
* methods of this object. Hence callers need to be aware of multiple
* threads that might access this and try to renew it at the same
* time.
*
* @throws RefreshFailedException if the ticket is not renewable, or
* the latest allowable renew time has passed, or the KDC returns some
* error.
*
* @see #isRenewable()
* @see #getRenewTill()
*/
public void refresh() throws RefreshFailedException {
if (destroyed)
throw new RefreshFailedException("A destroyed ticket "
+ "cannot be renewd.");
if (!isRenewable())
throw new RefreshFailedException("This ticket is not renewable");
if (getRenewTill() == null) {
// Renewable ticket without renew-till. Illegal and ignored.
return;
}
if (System.currentTimeMillis() > getRenewTill().getTime())
throw new RefreshFailedException("This ticket is past "
+ "its last renewal time.");
Throwable e = null;
sun.security.krb5.Credentials krb5Creds = null;
try {
krb5Creds = new sun.security.krb5.Credentials(asn1Encoding,
client.toString(),
(clientAlias != null ?
clientAlias.getName() : null),
server.toString(),
(serverAlias != null ?
serverAlias.getName() : null),
sessionKey.getEncoded(),
sessionKey.getKeyType(),
flags,
authTime,
startTime,
endTime,
renewTill,
clientAddresses);
krb5Creds = krb5Creds.renew();
} catch (sun.security.krb5.KrbException krbException) {
e = krbException;
} catch (java.io.IOException ioException) {
e = ioException;
}
if (e != null) {
RefreshFailedException rfException
= new RefreshFailedException("Failed to renew Kerberos Ticket "
+ "for client " + client
+ " and server " + server
+ " - " + e.getMessage());
rfException.initCause(e);
throw rfException;
}
/*
* In case multiple threads try to refresh it at the same time.
*/
synchronized (this) {
try {
this.destroy();
} catch (DestroyFailedException dfException) {
// Squelch it since we don't care about the old ticket.
}
init(krb5Creds.getEncoded(),
new KerberosPrincipal(krb5Creds.getClient().getName()),
new KerberosPrincipal(krb5Creds.getServer().getName(),
KerberosPrincipal.KRB_NT_SRV_INST),
krb5Creds.getSessionKey().getBytes(),
krb5Creds.getSessionKey().getEType(),
krb5Creds.getFlags(),
krb5Creds.getAuthTime(),
krb5Creds.getStartTime(),
krb5Creds.getEndTime(),
krb5Creds.getRenewTill(),
krb5Creds.getClientAddresses());
destroyed = false;
}
}
/**
* Destroys the ticket and destroys any sensitive information stored in
* it.
*/
public void destroy() throws DestroyFailedException {
if (!destroyed) {
Arrays.fill(asn1Encoding, (byte) 0);
client = null;
server = null;
sessionKey.destroy();
flags = null;
authTime = null;
startTime = null;
endTime = null;
renewTill = null;
clientAddresses = null;
destroyed = true;
}
}
/**
* Determines if this ticket has been destroyed.
*/
public boolean isDestroyed() {
return destroyed;
}
public String toString() {
if (destroyed) {
return "Destroyed KerberosTicket";
}
StringBuffer caddrBuf = new StringBuffer();
if (clientAddresses != null) {
for (int i = 0; i < clientAddresses.length; i++) {
caddrBuf.append("clientAddresses[" + i + "] = " +
clientAddresses[i].toString());
}
}
return ("Ticket (hex) = " + "\n" +
(new HexDumpEncoder()).encodeBuffer(asn1Encoding) + "\n" +
"Client Principal = " + client.toString() + "\n" +
"Server Principal = " + server.toString() + "\n" +
"Session Key = " + sessionKey.toString() + "\n" +
"Forwardable Ticket " + flags[FORWARDABLE_TICKET_FLAG] + "\n" +
"Forwarded Ticket " + flags[FORWARDED_TICKET_FLAG] + "\n" +
"Proxiable Ticket " + flags[PROXIABLE_TICKET_FLAG] + "\n" +
"Proxy Ticket " + flags[PROXY_TICKET_FLAG] + "\n" +
"Postdated Ticket " + flags[POSTDATED_TICKET_FLAG] + "\n" +
"Renewable Ticket " + flags[RENEWABLE_TICKET_FLAG] + "\n" +
"Initial Ticket " + flags[RENEWABLE_TICKET_FLAG] + "\n" +
"Auth Time = " + String.valueOf(authTime) + "\n" +
"Start Time = " + String.valueOf(startTime) + "\n" +
"End Time = " + endTime.toString() + "\n" +
"Renew Till = " + String.valueOf(renewTill) + "\n" +
"Client Addresses " +
(clientAddresses == null ? " Null " : caddrBuf.toString() +
(proxy == null ? "" : "\nwith a proxy ticket") +
"\n"));
}
/**
* Returns a hashcode for this KerberosTicket.
*
* @return a hashCode() for the {@code KerberosTicket}
* @since 1.6
*/
public int hashCode() {
int result = 17;
if (isDestroyed()) {
return result;
}
result = result * 37 + Arrays.hashCode(getEncoded());
result = result * 37 + endTime.hashCode();
result = result * 37 + client.hashCode();
result = result * 37 + server.hashCode();
result = result * 37 + sessionKey.hashCode();
// authTime may be null
if (authTime != null) {
result = result * 37 + authTime.hashCode();
}
// startTime may be null
if (startTime != null) {
result = result * 37 + startTime.hashCode();
}
// renewTill may be null
if (renewTill != null) {
result = result * 37 + renewTill.hashCode();
}
// clientAddress may be null, the array's hashCode is 0
result = result * 37 + Arrays.hashCode(clientAddresses);
if (proxy != null) {
result = result * 37 + proxy.hashCode();
}
return result * 37 + Arrays.hashCode(flags);
}
/**
* Compares the specified Object with this KerberosTicket for equality.
* Returns true if the given object is also a
* {@code KerberosTicket} and the two
* {@code KerberosTicket} instances are equivalent.
*
* @param other the Object to compare to
* @return true if the specified object is equal to this KerberosTicket,
* false otherwise. NOTE: Returns false if either of the KerberosTicket
* objects has been destroyed.
* @since 1.6
*/
public boolean equals(Object other) {
if (other == this)
return true;
if (! (other instanceof KerberosTicket)) {
return false;
}
KerberosTicket otherTicket = ((KerberosTicket) other);
if (isDestroyed() || otherTicket.isDestroyed()) {
return false;
}
if (!Arrays.equals(getEncoded(), otherTicket.getEncoded()) ||
!endTime.equals(otherTicket.getEndTime()) ||
!server.equals(otherTicket.getServer()) ||
!client.equals(otherTicket.getClient()) ||
!sessionKey.equals(otherTicket.getSessionKey()) ||
!Arrays.equals(clientAddresses, otherTicket.getClientAddresses()) ||
!Arrays.equals(flags, otherTicket.getFlags())) {
return false;
}
// authTime may be null
if (authTime == null) {
if (otherTicket.getAuthTime() != null)
return false;
} else {
if (!authTime.equals(otherTicket.getAuthTime()))
return false;
}
// startTime may be null
if (startTime == null) {
if (otherTicket.getStartTime() != null)
return false;
} else {
if (!startTime.equals(otherTicket.getStartTime()))
return false;
}
if (renewTill == null) {
if (otherTicket.getRenewTill() != null)
return false;
} else {
if (!renewTill.equals(otherTicket.getRenewTill()))
return false;
}
if (!Objects.equals(proxy, otherTicket.proxy)) {
return false;
}
return true;
}
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
if (sessionKey == null) {
throw new InvalidObjectException("Session key cannot be null");
}
try {
init(asn1Encoding, client, server, sessionKey,
flags, authTime, startTime, endTime,
renewTill, clientAddresses);
} catch (IllegalArgumentException iae) {
throw (InvalidObjectException)
new InvalidObjectException(iae.getMessage()).initCause(iae);
}
}
}

View File

@@ -0,0 +1,238 @@
/*
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.kerberos;
import java.io.*;
import java.util.Arrays;
import javax.crypto.SecretKey;
import javax.security.auth.Destroyable;
import javax.security.auth.DestroyFailedException;
import sun.security.jgss.krb5.Krb5Util;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.EncryptionKey;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.KrbException;
import sun.security.krb5.KrbCryptoException;
import sun.security.util.DerValue;
/**
* This class encapsulates a Kerberos encryption key. It is not associated
* with a principal and may represent an ephemeral session key.
*
* @author Mayank Upadhyay
* @since 1.4
*
* @serial include
*/
class KeyImpl implements SecretKey, Destroyable, Serializable {
private static final long serialVersionUID = -7889313790214321193L;
private transient byte[] keyBytes;
private transient int keyType;
private transient volatile boolean destroyed = false;
/**
* Constructs a KeyImpl from the given bytes.
*
* @param keyBytes the raw bytes for the secret key
* @param keyType the key type for the secret key as defined by the
* Kerberos protocol specification.
*/
public KeyImpl(byte[] keyBytes,
int keyType) {
this.keyBytes = keyBytes.clone();
this.keyType = keyType;
}
/**
* Constructs a KeyImpl from a password.
*
* @param principal the principal from which to derive the salt
* @param password the password that should be used to compute the
* key.
* @param algorithm the name for the algorithm that this key wil be
* used for. This parameter may be null in which case "DES" will be
* assumed.
*/
public KeyImpl(KerberosPrincipal principal,
char[] password,
String algorithm) {
try {
PrincipalName princ = new PrincipalName(principal.getName());
EncryptionKey key =
new EncryptionKey(password, princ.getSalt(), algorithm);
this.keyBytes = key.getBytes();
this.keyType = key.getEType();
} catch (KrbException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
/**
* Returns the keyType for this key as defined in the Kerberos Spec.
*/
public final int getKeyType() {
if (destroyed)
throw new IllegalStateException("This key is no longer valid");
return keyType;
}
/*
* Methods from java.security.Key
*/
public final String getAlgorithm() {
return getAlgorithmName(keyType);
}
private String getAlgorithmName(int eType) {
if (destroyed)
throw new IllegalStateException("This key is no longer valid");
switch (eType) {
case EncryptedData.ETYPE_DES_CBC_CRC:
case EncryptedData.ETYPE_DES_CBC_MD5:
return "DES";
case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD:
return "DESede";
case EncryptedData.ETYPE_ARCFOUR_HMAC:
return "ArcFourHmac";
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
return "AES128";
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
return "AES256";
case EncryptedData.ETYPE_NULL:
return "NULL";
default:
throw new IllegalArgumentException(
"Unsupported encryption type: " + eType);
}
}
public final String getFormat() {
if (destroyed)
throw new IllegalStateException("This key is no longer valid");
return "RAW";
}
public final byte[] getEncoded() {
if (destroyed)
throw new IllegalStateException("This key is no longer valid");
return keyBytes.clone();
}
public void destroy() throws DestroyFailedException {
if (!destroyed) {
destroyed = true;
Arrays.fill(keyBytes, (byte) 0);
}
}
public boolean isDestroyed() {
return destroyed;
}
/**
* @serialData this {@code KeyImpl} is serialized by
* writing out the ASN1 Encoded bytes of the encryption key.
* The ASN1 encoding is defined in RFC4120 and as follows:
* EncryptionKey ::= SEQUENCE {
* keytype [0] Int32 -- actually encryption type --,
* keyvalue [1] OCTET STRING
* }
*/
private void writeObject(ObjectOutputStream ois)
throws IOException {
if (destroyed) {
throw new IOException("This key is no longer valid");
}
try {
ois.writeObject((new EncryptionKey(keyType, keyBytes)).asn1Encode());
} catch (Asn1Exception ae) {
throw new IOException(ae.getMessage());
}
}
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
try {
EncryptionKey encKey = new EncryptionKey(new
DerValue((byte[])ois.readObject()));
keyType = encKey.getEType();
keyBytes = encKey.getBytes();
} catch (Asn1Exception ae) {
throw new IOException(ae.getMessage());
}
}
public String toString() {
return "keyType=" + keyType
+ ", " + Krb5Util.keyInfo(keyBytes);
}
public int hashCode() {
int result = 17;
if(isDestroyed()) {
return result;
}
result = 37 * result + Arrays.hashCode(keyBytes);
return 37 * result + keyType;
}
public boolean equals(Object other) {
if (other == this)
return true;
if (! (other instanceof KeyImpl)) {
return false;
}
KeyImpl otherKey = ((KeyImpl) other);
if (isDestroyed() || otherKey.isDestroyed()) {
return false;
}
if(keyType != otherKey.getKeyType() ||
!Arrays.equals(keyBytes, otherKey.getEncoded())) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,380 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.kerberos;
import java.io.File;
import java.security.AccessControlException;
import java.util.Objects;
import sun.security.krb5.EncryptionKey;
import sun.security.krb5.KerberosSecrets;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.RealmException;
/**
* This class encapsulates a keytab file.
* <p>
* A Kerberos JAAS login module that obtains long term secret keys from a
* keytab file should use this class. The login module will store
* an instance of this class in the private credential set of a
* {@link javax.security.auth.Subject Subject} during the commit phase of the
* authentication process.
* <p>
* If a {@code KeyTab} object is obtained from {@link #getUnboundInstance()}
* or {@link #getUnboundInstance(java.io.File)}, it is unbound and thus can be
* used by any service principal. Otherwise, if it's obtained from
* {@link #getInstance(KerberosPrincipal)} or
* {@link #getInstance(KerberosPrincipal, java.io.File)}, it is bound to the
* specific service principal and can only be used by it.
* <p>
* Please note the constructors {@link #getInstance()} and
* {@link #getInstance(java.io.File)} were created when there was no support
* for unbound keytabs. These methods should not be used anymore. An object
* created with either of these methods are considered to be bound to an
* unknown principal, which means, its {@link #isBound()} returns true and
* {@link #getPrincipal()} returns null.
* <p>
* It might be necessary for the application to be granted a
* {@link javax.security.auth.PrivateCredentialPermission
* PrivateCredentialPermission} if it needs to access the KeyTab
* instance from a Subject. This permission is not needed when the
* application depends on the default JGSS Kerberos mechanism to access the
* KeyTab. In that case, however, the application will need an appropriate
* {@link javax.security.auth.kerberos.ServicePermission ServicePermission}.
* <p>
* The keytab file format is described at
* <a href="http://www.ioplex.com/utilities/keytab.txt">
* http://www.ioplex.com/utilities/keytab.txt</a>.
* <p>
* @since 1.7
*/
public final class KeyTab {
/*
* Impl notes:
*
* This class is only a name, a permanent link to the keytab source
* (can be missing). Itself has no content. In order to read content,
* take a snapshot and read from it.
*
* The snapshot is of type sun.security.krb5.internal.ktab.KeyTab, which
* contains the content of the keytab file when the snapshot is taken.
* Itself has no refresh function and mostly an immutable class (except
* for the create/add/save methods only used by the ktab command).
*/
// Source, null if using the default one. Note that the default name
// is maintained in snapshot, this field is never "resolved".
private final File file;
// Bound user: normally from the "principal" value in a JAAS krb5
// login conf. Will be null if it's "*".
private final KerberosPrincipal princ;
private final boolean bound;
// Set up JavaxSecurityAuthKerberosAccess in KerberosSecrets
static {
KerberosSecrets.setJavaxSecurityAuthKerberosAccess(
new JavaxSecurityAuthKerberosAccessImpl());
}
private KeyTab(KerberosPrincipal princ, File file, boolean bound) {
this.princ = princ;
this.file = file;
this.bound = bound;
}
/**
* Returns a {@code KeyTab} instance from a {@code File} object
* that is bound to an unknown service principal.
* <p>
* The result of this method is never null. This method only associates
* the returned {@code KeyTab} object with the file and does not read it.
* <p>
* Developers should call {@link #getInstance(KerberosPrincipal,File)}
* when the bound service principal is known.
* @param file the keytab {@code File} object, must not be null
* @return the keytab instance
* @throws NullPointerException if the {@code file} argument is null
*/
public static KeyTab getInstance(File file) {
if (file == null) {
throw new NullPointerException("file must be non null");
}
return new KeyTab(null, file, true);
}
/**
* Returns an unbound {@code KeyTab} instance from a {@code File}
* object.
* <p>
* The result of this method is never null. This method only associates
* the returned {@code KeyTab} object with the file and does not read it.
* @param file the keytab {@code File} object, must not be null
* @return the keytab instance
* @throws NullPointerException if the file argument is null
* @since 1.8
*/
public static KeyTab getUnboundInstance(File file) {
if (file == null) {
throw new NullPointerException("file must be non null");
}
return new KeyTab(null, file, false);
}
/**
* Returns a {@code KeyTab} instance from a {@code File} object
* that is bound to the specified service principal.
* <p>
* The result of this method is never null. This method only associates
* the returned {@code KeyTab} object with the file and does not read it.
* @param princ the bound service principal, must not be null
* @param file the keytab {@code File} object, must not be null
* @return the keytab instance
* @throws NullPointerException if either of the arguments is null
* @since 1.8
*/
public static KeyTab getInstance(KerberosPrincipal princ, File file) {
if (princ == null) {
throw new NullPointerException("princ must be non null");
}
if (file == null) {
throw new NullPointerException("file must be non null");
}
return new KeyTab(princ, file, true);
}
/**
* Returns the default {@code KeyTab} instance that is bound
* to an unknown service principal.
* <p>
* The result of this method is never null. This method only associates
* the returned {@code KeyTab} object with the default keytab file and
* does not read it.
* <p>
* Developers should call {@link #getInstance(KerberosPrincipal)}
* when the bound service principal is known.
* @return the default keytab instance.
*/
public static KeyTab getInstance() {
return new KeyTab(null, null, true);
}
/**
* Returns the default unbound {@code KeyTab} instance.
* <p>
* The result of this method is never null. This method only associates
* the returned {@code KeyTab} object with the default keytab file and
* does not read it.
* @return the default keytab instance
* @since 1.8
*/
public static KeyTab getUnboundInstance() {
return new KeyTab(null, null, false);
}
/**
* Returns the default {@code KeyTab} instance that is bound
* to the specified service principal.
* <p>
* The result of this method is never null. This method only associates
* the returned {@code KeyTab} object with the default keytab file and
* does not read it.
* @param princ the bound service principal, must not be null
* @return the default keytab instance
* @throws NullPointerException if {@code princ} is null
* @since 1.8
*/
public static KeyTab getInstance(KerberosPrincipal princ) {
if (princ == null) {
throw new NullPointerException("princ must be non null");
}
return new KeyTab(princ, null, true);
}
// Takes a snapshot of the keytab content. This method is called by
// JavaxSecurityAuthKerberosAccessImpl so no more private
sun.security.krb5.internal.ktab.KeyTab takeSnapshot() {
try {
return sun.security.krb5.internal.ktab.KeyTab.getInstance(file);
} catch (AccessControlException ace) {
if (file != null) {
// It's OK to show the name if caller specified it
throw ace;
} else {
AccessControlException ace2 = new AccessControlException(
"Access to default keytab denied (modified exception)");
ace2.setStackTrace(ace.getStackTrace());
throw ace2;
}
}
}
/**
* Returns fresh keys for the given Kerberos principal.
* <p>
* Implementation of this method should make sure the returned keys match
* the latest content of the keytab file. The result is a newly created
* copy that can be modified by the caller without modifying the keytab
* object. The caller should {@link KerberosKey#destroy() destroy} the
* result keys after they are used.
* <p>
* Please note that the keytab file can be created after the
* {@code KeyTab} object is instantiated and its content may change over
* time. Therefore, an application should call this method only when it
* needs to use the keys. Any previous result from an earlier invocation
* could potentially be expired.
* <p>
* If there is any error (say, I/O error or format error)
* during the reading process of the KeyTab file, a saved result should be
* returned. If there is no saved result (say, this is the first time this
* method is called, or, all previous read attempts failed), an empty array
* should be returned. This can make sure the result is not drastically
* changed during the (probably slow) update of the keytab file.
* <p>
* Each time this method is called and the reading of the file succeeds
* with no exception (say, I/O error or file format error),
* the result should be saved for {@code principal}. The implementation can
* also save keys for other principals having keys in the same keytab object
* if convenient.
* <p>
* Any unsupported key read from the keytab is ignored and not included
* in the result.
* <p>
* If this keytab is bound to a specific principal, calling this method on
* another principal will return an empty array.
*
* @param principal the Kerberos principal, must not be null.
* @return the keys (never null, may be empty)
* @throws NullPointerException if the {@code principal}
* argument is null
* @throws SecurityException if a security manager exists and the read
* access to the keytab file is not permitted
*/
public KerberosKey[] getKeys(KerberosPrincipal principal) {
try {
if (princ != null && !principal.equals(princ)) {
return new KerberosKey[0];
}
PrincipalName pn = new PrincipalName(principal.getName());
EncryptionKey[] keys = takeSnapshot().readServiceKeys(pn);
KerberosKey[] kks = new KerberosKey[keys.length];
for (int i=0; i<kks.length; i++) {
Integer tmp = keys[i].getKeyVersionNumber();
kks[i] = new KerberosKey(
principal,
keys[i].getBytes(),
keys[i].getEType(),
tmp == null ? 0 : tmp.intValue());
keys[i].destroy();
}
return kks;
} catch (RealmException re) {
return new KerberosKey[0];
}
}
EncryptionKey[] getEncryptionKeys(PrincipalName principal) {
return takeSnapshot().readServiceKeys(principal);
}
/**
* Checks if the keytab file exists. Implementation of this method
* should make sure that the result matches the latest status of the
* keytab file.
* <p>
* The caller can use the result to determine if it should fallback to
* another mechanism to read the keys.
* @return true if the keytab file exists; false otherwise.
* @throws SecurityException if a security manager exists and the read
* access to the keytab file is not permitted
*/
public boolean exists() {
return !takeSnapshot().isMissing();
}
public String toString() {
String s = (file == null) ? "Default keytab" : file.toString();
if (!bound) return s;
else if (princ == null) return s + " for someone";
else return s + " for " + princ;
}
/**
* Returns a hashcode for this KeyTab.
*
* @return a hashCode() for the {@code KeyTab}
*/
public int hashCode() {
return Objects.hash(file, princ, bound);
}
/**
* Compares the specified Object with this KeyTab for equality.
* Returns true if the given object is also a
* {@code KeyTab} and the two
* {@code KeyTab} instances are equivalent.
*
* @param other the Object to compare to
* @return true if the specified object is equal to this KeyTab
*/
public boolean equals(Object other) {
if (other == this)
return true;
if (! (other instanceof KeyTab)) {
return false;
}
KeyTab otherKtab = (KeyTab) other;
return Objects.equals(otherKtab.princ, princ) &&
Objects.equals(otherKtab.file, file) &&
bound == otherKtab.bound;
}
/**
* Returns the service principal this {@code KeyTab} object
* is bound to. Returns {@code null} if it's not bound.
* <p>
* Please note the deprecated constructors create a KeyTab object bound for
* some unknown principal. In this case, this method also returns null.
* User can call {@link #isBound()} to verify this case.
* @return the service principal
* @since 1.8
*/
public KerberosPrincipal getPrincipal() {
return princ;
}
/**
* Returns if the keytab is bound to a principal
* @return if the keytab is bound to a principal
* @since 1.8
*/
public boolean isBound() {
return bound;
}
}

View File

@@ -0,0 +1,616 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.kerberos;
import java.util.*;
import java.security.Permission;
import java.security.PermissionCollection;
import java.io.ObjectStreamField;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
/**
* This class is used to protect Kerberos services and the
* credentials necessary to access those services. There is a one to
* one mapping of a service principal and the credentials necessary
* to access the service. Therefore granting access to a service
* principal implicitly grants access to the credential necessary to
* establish a security context with the service principal. This
* applies regardless of whether the credentials are in a cache
* or acquired via an exchange with the KDC. The credential can
* be either a ticket granting ticket, a service ticket or a secret
* key from a key table.
* <p>
* A ServicePermission contains a service principal name and
* a list of actions which specify the context the credential can be
* used within.
* <p>
* The service principal name is the canonical name of the
* {@code KerberosPrincipal} supplying the service, that is
* the KerberosPrincipal represents a Kerberos service
* principal. This name is treated in a case sensitive manner.
* An asterisk may appear by itself, to signify any service principal.
* <p>
* Granting this permission implies that the caller can use a cached
* credential (TGT, service ticket or secret key) within the context
* designated by the action. In the case of the TGT, granting this
* permission also implies that the TGT can be obtained by an
* Authentication Service exchange.
* <p>
* The possible actions are:
*
* <pre>
* initiate - allow the caller to use the credential to
* initiate a security context with a service
* principal.
*
* accept - allow the caller to use the credential to
* accept security context as a particular
* principal.
* </pre>
*
* For example, to specify the permission to access to the TGT to
* initiate a security context the permission is constructed as follows:
*
* <pre>
* ServicePermission("krbtgt/EXAMPLE.COM@EXAMPLE.COM", "initiate");
* </pre>
* <p>
* To obtain a service ticket to initiate a context with the "host"
* service the permission is constructed as follows:
* <pre>
* ServicePermission("host/foo.example.com@EXAMPLE.COM", "initiate");
* </pre>
* <p>
* For a Kerberized server the action is "accept". For example, the permission
* necessary to access and use the secret key of the Kerberized "host"
* service (telnet and the likes) would be constructed as follows:
*
* <pre>
* ServicePermission("host/foo.example.com@EXAMPLE.COM", "accept");
* </pre>
*
* @since 1.4
*/
public final class ServicePermission extends Permission
implements java.io.Serializable {
private static final long serialVersionUID = -1227585031618624935L;
/**
* Initiate a security context to the specified service
*/
private final static int INITIATE = 0x1;
/**
* Accept a security context
*/
private final static int ACCEPT = 0x2;
/**
* All actions
*/
private final static int ALL = INITIATE|ACCEPT;
/**
* No actions.
*/
private final static int NONE = 0x0;
// the actions mask
private transient int mask;
/**
* the actions string.
*
* @serial
*/
private String actions; // Left null as long as possible, then
// created and re-used in the getAction function.
/**
* Create a new {@code ServicePermission}
* with the specified {@code servicePrincipal}
* and {@code action}.
*
* @param servicePrincipal the name of the service principal.
* An asterisk may appear by itself, to signify any service principal.
* <p>
* @param action the action string
*/
public ServicePermission(String servicePrincipal, String action) {
// Note: servicePrincipal can be "@REALM" which means any principal in
// this realm implies it. action can be "-" which means any
// action implies it.
super(servicePrincipal);
init(servicePrincipal, getMask(action));
}
/**
* Initialize the ServicePermission object.
*/
private void init(String servicePrincipal, int mask) {
if (servicePrincipal == null)
throw new NullPointerException("service principal can't be null");
if ((mask & ALL) != mask)
throw new IllegalArgumentException("invalid actions mask");
this.mask = mask;
}
/**
* Checks if this Kerberos service permission object "implies" the
* specified permission.
* <P>
* If none of the above are true, {@code implies} returns false.
* @param p the permission to check against.
*
* @return true if the specified permission is implied by this object,
* false if not.
*/
public boolean implies(Permission p) {
if (!(p instanceof ServicePermission))
return false;
ServicePermission that = (ServicePermission) p;
return ((this.mask & that.mask) == that.mask) &&
impliesIgnoreMask(that);
}
boolean impliesIgnoreMask(ServicePermission p) {
return ((this.getName().equals("*")) ||
this.getName().equals(p.getName()) ||
(p.getName().startsWith("@") &&
this.getName().endsWith(p.getName())));
}
/**
* Checks two ServicePermission objects for equality.
* <P>
* @param obj the object to test for equality with this object.
*
* @return true if <i>obj</i> is a ServicePermission, and has the
* same service principal, and actions as this
* ServicePermission object.
*/
public boolean equals(Object obj) {
if (obj == this)
return true;
if (! (obj instanceof ServicePermission))
return false;
ServicePermission that = (ServicePermission) obj;
return ((this.mask & that.mask) == that.mask) &&
this.getName().equals(that.getName());
}
/**
* Returns the hash code value for this object.
*
* @return a hash code value for this object.
*/
public int hashCode() {
return (getName().hashCode() ^ mask);
}
/**
* Returns the "canonical string representation" of the actions in the
* specified mask.
* Always returns present actions in the following order:
* initiate, accept.
*
* @param mask a specific integer action mask to translate into a string
* @return the canonical string representation of the actions
*/
private static String getActions(int mask)
{
StringBuilder sb = new StringBuilder();
boolean comma = false;
if ((mask & INITIATE) == INITIATE) {
if (comma) sb.append(',');
else comma = true;
sb.append("initiate");
}
if ((mask & ACCEPT) == ACCEPT) {
if (comma) sb.append(',');
else comma = true;
sb.append("accept");
}
return sb.toString();
}
/**
* Returns the canonical string representation of the actions.
* Always returns present actions in the following order:
* initiate, accept.
*/
public String getActions() {
if (actions == null)
actions = getActions(this.mask);
return actions;
}
/**
* Returns a PermissionCollection object for storing
* ServicePermission objects.
* <br>
* ServicePermission objects must be stored in a manner that
* allows them to be inserted into the collection in any order, but
* that also enables the PermissionCollection implies method to
* be implemented in an efficient (and consistent) manner.
*
* @return a new PermissionCollection object suitable for storing
* ServicePermissions.
*/
public PermissionCollection newPermissionCollection() {
return new KrbServicePermissionCollection();
}
/**
* Return the current action mask.
*
* @return the actions mask.
*/
int getMask() {
return mask;
}
/**
* Convert an action string to an integer actions mask.
*
* Note: if action is "-", action will be NONE, which means any
* action implies it.
*
* @param action the action string.
* @return the action mask
*/
private static int getMask(String action) {
if (action == null) {
throw new NullPointerException("action can't be null");
}
if (action.equals("")) {
throw new IllegalArgumentException("action can't be empty");
}
int mask = NONE;
char[] a = action.toCharArray();
if (a.length == 1 && a[0] == '-') {
return mask;
}
int i = a.length - 1;
while (i != -1) {
char c;
// skip whitespace
while ((i!=-1) && ((c = a[i]) == ' ' ||
c == '\r' ||
c == '\n' ||
c == '\f' ||
c == '\t'))
i--;
// check for the known strings
int matchlen;
if (i >= 7 && (a[i-7] == 'i' || a[i-7] == 'I') &&
(a[i-6] == 'n' || a[i-6] == 'N') &&
(a[i-5] == 'i' || a[i-5] == 'I') &&
(a[i-4] == 't' || a[i-4] == 'T') &&
(a[i-3] == 'i' || a[i-3] == 'I') &&
(a[i-2] == 'a' || a[i-2] == 'A') &&
(a[i-1] == 't' || a[i-1] == 'T') &&
(a[i] == 'e' || a[i] == 'E'))
{
matchlen = 8;
mask |= INITIATE;
} else if (i >= 5 && (a[i-5] == 'a' || a[i-5] == 'A') &&
(a[i-4] == 'c' || a[i-4] == 'C') &&
(a[i-3] == 'c' || a[i-3] == 'C') &&
(a[i-2] == 'e' || a[i-2] == 'E') &&
(a[i-1] == 'p' || a[i-1] == 'P') &&
(a[i] == 't' || a[i] == 'T'))
{
matchlen = 6;
mask |= ACCEPT;
} else {
// parse error
throw new IllegalArgumentException(
"invalid permission: " + action);
}
// make sure we didn't just match the tail of a word
// like "ackbarfaccept". Also, skip to the comma.
boolean seencomma = false;
while (i >= matchlen && !seencomma) {
switch(a[i-matchlen]) {
case ',':
seencomma = true;
break;
case ' ': case '\r': case '\n':
case '\f': case '\t':
break;
default:
throw new IllegalArgumentException(
"invalid permission: " + action);
}
i--;
}
// point i at the location of the comma minus one (or -1).
i -= matchlen;
}
return mask;
}
/**
* WriteObject is called to save the state of the ServicePermission
* to a stream. The actions are serialized, and the superclass
* takes care of the name.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws IOException
{
// Write out the actions. The superclass takes care of the name
// call getActions to make sure actions field is initialized
if (actions == null)
getActions();
s.defaultWriteObject();
}
/**
* readObject is called to restore the state of the
* ServicePermission from a stream.
*/
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException
{
// Read in the action, then initialize the rest
s.defaultReadObject();
init(getName(),getMask(actions));
}
/*
public static void main(String args[]) throws Exception {
ServicePermission this_ =
new ServicePermission(args[0], "accept");
ServicePermission that_ =
new ServicePermission(args[1], "accept,initiate");
System.out.println("-----\n");
System.out.println("this.implies(that) = " + this_.implies(that_));
System.out.println("-----\n");
System.out.println("this = "+this_);
System.out.println("-----\n");
System.out.println("that = "+that_);
System.out.println("-----\n");
KrbServicePermissionCollection nps =
new KrbServicePermissionCollection();
nps.add(this_);
nps.add(new ServicePermission("nfs/example.com@EXAMPLE.COM",
"accept"));
nps.add(new ServicePermission("host/example.com@EXAMPLE.COM",
"initiate"));
System.out.println("nps.implies(that) = " + nps.implies(that_));
System.out.println("-----\n");
Enumeration e = nps.elements();
while (e.hasMoreElements()) {
ServicePermission x =
(ServicePermission) e.nextElement();
System.out.println("nps.e = " + x);
}
}
*/
}
final class KrbServicePermissionCollection extends PermissionCollection
implements java.io.Serializable {
// Not serialized; see serialization section at end of class
private transient List<Permission> perms;
public KrbServicePermissionCollection() {
perms = new ArrayList<Permission>();
}
/**
* Check and see if this collection of permissions implies the permissions
* expressed in "permission".
*
* @param permission the Permission object to compare
*
* @return true if "permission" is a proper subset of a permission in
* the collection, false if not.
*/
public boolean implies(Permission permission) {
if (! (permission instanceof ServicePermission))
return false;
ServicePermission np = (ServicePermission) permission;
int desired = np.getMask();
if (desired == 0) {
for (Permission p: perms) {
ServicePermission sp = (ServicePermission)p;
if (sp.impliesIgnoreMask(np)) {
return true;
}
}
return false;
}
int effective = 0;
int needed = desired;
synchronized (this) {
int len = perms.size();
// need to deal with the case where the needed permission has
// more than one action and the collection has individual permissions
// that sum up to the needed.
for (int i = 0; i < len; i++) {
ServicePermission x = (ServicePermission) perms.get(i);
//System.out.println(" trying "+x);
if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) {
effective |= x.getMask();
if ((effective & desired) == desired)
return true;
needed = (desired ^ effective);
}
}
}
return false;
}
/**
* Adds a permission to the ServicePermissions. The key for
* the hash is the name.
*
* @param permission the Permission object to add.
*
* @exception IllegalArgumentException - if the permission is not a
* ServicePermission
*
* @exception SecurityException - if this PermissionCollection object
* has been marked readonly
*/
public void add(Permission permission) {
if (! (permission instanceof ServicePermission))
throw new IllegalArgumentException("invalid permission: "+
permission);
if (isReadOnly())
throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection");
synchronized (this) {
perms.add(0, permission);
}
}
/**
* Returns an enumeration of all the ServicePermission objects
* in the container.
*
* @return an enumeration of all the ServicePermission objects.
*/
public Enumeration<Permission> elements() {
// Convert Iterator into Enumeration
synchronized (this) {
return Collections.enumeration(perms);
}
}
private static final long serialVersionUID = -4118834211490102011L;
// Need to maintain serialization interoperability with earlier releases,
// which had the serializable field:
// private Vector permissions;
/**
* @serialField permissions java.util.Vector
* A list of ServicePermission objects.
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("permissions", Vector.class),
};
/**
* @serialData "permissions" field (a Vector containing the ServicePermissions).
*/
/*
* Writes the contents of the perms field out as a Vector for
* serialization compatibility with earlier releases.
*/
private void writeObject(ObjectOutputStream out) throws IOException {
// Don't call out.defaultWriteObject()
// Write out Vector
Vector<Permission> permissions = new Vector<>(perms.size());
synchronized (this) {
permissions.addAll(perms);
}
ObjectOutputStream.PutField pfields = out.putFields();
pfields.put("permissions", permissions);
out.writeFields();
}
/*
* Reads in a Vector of ServicePermissions and saves them in the perms field.
*/
@SuppressWarnings("unchecked")
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException
{
// Don't call defaultReadObject()
// Read in serialized fields
ObjectInputStream.GetField gfields = in.readFields();
// Get the one we want
Vector<Permission> permissions =
(Vector<Permission>)gfields.get("permissions", null);
perms = new ArrayList<Permission>(permissions.size());
perms.addAll(permissions);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This package contains utility classes related to the Kerberos network
* authentication protocol. They do not provide much Kerberos support
* themselves.<p>
*
* The Kerberos network authentication protocol is defined in
* <a href=http://www.ietf.org/rfc/rfc4120.txt>RFC 4120</a>. The Java
* platform contains support for the client side of Kerberos via the
* {@link org.ietf.jgss} package. There might also be
* a login module that implements
* {@link javax.security.auth.spi.LoginModule LoginModule} to authenticate
* Kerberos principals.<p>
*
* You can provide the name of your default realm and Key Distribution
* Center (KDC) host for that realm using the system properties
* {@code java.security.krb5.realm} and {@code java.security.krb5.kdc}.
* Both properties must be set.
* Alternatively, the {@code java.security.krb5.conf} system property can
* be set to the location of an MIT style {@code krb5.conf} configuration
* file. If none of these system properties are set, the {@code krb5.conf}
* file is searched for in an implementation-specific manner. Typically,
* an implementation will first look for a {@code krb5.conf} file in
* {@code <java-home>/lib/security} and failing that, in an OS-specific
* location.<p>
*
* The {@code krb5.conf} file is formatted in the Windows INI file style,
* which contains a series of relations grouped into different sections.
* Each relation contains a key and a value, the value can be an arbitrary
* string or a boolean value. A boolean value can be one of "true", "false",
* "yes", or "no", case-insensitive.<p>
*
* @since JDK1.4
*/
package javax.security.auth.kerberos;

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
/**
* A generic account exception.
*
* @since 1.5
*/
public class AccountException extends LoginException {
private static final long serialVersionUID = -2112878680072211787L;
/**
* Constructs a AccountException with no detail message. A detail
* message is a String that describes this particular exception.
*/
public AccountException() {
super();
}
/**
* Constructs a AccountException with the specified detail message.
* A detail message is a String that describes this particular
* exception.
*
* <p>
*
* @param msg the detail message.
*/
public AccountException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
/**
* Signals that a user account has expired.
*
* <p> This exception is thrown by LoginModules when they determine
* that an account has expired. For example, a {@code LoginModule},
* after successfully authenticating a user, may determine that the
* user's account has expired. In this case the {@code LoginModule}
* throws this exception to notify the application. The application can
* then take the appropriate steps to notify the user.
*
*/
public class AccountExpiredException extends AccountException {
private static final long serialVersionUID = -6064064890162661560L;
/**
* Constructs a AccountExpiredException with no detail message. A detail
* message is a String that describes this particular exception.
*/
public AccountExpiredException() {
super();
}
/**
* Constructs a AccountExpiredException with the specified detail
* message. A detail message is a String that describes this particular
* exception.
*
* <p>
*
* @param msg the detail message.
*/
public AccountExpiredException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
/**
* Signals that an account was locked.
*
* <p> This exception may be thrown by a LoginModule if it
* determines that authentication is being attempted on a
* locked account.
*
* @since 1.5
*/
public class AccountLockedException extends AccountException {
private static final long serialVersionUID = 8280345554014066334L;
/**
* Constructs a AccountLockedException with no detail message.
* A detail message is a String that describes this particular exception.
*/
public AccountLockedException() {
super();
}
/**
* Constructs a AccountLockedException with the specified
* detail message. A detail message is a String that describes
* this particular exception.
*
* <p>
*
* @param msg the detail message.
*/
public AccountLockedException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
/**
* Signals that an account was not found.
*
* <p> This exception may be thrown by a LoginModule if it is unable
* to locate an account necessary to perform authentication.
*
* @since 1.5
*/
public class AccountNotFoundException extends AccountException {
private static final long serialVersionUID = 1498349563916294614L;
/**
* Constructs a AccountNotFoundException with no detail message.
* A detail message is a String that describes this particular exception.
*/
public AccountNotFoundException() {
super();
}
/**
* Constructs a AccountNotFoundException with the specified
* detail message. A detail message is a String that describes
* this particular exception.
*
* <p>
*
* @param msg the detail message.
*/
public AccountNotFoundException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
import java.util.Map;
import java.util.Collections;
/**
* This class represents a single {@code LoginModule} entry
* configured for the application specified in the
* {@code getAppConfigurationEntry(String appName)}
* method in the {@code Configuration} class. Each respective
* {@code AppConfigurationEntry} contains a {@code LoginModule} name,
* a control flag (specifying whether this {@code LoginModule} is
* REQUIRED, REQUISITE, SUFFICIENT, or OPTIONAL), and LoginModule-specific
* options. Please refer to the {@code Configuration} class for
* more information on the different control flags and their semantics.
*
* @see javax.security.auth.login.Configuration
*/
public class AppConfigurationEntry {
private String loginModuleName;
private LoginModuleControlFlag controlFlag;
private Map<String,?> options;
/**
* Default constructor for this class.
*
* <p> This entry represents a single {@code LoginModule}
* entry configured for the application specified in the
* {@code getAppConfigurationEntry(String appName)}
* method from the {@code Configuration} class.
*
* @param loginModuleName String representing the class name of the
* {@code LoginModule} configured for the
* specified application. <p>
*
* @param controlFlag either REQUIRED, REQUISITE, SUFFICIENT,
* or OPTIONAL. <p>
*
* @param options the options configured for this {@code LoginModule}.
*
* @exception IllegalArgumentException if {@code loginModuleName}
* is null, if {@code LoginModuleName}
* has a length of 0, if {@code controlFlag}
* is not either REQUIRED, REQUISITE, SUFFICIENT
* or OPTIONAL, or if {@code options} is null.
*/
public AppConfigurationEntry(String loginModuleName,
LoginModuleControlFlag controlFlag,
Map<String,?> options)
{
if (loginModuleName == null || loginModuleName.length() == 0 ||
(controlFlag != LoginModuleControlFlag.REQUIRED &&
controlFlag != LoginModuleControlFlag.REQUISITE &&
controlFlag != LoginModuleControlFlag.SUFFICIENT &&
controlFlag != LoginModuleControlFlag.OPTIONAL) ||
options == null)
throw new IllegalArgumentException();
this.loginModuleName = loginModuleName;
this.controlFlag = controlFlag;
this.options = Collections.unmodifiableMap(options);
}
/**
* Get the class name of the configured {@code LoginModule}.
*
* @return the class name of the configured {@code LoginModule} as
* a String.
*/
public String getLoginModuleName() {
return loginModuleName;
}
/**
* Return the controlFlag
* (either REQUIRED, REQUISITE, SUFFICIENT, or OPTIONAL)
* for this {@code LoginModule}.
*
* @return the controlFlag
* (either REQUIRED, REQUISITE, SUFFICIENT, or OPTIONAL)
* for this {@code LoginModule}.
*/
public LoginModuleControlFlag getControlFlag() {
return controlFlag;
}
/**
* Get the options configured for this {@code LoginModule}.
*
* @return the options configured for this {@code LoginModule}
* as an unmodifiable {@code Map}.
*/
public Map<String,?> getOptions() {
return options;
}
/**
* This class represents whether or not a {@code LoginModule}
* is REQUIRED, REQUISITE, SUFFICIENT or OPTIONAL.
*/
public static class LoginModuleControlFlag {
private String controlFlag;
/**
* Required {@code LoginModule}.
*/
public static final LoginModuleControlFlag REQUIRED =
new LoginModuleControlFlag("required");
/**
* Requisite {@code LoginModule}.
*/
public static final LoginModuleControlFlag REQUISITE =
new LoginModuleControlFlag("requisite");
/**
* Sufficient {@code LoginModule}.
*/
public static final LoginModuleControlFlag SUFFICIENT =
new LoginModuleControlFlag("sufficient");
/**
* Optional {@code LoginModule}.
*/
public static final LoginModuleControlFlag OPTIONAL =
new LoginModuleControlFlag("optional");
private LoginModuleControlFlag(String controlFlag) {
this.controlFlag = controlFlag;
}
/**
* Return a String representation of this controlFlag.
*
* <p> The String has the format, "LoginModuleControlFlag: <i>flag</i>",
* where <i>flag</i> is either <i>required</i>, <i>requisite</i>,
* <i>sufficient</i>, or <i>optional</i>.
*
* @return a String representation of this controlFlag.
*/
public String toString() {
return (sun.security.util.ResourcesMgr.getString
("LoginModuleControlFlag.") + controlFlag);
}
}
}

View File

@@ -0,0 +1,620 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
import javax.security.auth.AuthPermission;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Security;
import java.util.Objects;
import sun.security.jca.GetInstance;
/**
* A Configuration object is responsible for specifying which LoginModules
* should be used for a particular application, and in what order the
* LoginModules should be invoked.
*
* <p> A login configuration contains the following information.
* Note that this example only represents the default syntax for the
* {@code Configuration}. Subclass implementations of this class
* may implement alternative syntaxes and may retrieve the
* {@code Configuration} from any source such as files, databases,
* or servers.
*
* <pre>
* Name {
* ModuleClass Flag ModuleOptions;
* ModuleClass Flag ModuleOptions;
* ModuleClass Flag ModuleOptions;
* };
* Name {
* ModuleClass Flag ModuleOptions;
* ModuleClass Flag ModuleOptions;
* };
* other {
* ModuleClass Flag ModuleOptions;
* ModuleClass Flag ModuleOptions;
* };
* </pre>
*
* <p> Each entry in the {@code Configuration} is indexed via an
* application name, <i>Name</i>, and contains a list of
* LoginModules configured for that application. Each {@code LoginModule}
* is specified via its fully qualified class name.
* Authentication proceeds down the module list in the exact order specified.
* If an application does not have a specific entry,
* it defaults to the specific entry for "<i>other</i>".
*
* <p> The <i>Flag</i> value controls the overall behavior as authentication
* proceeds down the stack. The following represents a description of the
* valid values for <i>Flag</i> and their respective semantics:
*
* <pre>
* 1) Required - The {@code LoginModule} is required to succeed.
* If it succeeds or fails, authentication still continues
* to proceed down the {@code LoginModule} list.
*
* 2) Requisite - The {@code LoginModule} is required to succeed.
* If it succeeds, authentication continues down the
* {@code LoginModule} list. If it fails,
* control immediately returns to the application
* (authentication does not proceed down the
* {@code LoginModule} list).
*
* 3) Sufficient - The {@code LoginModule} is not required to
* succeed. If it does succeed, control immediately
* returns to the application (authentication does not
* proceed down the {@code LoginModule} list).
* If it fails, authentication continues down the
* {@code LoginModule} list.
*
* 4) Optional - The {@code LoginModule} is not required to
* succeed. If it succeeds or fails,
* authentication still continues to proceed down the
* {@code LoginModule} list.
* </pre>
*
* <p> The overall authentication succeeds only if all <i>Required</i> and
* <i>Requisite</i> LoginModules succeed. If a <i>Sufficient</i>
* {@code LoginModule} is configured and succeeds,
* then only the <i>Required</i> and <i>Requisite</i> LoginModules prior to
* that <i>Sufficient</i> {@code LoginModule} need to have succeeded for
* the overall authentication to succeed. If no <i>Required</i> or
* <i>Requisite</i> LoginModules are configured for an application,
* then at least one <i>Sufficient</i> or <i>Optional</i>
* {@code LoginModule} must succeed.
*
* <p> <i>ModuleOptions</i> is a space separated list of
* {@code LoginModule}-specific values which are passed directly to
* the underlying LoginModules. Options are defined by the
* {@code LoginModule} itself, and control the behavior within it.
* For example, a {@code LoginModule} may define options to support
* debugging/testing capabilities. The correct way to specify options in the
* {@code Configuration} is by using the following key-value pairing:
* <i>debug="true"</i>. The key and value should be separated by an
* 'equals' symbol, and the value should be surrounded by double quotes.
* If a String in the form, ${system.property}, occurs in the value,
* it will be expanded to the value of the system property.
* Note that there is no limit to the number of
* options a {@code LoginModule} may define.
*
* <p> The following represents an example {@code Configuration} entry
* based on the syntax above:
*
* <pre>
* Login {
* com.sun.security.auth.module.UnixLoginModule required;
* com.sun.security.auth.module.Krb5LoginModule optional
* useTicketCache="true"
* ticketCache="${user.home}${/}tickets";
* };
* </pre>
*
* <p> This {@code Configuration} specifies that an application named,
* "Login", requires users to first authenticate to the
* <i>com.sun.security.auth.module.UnixLoginModule</i>, which is
* required to succeed. Even if the <i>UnixLoginModule</i>
* authentication fails, the
* <i>com.sun.security.auth.module.Krb5LoginModule</i>
* still gets invoked. This helps hide the source of failure.
* Since the <i>Krb5LoginModule</i> is <i>Optional</i>, the overall
* authentication succeeds only if the <i>UnixLoginModule</i>
* (<i>Required</i>) succeeds.
*
* <p> Also note that the LoginModule-specific options,
* <i>useTicketCache="true"</i> and
* <i>ticketCache=${user.home}${/}tickets"</i>,
* are passed to the <i>Krb5LoginModule</i>.
* These options instruct the <i>Krb5LoginModule</i> to
* use the ticket cache at the specified location.
* The system properties, <i>user.home</i> and <i>/</i>
* (file.separator), are expanded to their respective values.
*
* <p> There is only one Configuration object installed in the runtime at any
* given time. A Configuration object can be installed by calling the
* {@code setConfiguration} method. The installed Configuration object
* can be obtained by calling the {@code getConfiguration} method.
*
* <p> If no Configuration object has been installed in the runtime, a call to
* {@code getConfiguration} installs an instance of the default
* Configuration implementation (a default subclass implementation of this
* abstract class).
* The default Configuration implementation can be changed by setting the value
* of the {@code login.configuration.provider} security property to the fully
* qualified name of the desired Configuration subclass implementation.
*
* <p> Application code can directly subclass Configuration to provide a custom
* implementation. In addition, an instance of a Configuration object can be
* constructed by invoking one of the {@code getInstance} factory methods
* with a standard type. The default policy type is "JavaLoginConfig".
* See the Configuration section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for a list of standard Configuration types.
*
* @see javax.security.auth.login.LoginContext
* @see java.security.Security security properties
*/
public abstract class Configuration {
private static Configuration configuration;
private final java.security.AccessControlContext acc =
java.security.AccessController.getContext();
private static void checkPermission(String type) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new AuthPermission
("createLoginConfiguration." + type));
}
}
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected Configuration() { }
/**
* Get the installed login Configuration.
*
* <p>
*
* @return the login Configuration. If a Configuration object was set
* via the {@code Configuration.setConfiguration} method,
* then that object is returned. Otherwise, a default
* Configuration object is returned.
*
* @exception SecurityException if the caller does not have permission
* to retrieve the Configuration.
*
* @see #setConfiguration
*/
public static Configuration getConfiguration() {
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new AuthPermission("getLoginConfiguration"));
synchronized (Configuration.class) {
if (configuration == null) {
String config_class = null;
config_class = AccessController.doPrivileged
(new PrivilegedAction<String>() {
public String run() {
return java.security.Security.getProperty
("login.configuration.provider");
}
});
if (config_class == null) {
config_class = "sun.security.provider.ConfigFile";
}
try {
final String finalClass = config_class;
Configuration untrustedImpl = AccessController.doPrivileged(
new PrivilegedExceptionAction<Configuration>() {
public Configuration run() throws ClassNotFoundException,
InstantiationException,
IllegalAccessException {
Class<? extends Configuration> implClass = Class.forName(
finalClass, false,
Thread.currentThread().getContextClassLoader()
).asSubclass(Configuration.class);
return implClass.newInstance();
}
});
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>() {
public Void run() {
setConfiguration(untrustedImpl);
return null;
}
}, Objects.requireNonNull(untrustedImpl.acc)
);
} catch (PrivilegedActionException e) {
Exception ee = e.getException();
if (ee instanceof InstantiationException) {
throw (SecurityException) new
SecurityException
("Configuration error:" +
ee.getCause().getMessage() +
"\n").initCause(ee.getCause());
} else {
throw (SecurityException) new
SecurityException
("Configuration error: " +
ee.toString() +
"\n").initCause(ee);
}
}
}
return configuration;
}
}
/**
* Set the login {@code Configuration}.
*
* <p>
*
* @param configuration the new {@code Configuration}
*
* @exception SecurityException if the current thread does not have
* Permission to set the {@code Configuration}.
*
* @see #getConfiguration
*/
public static void setConfiguration(Configuration configuration) {
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new AuthPermission("setLoginConfiguration"));
Configuration.configuration = configuration;
}
/**
* Returns a Configuration object of the specified type.
*
* <p> This method traverses the list of registered security providers,
* starting with the most preferred Provider.
* A new Configuration object encapsulating the
* ConfigurationSpi implementation from the first
* Provider that supports the specified type is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param type the specified Configuration type. See the Configuration
* section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration">
* Java Cryptography Architecture Standard Algorithm Name
* Documentation</a> for a list of standard Configuration types.
*
* @param params parameters for the Configuration, which may be null.
*
* @return the new Configuration object.
*
* @exception SecurityException if the caller does not have permission
* to get a Configuration instance for the specified type.
*
* @exception NullPointerException if the specified type is null.
*
* @exception IllegalArgumentException if the specified parameters
* are not understood by the ConfigurationSpi implementation
* from the selected Provider.
*
* @exception NoSuchAlgorithmException if no Provider supports a
* ConfigurationSpi implementation for the specified type.
*
* @see Provider
* @since 1.6
*/
public static Configuration getInstance(String type,
Configuration.Parameters params)
throws NoSuchAlgorithmException {
checkPermission(type);
try {
GetInstance.Instance instance = GetInstance.getInstance
("Configuration",
ConfigurationSpi.class,
type,
params);
return new ConfigDelegate((ConfigurationSpi)instance.impl,
instance.provider,
type,
params);
} catch (NoSuchAlgorithmException nsae) {
return handleException (nsae);
}
}
/**
* Returns a Configuration object of the specified type.
*
* <p> A new Configuration object encapsulating the
* ConfigurationSpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the provider list.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param type the specified Configuration type. See the Configuration
* section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration">
* Java Cryptography Architecture Standard Algorithm Name
* Documentation</a> for a list of standard Configuration types.
*
* @param params parameters for the Configuration, which may be null.
*
* @param provider the provider.
*
* @return the new Configuration object.
*
* @exception SecurityException if the caller does not have permission
* to get a Configuration instance for the specified type.
*
* @exception NullPointerException if the specified type is null.
*
* @exception IllegalArgumentException if the specified provider
* is null or empty,
* or if the specified parameters are not understood by
* the ConfigurationSpi implementation from the specified provider.
*
* @exception NoSuchProviderException if the specified provider is not
* registered in the security provider list.
*
* @exception NoSuchAlgorithmException if the specified provider does not
* support a ConfigurationSpi implementation for the specified
* type.
*
* @see Provider
* @since 1.6
*/
public static Configuration getInstance(String type,
Configuration.Parameters params,
String provider)
throws NoSuchProviderException, NoSuchAlgorithmException {
if (provider == null || provider.length() == 0) {
throw new IllegalArgumentException("missing provider");
}
checkPermission(type);
try {
GetInstance.Instance instance = GetInstance.getInstance
("Configuration",
ConfigurationSpi.class,
type,
params,
provider);
return new ConfigDelegate((ConfigurationSpi)instance.impl,
instance.provider,
type,
params);
} catch (NoSuchAlgorithmException nsae) {
return handleException (nsae);
}
}
/**
* Returns a Configuration object of the specified type.
*
* <p> A new Configuration object encapsulating the
* ConfigurationSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param type the specified Configuration type. See the Configuration
* section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration">
* Java Cryptography Architecture Standard Algorithm Name
* Documentation</a> for a list of standard Configuration types.
*
* @param params parameters for the Configuration, which may be null.
*
* @param provider the Provider.
*
* @return the new Configuration object.
*
* @exception SecurityException if the caller does not have permission
* to get a Configuration instance for the specified type.
*
* @exception NullPointerException if the specified type is null.
*
* @exception IllegalArgumentException if the specified Provider is null,
* or if the specified parameters are not understood by
* the ConfigurationSpi implementation from the specified Provider.
*
* @exception NoSuchAlgorithmException if the specified Provider does not
* support a ConfigurationSpi implementation for the specified
* type.
*
* @see Provider
* @since 1.6
*/
public static Configuration getInstance(String type,
Configuration.Parameters params,
Provider provider)
throws NoSuchAlgorithmException {
if (provider == null) {
throw new IllegalArgumentException("missing provider");
}
checkPermission(type);
try {
GetInstance.Instance instance = GetInstance.getInstance
("Configuration",
ConfigurationSpi.class,
type,
params,
provider);
return new ConfigDelegate((ConfigurationSpi)instance.impl,
instance.provider,
type,
params);
} catch (NoSuchAlgorithmException nsae) {
return handleException (nsae);
}
}
private static Configuration handleException(NoSuchAlgorithmException nsae)
throws NoSuchAlgorithmException {
Throwable cause = nsae.getCause();
if (cause instanceof IllegalArgumentException) {
throw (IllegalArgumentException)cause;
}
throw nsae;
}
/**
* Return the Provider of this Configuration.
*
* <p> This Configuration instance will only have a Provider if it
* was obtained via a call to {@code Configuration.getInstance}.
* Otherwise this method returns null.
*
* @return the Provider of this Configuration, or null.
*
* @since 1.6
*/
public Provider getProvider() {
return null;
}
/**
* Return the type of this Configuration.
*
* <p> This Configuration instance will only have a type if it
* was obtained via a call to {@code Configuration.getInstance}.
* Otherwise this method returns null.
*
* @return the type of this Configuration, or null.
*
* @since 1.6
*/
public String getType() {
return null;
}
/**
* Return Configuration parameters.
*
* <p> This Configuration instance will only have parameters if it
* was obtained via a call to {@code Configuration.getInstance}.
* Otherwise this method returns null.
*
* @return Configuration parameters, or null.
*
* @since 1.6
*/
public Configuration.Parameters getParameters() {
return null;
}
/**
* Retrieve the AppConfigurationEntries for the specified <i>name</i>
* from this Configuration.
*
* <p>
*
* @param name the name used to index the Configuration.
*
* @return an array of AppConfigurationEntries for the specified <i>name</i>
* from this Configuration, or null if there are no entries
* for the specified <i>name</i>
*/
public abstract AppConfigurationEntry[] getAppConfigurationEntry
(String name);
/**
* Refresh and reload the Configuration.
*
* <p> This method causes this Configuration object to refresh/reload its
* contents in an implementation-dependent manner.
* For example, if this Configuration object stores its entries in a file,
* calling {@code refresh} may cause the file to be re-read.
*
* <p> The default implementation of this method does nothing.
* This method should be overridden if a refresh operation is supported
* by the implementation.
*
* @exception SecurityException if the caller does not have permission
* to refresh its Configuration.
*/
public void refresh() { }
/**
* This subclass is returned by the getInstance calls. All Configuration
* calls are delegated to the underlying ConfigurationSpi.
*/
private static class ConfigDelegate extends Configuration {
private ConfigurationSpi spi;
private Provider p;
private String type;
private Configuration.Parameters params;
private ConfigDelegate(ConfigurationSpi spi, Provider p,
String type, Configuration.Parameters params) {
this.spi = spi;
this.p = p;
this.type = type;
this.params = params;
}
public String getType() { return type; }
public Configuration.Parameters getParameters() { return params; }
public Provider getProvider() { return p; }
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
return spi.engineGetAppConfigurationEntry(name);
}
public void refresh() {
spi.engineRefresh();
}
}
/**
* This represents a marker interface for Configuration parameters.
*
* @since 1.6
*/
public static interface Parameters { }
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the {@code Configuration} class.
* All the abstract methods in this class must be implemented by each
* service provider who wishes to supply a Configuration implementation.
*
* <p> Subclass implementations of this abstract class must provide
* a public constructor that takes a {@code Configuration.Parameters}
* object as an input parameter. This constructor also must throw
* an IllegalArgumentException if it does not understand the
* {@code Configuration.Parameters} input.
*
*
* @since 1.6
*/
public abstract class ConfigurationSpi {
/**
* Retrieve the AppConfigurationEntries for the specified <i>name</i>.
*
* <p>
*
* @param name the name used to index the Configuration.
*
* @return an array of AppConfigurationEntries for the specified
* <i>name</i>, or null if there are no entries.
*/
protected abstract AppConfigurationEntry[] engineGetAppConfigurationEntry
(String name);
/**
* Refresh and reload the Configuration.
*
* <p> This method causes this Configuration object to refresh/reload its
* contents in an implementation-dependent manner.
* For example, if this Configuration object stores its entries in a file,
* calling {@code refresh} may cause the file to be re-read.
*
* <p> The default implementation of this method does nothing.
* This method should be overridden if a refresh operation is supported
* by the implementation.
*
* @exception SecurityException if the caller does not have permission
* to refresh its Configuration.
*/
protected void engineRefresh() { }
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
/**
* A generic credential exception.
*
* @since 1.5
*/
public class CredentialException extends LoginException {
private static final long serialVersionUID = -4772893876810601859L;
/**
* Constructs a CredentialException with no detail message. A detail
* message is a String that describes this particular exception.
*/
public CredentialException() {
super();
}
/**
* Constructs a CredentialException with the specified detail message.
* A detail message is a String that describes this particular
* exception.
*
* <p>
*
* @param msg the detail message.
*/
public CredentialException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
/**
* Signals that a {@code Credential} has expired.
*
* <p> This exception is thrown by LoginModules when they determine
* that a {@code Credential} has expired.
* For example, a {@code LoginModule} authenticating a user
* in its {@code login} method may determine that the user's
* password, although entered correctly, has expired. In this case
* the {@code LoginModule} throws this exception to notify
* the application. The application can then take the appropriate
* steps to assist the user in updating the password.
*
*/
public class CredentialExpiredException extends CredentialException {
private static final long serialVersionUID = -5344739593859737937L;
/**
* Constructs a CredentialExpiredException with no detail message. A detail
* message is a String that describes this particular exception.
*/
public CredentialExpiredException() {
super();
}
/**
* Constructs a CredentialExpiredException with the specified detail
* message. A detail message is a String that describes this particular
* exception.
*
* <p>
*
* @param msg the detail message.
*/
public CredentialExpiredException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
/**
* Signals that a credential was not found.
*
* <p> This exception may be thrown by a LoginModule if it is unable
* to locate a credential necessary to perform authentication.
*
* @since 1.5
*/
public class CredentialNotFoundException extends CredentialException {
private static final long serialVersionUID = -7779934467214319475L;
/**
* Constructs a CredentialNotFoundException with no detail message.
* A detail message is a String that describes this particular exception.
*/
public CredentialNotFoundException() {
super();
}
/**
* Constructs a CredentialNotFoundException with the specified
* detail message. A detail message is a String that describes
* this particular exception.
*
* <p>
*
* @param msg the detail message.
*/
public CredentialNotFoundException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
/**
* Signals that user authentication failed.
*
* <p> This exception is thrown by LoginModules if authentication failed.
* For example, a {@code LoginModule} throws this exception if
* the user entered an incorrect password.
*
*/
public class FailedLoginException extends LoginException {
private static final long serialVersionUID = 802556922354616286L;
/**
* Constructs a FailedLoginException with no detail message. A detail
* message is a String that describes this particular exception.
*/
public FailedLoginException() {
super();
}
/**
* Constructs a FailedLoginException with the specified detail
* message. A detail message is a String that describes this particular
* exception.
*
* <p>
*
* @param msg the detail message.
*/
public FailedLoginException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,966 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import java.util.Map;
import java.util.HashMap;
import java.text.MessageFormat;
import javax.security.auth.Subject;
import javax.security.auth.AuthPermission;
import javax.security.auth.callback.*;
import java.security.AccessController;
import java.security.AccessControlContext;
import sun.security.util.PendingException;
import sun.security.util.ResourcesMgr;
/**
* <p> The {@code LoginContext} class describes the basic methods used
* to authenticate Subjects and provides a way to develop an
* application independent of the underlying authentication technology.
* A {@code Configuration} specifies the authentication technology, or
* {@code LoginModule}, to be used with a particular application.
* Different LoginModules can be plugged in under an application
* without requiring any modifications to the application itself.
*
* <p> In addition to supporting <i>pluggable</i> authentication, this class
* also supports the notion of <i>stacked</i> authentication.
* Applications may be configured to use more than one
* LoginModule. For example, one could
* configure both a Kerberos LoginModule and a smart card
* LoginModule under an application.
*
* <p> A typical caller instantiates a LoginContext with
* a <i>name</i> and a {@code CallbackHandler}.
* LoginContext uses the <i>name</i> as the index into a
* Configuration to determine which LoginModules should be used,
* and which ones must succeed in order for the overall authentication to
* succeed. The {@code CallbackHandler} is passed to the underlying
* LoginModules so they may communicate and interact with users
* (prompting for a username and password via a graphical user interface,
* for example).
*
* <p> Once the caller has instantiated a LoginContext,
* it invokes the {@code login} method to authenticate
* a {@code Subject}. The {@code login} method invokes
* the configured modules to perform their respective types of authentication
* (username/password, smart card pin verification, etc.).
* Note that the LoginModules will not attempt authentication retries nor
* introduce delays if the authentication fails.
* Such tasks belong to the LoginContext caller.
*
* <p> If the {@code login} method returns without
* throwing an exception, then the overall authentication succeeded.
* The caller can then retrieve
* the newly authenticated Subject by invoking the
* {@code getSubject} method. Principals and Credentials associated
* with the Subject may be retrieved by invoking the Subject's
* respective {@code getPrincipals}, {@code getPublicCredentials},
* and {@code getPrivateCredentials} methods.
*
* <p> To logout the Subject, the caller calls
* the {@code logout} method. As with the {@code login}
* method, this {@code logout} method invokes the {@code logout}
* method for the configured modules.
*
* <p> A LoginContext should not be used to authenticate
* more than one Subject. A separate LoginContext
* should be used to authenticate each different Subject.
*
* <p> The following documentation applies to all LoginContext constructors:
* <ol>
*
* <li> {@code Subject}
* <ul>
* <li> If the constructor has a Subject
* input parameter, the LoginContext uses the caller-specified
* Subject object.
*
* <li> If the caller specifies a {@code null} Subject
* and a {@code null} value is permitted,
* the LoginContext instantiates a new Subject.
*
* <li> If the constructor does <b>not</b> have a Subject
* input parameter, the LoginContext instantiates a new Subject.
* <p>
* </ul>
*
* <li> {@code Configuration}
* <ul>
* <li> If the constructor has a Configuration
* input parameter and the caller specifies a non-null Configuration,
* the LoginContext uses the caller-specified Configuration.
* <p>
* If the constructor does <b>not</b> have a Configuration
* input parameter, or if the caller specifies a {@code null}
* Configuration object, the constructor uses the following call to
* get the installed Configuration:
* <pre>
* config = Configuration.getConfiguration();
* </pre>
* For both cases,
* the <i>name</i> argument given to the constructor is passed to the
* {@code Configuration.getAppConfigurationEntry} method.
* If the Configuration has no entries for the specified <i>name</i>,
* then the {@code LoginContext} calls
* {@code getAppConfigurationEntry} with the name, "<i>other</i>"
* (the default entry name). If there is no entry for "<i>other</i>",
* then a {@code LoginException} is thrown.
*
* <li> When LoginContext uses the installed Configuration, the caller
* requires the createLoginContext.<em>name</em> and possibly
* createLoginContext.other AuthPermissions. Furthermore, the
* LoginContext will invoke configured modules from within an
* {@code AccessController.doPrivileged} call so that modules that
* perform security-sensitive tasks (such as connecting to remote hosts,
* and updating the Subject) will require the respective permissions, but
* the callers of the LoginContext will not require those permissions.
*
* <li> When LoginContext uses a caller-specified Configuration, the caller
* does not require any createLoginContext AuthPermission. The LoginContext
* saves the {@code AccessControlContext} for the caller,
* and invokes the configured modules from within an
* {@code AccessController.doPrivileged} call constrained by that context.
* This means the caller context (stored when the LoginContext was created)
* must have sufficient permissions to perform any security-sensitive tasks
* that the modules may perform.
* <p>
* </ul>
*
* <li> {@code CallbackHandler}
* <ul>
* <li> If the constructor has a CallbackHandler
* input parameter, the LoginContext uses the caller-specified
* CallbackHandler object.
*
* <li> If the constructor does <b>not</b> have a CallbackHandler
* input parameter, or if the caller specifies a {@code null}
* CallbackHandler object (and a {@code null} value is permitted),
* the LoginContext queries the
* {@code auth.login.defaultCallbackHandler} security property for the
* fully qualified class name of a default handler
* implementation. If the security property is not set,
* then the underlying modules will not have a
* CallbackHandler for use in communicating
* with users. The caller thus assumes that the configured
* modules have alternative means for authenticating the user.
*
*
* <li> When the LoginContext uses the installed Configuration (instead of
* a caller-specified Configuration, see above),
* then this LoginContext must wrap any
* caller-specified or default CallbackHandler implementation
* in a new CallbackHandler implementation
* whose {@code handle} method implementation invokes the
* specified CallbackHandler's {@code handle} method in a
* {@code java.security.AccessController.doPrivileged} call
* constrained by the caller's current {@code AccessControlContext}.
* </ul>
* </ol>
*
* @see java.security.Security
* @see javax.security.auth.AuthPermission
* @see javax.security.auth.Subject
* @see javax.security.auth.callback.CallbackHandler
* @see javax.security.auth.login.Configuration
* @see javax.security.auth.spi.LoginModule
* @see java.security.Security security properties
*/
public class LoginContext {
private static final String INIT_METHOD = "initialize";
private static final String LOGIN_METHOD = "login";
private static final String COMMIT_METHOD = "commit";
private static final String ABORT_METHOD = "abort";
private static final String LOGOUT_METHOD = "logout";
private static final String OTHER = "other";
private static final String DEFAULT_HANDLER =
"auth.login.defaultCallbackHandler";
private Subject subject = null;
private boolean subjectProvided = false;
private boolean loginSucceeded = false;
private CallbackHandler callbackHandler;
private Map<String,?> state = new HashMap<String,Object>();
private Configuration config;
private AccessControlContext creatorAcc = null; // customized config only
private ModuleInfo[] moduleStack;
private ClassLoader contextClassLoader = null;
private static final Class<?>[] PARAMS = { };
// state saved in the event a user-specified asynchronous exception
// was specified and thrown
private int moduleIndex = 0;
private LoginException firstError = null;
private LoginException firstRequiredError = null;
private boolean success = false;
private static final sun.security.util.Debug debug =
sun.security.util.Debug.getInstance("logincontext", "\t[LoginContext]");
private void init(String name) throws LoginException {
SecurityManager sm = System.getSecurityManager();
if (sm != null && creatorAcc == null) {
sm.checkPermission(new AuthPermission
("createLoginContext." + name));
}
if (name == null)
throw new LoginException
(ResourcesMgr.getString("Invalid.null.input.name"));
// get the Configuration
if (config == null) {
config = java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction<Configuration>() {
public Configuration run() {
return Configuration.getConfiguration();
}
});
}
// get the LoginModules configured for this application
AppConfigurationEntry[] entries = config.getAppConfigurationEntry(name);
if (entries == null) {
if (sm != null && creatorAcc == null) {
sm.checkPermission(new AuthPermission
("createLoginContext." + OTHER));
}
entries = config.getAppConfigurationEntry(OTHER);
if (entries == null) {
MessageFormat form = new MessageFormat(ResourcesMgr.getString
("No.LoginModules.configured.for.name"));
Object[] source = {name};
throw new LoginException(form.format(source));
}
}
moduleStack = new ModuleInfo[entries.length];
for (int i = 0; i < entries.length; i++) {
// clone returned array
moduleStack[i] = new ModuleInfo
(new AppConfigurationEntry
(entries[i].getLoginModuleName(),
entries[i].getControlFlag(),
entries[i].getOptions()),
null);
}
contextClassLoader = java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
ClassLoader loader =
Thread.currentThread().getContextClassLoader();
if (loader == null) {
// Don't use bootstrap class loader directly to ensure
// proper package access control!
loader = ClassLoader.getSystemClassLoader();
}
return loader;
}
});
}
private void loadDefaultCallbackHandler() throws LoginException {
// get the default handler class
try {
final ClassLoader finalLoader = contextClassLoader;
this.callbackHandler = java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<CallbackHandler>() {
public CallbackHandler run() throws Exception {
String defaultHandler = java.security.Security.getProperty
(DEFAULT_HANDLER);
if (defaultHandler == null || defaultHandler.length() == 0)
return null;
Class<? extends CallbackHandler> c = Class.forName(
defaultHandler, true,
finalLoader).asSubclass(CallbackHandler.class);
return c.newInstance();
}
});
} catch (java.security.PrivilegedActionException pae) {
throw new LoginException(pae.getException().toString());
}
// secure it with the caller's ACC
if (this.callbackHandler != null && creatorAcc == null) {
this.callbackHandler = new SecureCallbackHandler
(java.security.AccessController.getContext(),
this.callbackHandler);
}
}
/**
* Instantiate a new {@code LoginContext} object with a name.
*
* @param name the name used as the index into the
* {@code Configuration}.
*
* @exception LoginException if the caller-specified {@code name}
* does not appear in the {@code Configuration}
* and there is no {@code Configuration} entry
* for "<i>other</i>", or if the
* <i>auth.login.defaultCallbackHandler</i>
* security property was set, but the implementation
* class could not be loaded.
* <p>
* @exception SecurityException if a SecurityManager is set and
* the caller does not have
* AuthPermission("createLoginContext.<i>name</i>"),
* or if a configuration entry for <i>name</i> does not exist and
* the caller does not additionally have
* AuthPermission("createLoginContext.other")
*/
public LoginContext(String name) throws LoginException {
init(name);
loadDefaultCallbackHandler();
}
/**
* Instantiate a new {@code LoginContext} object with a name
* and a {@code Subject} object.
*
* <p>
*
* @param name the name used as the index into the
* {@code Configuration}. <p>
*
* @param subject the {@code Subject} to authenticate.
*
* @exception LoginException if the caller-specified {@code name}
* does not appear in the {@code Configuration}
* and there is no {@code Configuration} entry
* for "<i>other</i>", if the caller-specified {@code subject}
* is {@code null}, or if the
* <i>auth.login.defaultCallbackHandler</i>
* security property was set, but the implementation
* class could not be loaded.
* <p>
* @exception SecurityException if a SecurityManager is set and
* the caller does not have
* AuthPermission("createLoginContext.<i>name</i>"),
* or if a configuration entry for <i>name</i> does not exist and
* the caller does not additionally have
* AuthPermission("createLoginContext.other")
*/
public LoginContext(String name, Subject subject)
throws LoginException {
init(name);
if (subject == null)
throw new LoginException
(ResourcesMgr.getString("invalid.null.Subject.provided"));
this.subject = subject;
subjectProvided = true;
loadDefaultCallbackHandler();
}
/**
* Instantiate a new {@code LoginContext} object with a name
* and a {@code CallbackHandler} object.
*
* <p>
*
* @param name the name used as the index into the
* {@code Configuration}. <p>
*
* @param callbackHandler the {@code CallbackHandler} object used by
* LoginModules to communicate with the user.
*
* @exception LoginException if the caller-specified {@code name}
* does not appear in the {@code Configuration}
* and there is no {@code Configuration} entry
* for "<i>other</i>", or if the caller-specified
* {@code callbackHandler} is {@code null}.
* <p>
* @exception SecurityException if a SecurityManager is set and
* the caller does not have
* AuthPermission("createLoginContext.<i>name</i>"),
* or if a configuration entry for <i>name</i> does not exist and
* the caller does not additionally have
* AuthPermission("createLoginContext.other")
*/
public LoginContext(String name, CallbackHandler callbackHandler)
throws LoginException {
init(name);
if (callbackHandler == null)
throw new LoginException(ResourcesMgr.getString
("invalid.null.CallbackHandler.provided"));
this.callbackHandler = new SecureCallbackHandler
(java.security.AccessController.getContext(),
callbackHandler);
}
/**
* Instantiate a new {@code LoginContext} object with a name,
* a {@code Subject} to be authenticated, and a
* {@code CallbackHandler} object.
*
* <p>
*
* @param name the name used as the index into the
* {@code Configuration}. <p>
*
* @param subject the {@code Subject} to authenticate. <p>
*
* @param callbackHandler the {@code CallbackHandler} object used by
* LoginModules to communicate with the user.
*
* @exception LoginException if the caller-specified {@code name}
* does not appear in the {@code Configuration}
* and there is no {@code Configuration} entry
* for "<i>other</i>", or if the caller-specified
* {@code subject} is {@code null},
* or if the caller-specified
* {@code callbackHandler} is {@code null}.
* <p>
* @exception SecurityException if a SecurityManager is set and
* the caller does not have
* AuthPermission("createLoginContext.<i>name</i>"),
* or if a configuration entry for <i>name</i> does not exist and
* the caller does not additionally have
* AuthPermission("createLoginContext.other")
*/
public LoginContext(String name, Subject subject,
CallbackHandler callbackHandler) throws LoginException {
this(name, subject);
if (callbackHandler == null)
throw new LoginException(ResourcesMgr.getString
("invalid.null.CallbackHandler.provided"));
this.callbackHandler = new SecureCallbackHandler
(java.security.AccessController.getContext(),
callbackHandler);
}
/**
* Instantiate a new {@code LoginContext} object with a name,
* a {@code Subject} to be authenticated,
* a {@code CallbackHandler} object, and a login
* {@code Configuration}.
*
* <p>
*
* @param name the name used as the index into the caller-specified
* {@code Configuration}. <p>
*
* @param subject the {@code Subject} to authenticate,
* or {@code null}. <p>
*
* @param callbackHandler the {@code CallbackHandler} object used by
* LoginModules to communicate with the user, or {@code null}.
* <p>
*
* @param config the {@code Configuration} that lists the
* login modules to be called to perform the authentication,
* or {@code null}.
*
* @exception LoginException if the caller-specified {@code name}
* does not appear in the {@code Configuration}
* and there is no {@code Configuration} entry
* for "<i>other</i>".
* <p>
* @exception SecurityException if a SecurityManager is set,
* <i>config</i> is {@code null},
* and either the caller does not have
* AuthPermission("createLoginContext.<i>name</i>"),
* or if a configuration entry for <i>name</i> does not exist and
* the caller does not additionally have
* AuthPermission("createLoginContext.other")
*
* @since 1.5
*/
public LoginContext(String name, Subject subject,
CallbackHandler callbackHandler,
Configuration config) throws LoginException {
this.config = config;
if (config != null) {
creatorAcc = java.security.AccessController.getContext();
}
init(name);
if (subject != null) {
this.subject = subject;
subjectProvided = true;
}
if (callbackHandler == null) {
loadDefaultCallbackHandler();
} else if (creatorAcc == null) {
this.callbackHandler = new SecureCallbackHandler
(java.security.AccessController.getContext(),
callbackHandler);
} else {
this.callbackHandler = callbackHandler;
}
}
/**
* Perform the authentication.
*
* <p> This method invokes the {@code login} method for each
* LoginModule configured for the <i>name</i> specified to the
* {@code LoginContext} constructor, as determined by the login
* {@code Configuration}. Each {@code LoginModule}
* then performs its respective type of authentication
* (username/password, smart card pin verification, etc.).
*
* <p> This method completes a 2-phase authentication process by
* calling each configured LoginModule's {@code commit} method
* if the overall authentication succeeded (the relevant REQUIRED,
* REQUISITE, SUFFICIENT, and OPTIONAL LoginModules succeeded),
* or by calling each configured LoginModule's {@code abort} method
* if the overall authentication failed. If authentication succeeded,
* each successful LoginModule's {@code commit} method associates
* the relevant Principals and Credentials with the {@code Subject}.
* If authentication failed, each LoginModule's {@code abort} method
* removes/destroys any previously stored state.
*
* <p> If the {@code commit} phase of the authentication process
* fails, then the overall authentication fails and this method
* invokes the {@code abort} method for each configured
* {@code LoginModule}.
*
* <p> If the {@code abort} phase
* fails for any reason, then this method propagates the
* original exception thrown either during the {@code login} phase
* or the {@code commit} phase. In either case, the overall
* authentication fails.
*
* <p> In the case where multiple LoginModules fail,
* this method propagates the exception raised by the first
* {@code LoginModule} which failed.
*
* <p> Note that if this method enters the {@code abort} phase
* (either the {@code login} or {@code commit} phase failed),
* this method invokes all LoginModules configured for the
* application regardless of their respective {@code Configuration}
* flag parameters. Essentially this means that {@code Requisite}
* and {@code Sufficient} semantics are ignored during the
* {@code abort} phase. This guarantees that proper cleanup
* and state restoration can take place.
*
* <p>
*
* @exception LoginException if the authentication fails.
*/
public void login() throws LoginException {
loginSucceeded = false;
if (subject == null) {
subject = new Subject();
}
try {
// module invoked in doPrivileged
invokePriv(LOGIN_METHOD);
invokePriv(COMMIT_METHOD);
loginSucceeded = true;
} catch (LoginException le) {
try {
invokePriv(ABORT_METHOD);
} catch (LoginException le2) {
throw le;
}
throw le;
}
}
/**
* Logout the {@code Subject}.
*
* <p> This method invokes the {@code logout} method for each
* {@code LoginModule} configured for this {@code LoginContext}.
* Each {@code LoginModule} performs its respective logout procedure
* which may include removing/destroying
* {@code Principal} and {@code Credential} information
* from the {@code Subject} and state cleanup.
*
* <p> Note that this method invokes all LoginModules configured for the
* application regardless of their respective
* {@code Configuration} flag parameters. Essentially this means
* that {@code Requisite} and {@code Sufficient} semantics are
* ignored for this method. This guarantees that proper cleanup
* and state restoration can take place.
*
* <p>
*
* @exception LoginException if the logout fails.
*/
public void logout() throws LoginException {
if (subject == null) {
throw new LoginException(ResourcesMgr.getString
("null.subject.logout.called.before.login"));
}
// module invoked in doPrivileged
invokePriv(LOGOUT_METHOD);
}
/**
* Return the authenticated Subject.
*
* <p>
*
* @return the authenticated Subject. If the caller specified a
* Subject to this LoginContext's constructor,
* this method returns the caller-specified Subject.
* If a Subject was not specified and authentication succeeds,
* this method returns the Subject instantiated and used for
* authentication by this LoginContext.
* If a Subject was not specified, and authentication fails or
* has not been attempted, this method returns null.
*/
public Subject getSubject() {
if (!loginSucceeded && !subjectProvided)
return null;
return subject;
}
private void clearState() {
moduleIndex = 0;
firstError = null;
firstRequiredError = null;
success = false;
}
private void throwException(LoginException originalError, LoginException le)
throws LoginException {
// first clear state
clearState();
// throw the exception
LoginException error = (originalError != null) ? originalError : le;
throw error;
}
/**
* Invokes the login, commit, and logout methods
* from a LoginModule inside a doPrivileged block restricted
* by creatorAcc (may be null).
*
* This version is called if the caller did not instantiate
* the LoginContext with a Configuration object.
*/
private void invokePriv(final String methodName) throws LoginException {
try {
java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction<Void>() {
public Void run() throws LoginException {
invoke(methodName);
return null;
}
}, creatorAcc);
} catch (java.security.PrivilegedActionException pae) {
throw (LoginException)pae.getException();
}
}
private void invoke(String methodName) throws LoginException {
// start at moduleIndex
// - this can only be non-zero if methodName is LOGIN_METHOD
for (int i = moduleIndex; i < moduleStack.length; i++, moduleIndex++) {
try {
int mIndex = 0;
Method[] methods = null;
if (moduleStack[i].module != null) {
methods = moduleStack[i].module.getClass().getMethods();
} else {
// instantiate the LoginModule
//
// Allow any object to be a LoginModule as long as it
// conforms to the interface.
Class<?> c = Class.forName(
moduleStack[i].entry.getLoginModuleName(),
true,
contextClassLoader);
Constructor<?> constructor = c.getConstructor(PARAMS);
Object[] args = { };
moduleStack[i].module = constructor.newInstance(args);
// call the LoginModule's initialize method
methods = moduleStack[i].module.getClass().getMethods();
for (mIndex = 0; mIndex < methods.length; mIndex++) {
if (methods[mIndex].getName().equals(INIT_METHOD)) {
break;
}
}
Object[] initArgs = {subject,
callbackHandler,
state,
moduleStack[i].entry.getOptions() };
// invoke the LoginModule initialize method
//
// Throws ArrayIndexOutOfBoundsException if no such
// method defined. May improve to use LoginException in
// the future.
methods[mIndex].invoke(moduleStack[i].module, initArgs);
}
// find the requested method in the LoginModule
for (mIndex = 0; mIndex < methods.length; mIndex++) {
if (methods[mIndex].getName().equals(methodName)) {
break;
}
}
// set up the arguments to be passed to the LoginModule method
Object[] args = { };
// invoke the LoginModule method
//
// Throws ArrayIndexOutOfBoundsException if no such
// method defined. May improve to use LoginException in
// the future.
boolean status = ((Boolean)methods[mIndex].invoke
(moduleStack[i].module, args)).booleanValue();
if (status == true) {
// if SUFFICIENT, return if no prior REQUIRED errors
if (!methodName.equals(ABORT_METHOD) &&
!methodName.equals(LOGOUT_METHOD) &&
moduleStack[i].entry.getControlFlag() ==
AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT &&
firstRequiredError == null) {
// clear state
clearState();
if (debug != null)
debug.println(methodName + " SUFFICIENT success");
return;
}
if (debug != null)
debug.println(methodName + " success");
success = true;
} else {
if (debug != null)
debug.println(methodName + " ignored");
}
} catch (NoSuchMethodException nsme) {
MessageFormat form = new MessageFormat(ResourcesMgr.getString
("unable.to.instantiate.LoginModule.module.because.it.does.not.provide.a.no.argument.constructor"));
Object[] source = {moduleStack[i].entry.getLoginModuleName()};
throwException(null, new LoginException(form.format(source)));
} catch (InstantiationException ie) {
throwException(null, new LoginException(ResourcesMgr.getString
("unable.to.instantiate.LoginModule.") +
ie.getMessage()));
} catch (ClassNotFoundException cnfe) {
throwException(null, new LoginException(ResourcesMgr.getString
("unable.to.find.LoginModule.class.") +
cnfe.getMessage()));
} catch (IllegalAccessException iae) {
throwException(null, new LoginException(ResourcesMgr.getString
("unable.to.access.LoginModule.") +
iae.getMessage()));
} catch (InvocationTargetException ite) {
// failure cases
LoginException le;
if (ite.getCause() instanceof PendingException &&
methodName.equals(LOGIN_METHOD)) {
// XXX
//
// if a module's LOGIN_METHOD threw a PendingException
// then immediately throw it.
//
// when LoginContext is called again,
// the module that threw the exception is invoked first
// (the module list is not invoked from the start).
// previously thrown exception state is still present.
//
// it is assumed that the module which threw
// the exception can have its
// LOGIN_METHOD invoked twice in a row
// without any commit/abort in between.
//
// in all cases when LoginContext returns
// (either via natural return or by throwing an exception)
// we need to call clearState before returning.
// the only time that is not true is in this case -
// do not call throwException here.
throw (PendingException)ite.getCause();
} else if (ite.getCause() instanceof LoginException) {
le = (LoginException)ite.getCause();
} else if (ite.getCause() instanceof SecurityException) {
// do not want privacy leak
// (e.g., sensitive file path in exception msg)
le = new LoginException("Security Exception");
le.initCause(new SecurityException());
if (debug != null) {
debug.println
("original security exception with detail msg " +
"replaced by new exception with empty detail msg");
debug.println("original security exception: " +
ite.getCause().toString());
}
} else {
// capture an unexpected LoginModule exception
java.io.StringWriter sw = new java.io.StringWriter();
ite.getCause().printStackTrace
(new java.io.PrintWriter(sw));
sw.flush();
le = new LoginException(sw.toString());
}
if (moduleStack[i].entry.getControlFlag() ==
AppConfigurationEntry.LoginModuleControlFlag.REQUISITE) {
if (debug != null)
debug.println(methodName + " REQUISITE failure");
// if REQUISITE, then immediately throw an exception
if (methodName.equals(ABORT_METHOD) ||
methodName.equals(LOGOUT_METHOD)) {
if (firstRequiredError == null)
firstRequiredError = le;
} else {
throwException(firstRequiredError, le);
}
} else if (moduleStack[i].entry.getControlFlag() ==
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED) {
if (debug != null)
debug.println(methodName + " REQUIRED failure");
// mark down that a REQUIRED module failed
if (firstRequiredError == null)
firstRequiredError = le;
} else {
if (debug != null)
debug.println(methodName + " OPTIONAL failure");
// mark down that an OPTIONAL module failed
if (firstError == null)
firstError = le;
}
}
}
// we went thru all the LoginModules.
if (firstRequiredError != null) {
// a REQUIRED module failed -- return the error
throwException(firstRequiredError, null);
} else if (success == false && firstError != null) {
// no module succeeded -- return the first error
throwException(firstError, null);
} else if (success == false) {
// no module succeeded -- all modules were IGNORED
throwException(new LoginException
(ResourcesMgr.getString("Login.Failure.all.modules.ignored")),
null);
} else {
// success
clearState();
return;
}
}
/**
* Wrap the caller-specified CallbackHandler in our own
* and invoke it within a privileged block, constrained by
* the caller's AccessControlContext.
*/
private static class SecureCallbackHandler implements CallbackHandler {
private final java.security.AccessControlContext acc;
private final CallbackHandler ch;
SecureCallbackHandler(java.security.AccessControlContext acc,
CallbackHandler ch) {
this.acc = acc;
this.ch = ch;
}
public void handle(final Callback[] callbacks)
throws java.io.IOException, UnsupportedCallbackException {
try {
java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction<Void>() {
public Void run() throws java.io.IOException,
UnsupportedCallbackException {
ch.handle(callbacks);
return null;
}
}, acc);
} catch (java.security.PrivilegedActionException pae) {
if (pae.getException() instanceof java.io.IOException) {
throw (java.io.IOException)pae.getException();
} else {
throw (UnsupportedCallbackException)pae.getException();
}
}
}
}
/**
* LoginModule information -
* incapsulates Configuration info and actual module instances
*/
private static class ModuleInfo {
AppConfigurationEntry entry;
Object module;
ModuleInfo(AppConfigurationEntry newEntry, Object newModule) {
this.entry = newEntry;
this.module = newModule;
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.login;
/**
* This is the basic login exception.
*
* @see javax.security.auth.login.LoginContext
*/
public class LoginException extends java.security.GeneralSecurityException {
private static final long serialVersionUID = -4679091624035232488L;
/**
* Constructs a LoginException with no detail message. A detail
* message is a String that describes this particular exception.
*/
public LoginException() {
super();
}
/**
* Constructs a LoginException with the specified detail message.
* A detail message is a String that describes this particular
* exception.
*
* <p>
*
* @param msg the detail message.
*/
public LoginException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This package provides a pluggable authentication framework.
* <h2>Package Specification</h2>
*
* <ul>
* <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html">
* <b>Java&trade;
* Cryptography Architecture Standard Algorithm Name
* Documentation</b></a></li>
* </ul>
*
* @since 1.4
*/
package javax.security.auth.login;

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This package provides a framework for authentication and
* authorization. The framework allows
* authentication to be performed in pluggable fashion. Different
* authentication modules can be plugged under an application without
* requiring modifications to the application itself. The
* authorization component allows specification of access controls
* based on code location, code signers and code executors
* (Subjects).
*
* @since JDK1.4
*/
package javax.security.auth;

View File

@@ -0,0 +1,240 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.spi;
import javax.security.auth.Subject;
import javax.security.auth.AuthPermission;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
import java.util.Map;
/**
* <p> {@code LoginModule} describes the interface
* implemented by authentication technology providers. LoginModules
* are plugged in under applications to provide a particular type of
* authentication.
*
* <p> While applications write to the {@code LoginContext} API,
* authentication technology providers implement the
* {@code LoginModule} interface.
* A {@code Configuration} specifies the LoginModule(s)
* to be used with a particular login application. Therefore different
* LoginModules can be plugged in under the application without
* requiring any modifications to the application itself.
*
* <p> The {@code LoginContext} is responsible for reading the
* {@code Configuration} and instantiating the appropriate
* LoginModules. Each {@code LoginModule} is initialized with
* a {@code Subject}, a {@code CallbackHandler}, shared
* {@code LoginModule} state, and LoginModule-specific options.
*
* The {@code Subject} represents the
* {@code Subject} currently being authenticated and is updated
* with relevant Credentials if authentication succeeds.
* LoginModules use the {@code CallbackHandler} to
* communicate with users. The {@code CallbackHandler} may be
* used to prompt for usernames and passwords, for example.
* Note that the {@code CallbackHandler} may be null. LoginModules
* which absolutely require a {@code CallbackHandler} to authenticate
* the {@code Subject} may throw a {@code LoginException}.
* LoginModules optionally use the shared state to share information
* or data among themselves.
*
* <p> The LoginModule-specific options represent the options
* configured for this {@code LoginModule} by an administrator or user
* in the login {@code Configuration}.
* The options are defined by the {@code LoginModule} itself
* and control the behavior within it. For example, a
* {@code LoginModule} may define options to support debugging/testing
* capabilities. Options are defined using a key-value syntax,
* such as <i>debug=true</i>. The {@code LoginModule}
* stores the options as a {@code Map} so that the values may
* be retrieved using the key. Note that there is no limit to the number
* of options a {@code LoginModule} chooses to define.
*
* <p> The calling application sees the authentication process as a single
* operation. However, the authentication process within the
* {@code LoginModule} proceeds in two distinct phases.
* In the first phase, the LoginModule's
* {@code login} method gets invoked by the LoginContext's
* {@code login} method. The {@code login}
* method for the {@code LoginModule} then performs
* the actual authentication (prompt for and verify a password for example)
* and saves its authentication status as private state
* information. Once finished, the LoginModule's {@code login}
* method either returns {@code true} (if it succeeded) or
* {@code false} (if it should be ignored), or throws a
* {@code LoginException} to specify a failure.
* In the failure case, the {@code LoginModule} must not retry the
* authentication or introduce delays. The responsibility of such tasks
* belongs to the application. If the application attempts to retry
* the authentication, the LoginModule's {@code login} method will be
* called again.
*
* <p> In the second phase, if the LoginContext's overall authentication
* succeeded (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL
* LoginModules succeeded), then the {@code commit}
* method for the {@code LoginModule} gets invoked.
* The {@code commit} method for a {@code LoginModule} checks its
* privately saved state to see if its own authentication succeeded.
* If the overall {@code LoginContext} authentication succeeded
* and the LoginModule's own authentication succeeded, then the
* {@code commit} method associates the relevant
* Principals (authenticated identities) and Credentials (authentication data
* such as cryptographic keys) with the {@code Subject}
* located within the {@code LoginModule}.
*
* <p> If the LoginContext's overall authentication failed (the relevant
* REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules did not succeed),
* then the {@code abort} method for each {@code LoginModule}
* gets invoked. In this case, the {@code LoginModule} removes/destroys
* any authentication state originally saved.
*
* <p> Logging out a {@code Subject} involves only one phase.
* The {@code LoginContext} invokes the LoginModule's {@code logout}
* method. The {@code logout} method for the {@code LoginModule}
* then performs the logout procedures, such as removing Principals or
* Credentials from the {@code Subject} or logging session information.
*
* <p> A {@code LoginModule} implementation must have a constructor with
* no arguments. This allows classes which load the {@code LoginModule}
* to instantiate it.
*
* @see javax.security.auth.login.LoginContext
* @see javax.security.auth.login.Configuration
*/
public interface LoginModule {
/**
* Initialize this LoginModule.
*
* <p> This method is called by the {@code LoginContext}
* after this {@code LoginModule} has been instantiated.
* The purpose of this method is to initialize this
* {@code LoginModule} with the relevant information.
* If this {@code LoginModule} does not understand
* any of the data stored in {@code sharedState} or
* {@code options} parameters, they can be ignored.
*
* <p>
*
* @param subject the {@code Subject} to be authenticated. <p>
*
* @param callbackHandler a {@code CallbackHandler} for communicating
* with the end user (prompting for usernames and
* passwords, for example). <p>
*
* @param sharedState state shared with other configured LoginModules. <p>
*
* @param options options specified in the login
* {@code Configuration} for this particular
* {@code LoginModule}.
*/
void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String,?> sharedState,
Map<String,?> options);
/**
* Method to authenticate a {@code Subject} (phase 1).
*
* <p> The implementation of this method authenticates
* a {@code Subject}. For example, it may prompt for
* {@code Subject} information such
* as a username and password and then attempt to verify the password.
* This method saves the result of the authentication attempt
* as private state within the LoginModule.
*
* <p>
*
* @exception LoginException if the authentication fails
*
* @return true if the authentication succeeded, or false if this
* {@code LoginModule} should be ignored.
*/
boolean login() throws LoginException;
/**
* Method to commit the authentication process (phase 2).
*
* <p> This method is called if the LoginContext's
* overall authentication succeeded
* (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
* succeeded).
*
* <p> If this LoginModule's own authentication attempt
* succeeded (checked by retrieving the private state saved by the
* {@code login} method), then this method associates relevant
* Principals and Credentials with the {@code Subject} located in the
* {@code LoginModule}. If this LoginModule's own
* authentication attempted failed, then this method removes/destroys
* any state that was originally saved.
*
* <p>
*
* @exception LoginException if the commit fails
*
* @return true if this method succeeded, or false if this
* {@code LoginModule} should be ignored.
*/
boolean commit() throws LoginException;
/**
* Method to abort the authentication process (phase 2).
*
* <p> This method is called if the LoginContext's
* overall authentication failed.
* (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
* did not succeed).
*
* <p> If this LoginModule's own authentication attempt
* succeeded (checked by retrieving the private state saved by the
* {@code login} method), then this method cleans up any state
* that was originally saved.
*
* <p>
*
* @exception LoginException if the abort fails
*
* @return true if this method succeeded, or false if this
* {@code LoginModule} should be ignored.
*/
boolean abort() throws LoginException;
/**
* Method which logs out a {@code Subject}.
*
* <p>An implementation of this method might remove/destroy a Subject's
* Principals and Credentials.
*
* <p>
*
* @exception LoginException if the logout fails
*
* @return true if this method succeeded, or false if this
* {@code LoginModule} should be ignored.
*/
boolean logout() throws LoginException;
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This package provides the interface to be used for
* implementing pluggable authentication modules.
*
* @since JDK1.4
*/
package javax.security.auth.spi;

View File

@@ -0,0 +1,513 @@
/*
* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.x500;
import java.io.*;
import java.security.Principal;
import java.util.Collections;
import java.util.Map;
import sun.security.x509.X500Name;
import sun.security.util.*;
/**
* <p> This class represents an X.500 {@code Principal}.
* {@code X500Principal}s are represented by distinguished names such as
* "CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US".
*
* <p> This class can be instantiated by using a string representation
* of the distinguished name, or by using the ASN.1 DER encoded byte
* representation of the distinguished name. The current specification
* for the string representation of a distinguished name is defined in
* <a href="http://tools.ietf.org/html/rfc2253">RFC 2253: Lightweight
* Directory Access Protocol (v3): UTF-8 String Representation of
* Distinguished Names</a>. This class, however, accepts string formats from
* both RFC 2253 and <a href="http://tools.ietf.org/html/rfc1779">RFC 1779:
* A String Representation of Distinguished Names</a>, and also recognizes
* attribute type keywords whose OIDs (Object Identifiers) are defined in
* <a href="http://tools.ietf.org/html/rfc5280">RFC 5280: Internet X.509
* Public Key Infrastructure Certificate and CRL Profile</a>.
*
* <p> The string representation for this {@code X500Principal}
* can be obtained by calling the {@code getName} methods.
*
* <p> Note that the {@code getSubjectX500Principal} and
* {@code getIssuerX500Principal} methods of
* {@code X509Certificate} return X500Principals representing the
* issuer and subject fields of the certificate.
*
* @see java.security.cert.X509Certificate
* @since 1.4
*/
public final class X500Principal implements Principal, java.io.Serializable {
private static final long serialVersionUID = -500463348111345721L;
/**
* RFC 1779 String format of Distinguished Names.
*/
public static final String RFC1779 = "RFC1779";
/**
* RFC 2253 String format of Distinguished Names.
*/
public static final String RFC2253 = "RFC2253";
/**
* Canonical String format of Distinguished Names.
*/
public static final String CANONICAL = "CANONICAL";
/**
* The X500Name representing this principal.
*
* NOTE: this field is reflectively accessed from within X500Name.
*/
private transient X500Name thisX500Name;
/**
* Creates an X500Principal by wrapping an X500Name.
*
* NOTE: The constructor is package private. It is intended to be accessed
* using privileged reflection from classes in sun.security.*.
* Currently referenced from sun.security.x509.X500Name.asX500Principal().
*/
X500Principal(X500Name x500Name) {
thisX500Name = x500Name;
}
/**
* Creates an {@code X500Principal} from a string representation of
* an X.500 distinguished name (ex:
* "CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US").
* The distinguished name must be specified using the grammar defined in
* RFC 1779 or RFC 2253 (either format is acceptable).
*
* <p>This constructor recognizes the attribute type keywords
* defined in RFC 1779 and RFC 2253
* (and listed in {@link #getName(String format) getName(String format)}),
* as well as the T, DNQ or DNQUALIFIER, SURNAME, GIVENNAME, INITIALS,
* GENERATION, EMAILADDRESS, and SERIALNUMBER keywords whose Object
* Identifiers (OIDs) are defined in RFC 5280.
* Any other attribute type must be specified as an OID.
*
* <p>This implementation enforces a more restrictive OID syntax than
* defined in RFC 1779 and 2253. It uses the more correct syntax defined in
* <a href="http://www.ietf.org/rfc/rfc4512.txt">RFC 4512</a>, which
* specifies that OIDs contain at least 2 digits:
*
* <p>{@code numericoid = number 1*( DOT number ) }
*
* @param name an X.500 distinguished name in RFC 1779 or RFC 2253 format
* @exception NullPointerException if the {@code name}
* is {@code null}
* @exception IllegalArgumentException if the {@code name}
* is improperly specified
*/
public X500Principal(String name) {
this(name, Collections.<String, String>emptyMap());
}
/**
* Creates an {@code X500Principal} from a string representation of
* an X.500 distinguished name (ex:
* "CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US").
* The distinguished name must be specified using the grammar defined in
* RFC 1779 or RFC 2253 (either format is acceptable).
*
* <p> This constructor recognizes the attribute type keywords specified
* in {@link #X500Principal(String)} and also recognizes additional
* keywords that have entries in the {@code keywordMap} parameter.
* Keyword entries in the keywordMap take precedence over the default
* keywords recognized by {@code X500Principal(String)}. Keywords
* MUST be specified in all upper-case, otherwise they will be ignored.
* Improperly specified keywords are ignored; however if a keyword in the
* name maps to an improperly specified Object Identifier (OID), an
* {@code IllegalArgumentException} is thrown. It is permissible to
* have 2 different keywords that map to the same OID.
*
* <p>This implementation enforces a more restrictive OID syntax than
* defined in RFC 1779 and 2253. It uses the more correct syntax defined in
* <a href="http://www.ietf.org/rfc/rfc4512.txt">RFC 4512</a>, which
* specifies that OIDs contain at least 2 digits:
*
* <p>{@code numericoid = number 1*( DOT number ) }
*
* @param name an X.500 distinguished name in RFC 1779 or RFC 2253 format
* @param keywordMap an attribute type keyword map, where each key is a
* keyword String that maps to a corresponding object identifier in String
* form (a sequence of nonnegative integers separated by periods). The map
* may be empty but never {@code null}.
* @exception NullPointerException if {@code name} or
* {@code keywordMap} is {@code null}
* @exception IllegalArgumentException if the {@code name} is
* improperly specified or a keyword in the {@code name} maps to an
* OID that is not in the correct form
* @since 1.6
*/
public X500Principal(String name, Map<String, String> keywordMap) {
if (name == null) {
throw new NullPointerException
(sun.security.util.ResourcesMgr.getString
("provided.null.name"));
}
if (keywordMap == null) {
throw new NullPointerException
(sun.security.util.ResourcesMgr.getString
("provided.null.keyword.map"));
}
try {
thisX500Name = new X500Name(name, keywordMap);
} catch (Exception e) {
IllegalArgumentException iae = new IllegalArgumentException
("improperly specified input name: " + name);
iae.initCause(e);
throw iae;
}
}
/**
* Creates an {@code X500Principal} from a distinguished name in
* ASN.1 DER encoded form. The ASN.1 notation for this structure is as
* follows.
* <pre>{@code
* Name ::= CHOICE {
* RDNSequence }
*
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
*
* RelativeDistinguishedName ::=
* SET SIZE (1 .. MAX) OF AttributeTypeAndValue
*
* AttributeTypeAndValue ::= SEQUENCE {
* type AttributeType,
* value AttributeValue }
*
* AttributeType ::= OBJECT IDENTIFIER
*
* AttributeValue ::= ANY DEFINED BY AttributeType
* ....
* DirectoryString ::= CHOICE {
* teletexString TeletexString (SIZE (1..MAX)),
* printableString PrintableString (SIZE (1..MAX)),
* universalString UniversalString (SIZE (1..MAX)),
* utf8String UTF8String (SIZE (1.. MAX)),
* bmpString BMPString (SIZE (1..MAX)) }
* }</pre>
*
* @param name a byte array containing the distinguished name in ASN.1
* DER encoded form
* @throws IllegalArgumentException if an encoding error occurs
* (incorrect form for DN)
*/
public X500Principal(byte[] name) {
try {
thisX500Name = new X500Name(name);
} catch (Exception e) {
IllegalArgumentException iae = new IllegalArgumentException
("improperly specified input name");
iae.initCause(e);
throw iae;
}
}
/**
* Creates an {@code X500Principal} from an {@code InputStream}
* containing the distinguished name in ASN.1 DER encoded form.
* The ASN.1 notation for this structure is supplied in the
* documentation for
* {@link #X500Principal(byte[] name) X500Principal(byte[] name)}.
*
* <p> The read position of the input stream is positioned
* to the next available byte after the encoded distinguished name.
*
* @param is an {@code InputStream} containing the distinguished
* name in ASN.1 DER encoded form
*
* @exception NullPointerException if the {@code InputStream}
* is {@code null}
* @exception IllegalArgumentException if an encoding error occurs
* (incorrect form for DN)
*/
public X500Principal(InputStream is) {
if (is == null) {
throw new NullPointerException("provided null input stream");
}
try {
if (is.markSupported())
is.mark(is.available() + 1);
DerValue der = new DerValue(is);
thisX500Name = new X500Name(der.data);
} catch (Exception e) {
if (is.markSupported()) {
try {
is.reset();
} catch (IOException ioe) {
IllegalArgumentException iae = new IllegalArgumentException
("improperly specified input stream " +
("and unable to reset input stream"));
iae.initCause(e);
throw iae;
}
}
IllegalArgumentException iae = new IllegalArgumentException
("improperly specified input stream");
iae.initCause(e);
throw iae;
}
}
/**
* Returns a string representation of the X.500 distinguished name using
* the format defined in RFC 2253.
*
* <p>This method is equivalent to calling
* {@code getName(X500Principal.RFC2253)}.
*
* @return the distinguished name of this {@code X500Principal}
*/
public String getName() {
return getName(X500Principal.RFC2253);
}
/**
* Returns a string representation of the X.500 distinguished name
* using the specified format. Valid values for the format are
* "RFC1779", "RFC2253", and "CANONICAL" (case insensitive).
*
* <p> If "RFC1779" is specified as the format,
* this method emits the attribute type keywords defined in
* RFC 1779 (CN, L, ST, O, OU, C, STREET).
* Any other attribute type is emitted as an OID.
*
* <p> If "RFC2253" is specified as the format,
* this method emits the attribute type keywords defined in
* RFC 2253 (CN, L, ST, O, OU, C, STREET, DC, UID).
* Any other attribute type is emitted as an OID.
* Under a strict reading, RFC 2253 only specifies a UTF-8 string
* representation. The String returned by this method is the
* Unicode string achieved by decoding this UTF-8 representation.
*
* <p> If "CANONICAL" is specified as the format,
* this method returns an RFC 2253 conformant string representation
* with the following additional canonicalizations:
*
* <ol>
* <li> Leading zeros are removed from attribute types
* that are encoded as dotted decimal OIDs
* <li> DirectoryString attribute values of type
* PrintableString and UTF8String are not
* output in hexadecimal format
* <li> DirectoryString attribute values of types
* other than PrintableString and UTF8String
* are output in hexadecimal format
* <li> Leading and trailing white space characters
* are removed from non-hexadecimal attribute values
* (unless the value consists entirely of white space characters)
* <li> Internal substrings of one or more white space characters are
* converted to a single space in non-hexadecimal
* attribute values
* <li> Relative Distinguished Names containing more than one
* Attribute Value Assertion (AVA) are output in the
* following order: an alphabetical ordering of AVAs
* containing standard keywords, followed by a numeric
* ordering of AVAs containing OID keywords.
* <li> The only characters in attribute values that are escaped are
* those which section 2.4 of RFC 2253 states must be escaped
* (they are escaped using a preceding backslash character)
* <li> The entire name is converted to upper case
* using {@code String.toUpperCase(Locale.US)}
* <li> The entire name is converted to lower case
* using {@code String.toLowerCase(Locale.US)}
* <li> The name is finally normalized using normalization form KD,
* as described in the Unicode Standard and UAX #15
* </ol>
*
* <p> Additional standard formats may be introduced in the future.
*
* @param format the format to use
*
* @return a string representation of this {@code X500Principal}
* using the specified format
* @throws IllegalArgumentException if the specified format is invalid
* or null
*/
public String getName(String format) {
if (format != null) {
if (format.equalsIgnoreCase(RFC1779)) {
return thisX500Name.getRFC1779Name();
} else if (format.equalsIgnoreCase(RFC2253)) {
return thisX500Name.getRFC2253Name();
} else if (format.equalsIgnoreCase(CANONICAL)) {
return thisX500Name.getRFC2253CanonicalName();
}
}
throw new IllegalArgumentException("invalid format specified");
}
/**
* Returns a string representation of the X.500 distinguished name
* using the specified format. Valid values for the format are
* "RFC1779" and "RFC2253" (case insensitive). "CANONICAL" is not
* permitted and an {@code IllegalArgumentException} will be thrown.
*
* <p>This method returns Strings in the format as specified in
* {@link #getName(String)} and also emits additional attribute type
* keywords for OIDs that have entries in the {@code oidMap}
* parameter. OID entries in the oidMap take precedence over the default
* OIDs recognized by {@code getName(String)}.
* Improperly specified OIDs are ignored; however if an OID
* in the name maps to an improperly specified keyword, an
* {@code IllegalArgumentException} is thrown.
*
* <p> Additional standard formats may be introduced in the future.
*
* <p> Warning: additional attribute type keywords may not be recognized
* by other implementations; therefore do not use this method if
* you are unsure if these keywords will be recognized by other
* implementations.
*
* @param format the format to use
* @param oidMap an OID map, where each key is an object identifier in
* String form (a sequence of nonnegative integers separated by periods)
* that maps to a corresponding attribute type keyword String.
* The map may be empty but never {@code null}.
* @return a string representation of this {@code X500Principal}
* using the specified format
* @throws IllegalArgumentException if the specified format is invalid,
* null, or an OID in the name maps to an improperly specified keyword
* @throws NullPointerException if {@code oidMap} is {@code null}
* @since 1.6
*/
public String getName(String format, Map<String, String> oidMap) {
if (oidMap == null) {
throw new NullPointerException
(sun.security.util.ResourcesMgr.getString
("provided.null.OID.map"));
}
if (format != null) {
if (format.equalsIgnoreCase(RFC1779)) {
return thisX500Name.getRFC1779Name(oidMap);
} else if (format.equalsIgnoreCase(RFC2253)) {
return thisX500Name.getRFC2253Name(oidMap);
}
}
throw new IllegalArgumentException("invalid format specified");
}
/**
* Returns the distinguished name in ASN.1 DER encoded form. The ASN.1
* notation for this structure is supplied in the documentation for
* {@link #X500Principal(byte[] name) X500Principal(byte[] name)}.
*
* <p>Note that the byte array returned is cloned to protect against
* subsequent modifications.
*
* @return a byte array containing the distinguished name in ASN.1 DER
* encoded form
*/
public byte[] getEncoded() {
try {
return thisX500Name.getEncoded();
} catch (IOException e) {
throw new RuntimeException("unable to get encoding", e);
}
}
/**
* Return a user-friendly string representation of this
* {@code X500Principal}.
*
* @return a string representation of this {@code X500Principal}
*/
public String toString() {
return thisX500Name.toString();
}
/**
* Compares the specified {@code Object} with this
* {@code X500Principal} for equality.
*
* <p> Specifically, this method returns {@code true} if
* the {@code Object} <i>o</i> is an {@code X500Principal}
* and if the respective canonical string representations
* (obtained via the {@code getName(X500Principal.CANONICAL)} method)
* of this object and <i>o</i> are equal.
*
* <p> This implementation is compliant with the requirements of RFC 5280.
*
* @param o Object to be compared for equality with this
* {@code X500Principal}
*
* @return {@code true} if the specified {@code Object} is equal
* to this {@code X500Principal}, {@code false} otherwise
*/
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof X500Principal == false) {
return false;
}
X500Principal other = (X500Principal)o;
return this.thisX500Name.equals(other.thisX500Name);
}
/**
* Return a hash code for this {@code X500Principal}.
*
* <p> The hash code is calculated via:
* {@code getName(X500Principal.CANONICAL).hashCode()}
*
* @return a hash code for this {@code X500Principal}
*/
public int hashCode() {
return thisX500Name.hashCode();
}
/**
* Save the X500Principal object to a stream.
*
* @serialData this {@code X500Principal} is serialized
* by writing out its DER-encoded form
* (the value of {@code getEncoded} is serialized).
*/
private void writeObject(java.io.ObjectOutputStream s)
throws IOException {
s.writeObject(thisX500Name.getEncodedInternal());
}
/**
* Reads this object from a stream (i.e., deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException,
java.io.NotActiveException,
ClassNotFoundException {
// re-create thisX500Name
thisX500Name = new X500Name((byte[])s.readObject());
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.auth.x500;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import javax.security.auth.Destroyable;
/**
* <p> This class represents an {@code X500PrivateCredential}.
* It associates an X.509 certificate, corresponding private key and the
* KeyStore alias used to reference that exact key pair in the KeyStore.
* This enables looking up the private credentials for an X.500 principal
* in a subject.
*
*/
public final class X500PrivateCredential implements Destroyable {
private X509Certificate cert;
private PrivateKey key;
private String alias;
/**
* Creates an X500PrivateCredential that associates an X.509 certificate,
* a private key and the KeyStore alias.
* <p>
* @param cert X509Certificate
* @param key PrivateKey for the certificate
* @exception IllegalArgumentException if either {@code cert} or
* {@code key} is null
*
*/
public X500PrivateCredential(X509Certificate cert, PrivateKey key) {
if (cert == null || key == null )
throw new IllegalArgumentException();
this.cert = cert;
this.key = key;
this.alias=null;
}
/**
* Creates an X500PrivateCredential that associates an X.509 certificate,
* a private key and the KeyStore alias.
* <p>
* @param cert X509Certificate
* @param key PrivateKey for the certificate
* @param alias KeyStore alias
* @exception IllegalArgumentException if either {@code cert},
* {@code key} or {@code alias} is null
*
*/
public X500PrivateCredential(X509Certificate cert, PrivateKey key,
String alias) {
if (cert == null || key == null|| alias == null )
throw new IllegalArgumentException();
this.cert = cert;
this.key = key;
this.alias=alias;
}
/**
* Returns the X.509 certificate.
* <p>
* @return the X509Certificate
*/
public X509Certificate getCertificate() {
return cert;
}
/**
* Returns the PrivateKey.
* <p>
* @return the PrivateKey
*/
public PrivateKey getPrivateKey() {
return key;
}
/**
* Returns the KeyStore alias.
* <p>
* @return the KeyStore alias
*/
public String getAlias() {
return alias;
}
/**
* Clears the references to the X.509 certificate, private key and the
* KeyStore alias in this object.
*/
public void destroy() {
cert = null;
key = null;
alias =null;
}
/**
* Determines if the references to the X.509 certificate and private key
* in this object have been cleared.
* <p>
* @return true if X509Certificate and the PrivateKey are null
*/
public boolean isDestroyed() {
return cert == null && key == null && alias==null;
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This package contains the classes that should be used to store
* X500 Principal and X500 Private Credentials in a
* <i>Subject</i>.
*
* <h2>Package Specification</h2>
*
* <ul>
* <li><a href="http://tools.ietf.org/html/rfc1779">
* RFC 1779: A String Representation of Distinguished Names</a></li>
* <li><a href="http://tools.ietf.org/html/rfc2253">
* RFC 2253: Lightweight Directory Access Protocol (v3):
* UTF-8 String Representation of Distinguished Names</a></li>
* <li><a href="http://tools.ietf.org/html/rfc5280">
* RFC 5280: Internet X.509 Public Key Infrastructure
* Certificate and Certificate Revocation List (CRL) Profile</a></li>
* <li><a href="http://tools.ietf.org/html/rfc4512">
* RFC 4512: Lightweight Directory Access Protocol (LDAP):
* Directory Information Models</a></li>
* </ul>
*
* @since JDK1.4
*/
package javax.security.auth.x500;

View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.cert;
import java.security.PublicKey;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.InvalidKeyException;
import java.security.SignatureException;
/**
* <p>Abstract class for managing a variety of identity certificates.
* An identity certificate is a guarantee by a principal that
* a public key is that of another principal. (A principal represents
* an entity such as an individual user, a group, or a corporation.)
*<p>
* This class is an abstraction for certificates that have different
* formats but important common uses. For example, different types of
* certificates, such as X.509 and PGP, share general certificate
* functionality (like encoding and verifying) and
* some types of information (like a public key).
* <p>
* X.509, PGP, and SDSI certificates can all be implemented by
* subclassing the Certificate class, even though they contain different
* sets of information, and they store and retrieve the information in
* different ways.
*
* <p><em>Note: The classes in the package {@code javax.security.cert}
* exist for compatibility with earlier versions of the
* Java Secure Sockets Extension (JSSE). New applications should instead
* use the standard Java SE certificate classes located in
* {@code java.security.cert}.</em></p>
*
* @since 1.4
* @see X509Certificate
*
* @author Hemma Prafullchandra
*/
public abstract class Certificate {
/**
* Compares this certificate for equality with the specified
* object. If the {@code other} object is an
* {@code instanceof} {@code Certificate}, then
* its encoded form is retrieved and compared with the
* encoded form of this certificate.
*
* @param other the object to test for equality with this certificate.
* @return true if the encoded forms of the two certificates
* match, false otherwise.
*/
public boolean equals(Object other) {
if (this == other)
return true;
if (!(other instanceof Certificate))
return false;
try {
byte[] thisCert = this.getEncoded();
byte[] otherCert = ((Certificate)other).getEncoded();
if (thisCert.length != otherCert.length)
return false;
for (int i = 0; i < thisCert.length; i++)
if (thisCert[i] != otherCert[i])
return false;
return true;
} catch (CertificateException e) {
return false;
}
}
/**
* Returns a hashcode value for this certificate from its
* encoded form.
*
* @return the hashcode value.
*/
public int hashCode() {
int retval = 0;
try {
byte[] certData = this.getEncoded();
for (int i = 1; i < certData.length; i++) {
retval += certData[i] * i;
}
return (retval);
} catch (CertificateException e) {
return (retval);
}
}
/**
* Returns the encoded form of this certificate. It is
* assumed that each certificate type would have only a single
* form of encoding; for example, X.509 certificates would
* be encoded as ASN.1 DER.
*
* @return encoded form of this certificate
* @exception CertificateEncodingException on internal certificate
* encoding failure
*/
public abstract byte[] getEncoded() throws CertificateEncodingException;
/**
* Verifies that this certificate was signed using the
* private key that corresponds to the specified public key.
*
* @param key the PublicKey used to carry out the verification.
*
* @exception NoSuchAlgorithmException on unsupported signature
* algorithms.
* @exception InvalidKeyException on incorrect key.
* @exception NoSuchProviderException if there's no default provider.
* @exception SignatureException on signature errors.
* @exception CertificateException on encoding errors.
*/
public abstract void verify(PublicKey key)
throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException,
SignatureException;
/**
* Verifies that this certificate was signed using the
* private key that corresponds to the specified public key.
* This method uses the signature verification engine
* supplied by the specified provider.
*
* @param key the PublicKey used to carry out the verification.
* @param sigProvider the name of the signature provider.
* @exception NoSuchAlgorithmException on unsupported signature algorithms.
* @exception InvalidKeyException on incorrect key.
* @exception NoSuchProviderException on incorrect provider.
* @exception SignatureException on signature errors.
* @exception CertificateException on encoding errors.
*/
public abstract void verify(PublicKey key, String sigProvider)
throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException,
SignatureException;
/**
* Returns a string representation of this certificate.
*
* @return a string representation of this certificate.
*/
public abstract String toString();
/**
* Gets the public key from this certificate.
*
* @return the public key.
*/
public abstract PublicKey getPublicKey();
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.cert;
/**
* Certificate Encoding Exception. This is thrown whenever an error
* occurs whilst attempting to encode a certificate.
*
* <p><em>Note: The classes in the package {@code javax.security.cert}
* exist for compatibility with earlier versions of the
* Java Secure Sockets Extension (JSSE). New applications should instead
* use the standard Java SE certificate classes located in
* {@code java.security.cert}.</em></p>
*
* @since 1.4
* @author Hemma Prafullchandra
*/
public class CertificateEncodingException extends CertificateException {
private static final long serialVersionUID = -8187642723048403470L;
/**
* Constructs a CertificateEncodingException with no detail message. A
* detail message is a String that describes this particular
* exception.
*/
public CertificateEncodingException() {
super();
}
/**
* Constructs a CertificateEncodingException with the specified detail
* message. A detail message is a String that describes this
* particular exception.
*
* @param message the detail message.
*/
public CertificateEncodingException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.cert;
/**
* This exception indicates one of a variety of certificate problems.
*
* <p><em>Note: The classes in the package {@code javax.security.cert}
* exist for compatibility with earlier versions of the
* Java Secure Sockets Extension (JSSE). New applications should instead
* use the standard Java SE certificate classes located in
* {@code java.security.cert}.</em></p>
*
* @author Hemma Prafullchandra
* @since 1.4
* @see Certificate
*/
public class CertificateException extends Exception {
private static final long serialVersionUID = -5757213374030785290L;
/**
* Constructs a certificate exception with no detail message. A detail
* message is a String that describes this particular exception.
*/
public CertificateException() {
super();
}
/**
* Constructs a certificate exception with the given detail
* message. A detail message is a String that describes this
* particular exception.
*
* @param msg the detail message.
*/
public CertificateException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.cert;
/**
* Certificate Expired Exception. This is thrown whenever the current
* {@code Date} or the specified {@code Date} is after the
* {@code notAfter} date/time specified in the validity period
* of the certificate.
*
* <p><em>Note: The classes in the package {@code javax.security.cert}
* exist for compatibility with earlier versions of the
* Java Secure Sockets Extension (JSSE). New applications should instead
* use the standard Java SE certificate classes located in
* {@code java.security.cert}.</em></p>
*
* @since 1.4
* @author Hemma Prafullchandra
*/
public class CertificateExpiredException extends CertificateException {
private static final long serialVersionUID = 5091601212177261883L;
/**
* Constructs a CertificateExpiredException with no detail message. A
* detail message is a String that describes this particular
* exception.
*/
public CertificateExpiredException() {
super();
}
/**
* Constructs a CertificateExpiredException with the specified detail
* message. A detail message is a String that describes this
* particular exception.
*
* @param message the detail message.
*/
public CertificateExpiredException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.cert;
/**
* Certificate is not yet valid exception. This is thrown whenever
* the current {@code Date} or the specified {@code Date}
* is before the {@code notBefore} date/time in the Certificate
* validity period.
*
* <p><em>Note: The classes in the package {@code javax.security.cert}
* exist for compatibility with earlier versions of the
* Java Secure Sockets Extension (JSSE). New applications should instead
* use the standard Java SE certificate classes located in
* {@code java.security.cert}.</em></p>
*
* @since 1.4
* @author Hemma Prafullchandra
*/
public class CertificateNotYetValidException extends CertificateException {
private static final long serialVersionUID = -8976172474266822818L;
/**
* Constructs a CertificateNotYetValidException with no detail message. A
* detail message is a String that describes this particular
* exception.
*/
public CertificateNotYetValidException() {
super();
}
/**
* Constructs a CertificateNotYetValidException with the specified detail
* message. A detail message is a String that describes this
* particular exception.
*
* @param message the detail message.
*/
public CertificateNotYetValidException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.cert;
/**
* Certificate Parsing Exception. This is thrown whenever
* invalid DER encoded certificate is parsed or unsupported DER features
* are found in the Certificate.
*
* <p><em>Note: The classes in the package {@code javax.security.cert}
* exist for compatibility with earlier versions of the
* Java Secure Sockets Extension (JSSE). New applications should instead
* use the standard Java SE certificate classes located in
* {@code java.security.cert}.</em></p>
*
* @since 1.4
* @author Hemma Prafullchandra
*/
public class CertificateParsingException extends CertificateException {
private static final long serialVersionUID = -8449352422951136229L;
/**
* Constructs a CertificateParsingException with no detail message. A
* detail message is a String that describes this particular
* exception.
*/
public CertificateParsingException() {
super();
}
/**
* Constructs a CertificateParsingException with the specified detail
* message. A detail message is a String that describes this
* particular exception.
*
* @param message the detail message.
*/
public CertificateParsingException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,452 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.cert;
import java.io.InputStream;
import java.lang.Class;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.Security;
import java.math.BigInteger;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.PublicKey;
import java.util.BitSet;
import java.util.Date;
/**
* Abstract class for X.509 v1 certificates. This provides a standard
* way to access all the version 1 attributes of an X.509 certificate.
* Attributes that are specific to X.509 v2 or v3 are not available
* through this interface. Future API evolution will provide full access to
* complete X.509 v3 attributes.
* <p>
* The basic X.509 format was defined by
* ISO/IEC and ANSI X9 and is described below in ASN.1:
* <pre>
* Certificate ::= SEQUENCE {
* tbsCertificate TBSCertificate,
* signatureAlgorithm AlgorithmIdentifier,
* signature BIT STRING }
* </pre>
* <p>
* These certificates are widely used to support authentication and
* other functionality in Internet security systems. Common applications
* include Privacy Enhanced Mail (PEM), Transport Layer Security (SSL),
* code signing for trusted software distribution, and Secure Electronic
* Transactions (SET).
* <p>
* These certificates are managed and vouched for by <em>Certificate
* Authorities</em> (CAs). CAs are services which create certificates by
* placing data in the X.509 standard format and then digitally signing
* that data. CAs act as trusted third parties, making introductions
* between principals who have no direct knowledge of each other.
* CA certificates are either signed by themselves, or by some other
* CA such as a "root" CA.
* <p>
* The ASN.1 definition of {@code tbsCertificate} is:
* <pre>
* TBSCertificate ::= SEQUENCE {
* version [0] EXPLICIT Version DEFAULT v1,
* serialNumber CertificateSerialNumber,
* signature AlgorithmIdentifier,
* issuer Name,
* validity Validity,
* subject Name,
* subjectPublicKeyInfo SubjectPublicKeyInfo,
* }
* </pre>
* <p>
* Here is sample code to instantiate an X.509 certificate:
* <pre>
* InputStream inStream = new FileInputStream("fileName-of-cert");
* X509Certificate cert = X509Certificate.getInstance(inStream);
* inStream.close();
* </pre>
* OR
* <pre>
* byte[] certData = &lt;certificate read from a file, say&gt;
* X509Certificate cert = X509Certificate.getInstance(certData);
* </pre>
* <p>
* In either case, the code that instantiates an X.509 certificate
* consults the value of the {@code cert.provider.x509v1} security property
* to locate the actual implementation or instantiates a default implementation.
* <p>
* The {@code cert.provider.x509v1} property is set to a default
* implementation for X.509 such as:
* <pre>
* cert.provider.x509v1=com.sun.security.cert.internal.x509.X509V1CertImpl
* </pre>
* <p>
* The value of this {@code cert.provider.x509v1} property has to be
* changed to instantiate another implementation. If this security
* property is not set, a default implementation will be used.
* Currently, due to possible security restrictions on access to
* Security properties, this value is looked up and cached at class
* initialization time and will fallback on a default implementation if
* the Security property is not accessible.
*
* <p><em>Note: The classes in the package {@code javax.security.cert}
* exist for compatibility with earlier versions of the
* Java Secure Sockets Extension (JSSE). New applications should instead
* use the standard Java SE certificate classes located in
* {@code java.security.cert}.</em></p>
*
* @author Hemma Prafullchandra
* @since 1.4
* @see Certificate
* @see java.security.cert.X509Extension
* @see java.security.Security security properties
*/
public abstract class X509Certificate extends Certificate {
/*
* Constant to lookup in the Security properties file.
* In the Security properties file the default implementation
* for X.509 v3 is given as:
* <pre>
* cert.provider.x509v1=com.sun.security.cert.internal.x509.X509V1CertImpl
* </pre>
*/
private static final String X509_PROVIDER = "cert.provider.x509v1";
private static String X509Provider;
static {
X509Provider = AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
return Security.getProperty(X509_PROVIDER);
}
}
);
}
/**
* Instantiates an X509Certificate object, and initializes it with
* the data read from the input stream {@code inStream}.
* The implementation (X509Certificate is an abstract class) is
* provided by the class specified as the value of the
* {@code cert.provider.x509v1} security property.
*
* <p>Note: Only one DER-encoded
* certificate is expected to be in the input stream.
* Also, all X509Certificate
* subclasses must provide a constructor of the form:
* <pre>{@code
* public <subClass>(InputStream inStream) ...
* }</pre>
*
* @param inStream an input stream with the data to be read to
* initialize the certificate.
* @return an X509Certificate object initialized with the data
* from the input stream.
* @exception CertificateException if a class initialization
* or certificate parsing error occurs.
*/
public static final X509Certificate getInstance(InputStream inStream)
throws CertificateException {
return getInst((Object)inStream);
}
/**
* Instantiates an X509Certificate object, and initializes it with
* the specified byte array.
* The implementation (X509Certificate is an abstract class) is
* provided by the class specified as the value of the
* {@code cert.provider.x509v1} security property.
*
* <p>Note: All X509Certificate
* subclasses must provide a constructor of the form:
* <pre>{@code
* public <subClass>(InputStream inStream) ...
* }</pre>
*
* @param certData a byte array containing the DER-encoded
* certificate.
* @return an X509Certificate object initialized with the data
* from {@code certData}.
* @exception CertificateException if a class initialization
* or certificate parsing error occurs.
*/
public static final X509Certificate getInstance(byte[] certData)
throws CertificateException {
return getInst((Object)certData);
}
private static final X509Certificate getInst(Object value)
throws CertificateException {
/*
* This turns out not to work for now. To run under JDK1.2 we would
* need to call beginPrivileged() but we can't do that and run
* under JDK1.1.
*/
String className = X509Provider;
if (className == null || className.length() == 0) {
// shouldn't happen, but assume corrupted properties file
// provide access to sun implementation
className = "com.sun.security.cert.internal.x509.X509V1CertImpl";
}
try {
Class<?>[] params = null;
if (value instanceof InputStream) {
params = new Class<?>[] { InputStream.class };
} else if (value instanceof byte[]) {
params = new Class<?>[] { value.getClass() };
} else
throw new CertificateException("Unsupported argument type");
Class<?> certClass = Class.forName(className);
// get the appropriate constructor and instantiate it
Constructor<?> cons = certClass.getConstructor(params);
// get a new instance
Object obj = cons.newInstance(new Object[] {value});
return (X509Certificate)obj;
} catch (ClassNotFoundException e) {
throw new CertificateException("Could not find class: " + e);
} catch (IllegalAccessException e) {
throw new CertificateException("Could not access class: " + e);
} catch (InstantiationException e) {
throw new CertificateException("Problems instantiating: " + e);
} catch (InvocationTargetException e) {
throw new CertificateException("InvocationTargetException: "
+ e.getTargetException());
} catch (NoSuchMethodException e) {
throw new CertificateException("Could not find class method: "
+ e.getMessage());
}
}
/**
* Checks that the certificate is currently valid. It is if
* the current date and time are within the validity period given in the
* certificate.
* <p>
* The validity period consists of two date/time values:
* the first and last dates (and times) on which the certificate
* is valid. It is defined in
* ASN.1 as:
* <pre>
* validity Validity
*
* Validity ::= SEQUENCE {
* notBefore CertificateValidityDate,
* notAfter CertificateValidityDate }
*
* CertificateValidityDate ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
* </pre>
*
* @exception CertificateExpiredException if the certificate has expired.
* @exception CertificateNotYetValidException if the certificate is not
* yet valid.
*/
public abstract void checkValidity()
throws CertificateExpiredException, CertificateNotYetValidException;
/**
* Checks that the specified date is within the certificate's
* validity period. In other words, this determines whether the
* certificate would be valid at the specified date/time.
*
* @param date the Date to check against to see if this certificate
* is valid at that date/time.
* @exception CertificateExpiredException if the certificate has expired
* with respect to the {@code date} supplied.
* @exception CertificateNotYetValidException if the certificate is not
* yet valid with respect to the {@code date} supplied.
* @see #checkValidity()
*/
public abstract void checkValidity(Date date)
throws CertificateExpiredException, CertificateNotYetValidException;
/**
* Gets the {@code version} (version number) value from the
* certificate. The ASN.1 definition for this is:
* <pre>
* version [0] EXPLICIT Version DEFAULT v1
*
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
* </pre>
*
* @return the version number from the ASN.1 encoding, i.e. 0, 1 or 2.
*/
public abstract int getVersion();
/**
* Gets the {@code serialNumber} value from the certificate.
* The serial number is an integer assigned by the certification
* authority to each certificate. It must be unique for each
* certificate issued by a given CA (i.e., the issuer name and
* serial number identify a unique certificate).
* The ASN.1 definition for this is:
* <pre>
* serialNumber CertificateSerialNumber
*
* CertificateSerialNumber ::= INTEGER
* </pre>
*
* @return the serial number.
*/
public abstract BigInteger getSerialNumber();
/**
* Gets the {@code issuer} (issuer distinguished name) value from
* the certificate. The issuer name identifies the entity that signed (and
* issued) the certificate.
*
* <p>The issuer name field contains an
* X.500 distinguished name (DN).
* The ASN.1 definition for this is:
* <pre>
* issuer Name
*
* Name ::= CHOICE { RDNSequence }
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
* RelativeDistinguishedName ::=
* SET OF AttributeValueAssertion
*
* AttributeValueAssertion ::= SEQUENCE {
* AttributeType,
* AttributeValue }
* AttributeType ::= OBJECT IDENTIFIER
* AttributeValue ::= ANY
* </pre>
* The {@code Name} describes a hierarchical name composed of
* attributes, such as country name, and corresponding values, such as US.
* The type of the {@code AttributeValue} component is determined by
* the {@code AttributeType}; in general it will be a
* {@code directoryString}. A {@code directoryString} is usually
* one of {@code PrintableString},
* {@code TeletexString} or {@code UniversalString}.
*
* @return a Principal whose name is the issuer distinguished name.
*/
public abstract Principal getIssuerDN();
/**
* Gets the {@code subject} (subject distinguished name) value
* from the certificate.
* The ASN.1 definition for this is:
* <pre>
* subject Name
* </pre>
*
* <p>See {@link #getIssuerDN() getIssuerDN} for {@code Name}
* and other relevant definitions.
*
* @return a Principal whose name is the subject name.
* @see #getIssuerDN()
*/
public abstract Principal getSubjectDN();
/**
* Gets the {@code notBefore} date from the validity period of
* the certificate.
* The relevant ASN.1 definitions are:
* <pre>
* validity Validity
*
* Validity ::= SEQUENCE {
* notBefore CertificateValidityDate,
* notAfter CertificateValidityDate }
*
* CertificateValidityDate ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
* </pre>
*
* @return the start date of the validity period.
* @see #checkValidity()
*/
public abstract Date getNotBefore();
/**
* Gets the {@code notAfter} date from the validity period of
* the certificate. See {@link #getNotBefore() getNotBefore}
* for relevant ASN.1 definitions.
*
* @return the end date of the validity period.
* @see #checkValidity()
*/
public abstract Date getNotAfter();
/**
* Gets the signature algorithm name for the certificate
* signature algorithm. An example is the string "SHA-1/DSA".
* The ASN.1 definition for this is:
* <pre>
* signatureAlgorithm AlgorithmIdentifier
*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL }
* -- contains a value of the type
* -- registered for use with the
* -- algorithm object identifier value
* </pre>
*
* <p>The algorithm name is determined from the {@code algorithm}
* OID string.
*
* @return the signature algorithm name.
*/
public abstract String getSigAlgName();
/**
* Gets the signature algorithm OID string from the certificate.
* An OID is represented by a set of positive whole numbers separated
* by periods.
* For example, the string "1.2.840.10040.4.3" identifies the SHA-1
* with DSA signature algorithm, as per the PKIX part I.
*
* <p>See {@link #getSigAlgName() getSigAlgName} for
* relevant ASN.1 definitions.
*
* @return the signature algorithm OID string.
*/
public abstract String getSigAlgOID();
/**
* Gets the DER-encoded signature algorithm parameters from this
* certificate's signature algorithm. In most cases, the signature
* algorithm parameters are null; the parameters are usually
* supplied with the certificate's public key.
*
* <p>See {@link #getSigAlgName() getSigAlgName} for
* relevant ASN.1 definitions.
*
* @return the DER-encoded signature algorithm parameters, or
* null if no parameters are present.
*/
public abstract byte[] getSigAlgParams();
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Provides classes for public key certificates.
*
* These classes include a simplified version of the
* java.security.cert package. These classes were developed
* as part of the Java Secure Socket
* Extension (JSSE). When JSSE was added to the J2SE version 1.4, this
* package was added for backward-compatibility reasons only.
*
* New applications should not use this package, but rather
* java.security.cert.
*
* @since 1.4
*/
package javax.security.cert;

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.sasl;
/**
* This exception is thrown by a SASL mechanism implementation
* to indicate that the SASL
* exchange has failed due to reasons related to authentication, such as
* an invalid identity, passphrase, or key.
* <p>
* Note that the lack of an AuthenticationException does not mean that
* the failure was not due to an authentication error. A SASL mechanism
* implementation might throw the more general SaslException instead of
* AuthenticationException if it is unable to determine the nature
* of the failure, or if does not want to disclose the nature of
* the failure, for example, due to security reasons.
*
* @since 1.5
*
* @author Rosanna Lee
* @author Rob Weltman
*/
public class AuthenticationException extends SaslException {
/**
* Constructs a new instance of {@code AuthenticationException}.
* The root exception and the detailed message are null.
*/
public AuthenticationException () {
super();
}
/**
* Constructs a new instance of {@code AuthenticationException}
* with a detailed message.
* The root exception is null.
* @param detail A possibly null string containing details of the exception.
*
* @see java.lang.Throwable#getMessage
*/
public AuthenticationException (String detail) {
super(detail);
}
/**
* Constructs a new instance of {@code AuthenticationException} with a detailed message
* and a root exception.
*
* @param detail A possibly null string containing details of the exception.
* @param ex A possibly null root exception that caused this exception.
*
* @see java.lang.Throwable#getMessage
* @see #getCause
*/
public AuthenticationException (String detail, Throwable ex) {
super(detail, ex);
}
/** Use serialVersionUID from JSR 28 RI for interoperability */
private static final long serialVersionUID = -3579708765071815007L;
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.sasl;
import javax.security.auth.callback.Callback;
/**
* This callback is used by {@code SaslServer} to determine whether
* one entity (identified by an authenticated authentication id)
* can act on
* behalf of another entity (identified by an authorization id).
*
* @since 1.5
*
* @author Rosanna Lee
* @author Rob Weltman
*/
public class AuthorizeCallback implements Callback, java.io.Serializable {
/**
* The (authenticated) authentication id to check.
* @serial
*/
private String authenticationID;
/**
* The authorization id to check.
* @serial
*/
private String authorizationID;
/**
* The id of the authorized entity. If null, the id of
* the authorized entity is authorizationID.
* @serial
*/
private String authorizedID;
/**
* A flag indicating whether the authentication id is allowed to
* act on behalf of the authorization id.
* @serial
*/
private boolean authorized;
/**
* Constructs an instance of {@code AuthorizeCallback}.
*
* @param authnID The (authenticated) authentication id.
* @param authzID The authorization id.
*/
public AuthorizeCallback(String authnID, String authzID) {
authenticationID = authnID;
authorizationID = authzID;
}
/**
* Returns the authentication id to check.
* @return The authentication id to check.
*/
public String getAuthenticationID() {
return authenticationID;
}
/**
* Returns the authorization id to check.
* @return The authentication id to check.
*/
public String getAuthorizationID() {
return authorizationID;
}
/**
* Determines whether the authentication id is allowed to
* act on behalf of the authorization id.
*
* @return {@code true} if authorization is allowed; {@code false} otherwise
* @see #setAuthorized(boolean)
* @see #getAuthorizedID()
*/
public boolean isAuthorized() {
return authorized;
}
/**
* Sets whether the authorization is allowed.
* @param ok {@code true} if authorization is allowed; {@code false} otherwise
* @see #isAuthorized
* @see #setAuthorizedID(java.lang.String)
*/
public void setAuthorized(boolean ok) {
authorized = ok;
}
/**
* Returns the id of the authorized user.
* @return The id of the authorized user. {@code null} means the
* authorization failed.
* @see #setAuthorized(boolean)
* @see #setAuthorizedID(java.lang.String)
*/
public String getAuthorizedID() {
if (!authorized) {
return null;
}
return (authorizedID == null) ? authorizationID : authorizedID;
}
/**
* Sets the id of the authorized entity. Called by handler only when the id
* is different from getAuthorizationID(). For example, the id
* might need to be canonicalized for the environment in which it
* will be used.
* @param id The id of the authorized user.
* @see #setAuthorized(boolean)
* @see #getAuthorizedID
*/
public void setAuthorizedID(String id) {
authorizedID = id;
}
private static final long serialVersionUID = -2353344186490470805L;
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.sasl;
import javax.security.auth.callback.TextInputCallback;
/**
* This callback is used by {@code SaslClient} and {@code SaslServer}
* to retrieve realm information.
*
* @since 1.5
*
* @author Rosanna Lee
* @author Rob Weltman
*/
public class RealmCallback extends TextInputCallback {
/**
* Constructs a {@code RealmCallback} with a prompt.
*
* @param prompt The non-null prompt to use to request the realm information.
* @throws IllegalArgumentException If {@code prompt} is null or
* the empty string.
*/
public RealmCallback(String prompt) {
super(prompt);
}
/**
* Constructs a {@code RealmCallback} with a prompt and default
* realm information.
*
* @param prompt The non-null prompt to use to request the realm information.
* @param defaultRealmInfo The non-null default realm information to use.
* @throws IllegalArgumentException If {@code prompt} is null or
* the empty string,
* or if {@code defaultRealm} is empty or null.
*/
public RealmCallback(String prompt, String defaultRealmInfo) {
super(prompt, defaultRealmInfo);
}
private static final long serialVersionUID = -4342673378785456908L;
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.sasl;
import javax.security.auth.callback.ChoiceCallback;
/**
* This callback is used by {@code SaslClient} and {@code SaslServer}
* to obtain a realm given a list of realm choices.
*
* @since 1.5
*
* @author Rosanna Lee
* @author Rob Weltman
*/
public class RealmChoiceCallback extends ChoiceCallback {
/**
* Constructs a {@code RealmChoiceCallback} with a prompt, a list of
* choices and a default choice.
*
* @param prompt the non-null prompt to use to request the realm.
* @param choices the non-null list of realms to choose from.
* @param defaultChoice the choice to be used as the default choice
* when the list of choices is displayed. It is an index into
* the {@code choices} array.
* @param multiple true if multiple choices allowed; false otherwise
* @throws IllegalArgumentException If {@code prompt} is null or the empty string,
* if {@code choices} has a length of 0, if any element from
* {@code choices} is null or empty, or if {@code defaultChoice}
* does not fall within the array boundary of {@code choices}
*/
public RealmChoiceCallback(String prompt, String[]choices,
int defaultChoice, boolean multiple) {
super(prompt, choices, defaultChoice, multiple);
}
private static final long serialVersionUID = -8588141348846281332L;
}

View File

@@ -0,0 +1,668 @@
/*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.sasl;
import javax.security.auth.callback.CallbackHandler;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import java.security.Provider;
import java.security.Security;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A static class for creating SASL clients and servers.
*<p>
* This class defines the policy of how to locate, load, and instantiate
* SASL clients and servers.
*<p>
* For example, an application or library gets a SASL client by doing
* something like:
*<blockquote><pre>
* SaslClient sc = Sasl.createSaslClient(mechanisms,
* authorizationId, protocol, serverName, props, callbackHandler);
*</pre></blockquote>
* It can then proceed to use the instance to create an authentication connection.
*<p>
* Similarly, a server gets a SASL server by using code that looks as follows:
*<blockquote><pre>
* SaslServer ss = Sasl.createSaslServer(mechanism,
* protocol, serverName, props, callbackHandler);
*</pre></blockquote>
*
* @since 1.5
*
* @author Rosanna Lee
* @author Rob Weltman
*/
public class Sasl {
private static List<String> disabledMechanisms = new ArrayList<>();
static {
String prop = AccessController.doPrivileged(
(PrivilegedAction<String>)
() -> Security.getProperty("jdk.sasl.disabledMechanisms"));
if (prop != null) {
for (String s : prop.split("\\s*,\\s*")) {
if (!s.isEmpty()) {
disabledMechanisms.add(s);
}
}
}
}
private static final String SASL_LOGGER_NAME = "javax.security.sasl";
/**
* Logger for debug messages
*/
private static final Logger logger = Logger.getLogger(SASL_LOGGER_NAME);
// Cannot create one of these
private Sasl() {
}
/**
* The name of a property that specifies the quality-of-protection to use.
* The property contains a comma-separated, ordered list
* of quality-of-protection values that the
* client or server is willing to support. A qop value is one of
* <ul>
* <li>{@code "auth"} - authentication only</li>
* <li>{@code "auth-int"} - authentication plus integrity protection</li>
* <li>{@code "auth-conf"} - authentication plus integrity and confidentiality
* protection</li>
* </ul>
*
* The order of the list specifies the preference order of the client or
* server. If this property is absent, the default qop is {@code "auth"}.
* The value of this constant is {@code "javax.security.sasl.qop"}.
*/
public static final String QOP = "javax.security.sasl.qop";
/**
* The name of a property that specifies the cipher strength to use.
* The property contains a comma-separated, ordered list
* of cipher strength values that
* the client or server is willing to support. A strength value is one of
* <ul>
* <li>{@code "low"}</li>
* <li>{@code "medium"}</li>
* <li>{@code "high"}</li>
* </ul>
* The order of the list specifies the preference order of the client or
* server. An implementation should allow configuration of the meaning
* of these values. An application may use the Java Cryptography
* Extension (JCE) with JCE-aware mechanisms to control the selection of
* cipher suites that match the strength values.
* <BR>
* If this property is absent, the default strength is
* {@code "high,medium,low"}.
* The value of this constant is {@code "javax.security.sasl.strength"}.
*/
public static final String STRENGTH = "javax.security.sasl.strength";
/**
* The name of a property that specifies whether the
* server must authenticate to the client. The property contains
* {@code "true"} if the server must
* authenticate the to client; {@code "false"} otherwise.
* The default is {@code "false"}.
* <br>The value of this constant is
* {@code "javax.security.sasl.server.authentication"}.
*/
public static final String SERVER_AUTH =
"javax.security.sasl.server.authentication";
/**
* The name of a property that specifies the bound server name for
* an unbound server. A server is created as an unbound server by setting
* the {@code serverName} argument in {@link #createSaslServer} as null.
* The property contains the bound host name after the authentication
* exchange has completed. It is only available on the server side.
* <br>The value of this constant is
* {@code "javax.security.sasl.bound.server.name"}.
*/
public static final String BOUND_SERVER_NAME =
"javax.security.sasl.bound.server.name";
/**
* The name of a property that specifies the maximum size of the receive
* buffer in bytes of {@code SaslClient}/{@code SaslServer}.
* The property contains the string representation of an integer.
* <br>If this property is absent, the default size
* is defined by the mechanism.
* <br>The value of this constant is {@code "javax.security.sasl.maxbuffer"}.
*/
public static final String MAX_BUFFER = "javax.security.sasl.maxbuffer";
/**
* The name of a property that specifies the maximum size of the raw send
* buffer in bytes of {@code SaslClient}/{@code SaslServer}.
* The property contains the string representation of an integer.
* The value of this property is negotiated between the client and server
* during the authentication exchange.
* <br>The value of this constant is {@code "javax.security.sasl.rawsendsize"}.
*/
public static final String RAW_SEND_SIZE = "javax.security.sasl.rawsendsize";
/**
* The name of a property that specifies whether to reuse previously
* authenticated session information. The property contains "true" if the
* mechanism implementation may attempt to reuse previously authenticated
* session information; it contains "false" if the implementation must
* not reuse previously authenticated session information. A setting of
* "true" serves only as a hint: it does not necessarily entail actual
* reuse because reuse might not be possible due to a number of reasons,
* including, but not limited to, lack of mechanism support for reuse,
* expiration of reusable information, and the peer's refusal to support
* reuse.
*
* The property's default value is "false". The value of this constant
* is "javax.security.sasl.reuse".
*
* Note that all other parameters and properties required to create a
* SASL client/server instance must be provided regardless of whether
* this property has been supplied. That is, you cannot supply any less
* information in anticipation of reuse.
*
* Mechanism implementations that support reuse might allow customization
* of its implementation, for factors such as cache size, timeouts, and
* criteria for reusability. Such customizations are
* implementation-dependent.
*/
public static final String REUSE = "javax.security.sasl.reuse";
/**
* The name of a property that specifies
* whether mechanisms susceptible to simple plain passive attacks (e.g.,
* "PLAIN") are not permitted. The property
* contains {@code "true"} if such mechanisms are not permitted;
* {@code "false"} if such mechanisms are permitted.
* The default is {@code "false"}.
* <br>The value of this constant is
* {@code "javax.security.sasl.policy.noplaintext"}.
*/
public static final String POLICY_NOPLAINTEXT =
"javax.security.sasl.policy.noplaintext";
/**
* The name of a property that specifies whether
* mechanisms susceptible to active (non-dictionary) attacks
* are not permitted.
* The property contains {@code "true"}
* if mechanisms susceptible to active attacks
* are not permitted; {@code "false"} if such mechanisms are permitted.
* The default is {@code "false"}.
* <br>The value of this constant is
* {@code "javax.security.sasl.policy.noactive"}.
*/
public static final String POLICY_NOACTIVE =
"javax.security.sasl.policy.noactive";
/**
* The name of a property that specifies whether
* mechanisms susceptible to passive dictionary attacks are not permitted.
* The property contains {@code "true"}
* if mechanisms susceptible to dictionary attacks are not permitted;
* {@code "false"} if such mechanisms are permitted.
* The default is {@code "false"}.
*<br>
* The value of this constant is
* {@code "javax.security.sasl.policy.nodictionary"}.
*/
public static final String POLICY_NODICTIONARY =
"javax.security.sasl.policy.nodictionary";
/**
* The name of a property that specifies whether mechanisms that accept
* anonymous login are not permitted. The property contains {@code "true"}
* if mechanisms that accept anonymous login are not permitted;
* {@code "false"}
* if such mechanisms are permitted. The default is {@code "false"}.
*<br>
* The value of this constant is
* {@code "javax.security.sasl.policy.noanonymous"}.
*/
public static final String POLICY_NOANONYMOUS =
"javax.security.sasl.policy.noanonymous";
/**
* The name of a property that specifies whether mechanisms that implement
* forward secrecy between sessions are required. Forward secrecy
* means that breaking into one session will not automatically
* provide information for breaking into future sessions.
* The property
* contains {@code "true"} if mechanisms that implement forward secrecy
* between sessions are required; {@code "false"} if such mechanisms
* are not required. The default is {@code "false"}.
*<br>
* The value of this constant is
* {@code "javax.security.sasl.policy.forward"}.
*/
public static final String POLICY_FORWARD_SECRECY =
"javax.security.sasl.policy.forward";
/**
* The name of a property that specifies whether
* mechanisms that pass client credentials are required. The property
* contains {@code "true"} if mechanisms that pass
* client credentials are required; {@code "false"}
* if such mechanisms are not required. The default is {@code "false"}.
*<br>
* The value of this constant is
* {@code "javax.security.sasl.policy.credentials"}.
*/
public static final String POLICY_PASS_CREDENTIALS =
"javax.security.sasl.policy.credentials";
/**
* The name of a property that specifies the credentials to use.
* The property contains a mechanism-specific Java credential object.
* Mechanism implementations may examine the value of this property
* to determine whether it is a class that they support.
* The property may be used to supply credentials to a mechanism that
* supports delegated authentication.
*<br>
* The value of this constant is
* {@code "javax.security.sasl.credentials"}.
*/
public static final String CREDENTIALS = "javax.security.sasl.credentials";
/**
* Creates a {@code SaslClient} using the parameters supplied.
*
* This method uses the
<a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#Provider">JCA Security Provider Framework</a>, described in the
* "Java Cryptography Architecture API Specification &amp; Reference", for
* locating and selecting a {@code SaslClient} implementation.
*
* First, it
* obtains an ordered list of {@code SaslClientFactory} instances from
* the registered security providers for the "SaslClientFactory" service
* and the specified SASL mechanism(s). It then invokes
* {@code createSaslClient()} on each factory instance on the list
* until one produces a non-null {@code SaslClient} instance. It returns
* the non-null {@code SaslClient} instance, or null if the search fails
* to produce a non-null {@code SaslClient} instance.
*<p>
* A security provider for SaslClientFactory registers with the
* JCA Security Provider Framework keys of the form <br>
* {@code SaslClientFactory.}<em>{@code mechanism_name}</em>
* <br>
* and values that are class names of implementations of
* {@code javax.security.sasl.SaslClientFactory}.
*
* For example, a provider that contains a factory class,
* {@code com.wiz.sasl.digest.ClientFactory}, that supports the
* "DIGEST-MD5" mechanism would register the following entry with the JCA:
* {@code SaslClientFactory.DIGEST-MD5 com.wiz.sasl.digest.ClientFactory}
*<p>
* See the
* "Java Cryptography Architecture API Specification &amp; Reference"
* for information about how to install and configure security service
* providers.
* <p>
* If a mechanism is listed in the {@code jdk.sasl.disabledMechanisms}
* security property, it will be ignored and won't be negotiated.
*
* @param mechanisms The non-null list of mechanism names to try. Each is the
* IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
* @param authorizationId The possibly null protocol-dependent
* identification to be used for authorization.
* If null or empty, the server derives an authorization
* ID from the client's authentication credentials.
* When the SASL authentication completes successfully,
* the specified entity is granted access.
*
* @param protocol The non-null string name of the protocol for which
* the authentication is being performed (e.g., "ldap").
*
* @param serverName The non-null fully-qualified host name of the server
* to authenticate to.
*
* @param props The possibly null set of properties used to
* select the SASL mechanism and to configure the authentication
* exchange of the selected mechanism.
* For example, if {@code props} contains the
* {@code Sasl.POLICY_NOPLAINTEXT} property with the value
* {@code "true"}, then the selected
* SASL mechanism must not be susceptible to simple plain passive attacks.
* In addition to the standard properties declared in this class,
* other, possibly mechanism-specific, properties can be included.
* Properties not relevant to the selected mechanism are ignored,
* including any map entries with non-String keys.
*
* @param cbh The possibly null callback handler to used by the SASL
* mechanisms to get further information from the application/library
* to complete the authentication. For example, a SASL mechanism might
* require the authentication ID, password and realm from the caller.
* The authentication ID is requested by using a {@code NameCallback}.
* The password is requested by using a {@code PasswordCallback}.
* The realm is requested by using a {@code RealmChoiceCallback} if there is a list
* of realms to choose from, and by using a {@code RealmCallback} if
* the realm must be entered.
*
*@return A possibly null {@code SaslClient} created using the parameters
* supplied. If null, cannot find a {@code SaslClientFactory}
* that will produce one.
*@exception SaslException If cannot create a {@code SaslClient} because
* of an error.
*/
public static SaslClient createSaslClient(
String[] mechanisms,
String authorizationId,
String protocol,
String serverName,
Map<String,?> props,
CallbackHandler cbh) throws SaslException {
SaslClient mech = null;
SaslClientFactory fac;
String className;
String mechName;
for (int i = 0; i < mechanisms.length; i++) {
if ((mechName=mechanisms[i]) == null) {
throw new NullPointerException(
"Mechanism name cannot be null");
} else if (mechName.length() == 0) {
continue;
} else if (isDisabled(mechName)) {
logger.log(Level.FINE,
"Disabled " + mechName + " mechanism ignored");
continue;
}
String mechFilter = "SaslClientFactory." + mechName;
Provider[] provs = Security.getProviders(mechFilter);
for (int j = 0; provs != null && j < provs.length; j++) {
className = provs[j].getProperty(mechFilter);
if (className == null) {
// Case is ignored
continue;
}
fac = (SaslClientFactory) loadFactory(provs[j], className);
if (fac != null) {
mech = fac.createSaslClient(
new String[]{mechanisms[i]}, authorizationId,
protocol, serverName, props, cbh);
if (mech != null) {
return mech;
}
}
}
}
return null;
}
private static Object loadFactory(Provider p, String className)
throws SaslException {
try {
/*
* Load the implementation class with the same class loader
* that was used to load the provider.
* In order to get the class loader of a class, the
* caller's class loader must be the same as or an ancestor of
* the class loader being returned. Otherwise, the caller must
* have "getClassLoader" permission, or a SecurityException
* will be thrown.
*/
ClassLoader cl = p.getClass().getClassLoader();
Class<?> implClass;
implClass = Class.forName(className, true, cl);
return implClass.newInstance();
} catch (ClassNotFoundException e) {
throw new SaslException("Cannot load class " + className, e);
} catch (InstantiationException e) {
throw new SaslException("Cannot instantiate class " + className, e);
} catch (IllegalAccessException e) {
throw new SaslException("Cannot access class " + className, e);
} catch (SecurityException e) {
throw new SaslException("Cannot access class " + className, e);
}
}
/**
* Creates a {@code SaslServer} for the specified mechanism.
*
* This method uses the
<a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#Provider">JCA Security Provider Framework</a>,
* described in the
* "Java Cryptography Architecture API Specification &amp; Reference", for
* locating and selecting a {@code SaslServer} implementation.
*
* First, it
* obtains an ordered list of {@code SaslServerFactory} instances from
* the registered security providers for the "SaslServerFactory" service
* and the specified mechanism. It then invokes
* {@code createSaslServer()} on each factory instance on the list
* until one produces a non-null {@code SaslServer} instance. It returns
* the non-null {@code SaslServer} instance, or null if the search fails
* to produce a non-null {@code SaslServer} instance.
*<p>
* A security provider for SaslServerFactory registers with the
* JCA Security Provider Framework keys of the form <br>
* {@code SaslServerFactory.}<em>{@code mechanism_name}</em>
* <br>
* and values that are class names of implementations of
* {@code javax.security.sasl.SaslServerFactory}.
*
* For example, a provider that contains a factory class,
* {@code com.wiz.sasl.digest.ServerFactory}, that supports the
* "DIGEST-MD5" mechanism would register the following entry with the JCA:
* {@code SaslServerFactory.DIGEST-MD5 com.wiz.sasl.digest.ServerFactory}
*<p>
* See the
* "Java Cryptography Architecture API Specification &amp; Reference"
* for information about how to install and configure security
* service providers.
* <p>
* If {@code mechanism} is listed in the {@code jdk.sasl.disabledMechanisms}
* security property, it will be ignored and this method returns {@code null}.
*
* @param mechanism The non-null mechanism name. It must be an
* IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
* @param protocol The non-null string name of the protocol for which
* the authentication is being performed (e.g., "ldap").
* @param serverName The fully qualified host name of the server, or null
* if the server is not bound to any specific host name. If the mechanism
* does not allow an unbound server, a {@code SaslException} will
* be thrown.
* @param props The possibly null set of properties used to
* select the SASL mechanism and to configure the authentication
* exchange of the selected mechanism.
* For example, if {@code props} contains the
* {@code Sasl.POLICY_NOPLAINTEXT} property with the value
* {@code "true"}, then the selected
* SASL mechanism must not be susceptible to simple plain passive attacks.
* In addition to the standard properties declared in this class,
* other, possibly mechanism-specific, properties can be included.
* Properties not relevant to the selected mechanism are ignored,
* including any map entries with non-String keys.
*
* @param cbh The possibly null callback handler to used by the SASL
* mechanisms to get further information from the application/library
* to complete the authentication. For example, a SASL mechanism might
* require the authentication ID, password and realm from the caller.
* The authentication ID is requested by using a {@code NameCallback}.
* The password is requested by using a {@code PasswordCallback}.
* The realm is requested by using a {@code RealmChoiceCallback} if there is a list
* of realms to choose from, and by using a {@code RealmCallback} if
* the realm must be entered.
*
*@return A possibly null {@code SaslServer} created using the parameters
* supplied. If null, cannot find a {@code SaslServerFactory}
* that will produce one.
*@exception SaslException If cannot create a {@code SaslServer} because
* of an error.
**/
public static SaslServer
createSaslServer(String mechanism,
String protocol,
String serverName,
Map<String,?> props,
javax.security.auth.callback.CallbackHandler cbh)
throws SaslException {
SaslServer mech = null;
SaslServerFactory fac;
String className;
if (mechanism == null) {
throw new NullPointerException("Mechanism name cannot be null");
} else if (mechanism.length() == 0) {
return null;
} else if (isDisabled(mechanism)) {
logger.log(Level.FINE,
"Disabled " + mechanism + " mechanism ignored");
return null;
}
String mechFilter = "SaslServerFactory." + mechanism;
Provider[] provs = Security.getProviders(mechFilter);
for (int j = 0; provs != null && j < provs.length; j++) {
className = provs[j].getProperty(mechFilter);
if (className == null) {
throw new SaslException("Provider does not support " +
mechFilter);
}
fac = (SaslServerFactory) loadFactory(provs[j], className);
if (fac != null) {
mech = fac.createSaslServer(
mechanism, protocol, serverName, props, cbh);
if (mech != null) {
return mech;
}
}
}
return null;
}
/**
* Gets an enumeration of known factories for producing {@code SaslClient}.
* This method uses the same algorithm for locating factories as
* {@code createSaslClient()}.
* @return A non-null enumeration of known factories for producing
* {@code SaslClient}.
* @see #createSaslClient
*/
public static Enumeration<SaslClientFactory> getSaslClientFactories() {
Set<Object> facs = getFactories("SaslClientFactory");
final Iterator<Object> iter = facs.iterator();
return new Enumeration<SaslClientFactory>() {
public boolean hasMoreElements() {
return iter.hasNext();
}
public SaslClientFactory nextElement() {
return (SaslClientFactory)iter.next();
}
};
}
/**
* Gets an enumeration of known factories for producing {@code SaslServer}.
* This method uses the same algorithm for locating factories as
* {@code createSaslServer()}.
* @return A non-null enumeration of known factories for producing
* {@code SaslServer}.
* @see #createSaslServer
*/
public static Enumeration<SaslServerFactory> getSaslServerFactories() {
Set<Object> facs = getFactories("SaslServerFactory");
final Iterator<Object> iter = facs.iterator();
return new Enumeration<SaslServerFactory>() {
public boolean hasMoreElements() {
return iter.hasNext();
}
public SaslServerFactory nextElement() {
return (SaslServerFactory)iter.next();
}
};
}
private static Set<Object> getFactories(String serviceName) {
HashSet<Object> result = new HashSet<Object>();
if ((serviceName == null) || (serviceName.length() == 0) ||
(serviceName.endsWith("."))) {
return result;
}
Provider[] providers = Security.getProviders();
HashSet<String> classes = new HashSet<String>();
Object fac;
for (int i = 0; i < providers.length; i++) {
classes.clear();
// Check the keys for each provider.
for (Enumeration<Object> e = providers[i].keys(); e.hasMoreElements(); ) {
String currentKey = (String)e.nextElement();
if (currentKey.startsWith(serviceName)) {
// We should skip the currentKey if it contains a
// whitespace. The reason is: such an entry in the
// provider property contains attributes for the
// implementation of an algorithm. We are only interested
// in entries which lead to the implementation
// classes.
if (currentKey.indexOf(" ") < 0) {
String className = providers[i].getProperty(currentKey);
if (!classes.contains(className)) {
classes.add(className);
try {
fac = loadFactory(providers[i], className);
if (fac != null) {
result.add(fac);
}
}catch (Exception ignore) {
}
}
}
}
}
}
return Collections.unmodifiableSet(result);
}
private static boolean isDisabled(String name) {
return disabledMechanisms.contains(name);
}
}

View File

@@ -0,0 +1,225 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.sasl;
/**
* Performs SASL authentication as a client.
*<p>
* A protocol library such as one for LDAP gets an instance of this
* class in order to perform authentication defined by a specific SASL
* mechanism. Invoking methods on the {@code SaslClient} instance
* process challenges and create responses according to the SASL
* mechanism implemented by the {@code SaslClient}.
* As the authentication proceeds, the instance
* encapsulates the state of a SASL client's authentication exchange.
*<p>
* Here's an example of how an LDAP library might use a {@code SaslClient}.
* It first gets an instance of a {@code SaslClient}:
*<blockquote><pre>{@code
* SaslClient sc = Sasl.createSaslClient(mechanisms,
* authorizationId, protocol, serverName, props, callbackHandler);
*}</pre></blockquote>
* It can then proceed to use the client for authentication.
* For example, an LDAP library might use the client as follows:
*<blockquote><pre>{@code
* // Get initial response and send to server
* byte[] response = (sc.hasInitialResponse() ? sc.evaluateChallenge(new byte[0]) :
* null);
* LdapResult res = ldap.sendBindRequest(dn, sc.getName(), response);
* while (!sc.isComplete() &&
* (res.status == SASL_BIND_IN_PROGRESS || res.status == SUCCESS)) {
* response = sc.evaluateChallenge(res.getBytes());
* if (res.status == SUCCESS) {
* // we're done; don't expect to send another BIND
* if (response != null) {
* throw new SaslException(
* "Protocol error: attempting to send response after completion");
* }
* break;
* }
* res = ldap.sendBindRequest(dn, sc.getName(), response);
* }
* if (sc.isComplete() && res.status == SUCCESS) {
* String qop = (String) sc.getNegotiatedProperty(Sasl.QOP);
* if (qop != null
* && (qop.equalsIgnoreCase("auth-int")
* || qop.equalsIgnoreCase("auth-conf"))) {
*
* // Use SaslClient.wrap() and SaslClient.unwrap() for future
* // communication with server
* ldap.in = new SecureInputStream(sc, ldap.in);
* ldap.out = new SecureOutputStream(sc, ldap.out);
* }
* }
*}</pre></blockquote>
*
* If the mechanism has an initial response, the library invokes
* {@code evaluateChallenge()} with an empty
* challenge and to get initial response.
* Protocols such as IMAP4, which do not include an initial response with
* their first authentication command to the server, initiates the
* authentication without first calling {@code hasInitialResponse()}
* or {@code evaluateChallenge()}.
* When the server responds to the command, it sends an initial challenge.
* For a SASL mechanism in which the client sends data first, the server should
* have issued a challenge with no data. This will then result in a call
* (on the client) to {@code evaluateChallenge()} with an empty challenge.
*
* @since 1.5
*
* @see Sasl
* @see SaslClientFactory
*
* @author Rosanna Lee
* @author Rob Weltman
*/
public abstract interface SaslClient {
/**
* Returns the IANA-registered mechanism name of this SASL client.
* (e.g. "CRAM-MD5", "GSSAPI").
* @return A non-null string representing the IANA-registered mechanism name.
*/
public abstract String getMechanismName();
/**
* Determines whether this mechanism has an optional initial response.
* If true, caller should call {@code evaluateChallenge()} with an
* empty array to get the initial response.
*
* @return true if this mechanism has an initial response.
*/
public abstract boolean hasInitialResponse();
/**
* Evaluates the challenge data and generates a response.
* If a challenge is received from the server during the authentication
* process, this method is called to prepare an appropriate next
* response to submit to the server.
*
* @param challenge The non-null challenge sent from the server.
* The challenge array may have zero length.
*
* @return The possibly null response to send to the server.
* It is null if the challenge accompanied a "SUCCESS" status and the challenge
* only contains data for the client to update its state and no response
* needs to be sent to the server. The response is a zero-length byte
* array if the client is to send a response with no data.
* @exception SaslException If an error occurred while processing
* the challenge or generating a response.
*/
public abstract byte[] evaluateChallenge(byte[] challenge)
throws SaslException;
/**
* Determines whether the authentication exchange has completed.
* This method may be called at any time, but typically, it
* will not be called until the caller has received indication
* from the server
* (in a protocol-specific manner) that the exchange has completed.
*
* @return true if the authentication exchange has completed; false otherwise.
*/
public abstract boolean isComplete();
/**
* Unwraps a byte array received from the server.
* This method can be called only after the authentication exchange has
* completed (i.e., when {@code isComplete()} returns true) and only if
* the authentication exchange has negotiated integrity and/or privacy
* as the quality of protection; otherwise, an
* {@code IllegalStateException} is thrown.
*<p>
* {@code incoming} is the contents of the SASL buffer as defined in RFC 2222
* without the leading four octet field that represents the length.
* {@code offset} and {@code len} specify the portion of {@code incoming}
* to use.
*
* @param incoming A non-null byte array containing the encoded bytes
* from the server.
* @param offset The starting position at {@code incoming} of the bytes to use.
* @param len The number of bytes from {@code incoming} to use.
* @return A non-null byte array containing the decoded bytes.
* @exception SaslException if {@code incoming} cannot be successfully
* unwrapped.
* @exception IllegalStateException if the authentication exchange has
* not completed, or if the negotiated quality of protection
* has neither integrity nor privacy.
*/
public abstract byte[] unwrap(byte[] incoming, int offset, int len)
throws SaslException;
/**
* Wraps a byte array to be sent to the server.
* This method can be called only after the authentication exchange has
* completed (i.e., when {@code isComplete()} returns true) and only if
* the authentication exchange has negotiated integrity and/or privacy
* as the quality of protection; otherwise, an
* {@code IllegalStateException} is thrown.
*<p>
* The result of this method will make up the contents of the SASL buffer
* as defined in RFC 2222 without the leading four octet field that
* represents the length.
* {@code offset} and {@code len} specify the portion of {@code outgoing}
* to use.
*
* @param outgoing A non-null byte array containing the bytes to encode.
* @param offset The starting position at {@code outgoing} of the bytes to use.
* @param len The number of bytes from {@code outgoing} to use.
* @return A non-null byte array containing the encoded bytes.
* @exception SaslException if {@code outgoing} cannot be successfully
* wrapped.
* @exception IllegalStateException if the authentication exchange has
* not completed, or if the negotiated quality of protection
* has neither integrity nor privacy.
*/
public abstract byte[] wrap(byte[] outgoing, int offset, int len)
throws SaslException;
/**
* Retrieves the negotiated property.
* This method can be called only after the authentication exchange has
* completed (i.e., when {@code isComplete()} returns true); otherwise, an
* {@code IllegalStateException} is thrown.
*
* @param propName The non-null property name.
* @return The value of the negotiated property. If null, the property was
* not negotiated or is not applicable to this mechanism.
* @exception IllegalStateException if this authentication exchange
* has not completed
*/
public abstract Object getNegotiatedProperty(String propName);
/**
* Disposes of any system resources or security-sensitive information
* the SaslClient might be using. Invoking this method invalidates
* the SaslClient instance. This method is idempotent.
* @throws SaslException If a problem was encountered while disposing
* the resources.
*/
public abstract void dispose() throws SaslException;
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.sasl;
import java.util.Map;
import javax.security.auth.callback.CallbackHandler;
/**
* An interface for creating instances of {@code SaslClient}.
* A class that implements this interface
* must be thread-safe and handle multiple simultaneous
* requests. It must also have a public constructor that accepts no
* argument.
*<p>
* This interface is not normally accessed directly by a client, which will use the
* {@code Sasl} static methods
* instead. However, a particular environment may provide and install a
* new or different {@code SaslClientFactory}.
*
* @since 1.5
*
* @see SaslClient
* @see Sasl
*
* @author Rosanna Lee
* @author Rob Weltman
*/
public abstract interface SaslClientFactory {
/**
* Creates a SaslClient using the parameters supplied.
*
* @param mechanisms The non-null list of mechanism names to try. Each is the
* IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
* @param authorizationId The possibly null protocol-dependent
* identification to be used for authorization.
* If null or empty, the server derives an authorization
* ID from the client's authentication credentials.
* When the SASL authentication completes successfully,
* the specified entity is granted access.
* @param protocol The non-null string name of the protocol for which
* the authentication is being performed (e.g., "ldap").
* @param serverName The non-null fully qualified host name
* of the server to authenticate to.
* @param props The possibly null set of properties used to select the SASL
* mechanism and to configure the authentication exchange of the selected
* mechanism. See the {@code Sasl} class for a list of standard properties.
* Other, possibly mechanism-specific, properties can be included.
* Properties not relevant to the selected mechanism are ignored,
* including any map entries with non-String keys.
*
* @param cbh The possibly null callback handler to used by the SASL
* mechanisms to get further information from the application/library
* to complete the authentication. For example, a SASL mechanism might
* require the authentication ID, password and realm from the caller.
* The authentication ID is requested by using a {@code NameCallback}.
* The password is requested by using a {@code PasswordCallback}.
* The realm is requested by using a {@code RealmChoiceCallback} if there is a list
* of realms to choose from, and by using a {@code RealmCallback} if
* the realm must be entered.
*
*@return A possibly null {@code SaslClient} created using the parameters
* supplied. If null, this factory cannot produce a {@code SaslClient}
* using the parameters supplied.
*@exception SaslException If cannot create a {@code SaslClient} because
* of an error.
*/
public abstract SaslClient createSaslClient(
String[] mechanisms,
String authorizationId,
String protocol,
String serverName,
Map<String,?> props,
CallbackHandler cbh) throws SaslException;
/**
* Returns an array of names of mechanisms that match the specified
* mechanism selection policies.
* @param props The possibly null set of properties used to specify the
* security policy of the SASL mechanisms. For example, if {@code props}
* contains the {@code Sasl.POLICY_NOPLAINTEXT} property with the value
* {@code "true"}, then the factory must not return any SASL mechanisms
* that are susceptible to simple plain passive attacks.
* See the {@code Sasl} class for a complete list of policy properties.
* Non-policy related properties, if present in {@code props}, are ignored,
* including any map entries with non-String keys.
* @return A non-null array containing a IANA-registered SASL mechanism names.
*/
public abstract String[] getMechanismNames(Map<String,?> props);
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.sasl;
import java.io.IOException;
/**
* This class represents an error that has occurred when using SASL.
*
* @since 1.5
*
* @author Rosanna Lee
* @author Rob Weltman
*/
public class SaslException extends IOException {
/**
* The possibly null root cause exception.
* @serial
*/
// Required for serialization interoperability with JSR 28
private Throwable _exception;
/**
* Constructs a new instance of {@code SaslException}.
* The root exception and the detailed message are null.
*/
public SaslException () {
super();
}
/**
* Constructs a new instance of {@code SaslException} with a detailed message.
* The root exception is null.
* @param detail A possibly null string containing details of the exception.
*
* @see java.lang.Throwable#getMessage
*/
public SaslException (String detail) {
super(detail);
}
/**
* Constructs a new instance of {@code SaslException} with a detailed message
* and a root exception.
* For example, a SaslException might result from a problem with
* the callback handler, which might throw a NoSuchCallbackException if
* it does not support the requested callback, or throw an IOException
* if it had problems obtaining data for the callback. The
* SaslException's root exception would be then be the exception thrown
* by the callback handler.
*
* @param detail A possibly null string containing details of the exception.
* @param ex A possibly null root exception that caused this exception.
*
* @see java.lang.Throwable#getMessage
* @see #getCause
*/
public SaslException (String detail, Throwable ex) {
super(detail);
if (ex != null) {
initCause(ex);
}
}
/*
* Override Throwable.getCause() to ensure deserialized object from
* JSR 28 would return same value for getCause() (i.e., _exception).
*/
public Throwable getCause() {
return _exception;
}
/*
* Override Throwable.initCause() to match getCause() by updating
* _exception as well.
*/
public Throwable initCause(Throwable cause) {
super.initCause(cause);
_exception = cause;
return this;
}
/**
* Returns the string representation of this exception.
* The string representation contains
* this exception's class name, its detailed message, and if
* it has a root exception, the string representation of the root
* exception. This string representation
* is meant for debugging and not meant to be interpreted
* programmatically.
* @return The non-null string representation of this exception.
* @see java.lang.Throwable#getMessage
*/
// Override Throwable.toString() to conform to JSR 28
public String toString() {
String answer = super.toString();
if (_exception != null && _exception != this) {
answer += " [Caused by " + _exception.toString() + "]";
}
return answer;
}
/** Use serialVersionUID from JSR 28 RI for interoperability */
private static final long serialVersionUID = 4579784287983423626L;
}

View File

@@ -0,0 +1,216 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.sasl;
/**
* Performs SASL authentication as a server.
*<p>
* A server such an LDAP server gets an instance of this
* class in order to perform authentication defined by a specific SASL
* mechanism. Invoking methods on the {@code SaslServer} instance
* generates challenges according to the SASL
* mechanism implemented by the {@code SaslServer}.
* As the authentication proceeds, the instance
* encapsulates the state of a SASL server's authentication exchange.
*<p>
* Here's an example of how an LDAP server might use a {@code SaslServer}.
* It first gets an instance of a {@code SaslServer} for the SASL mechanism
* requested by the client:
*<blockquote><pre>
* SaslServer ss = Sasl.createSaslServer(mechanism,
* "ldap", myFQDN, props, callbackHandler);
*</pre></blockquote>
* It can then proceed to use the server for authentication.
* For example, suppose the LDAP server received an LDAP BIND request
* containing the name of the SASL mechanism and an (optional) initial
* response. It then might use the server as follows:
*<blockquote><pre>{@code
* while (!ss.isComplete()) {
* try {
* byte[] challenge = ss.evaluateResponse(response);
* if (ss.isComplete()) {
* status = ldap.sendBindResponse(mechanism, challenge, SUCCESS);
* } else {
* status = ldap.sendBindResponse(mechanism, challenge,
SASL_BIND_IN_PROGRESS);
* response = ldap.readBindRequest();
* }
* } catch (SaslException e) {
* status = ldap.sendErrorResponse(e);
* break;
* }
* }
* if (ss.isComplete() && status == SUCCESS) {
* String qop = (String) sc.getNegotiatedProperty(Sasl.QOP);
* if (qop != null
* && (qop.equalsIgnoreCase("auth-int")
* || qop.equalsIgnoreCase("auth-conf"))) {
*
* // Use SaslServer.wrap() and SaslServer.unwrap() for future
* // communication with client
* ldap.in = new SecureInputStream(ss, ldap.in);
* ldap.out = new SecureOutputStream(ss, ldap.out);
* }
* }
*}</pre></blockquote>
*
* @since 1.5
*
* @see Sasl
* @see SaslServerFactory
*
* @author Rosanna Lee
* @author Rob Weltman
*/
public abstract interface SaslServer {
/**
* Returns the IANA-registered mechanism name of this SASL server.
* (e.g. "CRAM-MD5", "GSSAPI").
* @return A non-null string representing the IANA-registered mechanism name.
*/
public abstract String getMechanismName();
/**
* Evaluates the response data and generates a challenge.
*
* If a response is received from the client during the authentication
* process, this method is called to prepare an appropriate next
* challenge to submit to the client. The challenge is null if the
* authentication has succeeded and no more challenge data is to be sent
* to the client. It is non-null if the authentication must be continued
* by sending a challenge to the client, or if the authentication has
* succeeded but challenge data needs to be processed by the client.
* {@code isComplete()} should be called
* after each call to {@code evaluateResponse()},to determine if any further
* response is needed from the client.
*
* @param response The non-null (but possibly empty) response sent
* by the client.
*
* @return The possibly null challenge to send to the client.
* It is null if the authentication has succeeded and there is
* no more challenge data to be sent to the client.
* @exception SaslException If an error occurred while processing
* the response or generating a challenge.
*/
public abstract byte[] evaluateResponse(byte[] response)
throws SaslException;
/**
* Determines whether the authentication exchange has completed.
* This method is typically called after each invocation of
* {@code evaluateResponse()} to determine whether the
* authentication has completed successfully or should be continued.
* @return true if the authentication exchange has completed; false otherwise.
*/
public abstract boolean isComplete();
/**
* Reports the authorization ID in effect for the client of this
* session.
* This method can only be called if isComplete() returns true.
* @return The authorization ID of the client.
* @exception IllegalStateException if this authentication session has not completed
*/
public String getAuthorizationID();
/**
* Unwraps a byte array received from the client.
* This method can be called only after the authentication exchange has
* completed (i.e., when {@code isComplete()} returns true) and only if
* the authentication exchange has negotiated integrity and/or privacy
* as the quality of protection; otherwise,
* an {@code IllegalStateException} is thrown.
*<p>
* {@code incoming} is the contents of the SASL buffer as defined in RFC 2222
* without the leading four octet field that represents the length.
* {@code offset} and {@code len} specify the portion of {@code incoming}
* to use.
*
* @param incoming A non-null byte array containing the encoded bytes
* from the client.
* @param offset The starting position at {@code incoming} of the bytes to use.
* @param len The number of bytes from {@code incoming} to use.
* @return A non-null byte array containing the decoded bytes.
* @exception SaslException if {@code incoming} cannot be successfully
* unwrapped.
* @exception IllegalStateException if the authentication exchange has
* not completed, or if the negotiated quality of protection
* has neither integrity nor privacy
*/
public abstract byte[] unwrap(byte[] incoming, int offset, int len)
throws SaslException;
/**
* Wraps a byte array to be sent to the client.
* This method can be called only after the authentication exchange has
* completed (i.e., when {@code isComplete()} returns true) and only if
* the authentication exchange has negotiated integrity and/or privacy
* as the quality of protection; otherwise, a {@code SaslException} is thrown.
*<p>
* The result of this method
* will make up the contents of the SASL buffer as defined in RFC 2222
* without the leading four octet field that represents the length.
* {@code offset} and {@code len} specify the portion of {@code outgoing}
* to use.
*
* @param outgoing A non-null byte array containing the bytes to encode.
* @param offset The starting position at {@code outgoing} of the bytes to use.
* @param len The number of bytes from {@code outgoing} to use.
* @return A non-null byte array containing the encoded bytes.
* @exception SaslException if {@code outgoing} cannot be successfully
* wrapped.
* @exception IllegalStateException if the authentication exchange has
* not completed, or if the negotiated quality of protection has
* neither integrity nor privacy.
*/
public abstract byte[] wrap(byte[] outgoing, int offset, int len)
throws SaslException;
/**
* Retrieves the negotiated property.
* This method can be called only after the authentication exchange has
* completed (i.e., when {@code isComplete()} returns true); otherwise, an
* {@code IllegalStateException} is thrown.
*
* @param propName the property
* @return The value of the negotiated property. If null, the property was
* not negotiated or is not applicable to this mechanism.
* @exception IllegalStateException if this authentication exchange has not completed
*/
public abstract Object getNegotiatedProperty(String propName);
/**
* Disposes of any system resources or security-sensitive information
* the SaslServer might be using. Invoking this method invalidates
* the SaslServer instance. This method is idempotent.
* @throws SaslException If a problem was encountered while disposing
* the resources.
*/
public abstract void dispose() throws SaslException;
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.security.sasl;
import java.util.Map;
import javax.security.auth.callback.CallbackHandler;
/**
* An interface for creating instances of {@code SaslServer}.
* A class that implements this interface
* must be thread-safe and handle multiple simultaneous
* requests. It must also have a public constructor that accepts no
* argument.
*<p>
* This interface is not normally accessed directly by a server, which will use the
* {@code Sasl} static methods
* instead. However, a particular environment may provide and install a
* new or different {@code SaslServerFactory}.
*
* @since 1.5
*
* @see SaslServer
* @see Sasl
*
* @author Rosanna Lee
* @author Rob Weltman
*/
public abstract interface SaslServerFactory {
/**
* Creates a {@code SaslServer} using the parameters supplied.
* It returns null
* if no {@code SaslServer} can be created using the parameters supplied.
* Throws {@code SaslException} if it cannot create a {@code SaslServer}
* because of an error.
*
* @param mechanism The non-null
* IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
* @param protocol The non-null string name of the protocol for which
* the authentication is being performed (e.g., "ldap").
* @param serverName The fully qualified host name of the server to
* authenticate to, or null if the server is not bound to any specific host
* name. If the mechanism does not allow an unbound server, a
* {@code SaslException} will be thrown.
* @param props The possibly null set of properties used to select the SASL
* mechanism and to configure the authentication exchange of the selected
* mechanism. See the {@code Sasl} class for a list of standard properties.
* Other, possibly mechanism-specific, properties can be included.
* Properties not relevant to the selected mechanism are ignored,
* including any map entries with non-String keys.
*
* @param cbh The possibly null callback handler to used by the SASL
* mechanisms to get further information from the application/library
* to complete the authentication. For example, a SASL mechanism might
* require the authentication ID, password and realm from the caller.
* The authentication ID is requested by using a {@code NameCallback}.
* The password is requested by using a {@code PasswordCallback}.
* The realm is requested by using a {@code RealmChoiceCallback} if there is a list
* of realms to choose from, and by using a {@code RealmCallback} if
* the realm must be entered.
*
*@return A possibly null {@code SaslServer} created using the parameters
* supplied. If null, this factory cannot produce a {@code SaslServer}
* using the parameters supplied.
*@exception SaslException If cannot create a {@code SaslServer} because
* of an error.
*/
public abstract SaslServer createSaslServer(
String mechanism,
String protocol,
String serverName,
Map<String,?> props,
CallbackHandler cbh) throws SaslException;
/**
* Returns an array of names of mechanisms that match the specified
* mechanism selection policies.
* @param props The possibly null set of properties used to specify the
* security policy of the SASL mechanisms. For example, if {@code props}
* contains the {@code Sasl.POLICY_NOPLAINTEXT} property with the value
* {@code "true"}, then the factory must not return any SASL mechanisms
* that are susceptible to simple plain passive attacks.
* See the {@code Sasl} class for a complete list of policy properties.
* Non-policy related properties, if present in {@code props}, are ignored,
* including any map entries with non-String keys.
* @return A non-null array containing a IANA-registered SASL mechanism names.
*/
public abstract String[] getMechanismNames(Map<String,?> props);
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Contains class and interfaces for supporting SASL.
*
* This package defines classes and interfaces for SASL mechanisms.
* It is used by developers to add authentication support for
* connection-based protocols that use SASL.
*
* <h3>SASL Overview</h3>
*
* Simple Authentication and Security Layer (SASL) specifies a
* challenge-response protocol in which data is exchanged between the
* client and the server for the purposes of
* authentication and (optional) establishment of a security layer on
* which to carry on subsequent communications. It is used with
* connection-based protocols such as LDAPv3 or IMAPv4. SASL is
* described in
* <A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>.
*
*
* There are various <em>mechanisms</em> defined for SASL.
* Each mechanism defines the data that must be exchanged between the
* client and server in order for the authentication to succeed.
* This data exchange required for a particular mechanism is referred to
* to as its <em>protocol profile</em>.
* The following are some examples of mechanisms that have been defined by
* the Internet standards community.
* <ul>
* <li>DIGEST-MD5 (<A HREF="http://www.ietf.org/rfc/rfc2831.txt">RFC 2831</a>).
* This mechanism defines how HTTP Digest Authentication can be used as a SASL
* mechanism.
* <li>Anonymous (<A HREF="http://www.ietf.org/rfc/rfc2245.txt">RFC 2245</a>).
* This mechanism is anonymous authentication in which no credentials are
* necessary.
* <li>External (<A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>).
* This mechanism obtains authentication information
* from an external source (such as TLS or IPsec).
* <li>S/Key (<A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>).
* This mechanism uses the MD4 digest algorithm to exchange data based on
* a shared secret.
* <li>GSSAPI (<A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>).
* This mechanism uses the
* <A HREF="http://www.ietf.org/rfc/rfc2078.txt">GSSAPI</A>
* for obtaining authentication information.
* </ul>
*
* Some of these mechanisms provide both authentication and establishment
* of a security layer, others only authentication. Anonymous and
* S/Key do not provide for any security layers. GSSAPI and DIGEST-MD5
* allow negotiation of the security layer. For External, the
* security layer is determined by the external protocol.
*
* <h3>Usage</h3>
*
* Users of this API are typically developers who produce
* client library implementations for connection-based protocols,
* such as LDAPv3 and IMAPv4,
* and developers who write servers (such as LDAP servers and IMAP servers).
* Developers who write client libraries use the
* {@code SaslClient} and {@code SaslClientFactory} interfaces.
* Developers who write servers use the
* {@code SaslServer} and {@code SaslServerFactory} interfaces.
*
* Among these two groups of users, each can be further divided into two groups:
* those who <em>produce</em> the SASL mechanisms and those
* who <em>use</em> the SASL mechanisms.
* The producers of SASL mechanisms need to provide implementations
* for these interfaces, while users of the SASL mechanisms use
* the APIs in this package to access those implementations.
*
* <h2>Related Documentation</h2>
*
* Please refer to the
* <a href="../../../../technotes/guides/security/sasl/sasl-refguide.html">Java
* SASL Programming Guide</a> for information on how to use this API.
*
* @since 1.5
*/
package javax.security.sasl;